# Triggers after the layered build has finished, taking the artifact and running cypress on it name: Cypress End to End Tests on: workflow_run: workflows: ["Element Web - Build"] types: - completed concurrency: group: ${{ github.workflow }}-${{ github.event.workflow_run.head_branch || github.ref }} cancel-in-progress: ${{ github.event.workflow_run.event == 'pull_request' }} jobs: prepare: name: Prepare if: github.event.workflow_run.conclusion == 'success' runs-on: ubuntu-latest permissions: actions: read issues: read statuses: write pull-requests: read outputs: uuid: ${{ steps.uuid.outputs.value }} pr_id: ${{ steps.prdetails.outputs.pr_id }} commit_message: ${{ steps.commit.outputs.message }} commit_author: ${{ steps.commit.outputs.author }} commit_email: ${{ steps.commit.outputs.email }} percy_enable: ${{ steps.percy.outputs.value || '1' }} testrail_enable: ${{ steps.testrail.outputs.value || '1' }} steps: # We create the status here and then update it to success/failure in the `report` stage # This provides an easy link to this workflow_run from the PR before Cypress is done. - uses: Sibz/github-status-action@v1 with: authToken: ${{ secrets.GITHUB_TOKEN }} state: pending context: ${{ github.workflow }} / cypress (${{ github.event.workflow_run.event }} => ${{ github.event_name }}) sha: ${{ github.event.workflow_run.head_sha }} target_url: https://github.com/${{ github.repository }}/actions/runs/${{ github.run_id }} - id: prdetails if: github.event.workflow_run.event == 'pull_request' uses: matrix-org/pr-details-action@v1.2 with: owner: ${{ github.event.workflow_run.head_repository.owner.login }} branch: ${{ github.event.workflow_run.head_branch }} - name: Get commit details id: commit if: github.event.workflow_run.event == 'pull_request' uses: actions/github-script@v6 with: script: | const response = await github.rest.git.getCommit({ owner: context.repo.owner, repo: context.repo.repo, commit_sha: "${{ github.event.workflow_run.head_sha }}", }); core.setOutput("message", response.data.message); core.setOutput("author", response.data.author.name); core.setOutput("email", response.data.author.email); # Only run Percy when it is demanded or on develop - name: Disable Percy if not needed id: percy if: | github.event.workflow_run.event == 'pull_request' && !contains(fromJSON(steps.prdetails.outputs.data).labels.*.name, 'X-Needs-Percy') run: echo "::set-output name=value::0" # Only run Testrail when it is demanded or on develop - name: Disable Testrail if not needed id: testrail if: | github.event.workflow_run.event == 'pull_request' && !contains(fromJSON(steps.prdetails.outputs.data).labels.*.name, 'X-Send-Testrail') run: echo "::set-output name=value::0" - name: Generate unique ID 💎 id: uuid run: echo "::set-output name=value::sha-$GITHUB_SHA-time-$(date +"%s")" tests: name: "Run Tests" needs: prepare runs-on: ubuntu-latest permissions: actions: read issues: read pull-requests: read environment: Cypress strategy: fail-fast: false matrix: # Run 4 instances in Parallel runner: [1, 2, 3, 4] steps: - uses: browser-actions/setup-chrome@latest - run: echo "BROWSER_PATH=$(which chrome)" >> $GITHUB_ENV - uses: tecolicom/actions-use-apt-tools@v1 with: # Our test suite includes some screenshot tests with unusual diacritics, which are # supposed to be covered by STIXGeneral. tools: fonts-stix - uses: actions/checkout@v3 with: # XXX: We're checking out untrusted code in a secure context # We need to be careful to not trust anything this code outputs/may do # We need to check this out to access the cypress tests which are on the head branch repository: ${{ github.event.workflow_run.head_repository.full_name }} ref: ${{ github.event.workflow_run.head_sha }} persist-credentials: false # There's a 'download artifact' action, but it hasn't been updated for the workflow_run action # (https://github.com/actions/download-artifact/issues/60) so instead we get this mess: - name: 📥 Download artifact uses: dawidd6/action-download-artifact@v2 with: run_id: ${{ github.event.workflow_run.id }} name: previewbuild path: webapp - name: Run Cypress tests uses: cypress-io/github-action@v5.0.2 with: # The built-in Electron runner seems to grind to a halt trying # to run the tests, so use chrome. browser: "${{ env.BROWSER_PATH }}" start: npx serve -p 8080 webapp wait-on: "http://localhost:8080" record: true parallel: true command-prefix: "yarn percy exec --parallel --" config: '{"reporter":"cypress-multi-reporters", "reporterOptions": { "configFile": "cypress-ci-reporter-config.json" } }' ci-build-id: ${{ needs.prepare.outputs.uuid }} env: # pass the Dashboard record key as an environment variable CYPRESS_RECORD_KEY: ${{ secrets.CYPRESS_RECORD_KEY }} # Use existing chromium rather than downloading another PUPPETEER_SKIP_CHROMIUM_DOWNLOAD: true # pass GitHub token to allow accurately detecting a build vs a re-run build GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} # make Node's os.tmpdir() return something where we actually have permissions TMPDIR: ${{ runner.temp }} # tell Cypress more details about the context of this run COMMIT_INFO_BRANCH: ${{ github.event.workflow_run.head_branch }} COMMIT_INFO_SHA: ${{ github.event.workflow_run.head_sha }} COMMIT_INFO_REMOTE: ${{ github.repositoryUrl }} COMMIT_INFO_MESSAGE: ${{ needs.prepare.outputs.commit_message }} COMMIT_INFO_AUTHOR: ${{ needs.prepare.outputs.commit_author }} COMMIT_INFO_EMAIL: ${{ needs.prepare.outputs.commit_email }} CYPRESS_PULL_REQUEST_ID: ${{ needs.prepare.outputs.pr_id }} CYPRESS_PULL_REQUEST_URL: https://github.com/${{ github.repository }}/pull/${{ needs.prepare.outputs.pr_id }} # pass the Percy token as an environment variable PERCY_TOKEN: ${{ secrets.PERCY_TOKEN }} PERCY_ENABLE: ${{ needs.prepare.outputs.percy_enable }} PERCY_BROWSER_EXECUTABLE: /usr/bin/chromium-browser # tell Percy more details about the context of this run PERCY_BRANCH: ${{ github.event.workflow_run.head_branch }} PERCY_COMMIT: ${{ github.event.workflow_run.head_sha }} PERCY_PULL_REQUEST: ${{ needs.prepare.outputs.pr_id }} PERCY_PARALLEL_TOTAL: ${{ strategy.job-total }} PERCY_PARALLEL_NONCE: ${{ needs.prepare.outputs.uuid }} - name: Upload Artifact if: failure() uses: actions/upload-artifact@v3 with: name: cypress-results path: | cypress/screenshots cypress/videos cypress/synapselogs - name: Upload reports if: always() uses: actions/upload-artifact@v2 with: name: cypress-junit path: cypress/results report: name: Report results needs: tests runs-on: ubuntu-latest if: always() permissions: statuses: write steps: - uses: Sibz/github-status-action@v1 with: authToken: ${{ secrets.GITHUB_TOKEN }} state: ${{ needs.tests.result == 'success' && 'success' || 'failure' }} context: ${{ github.workflow }} / cypress (${{ github.event.workflow_run.event }} => ${{ github.event_name }}) sha: ${{ github.event.workflow_run.head_sha }} target_url: https://github.com/${{ github.repository }}/actions/runs/${{ github.run_id }} testrail: name: Report results to testrail needs: - prepare - tests environment: Testrail runs-on: ubuntu-latest if: ${{ needs.prepare.outputs.testrail_enable }} steps: - uses: actions/download-artifact@v3 with: name: cypress-junit - name: Prepare testrail upload config id: testrailprep env: TESTRAIL_PROJECT_ID: ${{ secrets.TESTRAIL_PROJECT_ID }} TESTRAIL_SUITE_ID: ${{ secrets.TESTRAIL_SUITE_ID }} TEST_ID: ${{ github.run_id }} TESTRAIL_URL: https://elementqa.testrail.io TESTRAIL_USER: ${{ secrets.TESTRAIL_USER }} TESTRAIL_API_KEY: ${{ secrets.TESTRAIL_API_KEY }} run: | echo '{"name": "element-web cypress '$TEST_ID'", "suite_id": '$TESTRAIL_SUITE_ID' }' > body.json # TODO add description with more context? RUN_ID=`curl -X POST -d @body.json -u "$TESTRAIL_USER:$TESTRAIL_API_KEY" -H "Content-Type: application/json" "$TESTRAIL_URL/index.php?/api/v2/add_run/$TESTRAIL_PROJECT_ID" | jq '.id'` PROJECT_NAME=`curl -X GET -u "$TESTRAIL_USER:$TESTRAIL_API_KEY" -H "Content-Type: application/json" "$TESTRAIL_URL/index.php?/api/v2/get_project/$TESTRAIL_PROJECT_ID" | jq '.name'` echo "run_id=$RUN_ID" >> $GITHUB_OUTPUT echo "project_name=$PROJECT_NAME" >> $GITHUB_OUTPUT - name: setup python uses: actions/setup-python@v4 with: python-version: "3.11" - run: pip install trcli - name: Upload junit files env: TESTRAIL_PROJECT_ID: ${{ secrets.TESTRAIL_PROJECT_ID }} TESTRAIL_SUITE_ID: ${{ secrets.TESTRAIL_SUITE_ID }} TESTRAIL_URL: https://elementqa.testrail.io TESTRAIL_USER: ${{ secrets.TESTRAIL_USER }} TESTRAIL_API_KEY: ${{ secrets.TESTRAIL_API_KEY }} TESTRAIL_RUN_ID: ${{ steps.testrailprep.outputs.run_id }} run: | for file in results-*.xml; do echo "Handling $file" trcli -y -h $TESTRAIL_URL \ --project-id $TESTRAIL_PROJECT_ID \ --project ${{ steps.testrailprep.outputs.project_name }} \ --username $TESTRAIL_USER \ --password $TESTRAIL_API_KEY \ parse_junit \ --run-id $TESTRAIL_RUN_ID \ --suite-id $TESTRAIL_SUITE_ID \ --title "if you see this please check cypress build for run id not being provisioned" \ -f $file || true # We want to keep uploading what we can; but don't want the failures/red marks when it fails, so we add || true above. done - name: Close test run id: testrailpost if: always() env: TESTRAIL_URL: https://elementqa.testrail.io TESTRAIL_USER: ${{ secrets.TESTRAIL_USER }} TESTRAIL_API_KEY: ${{ secrets.TESTRAIL_API_KEY }} TESTRAIL_RUN_ID: ${{ steps.testrailprep.outputs.run_id }} run: | CLOSE_RESPONSE=`curl -X POST -d '{}' -u "$TESTRAIL_USER:$TESTRAIL_API_KEY" -H "Content-Type: application/json" "$TESTRAIL_URL/index.php?/api/v2/close_run/$TESTRAIL_RUN_ID"` if [ ! "0" == "`echo $CLOSE_RESPONSE | jq .untested_count`" ] ; then echo "::warning title=Missing Tests::Testrail reported some cypress tests were not run. $CLOSE_RESPONSE"; fi