fix(ci): run the lockfile-pinned Skills CLI in package verification (#6235)

* fix(ci): run the lockfile-pinned Skills CLI in package verification

The repository skill stage fetched skills@1.7.2 and its unlocked
dependencies from the npm registry on every run, taking 5-120 s and
intermittently exceeding the 120 s stage timeout on main and PRs.
Pin skills as a devDependency and run its locked bin directly.

Fixes #6234

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>

* fix(ci): lock the Skills CLI outside the root dependency tree

skills 1.6+ requires Node >=22.20.0, so pinning it as a root
devDependency made `npm ci` fail under engine-strict on the supported
Node 22.19.x. Keep the root install unchanged and give the verifier its
own package.json and lockfile, installed with `npm ci --prefer-offline`
in the verification workspace. The lockfile still removes all registry
metadata resolution and pins every transitive dependency.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>

---------

Co-authored-by: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
Kaoru0822
2026-10-21 21:19:45 -07:00
committed by GitHub
parent 3637205622
commit 89268f4a45
3 changed files with 147 additions and 8 deletions
+27 -8
View File
@@ -3,6 +3,26 @@ import { dirname, join, relative } from "node:path";
import { exec, execNpm, pathExists } from "./lib/verify-package-core.mjs";
/** Install the separately locked Skills CLI so verification resolves no registry metadata. */
const lockedSkillsCli = async (root, workspace) => {
const tool = join(workspace, "skills-cli");
await mkdir(tool, { recursive: true });
for (const file of ["package.json", "package-lock.json"])
await cp(join(root, "scripts/verify-tools/skills", file), join(tool, file));
await execNpm(
["ci", "--prefer-offline", "--ignore-scripts", "--no-audit", "--no-fund"],
{ cwd: tool, timeout: 120_000 },
);
const installed = join(tool, "node_modules/skills");
const manifest = JSON.parse(
await readFile(join(installed, "package.json"), "utf8"),
);
return {
version: manifest.version,
entry: join(installed, manifest.bin.skills),
};
};
/** Exercise Skills' default root discovery without ignored build outputs. */
export async function verifyRepositorySkill({ root, workspace }) {
const snapshot = join(workspace, "repository");
@@ -33,15 +53,14 @@ export async function verifyRepositorySkill({ root, workspace }) {
throw new Error("repository skill check must run without generated skills");
await mkdir(consumer, { recursive: true });
await mkdir(home, { recursive: true });
const skillsVersion = "1.7.2";
await execNpm(
const { version: skillsVersion, entry } = await lockedSkillsCli(
root,
workspace,
);
await exec(
process.execPath,
[
"exec",
"--yes",
"--package",
`skills@${skillsVersion}`,
"--",
"skills",
entry,
"add",
snapshot,
"--skill",
+112
View File
@@ -0,0 +1,112 @@
{
"name": "rea-verify-skills-cli",
"lockfileVersion": 3,
"requires": true,
"packages": {
"": {
"name": "rea-verify-skills-cli",
"dependencies": {
"skills": "1.7.2"
}
},
"node_modules/@isaacs/fs-minipass": {
"version": "4.0.1",
"resolved": "https://registry.npmjs.org/@isaacs/fs-minipass/-/fs-minipass-4.0.1.tgz",
"integrity": "sha512-wgm9Ehl2jpeqP3zw/7mo3kRHFp5MEDhqAdwy1fTGkHAwnkGOVsgpvQhL8B5n1qlb01jV3n/bI0ZfZp5lWA1k4w==",
"license": "ISC",
"dependencies": {
"minipass": "^7.0.4"
},
"engines": {
"node": ">=18.0.0"
}
},
"node_modules/chownr": {
"version": "3.0.0",
"resolved": "https://registry.npmjs.org/chownr/-/chownr-3.0.0.tgz",
"integrity": "sha512-+IxzY9BZOQd/XuYPRmrvEVjF/nqj5kgT4kEq7VofrDoM1MxoRjEWkrCC3EtLi59TVawxTAn+orJwFQcrqEN1+g==",
"license": "BlueOak-1.0.0",
"engines": {
"node": ">=18"
}
},
"node_modules/minipass": {
"version": "7.1.3",
"resolved": "https://registry.npmjs.org/minipass/-/minipass-7.1.3.tgz",
"integrity": "sha512-tEBHqDnIoM/1rXME1zgka9g6Q2lcoCkxHLuc7ODJ5BxbP5d4c2Z5cGgtXAku59200Cx7diuHTOYfSBD8n6mm8A==",
"license": "BlueOak-1.0.0",
"engines": {
"node": ">=16 || 14 >=14.17"
}
},
"node_modules/minizlib": {
"version": "3.1.0",
"resolved": "https://registry.npmjs.org/minizlib/-/minizlib-3.1.0.tgz",
"integrity": "sha512-KZxYo1BUkWD2TVFLr0MQoM8vUUigWD3LlD83a/75BqC+4qE0Hb1Vo5v1FgcfaNXvfXzr+5EhQ6ing/CaBijTlw==",
"license": "MIT",
"dependencies": {
"minipass": "^7.1.2"
},
"engines": {
"node": ">= 18"
}
},
"node_modules/skills": {
"version": "1.7.2",
"resolved": "https://registry.npmjs.org/skills/-/skills-1.7.2.tgz",
"integrity": "sha512-j+GzyF/oNahsjjjup6y3lJpFkC1lQjIkf4kAMXICA1hboBqi0fAGXAGoE4x9FRZiP1br/YE9+L3/Tqq6PIAe0A==",
"license": "MIT",
"dependencies": {
"tar": "^7.5.20",
"yaml": "^2.8.3"
},
"bin": {
"add-skill": "bin/cli.mjs",
"skills": "bin/cli.mjs"
},
"engines": {
"node": ">=22.20.0"
}
},
"node_modules/tar": {
"version": "7.5.22",
"resolved": "https://registry.npmjs.org/tar/-/tar-7.5.22.tgz",
"integrity": "sha512-MFO/QzvtAOmJbkhOaCTvbGcFN9L9b+JunIsDwaKljSOdcLMea3NJ1k9Usz/rjdfSXTq4dfzfeS7W4p4YOAAHeA==",
"license": "BlueOak-1.0.0",
"dependencies": {
"@isaacs/fs-minipass": "^4.0.0",
"chownr": "^3.0.0",
"minipass": "^7.1.2",
"minizlib": "^3.1.0",
"yallist": "^5.0.0"
},
"engines": {
"node": ">=18"
}
},
"node_modules/yallist": {
"version": "5.0.0",
"resolved": "https://registry.npmjs.org/yallist/-/yallist-5.0.0.tgz",
"integrity": "sha512-YgvUTfwqyc7UXVMrB+SImsVYSmTS8X/tSrtdNZMImM+n7+QTriRXyXim0mBrTXNeqzVF0KWGgHPeiyViFFrNDw==",
"license": "BlueOak-1.0.0",
"engines": {
"node": ">=18"
}
},
"node_modules/yaml": {
"version": "2.9.1",
"resolved": "https://registry.npmjs.org/yaml/-/yaml-2.9.1.tgz",
"integrity": "sha512-3NxN8+78OdzbT7C/WjGsyfPAtJaN3FNDsWxv7Y7mcDsT/oOmgW8BpyQQFFBnvZE3j9Y2Sdz1ULFLezL7Eb2yFw==",
"license": "ISC",
"bin": {
"yaml": "bin.mjs"
},
"engines": {
"node": ">= 14.6"
},
"funding": {
"url": "https://github.com/sponsors/eemeli"
}
}
}
}
+8
View File
@@ -0,0 +1,8 @@
{
"name": "rea-verify-skills-cli",
"private": true,
"description": "Lockfile-pinned Skills CLI for the repository skill check in verify:package.",
"dependencies": {
"skills": "1.7.2"
}
}