Repository navigation
fix(deps): bump the @sasjs packages, and pin the npm the release publishes with - #1483
Conversation
Coverage reportTotal coverage
Show files with reduced coverage 🔻Reduced coverage
Report generated by 🧪jest coverage report action from 632a23b |
@sasjs/adapter 4.19.2 -> 4.19.4
@sasjs/lint 4.1.2 -> 4.1.3
@sasjs/sas-language 0.3.0 -> 0.3.2
dotenv 17.4.2 -> 18.0.7
adapter 4.19.4 carries the Socket alert cleanup: tough-cookie 5.1.2 drops
psl, punycode, url-parse, querystringify and requires-port from the prod
tree. lint 4.1.3 requires node >= 22 and syncs its own lockfile engines.
sas-language 0.3.2 is the audit-exemption change; nothing in the language
server itself moves.
dotenv 18.0.7 is the latest line - the dependabot PR this supersedes
proposed 18.0.5, and 18.0.7 is what the registry resolves now.
@asjs/cli and @sasjs/utils are deliberately held at 4.20.9 and 3.6.5.
The CLI pins @sasjs/utils exactly, so the extension's own utils pin has
to match the CLI's until the CLI releases a version carrying utils 3.7.x:
two copies whose Target classes are nominally distinct fail to compile
with TS2345 at every cli call site that takes a Target. cli 4.20.9 ships
utils 3.6.5, so both pins move together once the CLI publish is
unblocked (sasjs/cli#1483).
Verification: tsc clean (0 errors), prettier clean, jest 4 suites / 16
tests pass, npm audit --omit=dev --audit-level=low reports 0
vulnerabilities.
There was a problem hiding this comment.
Reviewed the full diff at b13d8bc (one file: the publish workflow's npm-upgrade step) plus repo posture - .npmrc, audit steps, lockfile, gitleaks pre-commit hook, release config. The step's premise checks out against the npm trusted-publishing docs (npm CLI >= 11.5.1, Node >= 22.14; setup-node's node-version 22 resolves above that minimum, but its bundled npm is 10.x, so the upgrade step is genuinely needed).
- .github/workflows/npmpublish.yml:39 -
run: npm install -g npm@latestinstalls an unpinned, mutable version into the publish path. Whatever npm's latest release is on the day becomes the toolchain that publishes the package, which makes releases unrepeatable and lets a future npm major land in the release job unreviewed - the same exposure the locked release/ tree exists to avoid (its package.json documents installing a locked tree so versions and integrity hashes are pinned rather than fetched fresh). Pin an exact version (e.g. npm install -g npm@11.5.1 or the current 11.x) and bump it deliberately, so the minimum the comment states is also the maximum that ships.
1 finding above for review.
|
Addressed in 3823e11 - the step now reads I pinned the version Verified locally: the pinned version installs cleanly into a throwaway prefix and reports One thing worth deciding separately, since it is the same shape in four other repos: |
The parse fix removes the break; this removes the way it reached a release run instead of a pull request. `build-unit-tests.yml` parsed the pack report with whatever npm the runner ships (10.x on node 22, 11.x on node 24) while `npmpublish.yml` installs npm 12 before packing, so the two never agreed and only the release job could see the difference. Both now install the same pinned npm, at the same point in the job. Demonstrated with the previous parser, on the post-publishInit tree: old parser, npm 11.17.0 (what PR CI ran) -> 232 files, exit 0 old parser, npm 12.2.0 (what the release job runs) -> 0 files, exit 1 so with this step in place the pull request that introduced the array-only parse would have failed rather than the release. `npmpublish.yml` also moves off `npm@latest` to the same pin, so a new npm major cannot land in the release path without a commit - the reason sasjs/cli#1483 pins it too. 12.2.0 is what `@latest` resolved to when this was written, so neither workflow changes the toolchain it actually runs today. The steps that now run under npm 12 in PR CI were checked locally under both versions: `npm audit --omit=dev --audit-level=low` exits 0 and `node release/audit.mjs` exits 0 under 11.17.0 and 12.2.0. The failed release run is the other half of the evidence - its `npm ci`, build, publishInit, bundle-check, audit and release-tooling install all passed under npm 12, and only the pack-check failed. Both matrix legs satisfy npm 12's engine floor: setup-node's `22` resolves to 22.23.3 (needs ^22.22.2) and `24` to 24.22.0 (needs ^24.15.0).
* fix(release): read the pack report in the shape npm 12 reports it The 5.x release failed at "Check what the package would carry" ([run 38885452268](https://github.com/sasjs/adapter/actions/runs/38885452268)) with `packed files: 0`, naming DISCLOSURE as missing. The allowlist was fine; the parser was not. npm 12 changed the shape of `npm pack --json` from an array of results to an object keyed by package name, so `report[0]?.files ?? []` yielded an empty list and every entry was reported missing. Reproduced against both: ``` npm 11.17.0 -> [{"name":"@sasjs/adapter","files":[232 entries]}] npm 12.2.0 -> {"@sasjs/adapter":{"name":"@sasjs/adapter","files":[232 entries]}} ``` Why PR CI stayed green: build-unit-tests.yml runs the runner's npm (10/11), while npmpublish.yml installs `npm@latest` (12) before packing - so the shape the publish job parses is never the shape the pull request checked. The publish job is the first place it appears. The parser now reads either shape, and returns null when no entry carries a file list, so an unrecognised shape fails as a parse error rather than silently checking nothing and blaming the allowlist. Verified on the post-publishInit tree: 232 files and exit 0 under npm 11.17.0 and under npm 12.2.0; the mutation still bites under npm 12 (dropping DISCLOSURE from the allowlist packs 231 and exits 1 naming it); and a report with no file list exits 1 with "could not read the file list from the pack report". * ci(release): run the pack-check under the npm the release job uses The parse fix removes the break; this removes the way it reached a release run instead of a pull request. `build-unit-tests.yml` parsed the pack report with whatever npm the runner ships (10.x on node 22, 11.x on node 24) while `npmpublish.yml` installs npm 12 before packing, so the two never agreed and only the release job could see the difference. Both now install the same pinned npm, at the same point in the job. Demonstrated with the previous parser, on the post-publishInit tree: old parser, npm 11.17.0 (what PR CI ran) -> 232 files, exit 0 old parser, npm 12.2.0 (what the release job runs) -> 0 files, exit 1 so with this step in place the pull request that introduced the array-only parse would have failed rather than the release. `npmpublish.yml` also moves off `npm@latest` to the same pin, so a new npm major cannot land in the release path without a commit - the reason sasjs/cli#1483 pins it too. 12.2.0 is what `@latest` resolved to when this was written, so neither workflow changes the toolchain it actually runs today. The steps that now run under npm 12 in PR CI were checked locally under both versions: `npm audit --omit=dev --audit-level=low` exits 0 and `node release/audit.mjs` exits 0 under 11.17.0 and 12.2.0. The failed release run is the other half of the evidence - its `npm ci`, build, publishInit, bundle-check, audit and release-tooling install all passed under npm 12, and only the pack-check failed. Both matrix legs satisfy npm 12's engine floor: setup-node's `22` resolves to 22.23.3 (needs ^22.22.2) and `24` to 24.22.0 (needs ^24.15.0). --------- Co-authored-by: sasjs-dev[bot] <sasjs-dev[bot]@users.noreply.github.com>
# [5.1.0](v5.0.4...v5.1.0) (2026-10-16) ### Bug Fixes * **release:** read the pack report in the shape npm 12 reports it ([#933](#933)) ([6ff349c](6ff349c)), closes [sasjs/cli#1483](sasjs/cli#1483) ### Features * **package:** ship the adapter as compiled modules, with the browser build in dist ([#932](#932)) ([187f50e](187f50e)), closes [sasjs/utils#281](sasjs/utils#281) [sasjs/utils#275](sasjs/utils#275) [sasjs/utils#283](sasjs/utils#283) [sasjs/utils#275](sasjs/utils#275)
There was a problem hiding this comment.
Reviewed the full diff at 3823e11 (both commits): the pinned npm step added to the release workflow, superseding the review at b13d8bc. The prior finding - unpinned npm@latest in the publish path - is addressed by the 12.2.0 pin. The load-bearing claims check out: npm 12.2.0's engines floor is exactly ^22.22.2 || ^24.15.0 || >=26.0.0 and setup-node's 22 resolves to 22.23.3; npm publish --provenance --access public is unchanged in npm 12; and the pin is what @latest currently is (12.2.0), so the toolchain the release runs is byte-for-byte what the failed v5.0.0 run would have used had it installed correctly. CI at the head is green.
Because the release job runs npm ci, release/audit.mjs, and the publish under npm 12 for the first time only after merge, they were exercised locally on the head checkout: root npm audit --omit=dev --audit-level=low exits 0, the release-toolchain audit reports exactly the 13 advisories exempted in release/audit.mjs (no new ones, no stale exemptions), npm ci and npm ci --prefix release --ignore-scripts both install clean, the build completes, and the packed tree is identical under npm 10 and npm 12 (598 files, same byte size). Nothing in the release path regresses under the pinned version.
- .github/workflows/run-tests.yml - the PR-side divergence that bit sasjs/adapter (PR #933) exists here too, and this PR widens rather than narrows it: the release job now pins npm 12.2.0 while PR CI still runs node 22's bundled npm 10.x, so the artifact a pull request validates (Test Package Install, .github/workflows/run-tests.yml:63) is packed and installed with a different npm than the one that publishes it. Today the packed lists are identical (verified locally), so this is latent, not live - but if npm 12.x later changes packing the way it changed
pack --json, the break appears in a release run, not a PR. Mirroring the Update npm step into run-tests.yml (and run-tests-windows.yml:26) would close it; the adapter repo chose exactly that after its release failure.
1 finding above for review.
The v5.0.0 release failed at the publish step: `npm publish --provenance --access public` answered E404, "'@sasjs/cli@5.0.0' is not in this registry". Node 22 ships npm 10.x, and OIDC trusted publishing - the only credential the workflow has; setup-node writes a placeholder NODE_AUTH_TOKEN - needs npm >= 11.5.1. sasjs/adapter runs `npm install -g npm@latest` before semantic-release for exactly this reason, and its publish steps succeed. Mirror that step here. This is the release blocker: until it lands, no CLI release can publish, and every downstream pin of @sasjs/utils stays stranded at the nested 3.6.5 copy. Verification: the failing run (38581630499) and the last success (37217927917) show the same placeholder token; the difference is the npm version the publish runs under. adapter's npmpublish.yml carries the step, cli's did not.
`npm install -g npm@latest` put a mutable toolchain in the publish path: a new npm major would land in the release job with no commit here to review it, which is the exposure the locked release/ tree exists to avoid. The step's premise is unchanged - node 22 ships npm 10.x and OIDC trusted publishing needs >= 11.5.1 - so the fix is to name the version. Pinned to 12.2.0 rather than a minimum, because it is what `latest` resolved to when this was written, so the release path is byte-for-byte what it already did; it is also the version sasjs/lint published 4.1.4 with at 09:29 today through this same step, which is the evidence that it works on the node 22 matrix. Verified locally: the pinned version installs and reports 12.2.0 (>= 11.5.1), and its `npm publish` carries the --provenance/--access surface the trusted publisher uses. npm 12 requires node ^22.22.2 || ^24.15.0 || >=26.0.0; setup-node's `22` currently resolves to 22.23.3, which satisfies it. That floor is named in the workflow comment so a bump re-checks it.
| package | from | to | |---|---|---| | @sasjs/adapter | 4.19.4 | 5.1.0 | | @sasjs/utils | 3.7.2 | 4.0.0 | | @sasjs/lint | 4.1.3 | 4.1.4 | | @sasjs/core | 5.3.2 | 5.4.0 | adapter 5.1.0 is the first 5.x to reach the registry - the five before it were removed by npm's publish scanner - and it changes the package shape: the root is compiled modules rather than a UMD bundle, the browser build moves to dist/ behind the `browser` field, and `@sasjs/adapter/node` is a re-export of the same tree rather than a second bundle. Verified in this repo before bumping: the CLI builds and its mocked suite is unchanged against a packed 5.x. utils has to move with it. adapter 5.1.0 pins utils 4.0.0 exactly, so leaving the CLI on 3.7.2 nests a second copy of utils under the adapter - two copies of the classes and enums that cross the CLI/adapter boundary. utils 4.0.0 is the release whose barrel stops re-exporting ./fs, which is what #1484 prepared the fs command for; with both in place the tree carries one copy of utils. lint 4.1.4 and core 5.4.0 are the current releases of the other two packages this repo pins. Verified: npm install, `npm run build` (tsc) exit 0, the mocked suite is identical to the 4.19.4 baseline (87 suites / 671 tests, 650 passed, and the same two environment failures - doxygen is not installed here), `npm audit --omit=dev --audit-level=low` exit 0, `node release/audit.mjs` exit 0, prettier clean. The lockfile drops 177 lines, which is the nested utils and the packages utils 4.0.0 no longer carries.
3823e11 to
03cfedb
Compare
… with The release job pins npm 12.2.0 while the PR workflows ran node 22's bundled npm 10.x, so the artifact a pull request validates was packed and installed with a different npm than the one that publishes it. That divergence is exactly what turned the sasjs/adapter pack-report change into a release failure instead of a pull request failure, and pinning the release job here widened it rather than closing it. Both PR workflows now install the same pinned npm, at the same point in the job as npmpublish.yml does, so `Test Package Install` packs with the npm the release publishes with. Verified locally under both versions: - `npm pack` after a build produces the identical 598-file list under npm 11.17.0 and npm 12.2.0, so the step changes nothing about the artifact today - it is latent coverage, not a behaviour change. - `npm ci` under npm 12.2.0 exits 0 (677 packages) against the committed lockfile, so the pin does not disturb the install. - `npm audit --omit=dev --audit-level=low` and `node release/audit.mjs` both exit 0 under npm 12.2.0. All three workflows now carry the same `npm install -g npm@12.2.0`; bump them together.
|
Both addressed at The PR/release divergence - closed, not just noted. You are right that pinning the release job widened it. Verified under both versions rather than argued:
The dependency bump is in the same PR (your "bump everything that needs to be bumped"): Verified for the bump: The branch is rebased onto |
5.5.0 landed after the bump in the previous commit, so the pin in this PR was already a version behind. Nothing else moves: the other @sasjs packages are still at their current releases. Verified: npm install exit 0, `npm run build` (tsc) exit 0, mocked suite identical to the baseline (87 suites / 671 tests, 650 passed, same two `doxygen: not found` environment failures).
5.5.1 and 5.5.2 both landed after the previous commit pinned 5.5.0, so the pin was two patch releases behind within the hour. Nothing else moves - adapter, utils and lint are still at their current releases. The delta from 5.5.0 is three commits: a `sasjs lint` declaration fix (#463), the canonical `_sasjs_webout_headers` variable in the server macros (#464), and an `mp_getcols` refactor onto `mf_dttmfmts` (#462). No breaking changes. Verified: npm install exit 0, `npm run build` (tsc) exit 0, mocked suite identical to the baseline (87 suites / 671 tests, 650 passed, same two `doxygen: not found` environment failures).
There was a problem hiding this comment.
Reviewed the full diff at 632a23b: the two @sasjs/core bumps added since the last review (5.5.0, then 5.5.2), the npm 12.2.0 pin in all three workflows, the four @sasjs package bumps, plus repo posture - .npmrc ignore-scripts/save-exact, strict audit steps, npm ci, lockfile sync, gitleaks pre-commit hook, conventional-commit subjects, CI green at the head (run-tests.yml and run-tests-windows.yml, both node 22).
The prior finding (PR-side npm divergence) is addressed: the Update npm step is mirrored into run-tests.yml and run-tests-windows.yml, so Test Package Install now packs and installs the tarball under the same npm the release publishes with.
The major bumps check out against the published tarballs: adapter 5.1.0's node entry re-exports the root surface and every name the CLI imports from @sasjs/adapter/node is exported; utils 4.0.0's breaking change drops only export * from './fs' (the crypto/hash helpers), and every name the CLI imports from the barrel still resolves; @sasjs/lint/utils/getLintConfig with DefaultLintConfiguration exists in 4.1.4; the CLI's engine floor (node >=22) matches adapter 5.1.0's. All four pins are exact and the lockfile deduplicates the nested @sasjs/utils copy. depcheck triage at the head: no confirmed-unused packages, no ghost imports.
No blocking issues.
…sed dependencies (#447) * fix(package): stop installing the release tooling semantic-release and semantic-release-vsce were devDependencies. That tree is where most of this repo's advisories came from - micromatch -> braces, and the npm package @semantic-release/npm bundles - and none of them has a patched release. Run it the way sasjs/cli does instead: npx fetches the pinned pair for the release run only, so none of it enters the lockfile. The tree drops from 1361 lock entries to 920, the advisory count from 17 to 6, and the dead `semantic-release` script goes with it. Verification: - npm ci, then npm run lint: 0 errors - npm run test:unit: 4 suites, 16 tests pass - npm run vscode:prepublish: builds - npm audit --omit=dev --audit-level=low: 0 vulnerabilities (the CI gate) The 6 remaining advisories are not from the release tooling: they come from @vscode/vsce (globby -> fast-glob -> micromatch -> braces, and secretlint), which is a direct devDependency kept for the `package:lib` script. * fix(deps): drop the unused @vscode/vsce devDependency @vscode/vsce was the last source of advisories in this repo: globby -> fast-glob -> micromatch -> braces, plus secretlint. It was kept for the `package:lib` script, which is defined and referenced nowhere in the repo - and semantic-release-vsce already packages the .vsix at release time (packageVsix: true), so nothing needs it. The full audit, dev included, now reports 0 vulnerabilities. Verification: - package-lock.json: 920 -> 713 entries; @vscode/vsce, braces, micromatch, fast-glob and secretlint all gone from the tree - npm audit --audit-level=low: 0 vulnerabilities - npm ci: 643 packages - npm run lint: 0 errors - npm run test:unit: 4 suites, 16 tests pass - npm run vscode:prepublish: builds * fix(ci): install the release tooling from a locked tree The release toolchain now lives in `release/` with its own package.json and lockfile, installed by the publish workflow with `npm ci --prefix release`, rather than being resolved from npx at release time. Locked, so the resolved versions and their integrity hashes are pinned - the gap raised in review, where npx pinned only the top levels and fetched the transitive tree fresh. `.vscodeignore` excludes `release/**` so the toolchain's manifest and lockfile stay out of the packaged .vsix. Verification: every plugin in the release config resolves from release/node_modules. * chore(ci): audit the release toolchain in its own scope The toolchain in release/ carries twelve advisories that cannot be fixed from this repo - the ranges cover the newest published version - and that code runs with publish credentials. Moving it out of the package's dependencies kept it out of the package's `npm audit`, which is right; it also made it invisible, which is not. release/audit.mjs reports it separately and by name: the twelve are exempt with their reasons, anything else fails the build, and an exemption that stops appearing is reported so it can be deleted rather than left to rot. It uses --package-lock-only, so it needs no install and runs on every PR as well as in the release. Verification: node release/audit.mjs reports 12 exempt and exits 0. * chore(ci): format the release audit script for the prettier gate sas-language runs `prettier --check .`, which covers release/ - it is the only one of the five repos that checks that directory - and it rejected the new script. Formatted with that config (printWidth 100). The file is kept byte-identical in all five repos, so the same content goes to the four that do not check it. Otherwise the copies drift and a later fix lands in some of them only. Verification: `prettier --check .` clean, `node release/audit.mjs` still reports 12 exempt and exits 0, in all five. * fix(ci): give the release checkout the full history The publish workflow's checkout is shallow (depth 1), and semantic-release needs the full history and tags to compute the version. It fetches --unshallow itself, which works on a public repo but is a wasted round-trip on every release and fails outright if the fetch is blocked. The sibling release workflows (adapter, utils, sas-language) all set fetch-depth: 0 for this reason. * fix(ci): name the postcss-selector-parser advisory in the toolchain audit The audit caught a new advisory, which is what it is for: GHSA-rj75-hqrm-r3gf, moderate, quadratic complexity in flat selector parsing. It cannot be fixed from here. The vulnerable copy is npm's own bundled dependency - release/node_modules/npm/node_modules/postcss-selector-parser - so no resolver change reaches it, and 11.21.0 is the last npm 11.x while @semantic-release/npm requires ^11. The eventual fix is that plugin moving to npm 12. It is also unreachable in this usage: the parser reads this repo's own release config, not the commits being matched. Named with that reasoning rather than silenced, so the audit still fails on anything new. 13 exempt, exit 0. * fix(ci): name the postcss-selector-parser advisory in the toolchain audit The audit caught a new advisory, which is what it is for: GHSA-rj75-hqrm-r3gf, moderate, quadratic complexity in flat selector parsing. It cannot be fixed from here. The vulnerable copy is npm's own bundled dependency - release/node_modules/npm/node_modules/postcss-selector-parser - so no resolver change reaches it, and 11.21.0 is the last npm 11.x while @semantic-release/npm requires ^11. The eventual fix is that plugin moving to npm 12. It is also unreachable in this usage: the parser reads this repo's own release config, not the commits being matched. Named with that reasoning rather than silenced, so the audit still fails on anything new. 13 exempt, exit 0. * chore(deps): drop the unreferenced @types/tough-cookie Surfaced by the depcheck pass and carried through the last two reviews. Verified by full-tree grep: no tough-cookie import anywhere in src or test, and it is not the types package for anything the extension uses. `tsc` compiles clean after removal. * fix(deps): bump the released sasjs packages and dotenv @sasjs/adapter 4.19.2 -> 4.19.4 @sasjs/lint 4.1.2 -> 4.1.3 @sasjs/sas-language 0.3.0 -> 0.3.2 dotenv 17.4.2 -> 18.0.7 adapter 4.19.4 carries the Socket alert cleanup: tough-cookie 5.1.2 drops psl, punycode, url-parse, querystringify and requires-port from the prod tree. lint 4.1.3 requires node >= 22 and syncs its own lockfile engines. sas-language 0.3.2 is the audit-exemption change; nothing in the language server itself moves. dotenv 18.0.7 is the latest line - the dependabot PR this supersedes proposed 18.0.5, and 18.0.7 is what the registry resolves now. @asjs/cli and @sasjs/utils are deliberately held at 4.20.9 and 3.6.5. The CLI pins @sasjs/utils exactly, so the extension's own utils pin has to match the CLI's until the CLI releases a version carrying utils 3.7.x: two copies whose Target classes are nominally distinct fail to compile with TS2345 at every cli call site that takes a Target. cli 4.20.9 ships utils 3.6.5, so both pins move together once the CLI publish is unblocked (sasjs/cli#1483). Verification: tsc clean (0 errors), prettier clean, jest 4 suites / 16 tests pass, npm audit --omit=dev --audit-level=low reports 0 vulnerabilities. * fix(ci): clear the handlebars advisories from the release toolchain Three advisories were published against handlebars 4.7.9, which is what the release toolchain resolves: GHSA-xw65-4hp5-5hc7 moderate injection via unsafe inline embedding GHSA-8r5x-fm3f-whwj critical injection via AST type confusion GHSA-p8wg-vrv2-v86f critical injection via own property check bypass 4.7.10 is the first patched version for all three, and it is what release/audit.mjs now resolves, so the gate goes back to exit 0 with its 13 documented exemptions. This runs in CI as well as at release time, and the tree is installed with publish credentials, so the advisories were a live failure rather than a note: the next run of this branch would have gone red on the audit step. Lockfile-only, in release/ - the toolchain is not shipped, so nothing in the published extension moves. Verification: node release/audit.mjs -> 13 exempt, exit 0; npm ci --prefix release --dry-run resolves handlebars 4.7.10. * fix(ci): install the release toolchain on PRs, and version its manifest The PR workflow audits the release toolchain but never installed it, so nothing exercised release/package-lock.json against release/package.json. release/audit.mjs runs with --package-lock-only and reads the lockfile alone, so a dependency added to release/package.json without a matching lockfile update still exits 0 from it, and the drift surfaces only at publish time on main - a failure mode this repo's PR checks cannot catch. The new step runs the same `npm ci --prefix release --ignore-scripts` as sasjs/adapter's PR workflow (build-unit-tests.yml). release/package.json carries the version field its own lockfile root already records, matching the shape of the root manifest. Both findings of the review at c622fe7. * fix(deps): bump the released sasjs packages to their current lines @sasjs/adapter 4.19.4 -> 5.1.0 @sasjs/cli 4.20.9 -> 5.0.2 @sasjs/lint 4.1.3 -> 4.1.4 @sasjs/utils 3.6.5 -> 4.0.0 cli 5.0.2 ships utils 4.0.0 and adapter 5.1.0 / lint 4.1.4 pin it too, so the extension's own utils pin moves with the CLI and the tree deduplicates: every nested @sasjs copy collapses into the single top-level one, and the lockfile loses 26 entries. Those include psl, querystringify, requires-port, url-parse and cli's nested tough-cookie 4.1.3, which the adapter 5 line drops from the prod tree, and six lodash micro-packages with cli-table and colors from the CLI's own dependencies. cli 5.x also raises engines.node to >=22 and drops the ./fs subpath from utils' barrel; the extension compiles against both unchanged (tsc 0 errors). No engines.node field is added here: the extension runs in the VS Code extension host, whose node version is set by VS Code (engines.vscode ^1.96.0), not by this manifest. Verification: tsc clean, eslint clean, jest 4 suites / 16 tests pass, npm audit --audit-level=low --omit=dev reports 0 vulnerabilities, release audit exit 0, npm ci --prefix release exit 0. * fix(ci): clear the npm-vendored advisories from the release toolchain The review at bf81e70 read the exemption list correctly: undici, ip-address, http-cache-semantics, brace-expansion and postcss-selector-parser sit inside the npm CLI that @semantic-release/npm installs, and that CLI is on the registry path, so those entries were risk acceptances dressed up as non-issues. They were also not unfixable - npm 11.21.1, published after the list was written, vendors fixed copies of all five, and @semantic-release/npm requires ^11.6.2, so a lockfile refresh picks it up. npm 11.21.0 -> 11.21.1 brace-expansion 5.0.9 -> 5.0.12 http-cache-semantics 4.2.0 -> 4.3.0 ip-address 10.5.0 -> 10.7.2 postcss-selector-parser 7.1.4 -> 7.1.6 undici 6.28.0 -> 6.29.0 That clears twelve of the thirteen exemptions. braces 3.0.3 is the one left - the latest release, so no bump reaches it - and it keeps its own reachability argument. EXEMPT is pruned to that entry, and the header stops claiming blanket unreachability: an entry whose input arrives from outside this repo is a risk acceptance, and the entry says so rather than calling it a non-issue. Two other claims in that header were wrong and go with it: the copies in the other four repos are not byte-identical (cli carries a stricter revision that fails on a stale exemption, and each repo formats with its own prettier config), so EXEMPT is described as per repo rather than as one shared list. Verified: node release/audit.mjs exits 0 with 1 exempt; restoring the 11.21.0 lockfile makes it exit 1 with the twelve back, so the pruned list still fails closed; npm ci --prefix release installs npm 11.21.1 cleanly; tsc, eslint, jest 4 suites / 16 tests, npm audit --omit=dev at 0 vulnerabilities, prettier and the prepublish build all pass. * fix(ci): fail the release-toolchain audit on a stale exemption The exemption list is a claim about the locked tree, and the review at bf81e70 found twelve entries on it that no lockfile refresh justified. A stale entry that is reported without failing is invisible in a passing build, which is how those twelve sat: the audit printed them and exited 0. The stale report moves to stderr and joins the exit condition, so an unexempted advisory is never masked by a stale-exemption report or the reverse. cli already carries this revision on main; adapter, sas-language and utils only warn. Verified both directions: the current tree exits 0 with one exempt advisory; a bogus exemption id makes it exit 1 and names it on stderr; and the 11.21.0 lockfile makes it exit 1 with the twelve unexempted advisories. --------- Co-authored-by: sasjs-dev[bot] <sasjs-dev[bot]@users.noreply.github.com>
Two things the CLI's release path needs: a publish step that can authenticate, and dependencies that are not a major behind.
1. The publish step
The v5.0.0 release failed at its publish step:
npm publish --provenance --access publicanswered E404, "'@sasjs/cli@5.0.0' is not in this registry" (run 38581630499). The workflow carries no npm credential -actions/setup-nodeexports a placeholderNODE_AUTH_TOKEN, so publishing relies entirely on OIDC trusted publishing. Node 22 ships npm 10.x, and trusted publishing needs npm >= 11.5.1.So the workflow installs a newer npm before the release steps, and that npm is pinned:
Pinned rather than
@latestbecause@latestputs a mutable toolchain in the publish path - a new npm major would land in the release job with no commit here to review it, which is the exposure the lockedrelease/tree exists to avoid. 12.2.0 is what@latestresolved to when this was written, so the release path is unchanged by the pin; it is also the version sasjs/lint published 4.1.4 with, through this same step, on the same node 22 matrix.Verified locally: the pinned version installs and reports
12.2.0(>= 11.5.1), and itsnpm publishcarries the--provenance/--accesssurface the trusted publisher uses. npm 12 declaresengines.nodeas^22.22.2 || ^24.15.0 || >=26.0.0, which setup-node's22(22.23.3 today) satisfies; the floor is named in the workflow comment so a bump re-checks it.2. The dependency bumps
adapter 5.1.0 is the first 5.x to reach the registry - the five before it were removed by npm's publish scanner - and it changes the package shape: the root is compiled modules rather than a UMD bundle, the browser build moves to
dist/behind thebrowserfield, and@sasjs/adapter/nodebecomes a re-export of the same tree rather than a second bundle. This repo was checked against a packed 5.x before bumping: the CLI builds and its mocked suite is unchanged.utils has to move with it. adapter 5.1.0 pins utils 4.0.0 exactly, so leaving the CLI on 3.7.2 nests a second copy of utils under the adapter - two copies of the classes and enums that cross the CLI/adapter boundary. utils 4.0.0 is the release whose barrel stops re-exporting
./fs, which is what #1484 prepared the fs command for; with both in place the tree carries one copy.lint 4.1.4 and core 5.5.2 are the current releases of the other two packages this repo pins. Core moved twice within the hour the bump was open (5.4.0 -> 5.5.0 -> 5.5.2), so it is pinned to the release that exists now. Nothing else in
dependenciesis behind -npm outdatedreports no@sasjs/*rows.3. The PR workflows now run the npm the release publishes with
The review at
3823e11caught that pinning the release job widened an existing divergence: the release job would use npm 12.2.0 whilerun-tests.ymlandrun-tests-windows.ymlstill ran node 22's bundled npm 10.x, so the artifact a pull request validates was packed with a different npm than the one that publishes it. That is precisely the shape that turned the sasjs/adapter pack-report change into a release failure rather than a pull-request failure.Both PR workflows now install the same pin, at the same point in the job, before
Test Package Installpacks the tarball.Verified under both versions:
npm packafter a build produces the identical 598-file list under npm 11.17.0 and npm 12.2.0 - so this closes the gap without changing what a pull request validates today.npm ciunder npm 12.2.0 exits 0 (677 packages) against the committed lockfile.npm audit --omit=dev --audit-level=lowandnode release/audit.mjsboth exit 0 under npm 12.2.0.All three workflows carry the same
npm install -g npm@12.2.0; they are meant to be bumped together.Verified
npm ciexit 0;npm run build(tsc) exit 0.generateDocs.spec.ts,version.spec.ts-doxygen: not foundin this environment, present before the bump).npm audit --omit=dev --audit-level=lowexit 0;node release/audit.mjsexit 0; prettier clean.package-lock.jsondrops 177 lines: the nested utils, and the packages utils 4.0.0 no longer carries.Release note
v5.0.0andv5.0.1exist as git tags but never reached the registry, so the first release after this merges will land as5.0.2(patch) with those two versions absent from npm. Nothing is installed from them today - the registry'slatestfor@sasjs/cliis 4.20.9 - so the gap is cosmetic, but it is worth knowing before reading the release list.Rebased
The branch now sits on
mainafter #1484 merged, so the diff is the two workflow commits plus the bump.