Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
29 changes: 29 additions & 0 deletions .github/actions/composite/buildAndroidAPK/action.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
name: Build an Android apk
description: Build an Android apk for an E2E test build and upload it as an artifact

inputs:
ARTIFACT_NAME:
description: The name of the workflow artifact where the APK should be uploaded
required: true

runs:
using: composite
steps:
- uses: Expensify/App/.github/actions/composite/setupNode@main

- uses: ruby/setup-ruby@eae47962baca661befdfd24e4d6c34ade04858f7
with:
ruby-version: '2.7'
bundler-cache: true

- uses: gradle/gradle-build-action@3fbe033aaae657f011f88f29be9e65ed26bd29ef

- name: Build APK
run: npm run android-build-e2e
shell: bash

- name: Upload APK
uses: actions/upload-artifact@65d862660abb392b8c4a3d1195a2108db131dd05
with:
name: ${{ inputs.ARTIFACT_NAME }}
path: android/app/build/outputs/apk/e2eRelease/app-e2eRelease.apk
2 changes: 1 addition & 1 deletion .github/scripts/validateActionsAndWorkflows.sh
Original file line number Diff line number Diff line change
Expand Up @@ -43,7 +43,7 @@ for ((i=0; i < ${#WORKFLOWS[@]}; i++)); do
WORKFLOW=${WORKFLOWS[$i]}

# Skip linting e2e workflow due to bug here: https://github.com/SchemaStore/schemastore/issues/2579
if [[ "$WORKFLOW" == './workflows/preDeploy.yml' ]]; then
if [[ "$WORKFLOW" == './workflows/e2ePerformanceTests.yml' ]]; then
continue
fi

Expand Down
173 changes: 173 additions & 0 deletions .github/workflows/e2ePerformanceTests.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,173 @@
name: E2E Performance Tests

on:
workflow_call:
inputs:
PR_NUMBER:
description: A PR to run performance tests against. If already merged, the merge commit will be used. If not, the test merge commit will be used.
type: string
required: true

workflow_dispatch:
inputs:
PR_NUMBER:
description: A PR to run performance tests against. If already merged, the merge commit will be used. If not, the test merge commit will be used.
type: string
required: true
Comment thread
roryabraham marked this conversation as resolved.

jobs:
prepare:
runs-on: ubuntu-latest
name: Prepare to run builds
outputs:
VERSION: ${{ steps.getMostRecentRelease.outputs.VERSION }}
DELTA_REF: ${{ steps.getMergeCommitSha.outputs.MERGE_COMMIT_SHA }}
steps:
- uses: actions/checkout@93ea575cb5d8a053eaa0ac8fa3b40d7e05a33cc8

- name: Get most recent release version
id: getMostRecentRelease
run: echo "VERSION=$(gh release list --limit 1 | awk '{ print $1 }')" >> "$GITHUB_OUTPUT"
env:
GITHUB_TOKEN: ${{ github.token }}

- name: Get pull request details
id: getPullRequestDetails
uses: Expensify/App/.github/actions/javascript/getPullRequestDetails@main
with:
GITHUB_TOKEN: ${{ github.token }}
PULL_REQUEST_NUMBER: ${{ inputs.PR_NUMBER }}
user: ${{ github.actor }}

- name: Get merge commit sha for the pull request
id: getMergeCommitSha
run: echo "MERGE_COMMIT_SHA=${{ steps.getPullRequestDetails.outputs.MERGE_COMMIT_SHA }}" >> "$GITHUB_OUTPUT"
env:
GITHUB_TOKEN: ${{ github.token }}

buildBaseline:
runs-on: ubuntu-20.04-64core
needs: [prepare]
name: Build apk from latest release as a baseline
steps:
- uses: actions/checkout@93ea575cb5d8a053eaa0ac8fa3b40d7e05a33cc8
with:
fetch-depth: 0

- name: Check if there's an existing artifact for this baseline
id: checkForExistingArtifact
uses: xSAVIKx/artifact-exists-action@3c5206b1411c0d2fc0840f56b7140646933d9d6a
with:
name: baseline-apk-${{ needs.prepare.outputs.VERSION }}

- name: Skip build if there's already an existing artifact for the baseline
if: ${{ fromJSON(steps.checkForExistingArtifact.outputs.exists) }}
run: echo 'APK for baseline ${{ needs.prepare.outputs.VERSION }} already exists, reusing existing build'

- name: Checkout "Baseline" commit (last release)
if: ${{ !fromJSON(steps.checkForExistingArtifact.outputs.exists) }}
run: git checkout ${{ needs.prepare.outputs.VERSION }}

- name: Build APK
if: ${{ !fromJSON(steps.checkForExistingArtifact.outputs.exists) }}
uses: Expensify/App/.github/actions/composite/buildAndroidAPK@main
with:
ARTIFACT_NAME: baseline-apk-${{ needs.prepare.outputs.VERSION }}

buildDelta:
runs-on: ubuntu-20.04-64core
needs: [prepare]
name: Build apk from delta ref
steps:
- uses: actions/checkout@93ea575cb5d8a053eaa0ac8fa3b40d7e05a33cc8
with:
fetch-depth: 0

- name: Checkout "delta ref"
run: git checkout ${{ needs.prepare.outputs.DELTA_REF }}
env:
GITHUB_TOKEN: ${{ github.token }}

- name: Build APK
uses: Expensify/App/.github/actions/composite/buildAndroidAPK@main
with:
ARTIFACT_NAME: delta-apk-${{ needs.prepare.outputs.DELTA_REF }}

runTestsInAWS:
runs-on: ubuntu-20.04-64core
needs: [prepare, buildBaseline, buildDelta]
name: Run E2E tests in AWS device farm
steps:
- uses: actions/checkout@93ea575cb5d8a053eaa0ac8fa3b40d7e05a33cc8
with:
ref: ${{ needs.prepare.outputs.DELTA_REF }}

- name: Make zip directory for everything to send to AWS Device Farm
run: mkdir zip

- name: Download baseline APK
uses: actions/download-artifact@e9ef242655d12993efdcda9058dee2db83a2cb9b
with:
name: baseline-apk-${{ needs.prepare.outputs.VERSION }}
path: zip

- name: Download delta APK
uses: actions/download-artifact@e9ef242655d12993efdcda9058dee2db83a2cb9b
with:
name: delta-apk-${{ needs.prepare.outputs.DELTA_REF }}
path: zip

- name: Copy e2e code into zip folder
run: cp -r tests/e2e zip

- name: Zip everything in the zip directory up
run: zip -qr App.zip ./zip

- name: Configure AWS Credentials
uses: Expensify/App/.github/actions/composite/configureAwsCredentials@main
with:
AWS_ACCESS_KEY_ID: ${{ secrets.AWS_ACCESS_KEY_ID }}
AWS_SECRET_ACCESS_KEY: ${{ secrets.AWS_SECRET_ACCESS_KEY }}
AWS_REGION: us-west-2

- name: Schedule AWS Device Farm test run
uses: realm/aws-devicefarm/test-application@7b9a91236c456c97e28d384c9e476035d5ea686b
with:
name: App E2E Performance Regression Tests
project_arn: ${{ secrets.AWS_PROJECT_ARN }}
device_pool_arn: ${{ secrets.AWS_DEVICE_POOL_ARN }}
app_file: zip/app-e2eRelease-baseline.apk
app_type: ANDROID_APP
test_type: APPIUM_NODE
test_package_file: App.zip
test_package_type: APPIUM_NODE_TEST_PACKAGE
test_spec_file: tests/e2e/TestSpec.yml
test_spec_type: APPIUM_NODE_TEST_SPEC
remote_src: false
file_artifacts: CustomerArtifacts.zip
cleanup: true

- name: Unzip AWS Device Farm results
if: ${{ always() }}
run: unzip CustomerArtifacts.zip

- name: Print AWS Device Farm run results
if: ${{ always() }}
run: cat "./Host_Machine_Files/\$WORKING_DIRECTORY/output.md"

- name: Print AWS Device Farm verbose run results
if: ${{ always() && fromJSON(runner.debug) }}
run: cat "./Host_Machine_Files/\$WORKING_DIRECTORY/debug.log"

- name: Check if test failed, if so post the results and add the DeployBlocker label
if: ${{ github.event_name == 'workflow_call' }}
run: |
if grep -q '🔴' ./Host_Machine_Files/\$WORKING_DIRECTORY/output.md; then
gh pr edit ${{ inputs.PR_NUMBER }} --add-label DeployBlockerCash
gh pr comment ${{ inputs.PR_NUMBER }} -F ./Host_Machine_Files/\$WORKING_DIRECTORY/output.md
gh pr comment ${{ inputs.PR_NUMBER }} -b "@Expensify/mobile-deployers 📣 Please look into this performance regression as it's a deploy blocker."
else
echo '✅ no performance regression detected'
fi
env:
GITHUB_TOKEN: ${{ github.token }}
129 changes: 8 additions & 121 deletions .github/workflows/preDeploy.yml
Original file line number Diff line number Diff line change
Expand Up @@ -222,124 +222,11 @@ jobs:

So it might take a while before you're paid for your work, but we typically post multiple new jobs every day, so there's plenty of opportunity. I hope you've had a positive experience contributing to this repo! :blush:

e2e-tests:
name: "Run e2e performance regression tests"
runs-on: ubuntu-20.04-64core
steps:
- uses: actions/checkout@93ea575cb5d8a053eaa0ac8fa3b40d7e05a33cc8
with:
fetch-depth: 0

- uses: Expensify/App/.github/actions/composite/setupNode@main

- uses: ruby/setup-ruby@eae47962baca661befdfd24e4d6c34ade04858f7
with:
ruby-version: '2.7'
bundler-cache: true

# Cache gradle to improve Android build time
- name: Gradle cache
uses: gradle/gradle-build-action@3fbe033aaae657f011f88f29be9e65ed26bd29ef

- name: Make zip directory for everything to send to AWS Device Farm
run: mkdir zip

- name: Checkout "Compare" commit
run: git checkout ${{ github.event.before }}

- name: Install node packages
uses: nick-invision/retry@0711ba3d7808574133d713a0d92d2941be03a350
with:
timeout_minutes: 10
max_attempts: 5
command: npm ci

- name: Build "Compare" APK
run: npm run android-build-e2e

- name: Copy "Compare" APK
run: cp android/app/build/outputs/apk/e2eRelease/app-e2eRelease.apk zip/app-e2eRelease-compare.apk

- name: Checkout "Baseline" commit (last release)
run: git checkout "$(gh release list --limit 1 | awk '{ print $1 }')"
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}

- name: Install node packages
uses: nick-invision/retry@0711ba3d7808574133d713a0d92d2941be03a350
with:
timeout_minutes: 10
max_attempts: 5
command: npm ci

- name: Build "Baseline" APK
run: npm run android-build-e2e

- name: Copy "Baseline" APK
run: cp android/app/build/outputs/apk/e2eRelease/app-e2eRelease.apk zip/app-e2eRelease-baseline.apk

- name: Checkout previous branch for source code to run on AWS Device farm
run: git checkout -

- name: Copy e2e code into zip folder
run: cp -r tests/e2e zip

- name: Zip everything in the zip directory up
run: zip -qr App.zip ./zip

- name: Configure AWS Credentials
uses: Expensify/App/.github/actions/composite/configureAwsCredentials@main
with:
AWS_ACCESS_KEY_ID: ${{ secrets.AWS_ACCESS_KEY_ID }}
AWS_SECRET_ACCESS_KEY: ${{ secrets.AWS_SECRET_ACCESS_KEY }}
AWS_REGION: us-west-2

- name: Schedule AWS Device Farm test run
uses: realm/aws-devicefarm/test-application@7b9a91236c456c97e28d384c9e476035d5ea686b
with:
name: App E2E Performance Regression Tests
project_arn: ${{ secrets.AWS_PROJECT_ARN }}
device_pool_arn: ${{ secrets.AWS_DEVICE_POOL_ARN }}
app_file: zip/app-e2eRelease-baseline.apk
app_type: ANDROID_APP
test_type: APPIUM_NODE
test_package_file: App.zip
test_package_type: APPIUM_NODE_TEST_PACKAGE
test_spec_file: tests/e2e/TestSpec.yml
test_spec_type: APPIUM_NODE_TEST_SPEC
remote_src: false
file_artifacts: Customer Artifacts.zip
cleanup: true

- name: Unzip AWS Device Farm results
if: ${{ always() }}
run: unzip Customer\ Artifacts.zip

- name: Print AWS Device Farm run results
if: ${{ always() }}
run: cat "./Host_Machine_Files/\$WORKING_DIRECTORY/debug.log"

- name: Set output of AWS Device Farm into GitHub ENV
run: |
{ echo 'OUTPUT<<EOF'; cat ./Host_Machine_Files/\$WORKING_DIRECTORY/output.md; echo 'EOF'; } >> "$GITHUB_ENV"

- name: Get merged pull request
id: getMergedPullRequest
# TODO: Point back action actions-ecosystem after https://github.com/actions-ecosystem/action-get-merged-pull-request/pull/223 is merged
uses: roryabraham/action-get-merged-pull-request@7a7a194f6ff8f3eef58c822083695a97314ebec1
with:
github_token: ${{ secrets.GITHUB_TOKEN }}

- name: Leave output of AWS Device Farm as a PR comment
run: |
gh pr comment ${{ steps.getMergedPullRequest.outputs.number }} -F ./Host_Machine_Files/\$WORKING_DIRECTORY/output.md
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}

- name: Check if test failed, if so leave a deploy blocker label
if: ${{ contains(env.OUTPUT, '🔴') }}
run: |
gh pr edit ${{ steps.getMergedPullRequest.outputs.number }} --add-label 'DeployBlockerCash'
gh pr comment ${{ steps.getMergedPullRequest.outputs.number }} -b "@Expensify/mobile-deployers 📣 Please look into this performance regression as it's a deploy blocker."
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
e2ePerformanceTests:
needs: [chooseDeployActions]
if: ${{ needs.chooseDeployActions.outputs.SHOULD_DEPLOY }}
uses: Expensify/App/.github/workflows/e2ePerformanceTests.yml@main
secrets: inherit
with:
DELTA_REF: main
PR_NUMBER: ${{ needs.chooseDeployActions.outputs.MERGED_PR }}