Run Visual Tests #886
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
name: Run Visual Tests | |
on: | |
workflow_run: | |
workflows: ["Trigger Unsafe Workflows"] | |
types: [completed] | |
permissions: {} | |
jobs: | |
wait-for-docker-images-to-build: | |
name: Wait For Docker Images To Build | |
runs-on: ubuntu-20.04 | |
# Don't run this for dependabot merges to spare our free Percy limit as we assume | |
# that in the vast majority of cases this won't change anything. If we get unlimited | |
# Percy though we may want to reenable this | |
if: ${{ github.event.sender.login != 'dependabot[bot]' }} | |
outputs: | |
ci-chrome: ${{ steps.outputter.outputs.ci-chrome }} | |
production: ${{ steps.outputter.outputs.production }} | |
env: | |
REPOSITORY: sctrainer/main | |
PRODUCTION_TAG: production-${{ github.event.workflow_run.head_sha }} | |
CHROME_TAG: ci-chrome-v4 | |
steps: | |
- name: Wait for Production image to exist | |
shell: bash | |
run: | | |
SECONDS=0 | |
max_wait_time=300 | |
wait_interval=5 | |
while (( SECONDS < max_wait_time )); do | |
curl --silent -f -lSL https://hub.docker.com/v2/repositories/$REPOSITORY/tags/$PRODUCTION_TAG && break; | |
echo "Failed so sleeping" | |
sleep $wait_interval | |
echo "Trying again" | |
done | |
(( SECONDS >= max_wait_time )) && echo "failed" && exit 1 | |
echo "Success" | |
- name: Wait for CI Chrome image to exist | |
shell: bash | |
run: | | |
SECONDS=0 | |
max_wait_time=300 | |
wait_interval=5 | |
while (( SECONDS < max_wait_time )); do | |
curl --silent -f -lSL https://hub.docker.com/v2/repositories/$REPOSITORY/tags/$CHROME_TAG && break; | |
echo "Failed so sleeping" | |
sleep $wait_interval | |
echo "Trying again" | |
done | |
(( SECONDS >= max_wait_time )) && echo "failed" && exit 1 | |
echo "Success" | |
- name: Output the container names | |
id: outputter | |
run: | | |
echo "ci-chrome=$REPOSITORY:$CHROME_TAG" >> $GITHUB_OUTPUT | |
echo "production=$REPOSITORY:$PRODUCTION_TAG" >> $GITHUB_OUTPUT | |
run-visual-tests: | |
name: Run Visual Tests on ${{ matrix.sizes.name }} screen size | |
runs-on: ubuntu-20.04 | |
needs: wait-for-docker-images-to-build | |
# Don't run this for dependabot merges to spare our free Percy limit as we assume | |
# that in the vast majority of cases this won't change anything. If we get unlimited | |
# Percy though we may want to reenable this | |
if: ${{ github.event.sender.login != 'dependabot[bot]' }} | |
permissions: | |
contents: read | |
container: ${{ needs.wait-for-docker-images-to-build.outputs.ci-chrome }} | |
env: | |
PORT: 8080 | |
services: | |
sctrainer-server: | |
image: ${{ needs.wait-for-docker-images-to-build.outputs.production }} | |
env: | |
PORT: ${{ env.PORT }} | |
strategy: | |
fail-fast: false | |
matrix: | |
# Values for devices taken from https://docs.cypress.io/api/commands/viewport#Arguments | |
sizes: | |
- width: 1280 | |
height: 800 | |
name: Macbook 13 | |
- width: 375 | |
height: 667 | |
name: Iphone 8 | |
steps: | |
- name: Checkout unsafe code from forked repository | |
uses: actions/checkout@v4 | |
with: | |
ref: ${{ github.event.workflow_run.head_branch }} | |
### We are now working with unsafe code from a forked repository | |
### So don't allow any dangerous permissions on the github token | |
### or expose any of our secrets without great thought behind it | |
- name: Handle Yarn caching | |
uses: actions/cache@v4 | |
env: | |
cache-name: yarn-cache-v2 | |
with: | |
path: | | |
~/.cache/yarn | |
key: ${{ job.container.image }}-${{ env.cache-name }}-${{ hashFiles('end-to-end-tests/**/yarn.lock')}} | |
# Note we purposefully don't specify fallback restore keys. | |
# Explanation: https://glebbahmutov.com/blog/do-not-let-cypress-cache-snowball/ | |
- name: Handle Cypress caching | |
uses: actions/cache@v4 | |
env: | |
cache-name: cypress-cache-v2 | |
with: | |
path: | | |
~/.cache/Cypress | |
key: ${{ job.container.image }}-${{ env.cache-name }}-${{ hashFiles('end-to-end-tests/**/yarn.lock')}} | |
# Note we purposefully don't specify fallback restore keys. | |
# Explanation: https://glebbahmutov.com/blog/do-not-let-cypress-cache-snowball/ | |
- name: Install Dependencies | |
run: yarn --frozen-lockfile | |
working-directory: end-to-end-tests | |
- name: Log Cypress Info | |
run: npx cypress info | |
working-directory: end-to-end-tests | |
- name: Setup Percy Configuration | |
working-directory: end-to-end-tests | |
# The percyCSS override is what ensures full page snapshots | |
run: 'echo ''{ "version": 2, "snapshot": { "widths": [${{ matrix.sizes.width }}], "min-height": ${{ matrix.sizes.height }}, "percyCSS": "* { overflow-y: visible !important; } img { max-width: none !important; }" } }'' > percy-config.json' | |
### This is the only place we run the untrusted code | |
### We have made sure that the github token has minimum | |
### permissions and the only secret we are passing is the | |
### PERCY_TOKEN which shouldn't be able to do too much damage | |
### even if abused, though if there are ways to do this more securely | |
### though that would be appreciated | |
- name: Run Cypress Tests | |
working-directory: end-to-end-tests | |
env: | |
PERCY_TOKEN: ${{ secrets.PERCY_TOKEN }} | |
PERCY_PARALLEL_NONCE: ${{ github.run_id }} | |
PERCY_PARALLEL_TOTAL: ${{ strategy.job-total }} | |
PERCY_BRANCH: ${{ github.event.workflow_run.head_branch }} | |
PERCY_PULL_REQUEST: ${{ github.event.workflow_run.pull_requests[0].number }} | |
PERCY_COMMIT: ${{ github.event.workflow_run.head_sha }} | |
PERCY_DEBUG: "*" | |
run: > | |
./node_modules/.bin/percy exec --parallel --config percy-config.json -- | |
./node_modules/.bin/cypress run | |
--browser chrome | |
--config "viewportWidth=${{ matrix.sizes.width }},viewportHeight=${{ matrix.sizes.height }},baseUrl=http://sctrainer-server:${{ env.PORT }}" | |
--spec cypress/e2e/visual-tests.cy.ts |