mesh/merge-gate pass: the change touches no module of the mesh's graph
mesh/repo-check pass: THE CHANGE ALTERS ITS OWN CHECK (merge-check.sh, merge-check-typescript.sh): main's version judged it; the change's judges the pull r…
mesh/delivery delivered
mesh/delivery-group group fix/385-an-untestable-module-fails-the-check delivered: every member is delivered
A module whose dependencies could not be fetched was said NOT TESTED and the repository check passed, so a merge on it would have landed untested code. The build seat clones the SDK beside every check already: a forge requirement the module cache lacks is now taken from that clone through a go.mod of its own, and a module that still cannot be built fails the check by name and why. A TypeScript module whose dependencies the toolchain lacks fails the same way.
101 lines
5.0 KiB
Bash
101 lines
5.0 KiB
Bash
#!/bin/sh
|
|
# The catalogue's TypeScript part of its own check (novox/hq issue 302's `mesh-check-also`), declared in
|
|
# merge-check.sh's header and run by the build seat in the TypeScript toolchain, after the Go part. The media
|
|
# catalogue's twin is issue 311. Before this, a TypeScript module's change ran nothing of its own before it
|
|
# merged: the Go part said "NOT TESTED HERE", and a type error in the forge module would first have shown in
|
|
# its walk.
|
|
#
|
|
# For every touched module that has a package.json, in a copy of it outside the clone:
|
|
#
|
|
# 1. its dependencies are the toolchain's own (/app/node_modules: the mesh's SDK, Node's types and what the
|
|
# runtime carries), copied beside it, never fetched: the check holds no credential for the package
|
|
# registry. A module that depends on a package the toolchain does not hold **fails the check**, by name:
|
|
# it could not be type-checked or tested, and what could not run is a failure, never a note (novox/hq
|
|
# issue 385);
|
|
# 2. every source that is not a test is type-checked with the toolchain's compiler and the flags a build
|
|
# compiles with — the same check the build makes, before the merge rather than in the walk;
|
|
# 3. its tests (test/*.test.ts) run under Node's own runner with types stripped, as its own `npm test` does
|
|
# after its build: the sources are compiled to dist/ and beside themselves first, so a test that imports
|
|
# the compiled module, or a source that imports its sibling by its .js name, finds it.
|
|
#
|
|
# Said, never passed silently: a module with no tests is said NOT TESTED on every run that touches it —
|
|
# nothing of it could fail. A module whose tests exist and could not run fails (novox/hq issue 385).
|
|
#
|
|
# By hand: MESH_CHECK_MODULES=gitea sh merge-check-typescript.sh, in the toolchain image (it reads
|
|
# /app/node_modules), or with TOOLCHAIN_MODULES pointing at a node_modules that holds the same.
|
|
set -eu
|
|
|
|
deps="${TOOLCHAIN_MODULES:-/app/node_modules}"
|
|
tsc="$deps/typescript/bin/tsc"
|
|
if [ ! -f "$tsc" ]; then
|
|
echo "NOT CHECKED: no TypeScript compiler at $tsc — this part runs in the TypeScript toolchain"
|
|
exit 1
|
|
fi
|
|
|
|
# The modules the change reaches: the planner's answer (hq ADR 0238), and every module a changed file is in —
|
|
# a change to a module's tests alone moves no build (hq ADR 0267), and its tests must still run.
|
|
touched=$({
|
|
printf '%s\n' "${MESH_CHECK_MODULES:-}" | tr ',' '\n' | sed -e 's#^modules/##' -e '/\//d'
|
|
printf '%s\n' "${MESH_CHECK_CHANGED:-}" | tr ',' '\n' | sed -n 's#^modules/\([^/]*\)/.*#\1#p'
|
|
} | sed '/^$/d' | sort -u)
|
|
|
|
work=$(mktemp -d)
|
|
trap 'rm -rf "$work"' EXIT
|
|
failed=""
|
|
for m in $touched; do
|
|
d="modules/$m"
|
|
[ -f "$d/package.json" ] || continue
|
|
copy="$work/$m"
|
|
mkdir -p "$copy"
|
|
(cd "$d" && tar --exclude=./node_modules --exclude=./dist -cf - .) | (cd "$copy" && tar -xf -)
|
|
# What it depends on, against what the toolchain holds.
|
|
missing=$(node -e '
|
|
const p = require(process.argv[1]); const have = require("fs").readdirSync(process.argv[2]);
|
|
const scoped = (n) => n.startsWith("@") ? n.split("/")[0] : n;
|
|
const names = Object.keys({ ...(p.dependencies || {}), ...(p.devDependencies || {}) });
|
|
const held = (n) => have.includes(n) || (n.startsWith("@") && have.includes(scoped(n)) &&
|
|
require("fs").existsSync(process.argv[2] + "/" + n));
|
|
console.log(names.filter((n) => n !== "typescript" && !held(n)).join(" "));' "$copy/package.json" "$deps")
|
|
if [ -n "$missing" ]; then
|
|
echo "FAILED: $d could not be checked — it depends on $missing, which the toolchain does not hold and the check cannot fetch (novox/hq issue 385)"
|
|
failed="$failed $m"
|
|
continue
|
|
fi
|
|
mkdir -p "$copy/node_modules"
|
|
for p in "$deps"/*; do
|
|
case "$(basename "$p")" in typescript | esbuild | @esbuild) continue ;; esac
|
|
cp -r "$p" "$copy/node_modules/"
|
|
done
|
|
sources=$(cd "$copy" && find . -name '*.ts' ! -name '*.d.ts' ! -path './test/*' ! -path './node_modules/*' ! -path './dist/*' | sort)
|
|
if [ -n "$sources" ]; then
|
|
echo "type-checking $d (TypeScript)"
|
|
# shellcheck disable=SC2086 # the module's sources, none with a space in its name
|
|
if ! (cd "$copy" && node "$tsc" --noEmit --module NodeNext --moduleResolution NodeNext --target ES2022 \
|
|
--types node $sources); then
|
|
failed="$failed $m"
|
|
continue
|
|
fi
|
|
else
|
|
echo "$d has no TypeScript sources of its own to type-check: its tests read its files"
|
|
fi
|
|
if ! ls "$copy"/test/*.test.ts >/dev/null 2>&1; then
|
|
echo "NOT TESTED: $d is TypeScript and has no tests of its own"
|
|
continue
|
|
fi
|
|
if [ -n "$sources" ]; then
|
|
# shellcheck disable=SC2086
|
|
(cd "$copy" && node "$tsc" --module NodeNext --moduleResolution NodeNext --target ES2022 --types node \
|
|
--rootDir . --outDir dist $sources && node "$tsc" --module NodeNext --moduleResolution NodeNext \
|
|
--target ES2022 --types node --rootDir . --outDir . $sources)
|
|
fi
|
|
echo "testing $d (TypeScript)"
|
|
if ! (cd "$copy" && node --test --test-reporter=spec --experimental-strip-types \
|
|
--no-warnings=ExperimentalWarning test/*.test.ts); then
|
|
failed="$failed $m"
|
|
fi
|
|
done
|
|
if [ -n "$failed" ]; then
|
|
echo "TypeScript modules that failed:$failed"
|
|
exit 1
|
|
fi
|