From edce43bf5d5d4accc9397783d484a4d0b52f890a Mon Sep 17 00:00:00 2001 From: Alexey Alter-Pesotskiy Date: Thu, 2 Nov 2023 16:22:05 +0000 Subject: [PATCH] [CI] Capture snapshots --- .github/workflows/smoke-checks.yml | 18 +++++--- fastlane/Fastfile | 68 +++++++++++++++++++++++++++--- 2 files changed, 75 insertions(+), 11 deletions(-) diff --git a/.github/workflows/smoke-checks.yml b/.github/workflows/smoke-checks.yml index 45f65921..0823efd6 100644 --- a/.github/workflows/smoke-checks.yml +++ b/.github/workflows/smoke-checks.yml @@ -7,6 +7,12 @@ on: # - '!main' TODO: commented until `develop` branch is in place workflow_dispatch: + inputs: + snapshots: + description: 'Should Snapshots be recorded on CI?' + type: boolean + required: false + default: false concurrency: group: ${{ github.workflow }}-${{ github.ref }} @@ -23,7 +29,7 @@ jobs: env: GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} GITHUB_PR_NUM: ${{ github.event.number }} - if: ${{ github.event_name != 'push' }} + if: ${{ github.event_name != 'push' }} && github.event.inputs.snapshots != 'true' steps: - uses: actions/checkout@v3.1.0 - uses: ./.github/actions/bootstrap @@ -69,10 +75,10 @@ jobs: - uses: ./.github/actions/bootstrap - uses: ./.github/actions/python-cache - name: Run UI Tests (Debug) - run: bundle exec fastlane test_ui device:"${{ env.IOS_SIMULATOR_DEVICE }}" skip_build:true + run: bundle exec fastlane test_ui device:"${{ env.IOS_SIMULATOR_DEVICE }}" skip_build:true record:${{ github.event.inputs.snapshots }} timeout-minutes: 40 env: - GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} + GITHUB_TOKEN: ${{ secrets.CI_BOT_GITHUB_TOKEN }} # to open a PR GITHUB_PR_NUM: ${{ github.event.number }} - name: Get branch name id: get_branch_name @@ -110,7 +116,7 @@ jobs: test-e2e-debug: name: Test E2E UI (Debug) runs-on: macos-13 - if: ${{ github.event_name != 'push' }} + if: ${{ github.event_name != 'push' }} && github.event.inputs.snapshots != 'true' needs: - allure_testops_launch - build-test-app-and-frameworks @@ -165,7 +171,7 @@ jobs: allure_testops_launch: name: Launch Allure TestOps runs-on: macos-13 - if: ${{ github.event_name != 'push' }} + if: ${{ github.event_name != 'push' }} && github.event.inputs.snapshots != 'true' outputs: launch_id: ${{ steps.get_launch_id.outputs.launch_id }} steps: @@ -185,7 +191,7 @@ jobs: name: Build Demo App runs-on: macos-13 needs: build-test-app-and-frameworks - if: ${{ github.event_name != 'push' }} + if: ${{ github.event_name != 'push' }} && github.event.inputs.snapshots != 'true' steps: - uses: actions/checkout@v3.1.0 - uses: actions/download-artifact@v3 diff --git a/fastlane/Fastfile b/fastlane/Fastfile index 969f6fb3..3b8a0616 100644 --- a/fastlane/Fastfile +++ b/fastlane/Fastfile @@ -124,7 +124,7 @@ desc 'Runs tests in Debug config' lane :test_ui do |options| next unless is_check_required(sources: sources_matrix[:ui], force_check: @force_check) - remove_snapshots if options[:record] + remove_snapshots unless options[:record].to_s.empty? update_testplan_on_ci(path: 'StreamChatSwiftUITests/Tests/StreamChatSwiftUI.xctestplan') @@ -141,8 +141,30 @@ lane :test_ui do |options| build_for_testing: options[:build_for_testing], skip_build: options[:skip_build], number_of_retries: 1, - xcargs: buildcache_xcargs + xcargs: buildcache_xcargs, + fail_build: options[:record].to_s.empty? ) + + if options[:record] && is_ci + png_files = git_status(ext: '.png').map { |_, png| png }.flatten + next if png_files.empty? + + title = "[CI] Snapshots" + base = current_branch + head = "#{base}-snapshots" + sh("git checkout -b #{head}") + png_files.each { |png| sh("git add #{png}") || true } + sh("git commit -m '#{title}'") + push_to_git_remote(tags: false) + create_pull_request( + api_token: ENV.fetch('GITHUB_TOKEN', nil), + repo: github_repo, + title: title, + head: head, + base: base, + body: 'This PR was created automatically by CI.' + ) + end end lane :build_test_app_and_frameworks do @@ -336,9 +358,16 @@ lane :install_sim do |options| end end -desc 'Remove UI snapshots' -private_lane :remove_snapshots do - Dir.glob('../StreamChatSwiftUITests/**/__Snapshots__/**/*.png').select { |file| File.delete(file) } +desc 'Remove UI Snapshots' +lane :remove_snapshots do |options| + snapshots_path = "../StreamChatSwiftUITests/**/__Snapshots__/**/*.png" + if options[:only_unchanged] + pnf_files = git_status(ext: '.png') + changed_snapshots = (pnf_files[:a] + pnf_files[:m]).map { |f| File.expand_path(f) } + Dir.glob(snapshots_path).select { |f| File.delete(f) unless changed_snapshots.include?(File.expand_path(f)) } + else + Dir.glob(snapshots_path).select { |f| File.delete(f) } + end end lane :sources_matrix do @@ -353,3 +382,32 @@ end private_lane :current_branch do ENV['BRANCH_NAME'] || git_branch end + +private_lane :git_status do |options| + UI.user_error!('Extension should be provided') unless options[:ext] + + untracked_files = sh('git status -s', log: false).split("\n").map(&:strip) + UI.important("Git Status: #{untracked_files}") + + deleted_files = select_files_from(files: untracked_files, with_extension: options[:ext], that_start_with: 'D') + added_files = select_files_from(files: untracked_files, with_extension: options[:ext], that_start_with: ['A', '??']) + renamed_files = select_files_from(files: untracked_files, with_extension: options[:ext], that_start_with: 'R') + modified_files = select_files_from(files: untracked_files, with_extension: options[:ext], that_start_with: 'M') + + renamed_files.each do |renamed_file| + content = renamed_file.split.drop(1).join.split('->').map(&:strip) + deleted_files << content.first + added_files << content.last + end + { a: added_files, d: deleted_files, m: modified_files } +end + +def select_files_from(files:, with_extension:, that_start_with:) + files.select do |f| + f.start_with?(*that_start_with) + end.map do |f| + f.split.drop(1).join(' ') + end.select do |f| + f.gsub(/['"]/, '').end_with?(with_extension) + end +end \ No newline at end of file