ci(release): stop on a stale dialect, check it like CI would, give prereleases their own

A stable release without a dialect of its own now ships the one on main only while that one has 90 days left; dialect 0 or less stops the run before anything is committed, unless allow_stale_dialect is ticked. Fetching and checking moved into registration-dialect.yml, which never fails its caller and also type-checks the module under the strict config and lints it with --max-warnings 0, since the bump commit skips CI. The bump and everything after it run whatever became of the dialect job. Prereleases ask the issuer for a dialect of their -pre.N version and build it into the image without committing it. The release check reads the module token by token against an allowlist of keywords, globals and member names, refuses any assignment to a property, computed access and regular expressions, and names Object, JSON and defineProperty among the forbidden. The issuer's kitchen-sink sample is gone; the tests use a hand-written dialect instead.
This commit is contained in:
Maurice
2026-10-29 17:59:52 +01:00
parent cd5ce4b1d9
commit 12e22c258a
12 changed files with 732 additions and 439 deletions
+62 -24
View File
@@ -6,9 +6,12 @@ name: Build & Push Docker Image (Prerelease)
# release it refuses a commit whose ci-ok is not green. docker.yml with
# bump=auto later finalizes the line once main carries it.
#
# A prerelease gets no registration dialect of its own; it carries the one of
# the last stable release, which dev gets by merging main into dev after that
# release. The build warns when that dialect is the original one or old.
# A prerelease asks the TREK services issuer for a registration dialect of its
# own -pre.N version (registration-dialect.yml, as the stable release does)
# and builds it into the image; nothing of it is committed, dev keeps the
# module of the last stable release, which it gets when main is merged back
# into dev. Without one the image carries dev's module, with a warning when
# that is the original one or old.
on:
workflow_dispatch:
@@ -93,31 +96,23 @@ jobs:
echo "VERSION=$NEW_VERSION" >> "$GITHUB_OUTPUT"
echo "$STABLE to $NEW_VERSION"
# A prerelease registers new installations in the dialect of the last
# stable release, which reaches dev when main is merged into dev after
# the release. The issuer takes a dialect for 180 days, so this warns
# (without stopping the build) while dev still speaks the original
# registration or a dialect older than 150 days.
- name: Check the registration dialect's age
run: |
set -eu
file=server/src/nest/service-identity/registration-dialect.ts
id="$(sed -n "s/^const DIALECT = '\(.*\)';$/\1/p" "$file")"
created="$(sed -n "s/^ createdAt: '\(.*\)',$/\1/p" "$file")"
if [ "$id" = 0 ]; then
message="This build registers in the original dialect, which the issuer accepts only for a transition period. Merge main into dev once a stable release carries a dialect of its own."
else
age=$(( ($(date -u +%s) - $(date -u -d "$created" +%s)) / 86400 ))
[ "$age" -gt 150 ] || { echo "This build registers in dialect $id from $created ($age days old)."; exit 0; }
message="This build registers in dialect $id from $created, $age days old; new installations of it stop registering on $(date -u -d "$created + 180 days" +%Y-%m-%d). Merge main into dev after the next stable release."
fi
echo "::warning::$message"
printf '### Registration dialect\n%s\n' "$message" >> "$GITHUB_STEP_SUMMARY"
# The registration dialect of this prerelease, fetched and checked in a job
# without write access. It never fails the build.
dialect:
needs: version-bump
uses: ./.github/workflows/registration-dialect.yml
with:
version: ${{ needs.version-bump.outputs.version }}
ref: ${{ needs.version-bump.outputs.sha }}
secrets:
TREK_DIALECT_TOKEN: ${{ secrets.TREK_DIALECT_TOKEN }}
build:
runs-on: ${{ matrix.runner }}
timeout-minutes: 120
needs: version-bump
needs: [version-bump, dialect]
# Whatever became of the dialect job: without its artifact the image carries dev's module.
if: ${{ !cancelled() && needs.version-bump.result == 'success' }}
strategy:
fail-fast: false
matrix:
@@ -136,6 +131,48 @@ jobs:
with:
ref: ${{ needs.version-bump.outputs.sha }}
- name: Take over the prerelease's dialect
id: take
uses: actions/download-artifact@v7
continue-on-error: true
with:
name: registration-dialect
path: ${{ runner.temp }}/dialect
# Into the build context only; the commit stays as it is. Without a
# dialect of its own the image speaks dev's module, which the issuer
# takes for new installations for 180 days after it was made (longer
# while it is the newest stable release's). That is warned about, never
# stopped on, and a date that cannot be read only warns as well.
- name: Place the dialect
env:
VERSION: ${{ needs.version-bump.outputs.version }}
TAKEN: ${{ steps.take.outcome }}
REPORT: ${{ matrix.platform == 'linux/amd64' }}
run: |
set -u
target=server/src/nest/service-identity/registration-dialect.ts
fetched="$RUNNER_TEMP/dialect/registration-dialect.ts"
if [ "$TAKEN" = success ] && [ -f "$fetched" ]; then
cp "$fetched" "$target"
echo "$VERSION registers in dialect $(sed -n "s/^const DIALECT = '\(.*\)';$/\1/p" "$target") of its own."
exit 0
fi
[ "$REPORT" = true ] || exit 0
id="$(sed -n "s/^const DIALECT = '\(.*\)';$/\1/p" "$target")"
created="$(sed -n "s/^ createdAt: '\(.*\)',$/\1/p" "$target")"
if [ "$id" = 0 ]; then
message="$VERSION got no dialect of its own and registers in the original one, which the issuer accepts only for a transition period."
elif made="$(date -u -d "$created" +%s 2>/dev/null)"; then
age=$(( ($(date -u +%s) - made) / 86400 ))
message="$VERSION got no dialect of its own and registers in dev's dialect $id from $created, $age days old."
[ "$age" -gt 150 ] || { echo "$message"; exit 0; }
else
message="$VERSION got no dialect of its own, and the date of dev's dialect cannot be read from $target."
fi
echo "::warning::$message"
printf '### Registration dialect\n%s\n' "$message" >> "$GITHUB_STEP_SUMMARY"
- uses: docker/setup-buildx-action@f87e5991a6d7451dcb8d9637bfbc97413f497069 # v4.4.1
- uses: docker/login-action@dbcb813823bdd20940b903addbd779551569679f # v4.6.0
@@ -181,6 +218,7 @@ jobs:
runs-on: ubuntu-24.04
timeout-minutes: 120
needs: [version-bump, build]
if: ${{ !cancelled() && needs.build.result == 'success' }}
steps:
- uses: actions/checkout@v6
with: