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.
88 lines
4.2 KiB
Bash
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"
|