From 18b9db23fc3b1cdeda8f8c7696e1aba0840c5279 Mon Sep 17 00:00:00 2001 From: Day Dreamer <87640074+HugoXK@users.noreply.github.com> Date: Wed, 11 Nov 2026 14:59:56 +0800 Subject: [PATCH] fix(release): pack @flybot/project in the tarballs and test the list (#2840) #2829 moved the Project domain out of core into plugins/project, but the package list in check-pack.mjs was not updated: the Docker image and the release tarballs were built from five packages, so neither carried @flybot/project while the docs and the plugin suite said it shipped. A test now compares that list with the plugin directories on disk, so the next plugin cannot drop out silently. Refs #2831, which keeps test.yml and nightly.yml (gate files, need a signature). --- .github/scripts/check-pack.mjs | 2 +- .github/scripts/check-pack.test.mjs | 42 ++++++++++++++++++++ changelog.d/2840-check-pack-project.fixed.md | 1 + 3 files changed, 44 insertions(+), 1 deletion(-) create mode 100644 .github/scripts/check-pack.test.mjs create mode 100644 changelog.d/2840-check-pack-project.fixed.md diff --git a/.github/scripts/check-pack.mjs b/.github/scripts/check-pack.mjs index e4b67706e..5b4b8e5fe 100644 --- a/.github/scripts/check-pack.mjs +++ b/.github/scripts/check-pack.mjs @@ -6,7 +6,7 @@ import { execFileSync } from 'node:child_process' import { mkdirSync, readFileSync } from 'node:fs' import { join, resolve } from 'node:path' -const packages = ['core', 'plugins/social', 'plugins/tree', 'plugins/timeline', 'plugins/workflow'] +const packages = ['core', 'plugins/social', 'plugins/tree', 'plugins/timeline', 'plugins/workflow', 'plugins/project'] const out = process.argv[2] ? resolve(process.argv[2]) : undefined if (out) mkdirSync(out, { recursive: true }) let failed = false diff --git a/.github/scripts/check-pack.test.mjs b/.github/scripts/check-pack.test.mjs new file mode 100644 index 000000000..387c80f4a --- /dev/null +++ b/.github/scripts/check-pack.test.mjs @@ -0,0 +1,42 @@ +// `check-pack.mjs` is the list a release and the Docker image are built from: it packs each +// directory named there and the tarballs it writes are what `release.yml` and the `Dockerfile` +// install. The list is hand-maintained and nothing compared it with the tree, so a plugin added to +// `plugins/` stayed out of every tarball while `npm run verify` (which runs the plugin's own +// tests) and the docs both said it shipped — `plugins/project` after #2829 was the case. +// +// The script is a top-level CLI, so the check here reads the one line that decides what ships and +// compares it with the plugin directories on disk: a plugin package that exists but is not packed +// is the defect, whichever plugin it is. +import { test } from 'node:test' +import assert from 'node:assert/strict' +import { existsSync, readFileSync, readdirSync } from 'node:fs' +import { join } from 'node:path' + +const repo = join(import.meta.dirname, '..', '..') + +function packedPackages() { + const source = readFileSync(join(repo, '.github', 'scripts', 'check-pack.mjs'), 'utf8') + const match = /const packages = \[([^\]]*)\]/.exec(source) + assert.ok(match, 'check-pack.mjs must declare what it packs in a `const packages = [...]` list') + return match[1].split(',').map((entry) => entry.trim().replace(/^['"]|['"]$/g, '')).filter(Boolean) +} + +function pluginPackages() { + return readdirSync(join(repo, 'plugins'), { withFileTypes: true }) + .filter((entry) => entry.isDirectory() && existsSync(join(repo, 'plugins', entry.name, 'package.json'))) + .map((entry) => `plugins/${entry.name}`) + .sort() +} + +test('check-pack packs every plugin package in plugins/, so no tarball ships without one', () => { + const packed = packedPackages() + const missing = pluginPackages().filter((dir) => !packed.includes(dir)) + assert.deepEqual(missing, [], `the release and the Docker image pack these plugin packages: ${missing.join(', ')} is not among them`) +}) + +test('check-pack names core and only directories that are packages', () => { + const packed = packedPackages() + assert.ok(packed.includes('core'), 'check-pack must pack core') + const notPackages = packed.filter((dir) => !existsSync(join(repo, dir, 'package.json'))) + assert.deepEqual(notPackages, [], `check-pack names directories that are not packages: ${notPackages.join(', ')}`) +}) diff --git a/changelog.d/2840-check-pack-project.fixed.md b/changelog.d/2840-check-pack-project.fixed.md new file mode 100644 index 000000000..748ed44bd --- /dev/null +++ b/changelog.d/2840-check-pack-project.fixed.md @@ -0,0 +1 @@ +`check-pack.mjs` now packs `@flybot/project`, so the Docker image and the release tarballs carry the plugin the tree already runs; a test compares the pack list with `plugins/*` so a new plugin cannot silently drop out of both again.