diff --git a/.github/workflows/screenshot-comparison-comment.yml b/.github/workflows/screenshot-comparison-comment.yml new file mode 100644 index 00000000..578a1406 --- /dev/null +++ b/.github/workflows/screenshot-comparison-comment.yml @@ -0,0 +1,100 @@ +name: screenshot-comparison-comment + +on: + workflow_run: + workflows: ["screenshot-comparison"] + types: [completed] + +jobs: + comment: + if: github.event.workflow_run.conclusion == 'success' + runs-on: ubuntu-latest + permissions: + contents: write + pull-requests: write + actions: read + + steps: + - name: Download Diff Artifact + uses: dawidd6/action-download-artifact@v3 + with: + name: screenshot-diff-reports + run_id: ${{ github.event.workflow_run.id }} + path: diff-reports + + - id: get-pull-request-number + run: echo "pull_request_number=$(cat diff-reports/pr/NR)" >> "$GITHUB_OUTPUT" + + - name: Checkout Default Branch + uses: actions/checkout@v4 + with: + ref: ${{ github.event.repository.default_branch }} + + - name: Push to Companion Branch + env: + BRANCH_NAME: companion_${{ github.event.workflow_run.head_branch }} + run: | + git checkout --orphan "$BRANCH_NAME" + git rm -rf . + find diff-reports -type f -name "*.png" -exec cp {} . \; + + if [ -n "$(git status --porcelain)" ]; then + git config --global user.name "ScreenshotBot" + git config --global user.email "bot@github.com" + git add . + git commit -m "Add screenshot diffs" + git push origin "$BRANCH_NAME" -f + echo "exists=true" >> "$GITHUB_ENV" + fi + + - name: Generate Report Body + if: env.exists == 'true' + id: generate_report + run: | + BRANCH="companion_${{ github.event.workflow_run.head_branch }}" + REPO="${{ github.repository }}" + + echo "REPORT_BODY<> $GITHUB_OUTPUT + echo "### Roborazzi Snapshot Diff Report" >> $GITHUB_OUTPUT + echo "" >> $GITHUB_OUTPUT + echo "| File Name | Comparison |" >> $GITHUB_OUTPUT + echo "|---|---|" >> $GITHUB_OUTPUT + + for file in $(ls *.png | grep _compare.png); do + URL="https://github.com/${REPO}/blob/${BRANCH}/${file}?raw=true" + DISPLAY_NAME=$(echo $file | sed -r 's/(.{20})/\1
/g') + echo "| $DISPLAY_NAME | ![]($URL) |" >> $GITHUB_OUTPUT + done + echo "EOF" >> $GITHUB_OUTPUT + + - name: Find Old Comment + if: env.exists == 'true' + uses: peter-evans/find-comment@v3 + id: fc + with: + issue-number: ${{ steps.get-pull-request-number.outputs.pull_request_number }} + comment-author: 'github-actions[bot]' + body-includes: 'Roborazzi Snapshot Diff Report' + + - name: Add or Update Comment + if: env.exists == 'true' + uses: peter-evans/create-or-update-comment@v4 + with: + comment-id: ${{ steps.fc.outputs.comment-id }} + issue-number: ${{ steps.get-pull-request-number.outputs.pull_request_number }} + body: ${{ steps.generate_report.outputs.REPORT_BODY }} + edit-mode: replace + + - name: Cleanup outdated companion branches + shell: bash + run: | + git branch -r --format="%(refname:lstrip=3)" | grep companion_ | while read -r branch; do + last_commit_date_timestamp=$(git log -1 --format=%ct "origin/$branch") + now_timestamp=$(date +%s) + + # 30 days + if [ $((now_timestamp - last_commit_date_timestamp)) -gt 2592000 ]; then + echo "Deleting outdated branch: $branch" + git push origin --delete "$branch" + fi + done diff --git a/.github/workflows/screenshot-comparison.yml b/.github/workflows/screenshot-comparison.yml new file mode 100644 index 00000000..dc3b5ae7 --- /dev/null +++ b/.github/workflows/screenshot-comparison.yml @@ -0,0 +1,66 @@ +name: screenshot-comparison + +on: + pull_request: + paths-ignore: + - '**.md' + +concurrency: + group: ${{ github.workflow }}-${{ github.head_ref }} + cancel-in-progress: true + +jobs: + screenshot-comparison: + runs-on: ubuntu-latest + permissions: + contents: read + actions: write + checks: read + + steps: + - name: Checkout PR Branch + uses: actions/checkout@v4 + + - name: Get base branch HEAD commit + id: get_base_branch_head + run: | + git fetch origin ${{ github.base_ref }} + echo "sha=$(git rev-parse origin/${{ github.base_ref }})" >> "$GITHUB_OUTPUT" + + - name: Setup Android + uses: ./.github/actions/setup-android + env: + LOCAL_PROPERTIES: ${{ secrets.LOCAL_PROPERTIES }} + + - name: Wait for base unit-test + uses: lewagon/wait-on-check-action@v1.3.4 + with: + ref: ${{ steps.get_base_branch_head.outputs.sha }} + check-name: 'unit-test' + repo-token: ${{ github.token }} + wait-interval: 10 + + - name: Download Base Screenshot + uses: dawidd6/action-download-artifact@v3 + continue-on-error: true + with: + name: test-reports + workflow: unit-test.yml + commit: ${{ steps.get_base_branch_head.outputs.sha }} + + - name: Run Comparison + run: ./gradlew compareRoborazziDebug --stacktrace + + - name: Save PR number for comment + run: | + mkdir -p ./pr + echo ${{ github.event.number }} > ./pr/NR + + - name: Upload Diff Results + if: always() + uses: actions/upload-artifact@v4 + with: + name: screenshot-diff-reports + path: | + **/build/outputs/roborazzi + ./pr/NR diff --git a/.github/workflows/unit-test.yml b/.github/workflows/unit-test.yml index 98a7cdf7..e8dee727 100644 --- a/.github/workflows/unit-test.yml +++ b/.github/workflows/unit-test.yml @@ -1,6 +1,9 @@ name: unit-test on: + push: + branches: + - develop pull_request: paths-ignore: - '**.md' @@ -31,6 +34,12 @@ jobs: id: test run: ./gradlew testDebugUnitTest --parallel --stacktrace + - name: Save PR number + if: github.event_name == 'pull_request' + run: | + mkdir -p ./pr + echo ${{ github.event.number }} > ./pr/NR + - name: Upload Test Reports and Screenshots if: always() uses: actions/upload-artifact@v4 @@ -39,4 +48,5 @@ jobs: path: | **/build/reports/tests **/build/outputs/roborazzi + ./pr/NR retention-days: 7 diff --git a/gradle.properties b/gradle.properties index abf21fd0..d0f639ab 100644 --- a/gradle.properties +++ b/gradle.properties @@ -24,3 +24,4 @@ android.nonTransitiveRClass=true roborazzi.test.record=true roborazzi.record.filePathStrategy=relativePathFromRoborazziContextOutputDirectory robolectric.graphicsMode=NATIVE +roborazzi.test.compare=true