Skip to content

chore(worker): pin get.resq.software to v0.4.5 #166

chore(worker): pin get.resq.software to v0.4.5

chore(worker): pin get.resq.software to v0.4.5 #166

Workflow file for this run

# Copyright 2026 ResQ Systems, Inc.
# SPDX-License-Identifier: Apache-2.0
#
# `required` status check for the org ruleset (default-branch-baseline).
# It is the *only* required context, so it must actually gate: it depends on
# real lint/parse jobs and fails if any of them fail. (Secret/SAST scanning is
# already covered by the repo's Socket Security + Semgrep + CodeQL checks.)
name: required
on:
push:
# release/pins-* is listed so that a human pushing a fix onto a bump branch
# gets checks. It does NOT cover the bot's own push: GitHub suppresses
# run-triggering events originating from GITHUB_TOKEN, and that applies to
# push exactly as it does to pull_request. release.yml therefore calls
# `gh workflow run required.yml --ref <branch>` after pushing, because
# workflow_dispatch is one of the two documented exceptions.
branches: [main, master, 'release/pins-*']
pull_request:
# Load-bearing. This is how the pin-bump PR gets its `required` check without
# a PAT or GitHub App secret. Remove it and those PRs become unmergeable.
workflow_dispatch:
permissions:
contents: read
concurrency:
group: ${{ github.workflow }}-${{ github.ref }}
cancel-in-progress: true
jobs:
shellcheck:
name: shellcheck (install.sh + scripts)
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1
with:
# None of these jobs push; matches every other workflow in the repo.
persist-credentials: false
- name: Install shellcheck
run: sudo apt-get update -qq && sudo apt-get install -y shellcheck
# -S warning, not -S error. Every "In POSIX sh, X is undefined" check is
# SC30xx, and every SC30xx is WARNING severity — so -S error sits exactly
# one notch above the only rules that police this repo's hardest
# constraint, that install.sh stays POSIX because it is piped to sh.
# Verified: a #!/bin/sh file containing `arr=(a b)` and `[[ -n "$1" ]]`
# passes -S error and fails -S warning (SC3030, SC3010).
#
# The same notch swallowed SC2115 (`rm -rf "$dir/"` with an unset var) and
# SC2164 (`cd` without `||`) — both live hazards in a script that removes
# temp directories from a trap.
#
# The old comment here claimed "pre-existing warning debt". Measured: the
# repo is at ZERO findings across all 17 shell files at this level, so the
# debt was already paid and the gate was being held down for nothing.
#
# -x follows `source`/`.` includes; -exec handles filenames with spaces.
- name: Lint shell scripts
run: >-
find . -type f -name '*.sh' -not -path './node_modules/*' -not -path './.git/*'
-exec shellcheck -S warning -x {} +
# The check above lints each file under the shell its shebang declares.
# install.sh is the one file where the dialect is a distribution promise
# rather than a preference: it is curl-piped into whatever /bin/sh is, so
# it is asserted explicitly rather than left to the shebang being right.
- name: install.sh is POSIX sh
run: shellcheck -S warning -s sh -x install.sh
# Catch drift on the PR that causes it rather than at tag time. VERSION is
# the only authored copy of the version; SCRIPT_VERSION, $ScriptVersion
# and both hook digests are generated from it and from the hook files.
# Editing scripts/install-hooks.* without re-stamping would otherwise ship
# installers that reject the very file they are meant to run.
- name: Installers stamped from VERSION
run: sh bin/stamp.sh --check
# A released VERSION must keep describing the artifacts it was tagged on.
#
# `stamp.sh --check` only proves the tree is internally consistent: it
# hashes the working tree and compares against stamps in that same tree.
# It cannot notice that "0.4.4" means something different here than it
# does at the v0.4.4 tag. That gap is not hypothetical — it is why this
# step exists. A pin bump merged into main without a VERSION bump, every
# check stayed green, and main's install.sh was left expecting a hooks
# digest that the tag it downloads from does not have; running it from a
# main checkout refused to install hooks. The curl-piped path was
# unaffected, because the endpoint serves the tag, which is self-
# consistent — so the damage was invisible from outside.
#
# Only fires once the tag exists, so the ordinary flow (bump VERSION,
# merge, tag) is unaffected. It catches the reverse: editing a shipped
# artifact while VERSION still points at a tag that no longer matches it.
- name: A tagged VERSION still matches its artifacts
run: |
set -eu
version="$(tr -d ' \t\r\n' < VERSION)"
tag="v$version"
# checkout is shallow and fetches no tags, so asking the local repo
# whether the tag exists would answer "no" every time and this step
# would pass without comparing anything. Ask the remote, and treat
# only ls-remote's documented "no match" status as not-yet-tagged —
# any other failure is a broken check, not a clean tree.
set +e
git ls-remote --exit-code --tags origin "refs/tags/$tag" >/dev/null 2>&1
lookup=$?
set -e
case "$lookup" in
0) ;;
2) echo "ok — $tag is not tagged yet; nothing to compare against"; exit 0 ;;
*) echo "::error::could not determine whether $tag exists (git ls-remote exit $lookup)"; exit 1 ;;
esac
git fetch --no-tags --depth=1 origin "refs/tags/$tag:refs/tags/$tag"
rc=0
for f in install.sh install.ps1 scripts/install-hooks.sh \
scripts/install-hooks.ps1 scripts/install-resq.sh; do
if ! git cat-file -e "$tag:$f" 2>/dev/null; then
echo "::error::$f does not exist at $tag"
rc=1
continue
fi
tagged="$(git show "$tag:$f" | sha256sum | cut -d' ' -f1)"
here="$(sha256sum < "$f" | cut -d' ' -f1)"
if [ "$tagged" != "$here" ]; then
echo "::error::$f differs from $tag but VERSION is still $version — bump VERSION and restamp"
rc=1
fi
done
[ "$rc" -eq 0 ] && echo "ok — all five artifacts match $tag"
exit "$rc"
# Every source file carries the canonical copyright header.
#
# In every other ResQ repo this is enforced by `resq copyright`, run from
# the pre-commit hook. This repo SHIPS that hook installer and does not
# use it — core.hooksPath is unset here, because dev/ deliberately no
# longer keeps its own copy of the hooks (see hooks-sync.yml). So the one
# repo distributing the enforcement was the one repo without it, and it
# showed: 17 files had drifted to a stale holder name and 20 more carried
# no header at all.
#
# A CI check rather than a local hook, for the same reason: a hook can be
# skipped with GIT_HOOKS_SKIP=1 and only exists on machines that ran the
# installer. The holder string matches resq-cli's copyright default, and
# the year is left open so this does not need editing every January.
- name: Source files carry the copyright header
run: |
set -eu
rc=0
# grep -L lists files NOT matching, so find -exec does the whole job
# in one pass. A `for f in $(find ...)` loop would be SC2044-fragile
# on paths with spaces, and this repo now gates shellcheck at warning.
#
# `|| true` is LOAD-BEARING, for exactly the reason bin/gen-pins.sh
# documents about `grep -c`: grep reports "did I match anything?" in
# its exit status, and with -L the clean case lists NOTHING, so it
# exits 1. Under `set -e` the command substitution inherits that and
# kills the step — silently, with no error output, precisely when
# every file is compliant. The first version of this check failed on
# a fully compliant tree. It passed locally only because an
# interactive shell has no `set -e`.
# Classify each file ONCE. A file saying "Copyright 2026 ResQ Software"
# both lacks the canonical header and carries the stale holder, so a
# naive two-pass version reported it twice — as missing AND as stale —
# which contradicts the promise directly below. Stale wins, because it
# is the more specific and more actionable diagnosis.
stale="$(find . \( -name '*.sh' -o -name '*.ps1' -o -name '*.ts' \
-o -name '*.mjs' -o -name '*.bats' -o -name '*.bash' \) \
-not -path './worker/node_modules/*' -not -path './.git/*' \
-exec grep -lF 'ResQ Software' {} + || true)"
missing_all="$(find . \( -name '*.sh' -o -name '*.ps1' -o -name '*.ts' \
-o -name '*.mjs' -o -name '*.bats' -o -name '*.bash' \) \
-not -path './worker/node_modules/*' -not -path './.git/*' \
-exec grep -LE 'Copyright [0-9]{4} ResQ Systems, Inc\.' {} + || true)"
if [ -n "$stale" ]; then
# -x whole-line, -F literal: subtract the stale set from the missing
# set so each file produces exactly one diagnostic.
missing="$(printf '%s\n' "$missing_all" \
| grep -vxF -f <(printf '%s\n' "$stale") || true)"
else
missing="$missing_all"
fi
if [ -n "$missing" ]; then
printf '%s\n' "$missing" | while IFS= read -r f; do
[ -n "$f" ] && echo "::error file=$f::missing the copyright header (expected: Copyright <year> ResQ Systems, Inc.)"
done
rc=1
fi
# Report a wrong holder AS a wrong holder rather than as a missing
# header — that is the drift this check was added for.
if [ -n "$stale" ]; then
printf '%s\n' "$stale" | while IFS= read -r f; do
[ -n "$f" ] && echo "::error file=$f::stale holder 'ResQ Software'; the canonical holder is 'ResQ Systems, Inc.'"
done
rc=1
fi
[ "$rc" -eq 0 ] || exit 1
echo "ok - every source file carries the canonical header"
# The cargo fallback in install-resq.sh is not a rare path — it is the
# only one that runs, because crates publishes no resq-cli-v* release for
# resolve_tag to find. It must pin, and the unpinned form must require an
# explicit opt-out. Stubs cargo; compiles nothing, fetches nothing.
- name: install-resq.sh pins its cargo fallback
run: sh tests/installers/pinning.sh
- name: The pinned crates commits still exist upstream
# A commit SHA cannot be repointed, which is the point of pinning — but
# it can be mistyped or rebased away, and either way every user's
# install dies at `cargo install --rev`. Better a red check here.
#
# Ancestry, not merely existence: a commit can resolve while sitting on
# an abandoned branch, and pinning to something never merged is not the
# reviewed history this is meant to point at.
env:
GH_TOKEN: ${{ github.token }}
run: |
set -euo pipefail
resq_pin="$(sed -n 's/^CRATES_COMMIT="\(.*\)"$/\1/p' scripts/install-resq.sh)"
hooks_pin="$(sed -n 's/^ *CRATES_COMMIT="\(.*\)"$/\1/p' scripts/install-hooks.sh)"
[ -n "$resq_pin" ] || { echo "::error::could not read CRATES_COMMIT from scripts/install-resq.sh"; exit 1; }
rc=0
for pin in "$resq_pin" "$hooks_pin"; do
[ -n "$pin" ] || continue
if ! body="$(curl -fsSL -H "Authorization: Bearer $GH_TOKEN" \
"https://api.github.com/repos/resq-software/crates/compare/master...$pin")"; then
echo "::error::$pin is not resolvable in resq-software/crates"
rc=1; continue
fi
status="$(printf '%s' "$body" | sed -n 's/.*"status":[[:space:]]*"\([a-z]*\)".*/\1/p' | head -1)"
case "$status" in
identical|behind) echo "ok — $pin is on master ($status)" ;;
*) echo "::error::$pin is '$status' relative to master; pin a commit that is merged"; rc=1 ;;
esac
done
# They may legitimately differ — hooks and the CLI can move at
# different times — but if they agree, say so: one crates revision per
# dev release is the easier thing to reason about.
if [ "$resq_pin" = "$hooks_pin" ]; then
echo "ok — install-resq.sh and install-hooks.sh pin the same crates commit"
else
echo "::notice::install-resq.sh pins $resq_pin, install-hooks.sh pins $hooks_pin"
fi
exit "$rc"
- name: Hook digests match the pinned crates commit
# install-hooks.{sh,ps1} fetch six files that become executables git
# runs on every commit and push. They used to come from a mutable
# branch with no verification; they are now pinned and digest-checked.
#
# Pins rot silently: if the crates templates change, the installers keep
# refusing perfectly good hooks and every fresh onboard fails with a
# checksum mismatch. This turns that into a failing check here instead,
# and equally catches a mistyped digest that would never match anything.
run: |
set -euo pipefail
sh_commit="$(sed -n 's/^ *CRATES_COMMIT="\(.*\)"$/\1/p' scripts/install-hooks.sh)"
ps_commit="$(sed -n "s/^ *\$cratesCommit = '\(.*\)'$/\1/p" scripts/install-hooks.ps1)"
[ -n "$sh_commit" ] || { echo "::error::could not read CRATES_COMMIT from install-hooks.sh"; exit 1; }
if [ "$sh_commit" != "$ps_commit" ]; then
echo "::error::installers disagree on the pinned commit: sh=$sh_commit ps1=$ps_commit"
exit 1
fi
base="https://raw.githubusercontent.com/resq-software/crates/$sh_commit/crates/resq-cli/templates/git-hooks"
rc=0
for h in pre-commit commit-msg prepare-commit-msg pre-push post-checkout post-merge; do
if ! actual="$(curl -fsSL --proto '=https' --tlsv1.2 "$base/$h" | sha256sum | cut -d' ' -f1)"; then
echo "::error::could not fetch $h from the pinned commit"
rc=1; continue
fi
# Assert the real digest appears in both installers rather than
# parsing their formats — a shell case and a PowerShell hashtable
# would need two brittle parsers to say the same thing.
for f in scripts/install-hooks.sh scripts/install-hooks.ps1; do
if ! grep -q "$actual" "$f"; then
echo "::error::$f has no digest matching $h at $sh_commit (expected $actual)"
rc=1
fi
done
done
[ "$rc" -eq 0 ] && echo "ok — all six hook digests match $sh_commit in both installers"
exit "$rc"
- name: Nix installer digest matches the pinned URL
# Same reasoning as the hook digests. The Nix installer is pinned to a
# versioned Determinate URL and checked before execution; if that URL's
# content ever changes, every install fails on a checksum mismatch. A
# red check here is a better way to learn that than a user's report.
#
# This pins what we execute, not what Determinate wrote — they publish
# no digest of their own. It closes the "silently different tomorrow"
# gap, not the "already compromised when we pinned it" one.
run: |
set -euo pipefail
url="$(sed -n 's/^NIX_INSTALL_URL="\(.*\)"$/\1/p' install.sh)"
want="$(sed -n 's/^NIX_INSTALLER_SHA256="\(.*\)"$/\1/p' install.sh)"
# An explicit if, not `A && B || C` — shellcheck flags that as SC2015
# because C also runs when A succeeds and B fails, which is a genuine
# trap even where, as here, it happened to be the behaviour wanted.
if [ -z "$url" ] || [ -z "$want" ]; then
echo "::error::could not read the Nix pin from install.sh"
exit 1
fi
actual="$(curl -fsSL --proto '=https' --proto-redir '=https' --tlsv1.2 "$url" | sha256sum | cut -d' ' -f1)"
if [ "$actual" != "$want" ]; then
echo "::error::$url now hashes to $actual, but install.sh pins $want"
echo "::error::Review the change, then update the pin in install.sh, scripts/lib/nix.sh and scripts/lib/nix.ps1."
exit 1
fi
# All FOUR copies must agree. install.ps1 declares its own
# $NixInstallUrl and $NixInstallerSha256, so checking only the two
# libs would let the Windows entry point drift while this job passes —
# and drift there means Windows users get a different installer than
# everyone else, which is the failure this check exists to prevent.
rc=0
ps_url="$(sed -n "s/.*\$NixInstallUrl *= *'\([^']*\)'.*/\1/p" install.ps1 | head -1)"
ps_sha="$(sed -n "s/.*\$NixInstallerSha256 *= *'\([^']*\)'.*/\1/p" install.ps1 | head -1)"
if [ -z "$ps_url" ] || [ -z "$ps_sha" ]; then
echo "::error::could not read the Nix pin from install.ps1 — the extraction here no longer matches the file"
rc=1
else
[ "$ps_url" = "$url" ] || { echo "::error::install.ps1 pins URL $ps_url, install.sh pins $url"; rc=1; }
[ "$ps_sha" = "$want" ] || { echo "::error::install.ps1 pins digest $ps_sha, install.sh pins $want"; rc=1; }
fi
for f in scripts/lib/nix.sh scripts/lib/nix.ps1; do
grep -q "$want" "$f" || { echo "::error::$f does not carry the pinned digest $want"; rc=1; }
grep -q "$url" "$f" || { echo "::error::$f does not carry the pinned URL $url"; rc=1; }
done
[ "$rc" -eq 0 ] && echo "ok — Nix installer pin agrees across install.sh, install.ps1 and both libs"
exit "$rc"
- name: Bun installer digests match their pinned tags
# Same contract as the Nix and hook pins. Bun's installers are run
# rather than reimplemented — they do CPU baseline detection we do not
# want to duplicate — so what we verify is the script, pinned to a tag.
#
# Note the two are checked independently: the shell installer is
# byte-identical to bun.sh/install, the PowerShell one is not, so they
# cannot be assumed to move together.
run: |
set -euo pipefail
rc=0
# Extract by variable name rather than by matching a URL or a bare
# 64-hex run. bun.ps1 carries two pins, so a "first hex string wins"
# pattern would silently check one of them twice.
verify() { # label, url, want
if [ -z "$2" ] || [ -z "$3" ]; then
echo "::error::could not read the $1 pin — the extraction in this workflow no longer matches the file"
rc=1; return
fi
actual="$(curl -fsSL --proto '=https' --proto-redir '=https' --tlsv1.2 "$2" | sha256sum | cut -d' ' -f1)"
if [ "$actual" != "$3" ]; then
echo "::error::$1: $2 now hashes to $actual, but the pin says $3"
echo "::error::Review the change, then update scripts/lib/bun.sh and scripts/lib/bun.ps1 together."
rc=1
else
echo "ok — $1 matches its pin"
fi
}
verify "bun.sh install.sh" \
"$(sed -n 's/.*bun_url="\([^"]*\)".*/\1/p' scripts/lib/bun.sh)" \
"$(sed -n 's/.*bun_sha="\([^"]*\)".*/\1/p' scripts/lib/bun.sh)"
verify "bun.ps1 install.ps1" \
"$(sed -n "s/.*bunUrl = '\([^']*\)'.*/\1/p" scripts/lib/bun.ps1)" \
"$(sed -n "s/.*bunSha = '\([^']*\)'.*/\1/p" scripts/lib/bun.ps1)"
verify "bun.ps1 install.sh" \
"$(sed -n "s/.*shUrl = '\([^']*\)'.*/\1/p" scripts/lib/bun.ps1)" \
"$(sed -n "s/.*shSha = '\([^']*\)'.*/\1/p" scripts/lib/bun.ps1)"
# The shell installer is pinned in two files; they must not drift.
a="$(sed -n 's/.*bun_sha="\([^"]*\)".*/\1/p' scripts/lib/bun.sh)"
b="$(sed -n "s/.*shSha = '\([^']*\)'.*/\1/p" scripts/lib/bun.ps1)"
if [ "$a" != "$b" ]; then
echo "::error::bun.sh and bun.ps1 pin different digests for install.sh: $a vs $b"
rc=1
fi
exit "$rc"
- name: gen-pins missing-PINS guard is reachable
# `grep -c` exits 1 on zero matches, so without `|| true` the command
# substitution's status kills the script under `set -e` one line before
# the die that explains what went wrong — the guard becomes unreachable
# in exactly the case it exists for.
#
# Fixed once, then silently reverted by an unrelated PR that staged a
# stale copy of the file. Nothing caught it because nothing tested it.
# Asserting on the message rather than on a source line means a future
# rewrite still has to preserve the behaviour.
run: |
set -euo pipefail
tmp="$(mktemp -d)"
cp -a . "$tmp/r"
cd "$tmp/r"
# gen-pins needs at least one v* tag before it reaches write_source.
git tag -f v0.0.1 HEAD >/dev/null 2>&1
printf 'not a worker\n' > worker/src/index.ts
# Assert the exit status too, not only the message. The guard exists
# to *stop* the run; a script that printed this text and exited 0
# would satisfy a message-only check while being broken in precisely
# the way that matters. `if out="$(...)"` keeps set -e out of the way.
if out="$(sh bin/gen-pins.sh --write 2>&1)"; then
echo "::error::gen-pins.sh exited 0 on a file with no PINS block; it must fail"
echo "::error::output was: ${out:-<no output>}"
exit 1
fi
# Match the whole diagnostic rather than a fragment, so a message that
# drifts into meaning something else cannot keep passing.
case "$out" in
*"expected exactly one 'const PINS = {' in worker/src/index.ts, found 0"*)
echo "ok — guard failed with: $out" ;;
*)
echo "::error::gen-pins.sh failed, but not with the missing-PINS diagnostic"
echo "::error::got: ${out:-<no output>}"
exit 1 ;;
esac
powershell:
name: PowerShell parse + analyze (*.ps1)
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1
with:
# None of these jobs push; matches every other workflow in the repo.
persist-credentials: false
- name: Parse-check (gating) + PSScriptAnalyzer (advisory)
shell: pwsh
run: |
Set-StrictMode -Version Latest
$ErrorActionPreference = 'Stop'
$ps1 = Get-ChildItem -Recurse -Filter *.ps1 -File | Where-Object { $_.FullName -notmatch '[\\/](node_modules|\.git)[\\/]' }
if (-not $ps1) { Write-Host 'No .ps1 files'; exit 0 }
# Gate on parse errors (genuinely broken scripts).
$fail = $false
foreach ($f in $ps1) {
$tok = $null; $perr = $null
[System.Management.Automation.Language.Parser]::ParseFile($f.FullName, [ref]$tok, [ref]$perr) | Out-Null
if ($perr) { $fail = $true; Write-Host "PARSE ERROR: $($f.FullName)"; $perr | ForEach-Object { Write-Host " $($_.Message)" } }
}
# PSScriptAnalyzer findings are advisory while the real debt is measured.
#
# This step used to pass `-Path $ps1.FullName`, where $ps1 is an ARRAY of
# FileInfo — so .FullName is String[] and -Path, which takes a single
# string, threw:
#
# Cannot convert 'System.Object[]' to the type 'System.String'
# required by parameter 'Path'
#
# The catch swallowed it, printed "skipped", and the job went green. The
# analyser had never examined a single line while the step name promised
# it had. Analysing per file removes the array entirely.
#
# The catch is kept for a genuinely absent module (offline runner), but it
# now names the stage that failed, so "not installed" can never again read
# the same as "found nothing".
# Availability and findings are tracked as SEPARATE facts, because
# conflating them is the defect this step is fixing. "No findings" may
# only be printed when every file was actually analysed; otherwise a
# broken analyser reads exactly like clean code.
#
# Import explicitly rather than trusting Get-Module -ListAvailable:
# that tests discoverability, not importability, and a module can sit
# on disk yet fail to load.
$analyzerReady = $false
try {
Install-Module PSScriptAnalyzer -Force -Scope CurrentUser -ErrorAction Stop
Import-Module PSScriptAnalyzer -Force -ErrorAction Stop
$analyzerReady = $true
} catch {
Write-Host "::warning::PSScriptAnalyzer unavailable, PowerShell was NOT analysed: $($_.Exception.Message)"
}
if ($analyzerReady) {
$issues = @()
$analyzed = 0
$failed = @()
foreach ($f in $ps1) {
try {
# -ErrorAction Stop, not Continue. With Continue, a per-file
# failure leaves $issues untouched and that file is silently
# counted as clean — the same "absence reads as success" shape
# this step exists to remove.
$issues += Invoke-ScriptAnalyzer -Path $f.FullName -Severity Error,Warning -ErrorAction Stop
$analyzed++
} catch {
$failed += $f.FullName
Write-Host "::warning::PSScriptAnalyzer failed on $($f.FullName): $($_.Exception.Message)"
}
}
if ($issues) {
Write-Host '::group::PSScriptAnalyzer (advisory)'
($issues | Format-Table RuleName, Severity, ScriptName, Line, Message -AutoSize | Out-String -Width 200) | Write-Host
Write-Host '::endgroup::'
# A count, so the debt is a number someone can watch shrink rather than
# a wall of text nobody reads.
$bySeverity = $issues | Group-Object Severity | ForEach-Object { "$($_.Name)=$($_.Count)" }
Write-Host "::notice::PSScriptAnalyzer: $($issues.Count) findings across $analyzed/$($ps1.Count) files ($($bySeverity -join ', '))"
} elseif ($failed.Count -gt 0) {
# Empty findings AND failed files is the false zero. Never report
# it as clean: an analyser that could not read a file has said
# nothing about that file, which is not the same as approving it.
Write-Host "::warning::PSScriptAnalyzer produced no findings, but $($failed.Count) of $($ps1.Count) file(s) could not be analysed — this is NOT a clean result"
} else {
Write-Host "PSScriptAnalyzer: no Error/Warning findings across all $analyzed file(s)"
}
}
if ($fail) { throw 'PowerShell parse errors found' }
worker:
name: worker (get.resq.software)
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1
with:
# None of these jobs push; matches every other workflow in the repo.
persist-credentials: false
# Node is pinned rather than inherited. The suite and worker-live import
# worker/src/index.ts directly and rely on native type stripping, which
# only exists from Node 23.6 — on an older default runner image the
# import fails outright. Leaving that to whatever the image ships is the
# kind of unstated assumption this repo pins everything else against.
- uses: actions/setup-node@820762786026740c76f36085b0efc47a31fe5020 # v7.0.0
with:
node-version: '24'
# setup-node v7 added package-manager-cache, which defaults to TRUE
# and turns on npm caching automatically when package.json names a
# package manager. zizmor flags that as cache poisoning and is right
# to: a poisoned cache would feed the job that decides which bytes
# get pinned. Restoring a few seconds of npm download is a trade
# worth making here. Not a suppression — caching is genuinely off.
package-manager-cache: false
- name: Install worker devDependencies
working-directory: worker
run: npm ci --no-audit --no-fund
# Type checking is a separate gate from the tests: tsc proves the source
# is internally consistent, the suite proves it behaves. Neither subsumes
# the other — both of this Worker's production outages typechecked fine.
- name: Typecheck
working-directory: worker
run: npm run typecheck
# Biome, pinned to the same 2.5.2 that resq-software/npm standardises on,
# so this repo and the org's TypeScript repo report the same findings.
# It runs on Biome's defaults with no biome.json on purpose — the org
# config's formatter unquotes the generated PINS keys that gen-pins.sh
# writes back, and the two would fight forever. Defaults lint clean.
- name: Lint (biome)
working-directory: worker
run: npm run lint
# Also validates the inline PINS in worker/src/index.ts against live
# GitHub, so digests that have rotted surface here as a 502 rather than in
# production, where the Worker would correctly refuse to serve anything.
#
# And it backs the single `as PinConfig` assertion on DEFAULT_PINS: the
# compiler checks the shape, this suite checks the strings really are hex,
# by running the exported validatePinConfig over those very pins.
- name: Worker test suite
run: |
set -euo pipefail
node --version
node worker/test/index.test.mjs
required:
name: required
needs: [shellcheck, powershell, worker]
if: always()
runs-on: ubuntu-latest
steps:
- name: Gate on required checks
run: |
set -euo pipefail
for r in \
"shellcheck=${{ needs.shellcheck.result }}" \
"powershell=${{ needs.powershell.result }}" \
"worker=${{ needs.worker.result }}"; do
name=${r%%=*}; res=${r#*=}
echo "$name: $res"
[ "$res" = "success" ] || { echo "::error::required check '$name' did not pass"; exit 1; }
done
echo "ok — all required checks passed"