Files
dc/.gitea/scripts/cypress-changes.sh
T
dc 2e5b02aa51
Build / Build-and-ng-test (pull_request) Successful in 4m26s
Build / lighthouse (pull_request) Failing after 2m12s
Build / Build-and-test-development (pull_request) Canceled after 12m37s
ci(build): run the Lighthouse audit in the build workflow
The audit needs the production build, and an artifact belongs to the run that
produced it (needs: cannot cross workflows), so as a separate workflow it
compiled the frontend a second time - 92-104s measured - and then started an
ng serve that nothing audited: every URL in client/lighthouserc.js is on
:5000, which the SASjs server feeds from client/dist.

As a job in build.yaml it takes the change decision from the build job
(the same inputs gate both), downloads client-dist, and patches appLoc in the
built index.html instead of compiling a patched copy of the source. The
second compile, the dev server and the source generator in this job are gone;
what remains is node_modules for lhci, the pinned CLI, the SASjs server and
the mock estate deploy.

The check name moves from 'Lighthouse Checks / lighthouse' to
'Build / lighthouse'; there are no required contexts to update. The
changed-path matcher already covers everything this job reads, so its only
change is a comment and the fixture that used to assert lighthouse.yaml was
not an input.
2026-11-07 10:46:11 +00:00

88 lines
4.2 KiB
Bash

#!/usr/bin/env bash
# Decide whether this pull request can change the Cypress job's outcome.
#
# The Cypress job runs the mocked estate (sas/mocks) against the client, so a
# pull request that touches none of what it exercises cannot change its
# result: a sas/ service change is not deployed there, and a documentation
# change is not read. The build job decides once and publishes the answer as a
# job output, so its gate on the cold production build and the artifact upload
# cannot disagree with the job that downloads them - re-deciding in the second
# job could see a moved base branch and ask for an artifact the first job never
# built. The Lighthouse job takes the same decision: it reads the client build,
# the mock services and the CLI pin, and nothing else.
#
# Writes client=true|false to $GITHUB_OUTPUT when a decision can be made, and
# prints the files it saw. It exits 0 WITHOUT writing anything when it cannot
# decide (no base ref, a failed fetch, a failed diff): every caller gates on
# `!= 'false'`, so an undecidable pull request runs everything. A CI change
# whose worst case is "slow" is safe; one whose worst case is "silently tests
# nothing" is not, and one whose worst case is "every pull request goes red
# because a fetch failed" is not acceptable either.
#
# .gitea/scripts/ is in the set because the spec list (cypress-specs.sh) and
# the memory gate (check-runner-memory.sh) live there: a pull request that
# changes what the suite runs, or the gate that lets it run, has to run it.
# build.yaml is in the set for the same reason.
#
# sas/package.json is in the set because the job installs the CLI from the
# version it pins (`CLI_VERSION=$(node -p "...dependencies['@sasjs/cli']")`
# in "Deploy mocked services"): bumping that pin changes the toolchain the
# suite runs, even though no file under sas/mocks/ changes. The sas lockfile
# is not in the set - the job installs that CLI globally by version string,
# so the lockfile cannot change what it resolves.
#
# sas/mocks/test/ is dropped from the list before the match. Those files are
# node:test harnesses that read the payload files; the job deploys
# sas/mocks/sasjs/ and nothing else, so a pull request that changes only the
# tests cannot change what the browser is served. Any other file under
# sas/mocks/ still counts, including a change that touches the tests alongside
# a service.
#
# Usage: BASE_REF=<base branch> bash .gitea/scripts/cypress-changes.sh
set -uo pipefail
# The paths the Cypress job reads, and nothing else. The tests in
# tests/cypress-changes.test.sh exist because this list is the whole gate: a
# dropped alternative would silently stop the suite running on a class of
# change, and the only symptom would be a green job that finished sooner.
PATHS='client/|sas/mocks/|sas/package\.json|\.gitea/scripts/|package-lock\.json|\.gitea/workflows/build\.yaml'
# --match < file-list reads newline-separated paths on stdin and prints
# true/false, so the matcher can be exercised with fixed lists and no
# repository. It is what the test above drives.
# A path list on stdin, minus the mock tree's own tests, which the job does
# not deploy.
served_changes() { grep -v '^sas/mocks/test/' || true; }
if [ "${1:-}" = "--match" ]; then
if served_changes | grep -qE "^(${PATHS})"; then echo true; else echo false; fi
exit 0
fi
BASE="${BASE_REF:-}"
if [ -z "$BASE" ]; then
echo "no base ref (not a pull request) - running the suite"
exit 0
fi
if ! git fetch --no-tags --depth=1 origin \
"+refs/heads/${BASE}:refs/remotes/origin/${BASE}"; then
echo "::warning::could not fetch ${BASE} - running the suite rather than deciding"
exit 0
fi
if ! CHANGED="$(git diff --name-only "refs/remotes/origin/${BASE}" HEAD)"; then
echo "::warning::could not diff against ${BASE} - running the suite rather than deciding"
exit 0
fi
if served_changes <<<"$CHANGED" | grep -qE "^(${PATHS})"; then
echo "client=true" >>"${GITHUB_OUTPUT:-/dev/null}"
echo "the Cypress job's inputs changed:"
else
echo "client=false" >>"${GITHUB_OUTPUT:-/dev/null}"
echo "::notice::Cypress suite skipped - nothing under client/, sas/mocks/ (outside sas/mocks/test/) or .gitea/scripts/ changed"
echo "Skipping the Cypress suite - nothing it exercises changed:"
fi
printf '%s\n' "$CHANGED"