Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

AWS test run #29758

Merged
merged 39 commits into from
Oct 23, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
39 commits
Select commit Hold shift + click to select a range
4f35243
Run main and delta tests in different AWS device farm runs and merge …
ospfranco Oct 16, 2023
e40a174
Merge branch 'main' into osp/separate-test-runs
ospfranco Oct 16, 2023
86c5d71
Update paths and restore file_artifacts on aws step
ospfranco Oct 17, 2023
073ea41
Only delete json result file if it exists
ospfranco Oct 17, 2023
a357848
Re-insert deleting the output container
ospfranco Oct 17, 2023
8944963
Handle skip checkout flag to avoid git operation on CI
ospfranco Oct 18, 2023
d1531a0
Revert Customer Artifacts.zip
ospfranco Oct 18, 2023
a855c92
Update script to make it a bit more undestandable and run in local bu…
ospfranco Oct 18, 2023
5861ca7
Handle not passing branch name
ospfranco Oct 18, 2023
38d4b88
Move variable configuration to top of file
ospfranco Oct 18, 2023
8fb3826
Update config.local and fix detected appPath
ospfranco Oct 18, 2023
61ae5b7
Update configs
ospfranco Oct 18, 2023
8df571c
Logs improvements
ospfranco Oct 18, 2023
78d1e5f
Correct paths on when running merge script
ospfranco Oct 18, 2023
ccae18e
use traditional child_process import
hannojg Oct 18, 2023
95cc214
fix node setup
hannojg Oct 18, 2023
cf86f38
Merge branch 'main' of github.com:margelo/expensify-app-fork into osp…
hannojg Oct 18, 2023
175cd23
Install underscore
ospfranco Oct 18, 2023
b095730
Remove underscore step
ospfranco Oct 19, 2023
2cf1f75
Move buildMode param below dev flag setting
ospfranco Oct 19, 2023
4900518
add env variable to asyncExec
ospfranco Oct 19, 2023
09c0a4d
fix crash because log dir doesn't exist
hannojg Oct 19, 2023
41a5078
wording
hannojg Oct 19, 2023
8dbd16a
Log execAsync environment
ospfranco Oct 19, 2023
e74a276
Fix path for API mock
ospfranco Oct 19, 2023
f8e8a4f
Undo unnecessary mocks
ospfranco Oct 19, 2023
25fe137
Add an attempt to log errors on github actions
ospfranco Oct 19, 2023
58ffed6
Try both ts replace and js replace on the mock api metro config
ospfranco Oct 19, 2023
809355f
add logging for replacing mock API
hannojg Oct 19, 2023
fb4b503
Add more logs to metro config
ospfranco Oct 20, 2023
744323a
test: skip checking out release version
hannojg Oct 20, 2023
57db0ac
Remove check for previous artifacts
ospfranco Oct 20, 2023
7b245f4
Do not use extended name on generated baseline apk
ospfranco Oct 20, 2023
5a90797
Simple script to trigger an aws device farm run
ospfranco Oct 20, 2023
bbcad66
Remove logging on replaced paths
ospfranco Oct 20, 2023
301221f
Fix name of download in baseline apk
ospfranco Oct 20, 2023
4fcdc0c
correct actions for e2e workflow
hannojg Oct 20, 2023
fd5c610
Restore generated artifact name
ospfranco Oct 23, 2023
2e73a3f
ADd version tag to Download baseline APK step
ospfranco Oct 23, 2023
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
89 changes: 60 additions & 29 deletions .github/workflows/e2ePerformanceTests.yml
Original file line number Diff line number Diff line change
Expand Up @@ -125,6 +125,9 @@ jobs:
steps:
- uses: actions/checkout@v3

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

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

Expand All @@ -137,7 +140,7 @@ jobs:

# The downloaded artifact will be a file named "app-e2e-release.apk" so we have to rename it
- name: Rename baseline APK
run: mv "${{steps.downloadBaselineAPK.outputs.download-path}}/app-e2e-release.apk" "${{steps.downloadBaselineAPK.outputs.download-path}}/app-e2eRelease-baseline.apk"
run: mv "${{steps.downloadBaselineAPK.outputs.download-path}}/app-e2e-release.apk" "${{steps.downloadBaselineAPK.outputs.download-path}}/app-e2eRelease-main.apk"

- name: Download delta APK
uses: actions/download-artifact@e9ef242655d12993efdcda9058dee2db83a2cb9b
Expand All @@ -147,7 +150,7 @@ jobs:
path: zip

- name: Rename delta APK
run: mv "${{steps.downloadDeltaAPK.outputs.download-path}}/app-e2e-release.apk" "${{steps.downloadDeltaAPK.outputs.download-path}}/app-e2eRelease-compare.apk"
run: mv "${{steps.downloadDeltaAPK.outputs.download-path}}/app-e2e-release.apk" "${{steps.downloadDeltaAPK.outputs.download-path}}/app-e2eRelease-delta.apk"

- name: Copy e2e code into zip folder
run: cp -r tests/e2e zip
Expand All @@ -162,44 +165,72 @@ jobs:
AWS_SECRET_ACCESS_KEY: ${{ secrets.AWS_SECRET_ACCESS_KEY }}
AWS_REGION: us-west-2

- name: Schedule AWS Device Farm test run
- name: Schedule AWS Device Farm test run on main branch
uses: realm/aws-devicefarm/test-application@7b9a91236c456c97e28d384c9e476035d5ea686b
id: schedule-awsdf-main
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_file: zip/app-e2eRelease-main.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_file: tests/e2e/TestSpecMain.yml
test_spec_type: APPIUM_NODE_TEST_SPEC
remote_src: false
file_artifacts: Customer Artifacts.zip
log_artifacts: debug.log
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/output.md"

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

# TODO: Once tests are more reliable we should uncomment this
# - name: Check if test failed, if so post the results and add the DeployBlocker label
# 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 }}
- name: Print logs if run failed
if: failure()
run: |
echo ${{ steps.schedule-awsdf-main.outputs.data }}
unzip "Customer Artifacts.zip" -d mainResults
cat ./mainResults/Host_Machine_Files/\$WORKING_DIRECTORY/debug.log

- name: Unzip AWS Device Farm main results
run: unzip "Customer Artifacts.zip" -d mainResults

- name: Delete Customer Artifacts.zip
run: rm "Customer Artifacts.zip"

- name: Schedule AWS Device Farm test run on delta branch
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-delta.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/TestSpecDelta.yml
test_spec_type: APPIUM_NODE_TEST_SPEC
remote_src: false
file_artifacts: Customer Artifacts.zip
cleanup: true

- name: Unzip AWS Device Farm delta results
run: unzip "Customer Artifacts.zip" -d deltaResults

- name: Compare results
run: node tests/e2e/merge.js --mainPath ./mainResults/Host_Machine_Files/\$WORKING_DIRECTORY/main.json --deltaPath ./deltaResults//Host_Machine_Files/\$WORKING_DIRECTORY/delta.json --outputPath ./output.md

- name: Print results
run: cat "./output.md"

- name: Check if test failed, if so post the results and add the DeployBlocker label
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 }}
1 change: 1 addition & 0 deletions .tool-versions
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
nodejs 16.15.1
11 changes: 8 additions & 3 deletions metro.config.js
Original file line number Diff line number Diff line change
Expand Up @@ -7,9 +7,10 @@ require('dotenv').config();
const defaultConfig = getDefaultConfig(__dirname);

const isUsingMockAPI = process.env.E2E_TESTING === 'true';

if (isUsingMockAPI) {
// eslint-disable-next-line no-console
console.warn('⚠️ Using mock API');
console.log('⚠️⚠️⚠️⚠️ Using mock API ⚠️⚠️⚠️⚠️');
}

/**
Expand All @@ -25,10 +26,14 @@ const config = {
resolveRequest: (context, moduleName, platform) => {
const resolution = context.resolveRequest(context, moduleName, platform);
if (isUsingMockAPI && moduleName.includes('/API')) {
const originalPath = resolution.filePath;
const mockPath = originalPath.replace('src/libs/API.ts', 'src/libs/E2E/API.mock.js').replace('/src/libs/API.js/', 'src/libs/E2E/API.mock.js');
// eslint-disable-next-line no-console
console.log('⚠️⚠️⚠️⚠️ Replacing resolution path', originalPath, ' => ', mockPath);

return {
...resolution,
// TODO: Change API.mock.js extension once it is migrated to TypeScript
filePath: resolution.filePath.replace(/src\/libs\/API.js/, 'src/libs/E2E/API.mock.js'),
filePath: mockPath,
};
}
return resolution;
Expand Down
4 changes: 3 additions & 1 deletion package.json
Original file line number Diff line number Diff line change
Expand Up @@ -49,7 +49,9 @@
"analyze-packages": "ANALYZE_BUNDLE=true webpack --config config/webpack/webpack.common.js --env envFile=.env.production",
"symbolicate:android": "npx metro-symbolicate android/app/build/generated/sourcemaps/react/release/index.android.bundle.map",
"symbolicate:ios": "npx metro-symbolicate main.jsbundle.map",
"test:e2e": "node tests/e2e/testRunner.js --development",
"test:e2e:main": "node tests/e2e/testRunner.js --development --branch main --skipCheckout",
"test:e2e:delta": "node tests/e2e/testRunner.js --development --branch main --label delta --skipCheckout",
"test:e2e:compare": "node tests/e2e/merge.js",
"gh-actions-unused-styles": "./.github/scripts/findUnusedKeys.sh",
"workflow-test": "./workflow_tests/scripts/runWorkflowTests.sh",
"workflow-test:generate": "node workflow_tests/utils/preGenerateTest.js"
Expand Down
26 changes: 26 additions & 0 deletions tests/e2e/TestSpecDelta.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
version: 0.1

phases:
install:
commands:
# Install correct version of node
- export NVM_DIR=$HOME/.nvm
- . $NVM_DIR/nvm.sh
- nvm install 16.15.1
- nvm use 16.15.1

# Reverse ports using AWS magic
- PORT=4723
- IP_ADDRESS=$(ip -4 addr show eth0 | grep -Po "(?<=inet\s)\d+(\.\d+){3}")
- reverse_values="{\"ip_address\":\"$IP_ADDRESS\",\"local_port\":\"$PORT\",\"remote_port\":\"$PORT\"}"
- "curl -H \"Content-Type: application/json\" -X POST -d \"$reverse_values\" http://localhost:31007/reverse_forward_tcp"
- adb reverse tcp:$PORT tcp:$PORT

test:
commands:
- cd zip
- npm install underscore
- node e2e/testRunner.js -- --skipInstallDeps --buildMode "skip" --skipCheckout --label delta --appPath app-e2eRelease-delta.apk

artifacts:
- $WORKING_DIRECTORY
2 changes: 1 addition & 1 deletion tests/e2e/TestSpec.yml → tests/e2e/TestSpecMain.yml
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,7 @@ phases:
commands:
- cd zip
- npm install underscore
- node e2e/testRunner.js -- --skipInstallDeps --buildMode "skip" --skipCheckout
- node e2e/testRunner.js -- --skipInstallDeps --buildMode "skip" --skipCheckout --branch main --appPath app-e2eRelease-main.apk

artifacts:
- $WORKING_DIRECTORY
5 changes: 2 additions & 3 deletions tests/e2e/compare/compare.js
Original file line number Diff line number Diff line change
@@ -1,7 +1,6 @@
const fs = require('fs/promises');
const fsSync = require('fs');
const _ = require('underscore');
const {OUTPUT_DIR} = require('../config');
const {computeProbability, computeZ} = require('./math');
const printToConsole = require('./output/console');
const writeToMarkdown = require('./output/markdown');
Expand Down Expand Up @@ -119,7 +118,7 @@ function compareResults(compareEntries, baselineEntries) {
};
}

module.exports = (baselineFile = `${OUTPUT_DIR}/baseline.json`, compareFile = `${OUTPUT_DIR}/compare.json`, outputFormat = 'all') => {
module.exports = (baselineFile, compareFile, outputFile, outputFormat = 'all') => {
const hasBaselineFile = fsSync.existsSync(baselineFile);
if (!hasBaselineFile) {
throw new Error(`Baseline results files "${baselineFile}" does not exists.`);
Expand All @@ -136,7 +135,7 @@ module.exports = (baselineFile = `${OUTPUT_DIR}/baseline.json`, compareFile = `$
printToConsole(outputData);
}
if (outputFormat === 'markdown' || outputFormat === 'all') {
return writeToMarkdown(`${OUTPUT_DIR}/output.md`, outputData);
return writeToMarkdown(outputFile, outputData);
}
});
});
Expand Down
10 changes: 2 additions & 8 deletions tests/e2e/config.js
Original file line number Diff line number Diff line change
Expand Up @@ -23,24 +23,18 @@ const TEST_NAMES = {
module.exports = {
APP_PACKAGE: 'com.expensify.chat.adhoc',

APP_PATHS: {
baseline: './app-e2eRelease-baseline.apk',
compare: './app-e2eRelease-compare.apk',
},
APP_PATH: './app-e2eRelease-main.apk',

ENTRY_FILE: 'src/libs/E2E/reactNativeLaunchingTest.js',

// The port of the testing server that communicates with the app
SERVER_PORT: 4723,

// The amount of times a test should be executed for average performance metrics
RUNS: 90,
RUNS: 30,

DEFAULT_BASELINE_BRANCH: 'main',

// The amount of runs that should happen without counting test results
WARM_UP_RUNS: 3,

OUTPUT_DIR,

// The file to write intermediate results to
Expand Down
9 changes: 2 additions & 7 deletions tests/e2e/config.local.js
Original file line number Diff line number Diff line change
@@ -1,10 +1,5 @@
module.exports = {
APP_PACKAGE: 'com.expensify.chat.dev',

WARM_UP_RUNS: 1,
APP_PACKAGE: 'com.expensify.chat.adhoc',
APP_PATH: './android/app/build/outputs/apk/e2e/release/app-e2e-release.apk',
RUNS: 8,
APP_PATHS: {
baseline: './android/app/build/outputs/apk/e2e/release/app-e2e-release.apk',
compare: './android/app/build/outputs/apk/e2e/release/app-e2e-release.apk',
},
};
14 changes: 14 additions & 0 deletions tests/e2e/manually_trigger_aws_df.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
#!/bin/sh

set -ex

PROJECT_ARN=arn:aws:devicefarm:us-west-2:015174472939:project:741d1dac-84e7-4c6f-84ed-b41a2209319d
DEVICE_POOL_ARN=arn:aws:devicefarm:us-west-2:015174472939:devicepool:741d1dac-84e7-4c6f-84ed-b41a2209319d/efa4b3bb-85ef-45f2-a063-14393eb4d2c2
UPLOAD_ARN=arn:aws:devicefarm:us-west-2:015174472939:upload:741d1dac-84e7-4c6f-84ed-b41a2209319d/e65b711b-9dba-45dd-aeb4-e7c0449bccc8
TEST_SPEC_ARN=arn:aws:devicefarm:us-west-2:015174472939:upload:741d1dac-84e7-4c6f-84ed-b41a2209319d/8e694a23-1dbb-40ff-a0ef-a8077dbfa729
TEST_PACKAGE_ARN=arn:aws:devicefarm:us-west-2:015174472939:upload:741d1dac-84e7-4c6f-84ed-b41a2209319d/6d61e606-5450-43f2-be94-0bee759569e5

aws devicefarm schedule-run --project-arn "${PROJECT_ARN}" --app-arn "${UPLOAD_ARN}" --device-pool-arn "${DEVICE_POOL_ARN}" --name "Test run" --test type=APPIUM_NODE,testPackageArn="${TEST_PACKAGE_ARN}",testSpecArn="${TEST_SPEC_ARN}"
# aws devicefarm list-uploads --arn "${PROJECT_ARN}"
#
# aws devicefarm create-upload --name TestSpecMain.yml --type APPIUM_NODE_TEST_SPEC --project-arn "${PROJECT_ARN}"
27 changes: 27 additions & 0 deletions tests/e2e/merge.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
const compare = require('./compare/compare');
const {OUTPUT_DIR} = require('./config');

const args = process.argv.slice(2);

let mainPath = `${OUTPUT_DIR}/main.json`;
if (args.includes('--mainPath')) {
mainPath = args[args.indexOf('--mainPath') + 1];
}

let deltaPath = `${OUTPUT_DIR}/delta.json`;
if (args.includes('--deltaPath')) {
deltaPath = args[args.indexOf('--deltaPath') + 1];
}

let outputPath = `${OUTPUT_DIR}/output.md`;
if (args.includes('--outputPath')) {
outputPath = args[args.indexOf('--outputPath') + 1];
}

async function run() {
await compare(mainPath, deltaPath, outputPath, 'all');

process.exit(0);
}

run();
Loading
Loading