diff --git a/.circleci/config.yml b/.circleci/config.yml index 932ca96c..1e2a1809 100644 --- a/.circleci/config.yml +++ b/.circleci/config.yml @@ -3,6 +3,8 @@ version: 2.1 orbs: slack: circleci/slack@4.12.6 gh: circleci/github-cli@2.3.0 + aws-cli: circleci/aws-cli@4.1.3 + aws-s3: circleci/aws-s3@4.0.0 executors: android: @@ -21,6 +23,9 @@ commands: steps: - restore_cache: key: jars-{{ checksum "build.gradle.kts" }}-{{ checksum "app/build.gradle.kts" }} + - run: + name: Download dependencies + command: ./gradlew androidDependencies - save_cache: paths: - ~/.gradle @@ -78,6 +83,12 @@ commands: # set github access token echo "export GITHUB_ACCESS_TOKEN='$access_token'" >> $BASH_ENV + aws-cli-setup: + steps: + - aws-cli/setup: + aws_access_key_id: AWS_ACCESS_KEY_ID + aws_secret_access_key: AWS_SECRET_ACCESS_KEY + region: AWS_REGION jobs: dependencies: @@ -147,27 +158,85 @@ jobs: executor: android steps: - checkout - - gh/install - - set-github-access-token - - run: - name: gh login - command: echo "$GITHUB_ACCESS_TOKEN" | gh auth login --with-token + - attach_workspace: + at: . - run: - name: use github actions workflow - command: gh workflow run "SaveScreenshot.yml" + name: create screenshots + command: ./gradlew recordRoborazziProdDebug --stacktrace + - aws-cli-setup + - aws-s3/sync: + arguments: --delete + from: ./app/build/outputs/roborazzi + to: s3://hiraganaconverter-roborazzi/image/$CIRCLE_BRANCH compare-screenshots: executor: android steps: - checkout + - attach_workspace: + at: . - gh/install - set-github-access-token - run: name: gh login command: echo "$GITHUB_ACCESS_TOKEN" | gh auth login --with-token - run: - name: use github actions workflow - command: gh workflow run "CompareScreenshot.yml" + name: get base branch name + # ref: https://discuss.circleci.com/t/how-to-retrieve-a-pull-requests-base-branch-name-github/36911 + command: | + # ◼ get base branch name + pr=$(echo https://api.github.com/repos/${CIRCLE_PULL_REQUEST:19} | sed "s/\/pull\//\/pulls\//") + base=$(curl -s -H "Authorization: token ${GITHUB_ACCESS_TOKEN}" $pr | jq '.base.ref') + echo "base branch name: $base" + echo "export BASE_BRANCH_NAME=${base}" >> $BASH_ENV + - aws-cli-setup + - aws-s3/copy: + arguments: --recursive + from: "s3://hiraganaconverter-roborazzi/image/$BASE_BRANCH_NAME" + to: ./app/build/outputs/roborazzi + - run: + name: compare screenshots + command: ./gradlew compareRoborazziProdDebug --stacktrace + - run: + name: move screenshots files + command: | + mkdir -p ./build/outputs/roborazzi/compareProdDebug + mv ./app/build/outputs/roborazzi ./build/outputs/roborazzi/compareProdDebug + # delete except *_compare.png + find ./build/outputs/roborazzi/compareProdDebug/roborazzi -type f | grep -v -e '.*_compare.png' | xargs rm -rf + ls ./build/outputs/roborazzi/compareProdDebug/roborazzi + - run: + name: set pr number + command: | + pr_number=$(basename $CIRCLE_PULL_REQUEST) + echo "export PR_NUMBER=${pr_number}" >> $BASH_ENV + - aws-s3/sync: + arguments: --delete + from: ./build/outputs/roborazzi/compareProdDebug/roborazzi + to: s3://hiraganaconverter-roborazzi/image/pr/$PR_NUMBER + - run: + name: create comments + command: | + cat \<< EOF > comments + |File name|Image| + |---|---| + EOF + + # Find all the files ending with _compare.png + files_to_add=$(find . -type f -path "./build/outputs/roborazzi/compareProdDebug/roborazzi/*" -name "*_compare.png") + + # Add compare image + for file in $files_to_add; do + compare_file_path=$(basename $file) + echo "compare file path: $compare_file_path" + compare_file_name=$(echo $compare_file_path | rev | cut -d. -f-2 | rev ) + image_url="https://hiraganaconverter-roborazzi.s3.ap-northeast-1.amazonaws.com/image/pr/$PR_NUMBER/$compare_file_path" + echo "| $compare_file_name | |" >> comments + done + - run: + # ref: https://github.com/cli/cli/issues/6790 + name: test comment + command: gh pr comment "$CIRCLE_PULL_REQUEST" --edit-last -F ./comments || gh pr comment "$CIRCLE_PULL_REQUEST" -F ./comments workflows: test: diff --git a/.github/workflows/CompareScreenshot.yml b/.github/workflows/CompareScreenshot.yml deleted file mode 100644 index 07c43d43..00000000 --- a/.github/workflows/CompareScreenshot.yml +++ /dev/null @@ -1,199 +0,0 @@ -# ref: https://github.com/kosenda/hiragana-converter/blob/develop/REFERENCE.md - -name: CompareScreenshot - -on: workflow_dispatch - -permissions: - contents: write - actions: read - pull-requests: write - -jobs: - compare-screnshots: - runs-on: ubuntu-latest - steps: - - name: Checkout sources - uses: actions/checkout@v4 - - - name: Check exist screenshots branch - id: check-exist-screenshots - run: | - echo is_exist=$( - git fetch origin screenshots_${{ github.base_ref }} && - echo true || echo false - ) >> "$GITHUB_OUTPUT" - - - name: Checkout screenshots branch - if: steps.check-exist-screenshots.outputs.is_exist == 'true' - uses: actions/checkout@v4 - with: - ref: screenshots_${{ github.base_ref }} - - - name: Make screenshots directory - run: mkdir -p ./app/build/outputs/roborazzi - - - name: Upload screenshots - if: steps.check-exist-screenshots.outputs.is_exist == 'true' - uses: actions/upload-artifact@v4 - with: - name: screenshots - path: ./app/build/outputs/roborazzi/ - retention-days: 1 - - - name: Checkout pr branch - if: steps.check-exist-screenshots.outputs.is_exist == 'true' - uses: actions/checkout@v4 - with: - ref: ${{ github.head_ref }} - - - name: Setup - uses: ./.github/actions/setup - with: - api-key: ${{ secrets.API_KEY }} - - - name: Download screenshots from PR number directory - continue-on-error: true - uses: actions/download-artifact@v4 - with: - name: screenshots - path: ./app/build/outputs/roborazzi/ - - - name: Compare screenshots - run: ./gradlew compareRoborazziProdDebug --stacktrace - - - name: Check screenshot diff - id: check-screenshot-diff - run: | - # To avoid "No such file or directory" - mkdir -p ./app/build/outputs/roborazzi - - file_size=$(find ./app/build/outputs/roborazzi -type f | grep -e '.*_compare.png' | wc -l | sed -e 's/[^0-9]//g') - is_exist_screenshot_diff="false" - if [ $file_size -ne 0 ]; then - echo "file_size=$file_size" - is_exist_screenshot_diff="true" - fi - echo "is_exist=${is_exist_screenshot_diff}" >> "$GITHUB_OUTPUT" - - - name: Make PR number directory for saving screenshots - if: steps.check-screenshot-diff.outputs.is_exist == 'true' - run: mkdir -p ./pr/${{ github.event.number }} - - - name: Move screenshots to PR number directory - if: steps.check-screenshot-diff.outputs.is_exist == 'true' - run: | - # delete except *_compare.png - find ./app/build/outputs/roborazzi -type f | grep -v -e '.*_compare.png' | xargs rm -rf - mv ./app/build/outputs/roborazzi ./pr/${{ github.event.number }}/ - ls ./pr/${{ github.event.number }} - - - name: Save screenshots - if: steps.check-screenshot-diff.outputs.is_exist == 'true' - uses: actions/upload-artifact@v4 - with: - name: pr directory - path: pr/${{ github.event.number }}/ - - - name: Save pr number and branch name - run: | - echo "PR_NUMBER=${{ github.event.number }}" >> $GITHUB_ENV - echo "COMPANION_BRANCH_NAME=companion_${{ github.head_ref }}" >> $GITHUB_ENV - - - name: Checkout main branch - if: steps.check-screenshot-diff.outputs.is_exist == 'true' - uses: actions/checkout@v4 - with: - ref: main - - - name: Checkout companion branch - if: steps.check-screenshot-diff.outputs.is_exist == 'true' - run: | - git branch -D ${{ env.COMPANION_BRANCH_NAME }} || true - git checkout --orphan ${{ env.COMPANION_BRANCH_NAME }} - git rm -rf . - - - name: Download screenshots from PR number directory - if: steps.check-screenshot-diff.outputs.is_exist == 'true' - uses: actions/download-artifact@v4 - with: - name: pr directory - - - name: Push screenshots to companion branch - if: steps.check-screenshot-diff.outputs.is_exist == 'true' - id: push-screenshot-diff - run: | - files_to_add=$(find . -type f -name "*_compare.png") - - for file in $files_to_add; do - if [[ $file =~ ^[a-zA-Z0-9_./-]+$ ]]; then - git add $file - fi - done - git config --global user.name ScreenshotBot - git config --global user.email 41898282+github-actions[bot]@users.noreply.github.com - git commit -m "Add screenshot diff" - git push origin HEAD:${{ env.COMPANION_BRANCH_NAME }} -f - - - name: Create comments - if: steps.check-screenshot-diff.outputs.is_exist == 'true' - id: create-comments - run: | - files=$(find . -type f -name "*_compare.png") - delimiter="$(openssl rand -hex 8)" - { - echo "reports<<${delimiter}" - - echo "Snapshot diff report" - echo "| File name | Image |" - echo "|-------|-------|" - } >> "$GITHUB_OUTPUT" - - for file in $files; do - fileName=$(basename "$file" | sed -r 's/(.{20})/\1
/g') - echo "| [$fileName](https://github.com/${{ github.repository }}/blob/${{ env.COMPANION_BRANCH_NAME }}/$file) | ![](https://github.com/${{ github.repository }}/blob/${{ env.COMPANION_BRANCH_NAME }}/$file?raw=true) |" >> "$GITHUB_OUTPUT" - done - echo "${delimiter}" >> "$GITHUB_OUTPUT" - - - name: Find comment - continue-on-error: true - uses: peter-evans/find-comment@v3 - id: fc - with: - issue-number: ${{ github.event.number }} - comment-author: 'github-actions[bot]' - body-includes: Snapshot diff report - - - name: Add or update comment on PR (exist screenshot diff) - if: steps.check-screenshot-diff.outputs.is_exist == 'true' - uses: peter-evans/create-or-update-comment@v4 - with: - comment-id: ${{ steps.fc.outputs.comment-id }} - issue-number: ${{ env.PR_NUMBER }} - body: ${{ steps.create-comments.outputs.reports }} - edit-mode: replace - - - name: Add or update comment on PR (not exist screenshot diff) - if: steps.check-screenshot-diff.outputs.is_exist == 'false' - uses: peter-evans/create-or-update-comment@v4 - with: - comment-id: ${{ steps.fc.outputs.comment-id }} - issue-number: ${{ env.PR_NUMBER }} - body: Snapshot diff report - edit-mode: replace - - - name: Cleanup outdated companion or screenshots branches - run: | - git branch -r --format="%(refname:lstrip=3)" | grep -e companion_ -e screenshots_ | while read -r branch; do - last_commit_date_timestamp=$(git log -1 --format=%ct "origin/$branch") - now_timestamp=$(date +%s) - maximum_seconds_past=2592000 # 30 days - if [ $((now_timestamp - last_commit_date_timestamp)) -gt maximum_seconds_past ]; then - git push origin --delete "$branch" - fi - done - - - name: Checkout pr branch - uses: actions/checkout@v4 - with: - ref: ${{ github.event.workflow_run.head_branch }} diff --git a/.github/workflows/SaveScreenshot.yml b/.github/workflows/SaveScreenshot.yml index 2d2f4608..32d15960 100644 --- a/.github/workflows/SaveScreenshot.yml +++ b/.github/workflows/SaveScreenshot.yml @@ -2,7 +2,12 @@ name: SaveScreenshot -on: workflow_dispatch +on: + pull_request: + types: + - closed + paths-ignore: + - README.md jobs: save-screenshot: diff --git a/.github/workflows/Test.yml b/.github/workflows/Test.yml index bab397c3..07bdf832 100644 --- a/.github/workflows/Test.yml +++ b/.github/workflows/Test.yml @@ -1,84 +1,274 @@ -## ref: https://github.com/kosenda/hiragana-converter/blob/develop/REFERENCE.md -# -#name: Test -# -#on: -# pull_request: -# paths-ignore: -# - README.md -# types: [ opened, synchronize, reopened, closed ] -# -#concurrency: -# group: ${{ github.workflow }}-${{ github.ref }} -# cancel-in-progress: true -# -#permissions: -# actions: read -# pull-requests: write -#jobs: -# test-prod: -# runs-on: ubuntu-latest -# steps: -# - name: Checkout sources -# uses: actions/checkout@v4 -# with: -# # ref: https://github.com/danger/danger/issues/913 -# fetch-depth: 100 -# -# - name: Setup -# uses: ./.github/actions/setup -# with: -# api-key: ${{ secrets.API_KEY }} -# -# - name: ktlint-check -# run: ./gradlew --continue ktlintCheck -# -# - name: Test ProdDebug -# run: ./gradlew testProdDebugUnitTest -# -# - name: Report jacoco -# run: ./gradlew jacocoTestReport -# -# - name: jacoco-report to zip -# run: zip -r jacocoTestReport.zip ./build/reports/jacoco/jacocoTestReport/html -# -# - name: Archive jacoco report -# uses: actions/upload-artifact@v4 -# with: -# name: jacocoTestReport -# path: ./build/reports/jacoco/jacocoTestReport/html -# -# - name: Setup Ruby -# uses: ruby/setup-ruby@v1 -# with: -# ruby-version: 3.2.2 -# bundler-cache: true -# -# - name: Danger -# uses: MeilCli/danger-action@v5 -# with: -# plugins_file: Gemfile -# install_path: vendor/bundle -# danger_file: Dangerfile -# danger_id: danger-pr -# env: -# DANGER_GITHUB_API_TOKEN: ${{ secrets.DANGER_GITHUB_API_TOKEN }} -# -# - name: Slack notify -# uses: ./.github/actions/incoming-webhook -# with: -# slack-webhook-url: ${{ secrets.SLACK_INCOMING_WEBHOOK_URL }} -# -# compile-mock: -# runs-on: ubuntu-latest -# steps: -# - name: Checkout sources -# uses: actions/checkout@v4 -# -# - name: Setup -# uses: ./.github/actions/setup -# with: -# api-key: ${{ secrets.API_KEY }} -# -# - name: Compile MockDebug -# run: ./gradlew compileMockDebugSource +# ref: https://github.com/kosenda/hiragana-converter/blob/develop/REFERENCE.md + +name: Test + +on: + pull_request: + paths-ignore: + - README.md + types: [ opened, synchronize, reopened, closed ] + +concurrency: + group: ${{ github.workflow }}-${{ github.ref }} + cancel-in-progress: true + +permissions: + contents: write + actions: read + pull-requests: write +jobs: + test-prod: + runs-on: ubuntu-latest + steps: + - name: Checkout sources + uses: actions/checkout@v4 + with: + # ref: https://github.com/danger/danger/issues/913 + fetch-depth: 100 + + - name: Setup + uses: ./.github/actions/setup + with: + api-key: ${{ secrets.API_KEY }} + + - name: ktlint-check + run: ./gradlew --continue ktlintCheck + + - name: Test ProdDebug + run: ./gradlew testProdDebugUnitTest + + - name: Report jacoco + run: ./gradlew jacocoTestReport + + - name: jacoco-report to zip + run: zip -r jacocoTestReport.zip ./build/reports/jacoco/jacocoTestReport/html + + - name: Archive jacoco report + uses: actions/upload-artifact@v4 + with: + name: jacocoTestReport + path: ./build/reports/jacoco/jacocoTestReport/html + + - name: Setup Ruby + uses: ruby/setup-ruby@v1 + with: + ruby-version: 3.2.2 + bundler-cache: true + + - name: Danger + uses: MeilCli/danger-action@v5 + with: + plugins_file: Gemfile + install_path: vendor/bundle + danger_file: Dangerfile + danger_id: danger-pr + env: + DANGER_GITHUB_API_TOKEN: ${{ secrets.DANGER_GITHUB_API_TOKEN }} + + - name: Slack notify + uses: ./.github/actions/incoming-webhook + with: + slack-webhook-url: ${{ secrets.SLACK_INCOMING_WEBHOOK_URL }} + + compile-mock: + runs-on: ubuntu-latest + steps: + - name: Checkout sources + uses: actions/checkout@v4 + + - name: Setup + uses: ./.github/actions/setup + with: + api-key: ${{ secrets.API_KEY }} + + - name: Compile MockDebug + run: ./gradlew compileMockDebugSource + + compare-screnshots: + if: github.event.pull_request.merged == false && github.event_name == 'pull_request' + runs-on: ubuntu-latest + steps: + - name: Checkout sources + uses: actions/checkout@v4 + + - name: Check exist screenshots branch + id: check-exist-screenshots + run: | + echo is_exist=$( + git fetch origin screenshots_${{ github.base_ref }} && + echo true || echo false + ) >> "$GITHUB_OUTPUT" + + - name: Checkout screenshots branch + if: steps.check-exist-screenshots.outputs.is_exist == 'true' + uses: actions/checkout@v4 + with: + ref: screenshots_${{ github.base_ref }} + + - name: Make screenshots directory + run: mkdir -p ./app/build/outputs/roborazzi + + - name: Upload screenshots + if: steps.check-exist-screenshots.outputs.is_exist == 'true' + uses: actions/upload-artifact@v4 + with: + name: screenshots + path: ./app/build/outputs/roborazzi/ + retention-days: 1 + + - name: Checkout pr branch + if: steps.check-exist-screenshots.outputs.is_exist == 'true' + uses: actions/checkout@v4 + with: + ref: ${{ github.head_ref }} + + - name: Setup + uses: ./.github/actions/setup + with: + api-key: ${{ secrets.API_KEY }} + + - name: Download screenshots from PR number directory + continue-on-error: true + uses: actions/download-artifact@v4 + with: + name: screenshots + path: ./app/build/outputs/roborazzi/ + + - name: Compare screenshots + run: ./gradlew compareRoborazziProdDebug --stacktrace + + - name: Check screenshot diff + id: check-screenshot-diff + run: | + # To avoid "No such file or directory" + mkdir -p ./app/build/outputs/roborazzi + + file_size=$(find ./app/build/outputs/roborazzi -type f | grep -e '.*_compare.png' | wc -l | sed -e 's/[^0-9]//g') + is_exist_screenshot_diff="false" + if [ $file_size -ne 0 ]; then + echo "file_size=$file_size" + is_exist_screenshot_diff="true" + fi + echo "is_exist=${is_exist_screenshot_diff}" >> "$GITHUB_OUTPUT" + + - name: Make PR number directory for saving screenshots + if: steps.check-screenshot-diff.outputs.is_exist == 'true' + run: mkdir -p ./pr/${{ github.event.number }} + + - name: Move screenshots to PR number directory + if: steps.check-screenshot-diff.outputs.is_exist == 'true' + run: | + # delete except *_compare.png + find ./app/build/outputs/roborazzi -type f | grep -v -e '.*_compare.png' | xargs rm -rf + mv ./app/build/outputs/roborazzi ./pr/${{ github.event.number }}/ + ls ./pr/${{ github.event.number }} + + - name: Save screenshots + if: steps.check-screenshot-diff.outputs.is_exist == 'true' + uses: actions/upload-artifact@v4 + with: + name: pr directory + path: pr/${{ github.event.number }}/ + + - name: Save pr number and branch name + run: | + echo "PR_NUMBER=${{ github.event.number }}" >> $GITHUB_ENV + echo "COMPANION_BRANCH_NAME=companion_${{ github.head_ref }}" >> $GITHUB_ENV + + - name: Checkout main branch + if: steps.check-screenshot-diff.outputs.is_exist == 'true' + uses: actions/checkout@v4 + with: + ref: main + + - name: Checkout companion branch + if: steps.check-screenshot-diff.outputs.is_exist == 'true' + run: | + git branch -D ${{ env.COMPANION_BRANCH_NAME }} || true + git checkout --orphan ${{ env.COMPANION_BRANCH_NAME }} + git rm -rf . + + - name: Download screenshots from PR number directory + if: steps.check-screenshot-diff.outputs.is_exist == 'true' + uses: actions/download-artifact@v4 + with: + name: pr directory + + - name: Push screenshots to companion branch + if: steps.check-screenshot-diff.outputs.is_exist == 'true' + id: push-screenshot-diff + run: | + files_to_add=$(find . -type f -name "*_compare.png") + + for file in $files_to_add; do + if [[ $file =~ ^[a-zA-Z0-9_./-]+$ ]]; then + git add $file + fi + done + git config --global user.name ScreenshotBot + git config --global user.email 41898282+github-actions[bot]@users.noreply.github.com + git commit -m "Add screenshot diff" + git push origin HEAD:${{ env.COMPANION_BRANCH_NAME }} -f + + - name: Create comments + if: steps.check-screenshot-diff.outputs.is_exist == 'true' + id: create-comments + run: | + files=$(find . -type f -name "*_compare.png") + delimiter="$(openssl rand -hex 8)" + { + echo "reports<<${delimiter}" + + echo "Snapshot diff report" + echo "| File name | Image |" + echo "|-------|-------|" + } >> "$GITHUB_OUTPUT" + + for file in $files; do + fileName=$(basename "$file" | sed -r 's/(.{20})/\1
/g') + echo "| [$fileName](https://github.com/${{ github.repository }}/blob/${{ env.COMPANION_BRANCH_NAME }}/$file) | ![](https://github.com/${{ github.repository }}/blob/${{ env.COMPANION_BRANCH_NAME }}/$file?raw=true) |" >> "$GITHUB_OUTPUT" + done + echo "${delimiter}" >> "$GITHUB_OUTPUT" + + - name: Find comment + continue-on-error: true + uses: peter-evans/find-comment@v3 + id: fc + with: + issue-number: ${{ github.event.number }} + comment-author: 'github-actions[bot]' + body-includes: Snapshot diff report + + - name: Add or update comment on PR (exist screenshot diff) + if: steps.check-screenshot-diff.outputs.is_exist == 'true' + uses: peter-evans/create-or-update-comment@v4 + with: + comment-id: ${{ steps.fc.outputs.comment-id }} + issue-number: ${{ env.PR_NUMBER }} + body: ${{ steps.create-comments.outputs.reports }} + edit-mode: replace + + - name: Add or update comment on PR (not exist screenshot diff) + if: steps.check-screenshot-diff.outputs.is_exist == 'false' + uses: peter-evans/create-or-update-comment@v4 + with: + comment-id: ${{ steps.fc.outputs.comment-id }} + issue-number: ${{ env.PR_NUMBER }} + body: Snapshot diff report + edit-mode: replace + + - name: Cleanup outdated companion or screenshots branches + run: | + git branch -r --format="%(refname:lstrip=3)" | grep -e companion_ -e screenshots_ | while read -r branch; do + last_commit_date_timestamp=$(git log -1 --format=%ct "origin/$branch") + now_timestamp=$(date +%s) + maximum_seconds_past=2592000 # 30 days + if [ $((now_timestamp - last_commit_date_timestamp)) -gt maximum_seconds_past ]; then + git push origin --delete "$branch" + fi + done + + - name: Checkout pr branch + uses: actions/checkout@v4 + with: + ref: ${{ github.event.workflow_run.head_branch }}