mesh/delivery superseded: a newer head of the same pull request
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): main's version judged it; the change's judges the pull requests after it merges; it…
The catalogue's check ran only Go. A TypeScript module's change, the forge's among them, ran nothing of its own before it merged, and a type error would first have shown in its walk. A second part, declared with mesh-check-also and run in the TypeScript toolchain, type-checks each touched TypeScript module with the compiler and flags a build uses, against the SDK and Node types the toolchain holds, and runs its tests as its own npm test does. A module that needs a package the toolchain lacks, or has no tests, is said by name, never passed. The media catalogue's twin is hq issue 311.
94 lines
4.5 KiB
Bash
94 lines
4.5 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 is said NOT CHECKED, by name;
|
|
# 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.
|
|
#
|
|
# 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, as merge-check.sh reads them (hq ADR 0238).
|
|
if [ -n "${MESH_CHECK_MODULES:-}" ]; then
|
|
touched=$(printf '%s\n' "$MESH_CHECK_MODULES" | tr ',' '\n' | sed -e 's#^modules/##' -e '/\//d' | sort -u)
|
|
else
|
|
touched=$(printf '%s\n' "${MESH_CHECK_CHANGED:-}" | tr ',' '\n' | sed -n 's#^modules/\([^/]*\)/.*#\1#p' | sort -u)
|
|
fi
|
|
|
|
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 "NOT CHECKED: $d depends on $missing, which the toolchain does not hold and the check cannot fetch"
|
|
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 [ -z "$sources" ]; then
|
|
continue
|
|
fi
|
|
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
|
|
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
|
|
# 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)
|
|
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
|