mattermost-mobile/.github/workflows/e2e-detox-template.yml
Rahim Rahman e7d597f70e
test: mitmproxy + low bandwidth + automated QA using detox (#8202)
* experimental github action

* start mtmproxy then kill it

* suspend test for now

* dont need to be in a PR to trigger

* trying again with mitmdump

* where is .mitmproxy folder?

* run with +e

* not sure why exit code 1

* if this is a better path

* let's try killing using trap?

* trying a different path

* maybe using ~  would work?

* looking at output to networksetup command

* minor mistake

* throttling bandwidth

* lets try with sudo

* missing sudo

* using mitmdump

* remove spaces

* tried diff path

* change to the proper file

* upload artifacts

* install cert

* added cert to simulator

* getting simulator UDID

* proper scoped var

* using github outputs

* getenv doesn't have IOS_SIMULATOR_UDID

* using echo command

* maybe forgot to scope outputs

* lets run the command directly

* changed to iPhone 14

* let me see all the devices

* try something new

* rearrange my steps to get cert

* getenv booted

* remove too many outputs

* using mm mobile test server

* tie it all together with detox test

* removed dependency for another job

* put dependency on a job

* simplify process even more

* add github-token on download artifact

* add run-id, hopefully that's what needed to download

* incorrect speed for download

* update to the correct dummynet syntax

* proper mitmdump flow report

* update allow-hosts

* commenting out mitmdump for now

* back to rahim-experiments

* overly commented out

* cacert not --ca-cert

* maybe i allow the wrong host?

* maybe i just forgotr to kill mitmdump after I'm done?

* using pm2

* reinstate jobs. and longer timeout for detox

* need sudo

* recording videos and limiting to 1 test

* just want to run 1 test.

* back to experimenting

* using wget

* test using chrome

* using chrome and add delay

* ok test again with detox

* go back to testing all server_login

* compare booted simulators

* few more experiments

* no \

* using github_outputs

* using fromJSON

* too many $

* can i do this another way?

* two runs to get the it assigned

* try again

* .

* trying to access devices array

* try again

* using jq

* keep it simple

* might not need outputs

* forgot pipe

* will this work?

* will first element of an array works

* see if we got the udid

* did we get it wrong?

* will this work?

* let's assign?

* we have to put into string

* ok 1 more

* will it have quotes?

* echo in an echo

* is this working?

* let's hope this works.

* it's actually using 17.4 iPhone 14 not 17.0

* broke because i add &

* removed failed step

* lowering ping and going back to 10 parallel test

* double-up ONE_SEC to see if tests will pass

* why curl failed after?

* getting more data from failures

* let's get more logs with pm and mitmdump

* more logging and improvement

* silly error!

* problem with throttling, let's figure out where we can improve

* increase timeout for low-bandwidth

* increased delay + run all tests

* lets see if this will be better for throttling

* try set +e to see if it will return failure

* check disk space.

* deleting zip and trash to free up space.

* try to do pfctl twice to see if that would help

* making bandwidth-throttling a composite action

* would 5 seconds make a diff?

* add shell

* throttle bandwidth experiment

* fix quick problem

* 5s sleep, and throttling at the right time

* the throttling was working better earlier.

* add a flush in between

* no exit, see if it works well

* trying continue-on-error

* resetting with continue-on-error vs checking for if steps before worked

* adding flush before throttling to see if it makes a diff

* put it back where we think is the best spot

* change timeout to 60 and some cleanup

* forgot a simple $

* move network throttling again to see if this is better?

* rearranging

* move throttling back to where it used to work well
making bandwidth-throttling action taking inputs

* forgot shell

* inputs not input, and continue-on-error

* getting host from site_1_url

* update the sed script

* move more steps into composite action file

* add shell

* add more shell

* action cleanup

* see if our reset network setting works

* delete unused files

* more clean up

* wrong indentation

* wrong context

* see if not having low bandwidth enabled would cause stuff to break

* will it fail on non-existent step name?

* things are failing after proxy started

* start using low_bandwidth_mode input

* incorrect use of curly bracket

* low_bandwidth_mode vs low_bandwidth

* correcting the use of curly bracket in if check

* low_bandwidth_mode correction

* why would https:// makes a diff?

* just going to start pm2 after stopping

* move things around again

* some more re-arranging

* exit 1

* rearranged too much

* clean up

* start-proxy action

* incorrect variable name

* use test_server_url instead

* reverting back to original

* use pull_request

* using env var prepend

* using existing artifact

* not in ""

* not going to prepend anymore

* incorrectly removed input instead of env

* close to final

* using original e2e-detox-template

* timeout-minutes need to be higher for low_bandwidth.

* using label instead of push to branch

* add check-label

* remove unneeded test

* renamed ci.yml back to original

* different way to remove label
remove experiment files
reinstate ci.yml

* remove experiment file

* see label again

* output labels

* another experiment

* test again

* fix issue when checking for low bandwidth

* revert changes to package.json in detox/

* changed download to upload in the description

* changes based on review

* add github.event.label.name to the group "id" per @mvitale1989 suggestion

---------

Co-authored-by: Mattermost Build <build@mattermost.com>
2024-10-14 07:56:52 -06:00

304 lines
12 KiB
YAML

name: Detox E2E Tests Template
on:
workflow_call:
inputs:
MM_TEST_SERVER_URL:
description: "The test server URL"
required: false
type: string
MM_TEST_USER_NAME:
description: "The admin username of the test instance"
required: false
type: string
MM_TEST_PASSWORD:
description: "The admin password of the test instance"
required: false
type: string
MOBILE_VERSION:
description: "The mobile version to test"
required: false
default: ${{ github.head_ref || github.ref }}
type: string
run-ios-tests:
description: "Run iOS tests"
required: true
type: boolean
run-type:
type: string
required: false
default: "PR"
testcase_failure_fatal:
description: "Should failures be considered fatal"
required: false
type: boolean
default: false
record_tests_in_zephyr:
description: "Record test results in Zephyr, typically for nightly and release runs"
required: false
type: string
default: 'false'
ios_device_name:
description: "iPhone simulator name"
required: false
type: string
default: "iPhone 14"
ios_device_os_name:
description: "iPhone simulator OS version"
required: false
type: string
default: "iOS 17.0"
low_bandwidth_mode:
description: "Enable low bandwidth mode"
required: false
type: boolean
default: false
outputs:
STATUS:
value: ${{ jobs.generate-report.outputs.STATUS }}
TARGET_URL:
value: ${{ jobs.generate-report.outputs.TARGET_URL }}
FAILURES:
value: ${{ jobs.generate-report.outputs.FAILURES }}
env:
AWS_REGION: "us-east-1"
ADMIN_EMAIL: ${{ secrets.MM_MOBILE_E2E_ADMIN_EMAIL }}
ADMIN_USERNAME: ${{ secrets.MM_MOBILE_E2E_ADMIN_USERNAME }}
ADMIN_PASSWORD: ${{ secrets.MM_MOBILE_E2E_ADMIN_PASSWORD }}
# BRANCH: ${{ github.head_ref || github.ref_name }}
# COMMIT_HASH: ${{ github.sha }}
DEVICE_NAME: ${{ inputs.ios_device_name }}
DEVICE_OS_VERSION: ${{ inputs.ios_device_os_name }}
DETOX_AWS_S3_BUCKET: "mattermost-detox-report"
HEADLESS: "true"
TYPE: ${{ inputs.run-type }}
PULL_REQUEST: "https://github.com/mattermost/mattermost-mobile/pull/${{ github.event.number }}"
SITE_1_URL: ${{ inputs.MM_TEST_SERVER_URL || 'https://mobile-e2e-site-1.test.mattermost.cloud' }}
SITE_2_URL: "https://mobile-e2e-site-2.test.mattermost.cloud"
SITE_3_URL: "https://mobile-e2e-site-3.test.mattermost.cloud"
ZEPHYR_ENABLE: ${{ inputs.record_tests_in_zephyr }}
JIRA_PROJECT_KEY: "MM"
ZEPHYR_API_KEY: ${{ secrets.MM_MOBILE_E2E_ZEPHYR_API_KEY }}
ZEPHYR_FOLDER_ID: "3233873"
TEST_CYCLE_LINK_PREFIX: ${{ secrets.MM_MOBILE_E2E_TEST_CYCLE_LINK_PREFIX }}
WEBHOOK_URL: ${{ secrets.MM_MOBILE_E2E_WEBHOOK_URL }}
FAILURE_MESSAGE: "Something has failed"
jobs:
generate-specs:
runs-on: ubuntu-22.04
if: ${{ inputs.run-ios-tests }}
outputs:
specs: ${{ steps.generate-specs.outputs.specs }}
build_id: ${{ steps.resolve-device.outputs.BUILD_ID }}
mobile_sha: ${{ steps.resolve-device.outputs.MOBILE_SHA }}
mobile_ref: ${{ steps.resolve-device.outputs.MOBILE_REF }}
workflow_hash: ${{ steps.resolve-device.outputs.WORKFLOW_HASH }}
steps:
- name: Checkout Repository
uses: actions/checkout@b4ffde65f46336ab88eb53be808477a3936bae11 # v4.1.1
with:
ref: ${{ inputs.MOBILE_VERSION }}
- name: Set Build ID
id: resolve-device
run: |
BUILD_ID="${{ github.run_id }}-${{ env.DEVICE_NAME }}-${{ env.DEVICE_OS_VERSION}}"
WORKFLOW_HASH=$(tr -dc a-z0-9 </dev/urandom | head -c 10)
## We need that hash to separate the artifacts
echo "WORKFLOW_HASH=${WORKFLOW_HASH}" >> ${GITHUB_OUTPUT}
echo "BUILD_ID=$(echo ${BUILD_ID} | sed 's/ /_/g')" >> ${GITHUB_OUTPUT}
echo "MOBILE_SHA=$(git rev-parse HEAD)" >> ${GITHUB_OUTPUT}
echo "MOBILE_REF=$(git rev-parse --abbrev-ref HEAD)" >> ${GITHUB_OUTPUT}
- name: Generate Test Specs
id: generate-specs
uses: ./.github/actions/generate-specs
with:
parallelism: 10
search_path: detox/e2e/test
device_name: ${{ env.DEVICE_NAME }}
device_os_version: ${{ env.DEVICE_OS_VERSION }}
e2e-ios:
name: ios-detox-e2e-${{ matrix.runId }}-${{ matrix.deviceName }}-${{ matrix.deviceOsVersion }}
if: ${{ inputs.run-ios-tests }}
runs-on: macos-14
continue-on-error: true
timeout-minutes: ${{ inputs.low_bandwidth_mode && 80 || 40 }}
env:
IOS: true
needs:
- generate-specs
strategy:
fail-fast: false
matrix: ${{ fromJSON(needs.generate-specs.outputs.specs) }}
steps:
- name: Checkout Repository
uses: actions/checkout@b4ffde65f46336ab88eb53be808477a3936bae11 # v4.1.1
with:
ref: ${{ inputs.MOBILE_VERSION }}
- name: ci/prepare-node-deps
uses: ./.github/actions/prepare-node-deps
- name: Install Homebrew Dependencies
run: |
brew tap wix/brew
brew install applesimutils
- name: Download iOS Simulator Build
uses: actions/download-artifact@c850b930e6ba138125429b7e5c93fc707a7f8427 # v4.1.4
with:
name: ios-build-simulator-${{ github.run_id }}
path: mobile-artifacts
- name: Unzip iOS Simulator Build
run: unzip -o mobile-artifacts/*.zip -d mobile-artifacts/
- name: Prepare Low Bandwidth Environment
id: prepare-low-bandwidth
uses: ./.github/actions/prepare-low-bandwidth
if: ${{ inputs.low_bandwidth_mode }}
with:
test_server_url: ${{ env.SITE_1_URL }}
device_name: ${{ env.DEVICE_NAME }}
# all these value should be configurable
download_speed: "3300"
upload_speed: "3300"
latency: "500"
- name: Start React Native Metro Server
run: npm run start &
- name: Install Detox Dependencies
run: cd detox && npm i
- name: Start Proxy
if: ${{ inputs.low_bandwidth_mode }}
id: start-proxy
uses: ./.github/actions/start-proxy
with:
test_server_url: ${{ env.SITE_1_URL }}
- name: Run Detox E2E Tests
continue-on-error: true # Label might have been removed manually
run: |
cd detox
npm run detox:config-gen
npm run e2e:ios-test -- ${{ matrix.specs }}
env:
DETOX_DEVICE_TYPE: ${{ env.DEVICE_NAME }}
DETOX_OS_VERSION: ${{ env.DEVICE_OS_VERSION }}
LOW_BANDWIDTH_MODE: ${{ inputs.low_bandwidth_mode }}
- name: reset network settings
if: ${{ inputs.low_bandwidth_mode || failure() }}
run: |
networksetup -setwebproxystate Ethernet "off"
networksetup -setsecurewebproxystate Ethernet "off"
if (sudo pfctl -q -sa | grep 'Status: Enabled') then sudo pfctl -d; fi
if (command -v pm2 &> /dev/null) then pm2 stop mitmdump; fi
sleep 5;
- name: Upload mitmdump Flow Output
if: ${{ inputs.low_bandwidth_mode }}
uses: actions/upload-artifact@5d5d22a31266ced268874388b861e4b58bb5c2f3 # v4.3.1
with:
name: ios-mitmdump-flow-output-${{ needs.generate-specs.outputs.workflow_hash }}-${{ matrix.runId }}
path: |
/Users/runner/work/mattermost-mobile/mattermost-mobile/flow-output.csv
/Users/runner/work/mattermost-mobile/mattermost-mobile/mitmdump.log
- name: Upload iOS Test Report
if: always()
uses: actions/upload-artifact@5d5d22a31266ced268874388b861e4b58bb5c2f3 # v4.3.1
with:
name: ios-results-${{ needs.generate-specs.outputs.workflow_hash }}-${{ matrix.runId }}
path: detox/artifacts/
generate-report:
runs-on: ubuntu-22.04
if: ${{ inputs.run-ios-tests}}
needs:
- generate-specs
- e2e-ios
outputs:
TARGET_URL: ${{ steps.set-url.outputs.TARGET_URL }}
STATUS: ${{ steps.determine-status.outputs.STATUS }}
FAILURES: ${{ steps.summary.outputs.FAILURES }}
steps:
- name: Checkout Repository
uses: actions/checkout@b4ffde65f46336ab88eb53be808477a3936bae11 # v4.1.1
with:
ref: ${{ inputs.MOBILE_VERSION }}
- name: ci/prepare-node-deps
uses: ./.github/actions/prepare-node-deps
- name: Download All Artifacts
uses: actions/download-artifact@c850b930e6ba138125429b7e5c93fc707a7f8427 # v4.1.4
with:
path: detox/artifacts/
pattern: ios-results-${{ needs.generate-specs.outputs.workflow_hash }}-*
- name: Generate Report Path
id: s3
run: |
path="${{ needs.generate-specs.outputs.build_id }}-${{ needs.generate-specs.outputs.mobile_sha }}-${{ needs.generate-specs.outputs.mobile_ref }}"
echo "path=$(echo "${path}" | sed 's/\./-/g')" >> ${GITHUB_OUTPUT}
- name: Save report Detox Dependencies
id: report-link
run: |
cd detox
npm ci
npm run e2e:save-report
env:
DETOX_AWS_ACCESS_KEY_ID: ${{ secrets.MM_MOBILE_DETOX_AWS_ACCESS_KEY_ID }}
DETOX_AWS_SECRET_ACCESS_KEY: ${{ secrets.MM_MOBILE_DETOX_AWS_SECRET_ACCESS_KEY }}
IOS: ${{ inputs.run-ios-tests }}
BUILD_ID: ${{ needs.generate-specs.outputs.build_id }}
REPORT_PATH: ${{ steps.s3.outputs.path }}
## These are needed for the MM Webhook report
COMMIT_HASH: ${{ needs.generate-specs.outputs.mobile_sha }}
BRANCH: ${{ needs.generate-specs.outputs.mobile_ref }}
- name: Calculate failures
id: summary
run: |
echo "FAILURES=$(cat detox/artifacts/summary.json | jq .stats.failures)" >> ${GITHUB_OUTPUT}
echo "PASSES=$(cat detox/artifacts/summary.json | jq .stats.passes)" >> ${GITHUB_OUTPUT}
echo "SKIPPED=$(cat detox/artifacts/summary.json | jq .stats.skipped)" >> ${GITHUB_OUTPUT}
echo "TOTAL=$(cat detox/artifacts/summary.json | jq .stats.tests)" >> ${GITHUB_OUTPUT}
echo "ERRORS=$(cat detox/artifacts/summary.json | jq .stats.errors)" >> ${GITHUB_OUTPUT}
echo "PERCENTAGE=$(cat detox/artifacts/summary.json | jq .stats.passPercent)" >> ${GITHUB_OUTPUT}
- name: Set Target URL
id: set-url
run: |
echo "TARGET_URL=https://${{ env.DETOX_AWS_S3_BUCKET }}.s3.amazonaws.com/${{ steps.s3.outputs.path }}/jest-stare/ios-report.html" >> ${GITHUB_OUTPUT}
- name: Determine Status
id: determine-status
run: |
if [[ ${{ steps.summary.outputs.failures }} -gt 0 && "${{ inputs.testcase_failure_fatal }}" == "true" ]]; then
echo "STATUS=failure" >> ${GITHUB_OUTPUT}
else
echo "STATUS=success" >> ${GITHUB_OUTPUT}
fi
- name: Generate Summary
run: |
echo "| Tests | Passed :white_check_mark: | Failed :x: | Skipped :fast_forward: | Errors :warning: | " >> ${GITHUB_STEP_SUMMARY}
echo "|:---:|:---:|:---:|:---:|:---:|" >> ${GITHUB_STEP_SUMMARY}
echo "| ${{ steps.summary.outputs.TOTAL }} | ${{ steps.summary.outputs.PASSES }} | ${{ steps.summary.outputs.FAILURES }} | ${{ steps.summary.outputs.SKIPPED }} | ${{ steps.summary.outputs.ERRORS }} |" >> ${GITHUB_STEP_SUMMARY}
echo "" >> ${GITHUB_STEP_SUMMARY}
echo "You can check the full report [here](${{ steps.set-url.outputs.TARGET_URL }})" >> ${GITHUB_STEP_SUMMARY}
echo "There was **${{ steps.summary.outputs.PERCENTAGE }}%** success rate." >> ${GITHUB_STEP_SUMMARY}