Skip to content

fix(deps): bump the @sasjs packages, and pin the npm the release publishes with - #1483

Merged
allanbowe merged 6 commits into
mainfrom
fix/oidc-publish
Oct 16, 2026
Merged

allanbowe merged 6 commits into
mainfrom
fix/oidc-publish

Conversation

@sasjs-dev

@sasjs-dev sasjs-dev Bot commented Oct 14, 2026 •

Copy link
Copy Markdown
Contributor

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 public answered E404, "'@sasjs/cli@5.0.0' is not in this registry" (run 38581630499). The workflow carries no npm credential - actions/setup-node exports a placeholder NODE_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:

      - name: Update npm
        run: npm install -g npm@12.2.0

Pinned rather than @latest because @latest puts 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. 12.2.0 is what @latest resolved 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 its npm publish carries the --provenance/--access surface the trusted publisher uses. npm 12 declares engines.node as ^22.22.2 || ^24.15.0 || >=26.0.0, which setup-node's 22 (22.23.3 today) satisfies; the floor is named in the workflow comment so a bump re-checks it.

2. The dependency bumps

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.5.2

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 becomes 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 dependencies is behind - npm outdated reports no @sasjs/* rows.

3. The PR workflows now run the npm the release publishes with

The review at 3823e11 caught that pinning the release job widened an existing divergence: the release job would use npm 12.2.0 while run-tests.yml and run-tests-windows.yml still 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 Install packs the tarball.

Verified 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 this closes the gap without changing what a pull request validates today.
  • npm ci under npm 12.2.0 exits 0 (677 packages) against the committed lockfile.
  • npm audit --omit=dev --audit-level=low and node release/audit.mjs both 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 ci exit 0; npm run build (tsc) exit 0.
  • Mocked suite identical to the 4.19.4 baseline: 87 suites / 671 tests, 650 passed, and the same two failures (generateDocs.spec.ts, version.spec.ts - doxygen: not found in this environment, present before the bump).
  • npm audit --omit=dev --audit-level=low exit 0; node release/audit.mjs exit 0; prettier clean.
  • package-lock.json drops 177 lines: the nested utils, and the packages utils 4.0.0 no longer carries.

Release note

v5.0.0 and v5.0.1 exist as git tags but never reached the registry, so the first release after this merges will land as 5.0.2 (patch) with those two versions absent from npm. Nothing is installed from them today - the registry's latest for @sasjs/cli is 4.20.9 - so the gap is cosmetic, but it is worth knowing before reading the release list.

Rebased

The branch now sits on main after #1484 merged, so the diff is the two workflow commits plus the bump.

@github-actions

github-actions Bot commented Oct 14, 2026 •

Copy link
Copy Markdown

Coverage report

Total coverage

Status Category Percentage Covered / Total
🟡 Statements 75.72% 3570/4715
🟡 Branches 63.43% 1464/2308
🟡 Functions 75.53% 716/948
🟢 Lines 84.28% 9089/10784

Status of coverage: 🟢 - ok, 🟡 - slightly more than threshold, 🔴 - under the threshold

Show files with reduced coverage 🔻

Reduced coverage

Status Filename Statements Branches Functions Lines
🟢 src/commands/compile/compileSingleFile.ts 95.83% (-2.08% 🔻) 84% (-4% 🔻) 100% 100%

Status of coverage: 🟢 - ok, 🟡 - slightly more than threshold, 🔴 - under the threshold

Report generated by 🧪jest coverage report action from 632a23b

sasjs-dev Bot added a commit to sasjs/vscode-extension that referenced this pull request Oct 14, 2026
    @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.

@sasjs-dev sasjs-dev Bot left a comment

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

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@latest installs 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.

@sasjs-dev

sasjs-dev Bot commented Oct 16, 2026

Copy link
Copy Markdown
Contributor Author

Addressed in 3823e11 - the step now reads npm install -g npm@12.2.0.

I pinned the version @latest resolves to today rather than the minimum the comment names, because that makes the change determinism-only: the release path keeps publishing with exactly the npm it already publishes with, and the version becomes something a commit controls. It is also not an untested choice - sasjs/lint published 4.1.4 at 09:29 today through this same step (npm install -g npm@latest at 09:29:48, publish at 09:30:41, run 38880823235) on the same node 22 matrix, and the registry confirms 4.1.4 is live. So the version now pinned is the one that has demonstrably done this job in this org.

Verified locally: the pinned version installs cleanly into a throwaway prefix and reports 12.2.0 (>= 11.5.1), and its npm publish carries the --provenance/--access surface the trusted publisher uses. One thing the pin introduces that @latest hid: npm 12 declares engines.node as ^22.22.2 || ^24.15.0 || >=26.0.0, so it depends on how far setup-node's 22 has advanced. It currently resolves to 22.23.3 and satisfies that, and I named the floor in the workflow comment so a bump re-checks it rather than discovering it as an EBADENGINE in the release job.

One thing worth deciding separately, since it is the same shape in four other repos: npm install -g npm@latest is also in sasjs/adapter/.github/workflows/npmpublish.yml:48, sasjs/core/.github/workflows/main.yml:30, sasjs/lint/.github/workflows/publish.yml:49 and sasjs/utils/.github/workflows/publish.yml:53. Your finding applies to all of them equally - I have kept this PR to the CLI, and can pin the same version across the estate in a follow-up if you want them consistent.

sasjs-dev Bot added a commit to sasjs/adapter that referenced this pull request Oct 16, 2026
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).
allanbowe pushed a commit to sasjs/adapter that referenced this pull request Oct 16, 2026
* 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>
sasjs-gha Bot pushed a commit to sasjs/adapter that referenced this pull request Oct 16, 2026
# [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)

@sasjs-dev sasjs-dev Bot left a comment

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

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.

sasjs-dev Bot added 3 commits October 16, 2026 11:34
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.
@sasjs-dev
sasjs-dev Bot force-pushed the fix/oidc-publish branch from 3823e11 to 03cfedb Compare October 16, 2026 11:38
@sasjs-dev sasjs-dev Bot changed the title fix(ci): publish through OIDC trusted publishing, not npm 10 fix(deps): bump the @sasjs packages, and pin the npm the release publishes with Oct 16, 2026
… 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.
@sasjs-dev

sasjs-dev Bot commented Oct 16, 2026

Copy link
Copy Markdown
Contributor Author

Both addressed at 50ab72f0, and the PR is now the whole CLI release-path change rather than the npm step alone.

The PR/release divergence - closed, not just noted. You are right that pinning the release job widened it. run-tests.yml and run-tests-windows.yml now install the same npm@12.2.0, at the same point in the job as npmpublish.yml does, so Test Package Install packs with the npm that publishes.

Verified under both versions rather than argued:

  • npm pack after a build produces the identical 598-file list under npm 11.17.0 and npm 12.2.0 - matching your measurement, and confirming this is latent coverage rather than 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 the PR workflows do.
  • npm audit --omit=dev --audit-level=low and node release/audit.mjs both exit 0 under npm 12.2.0.

The dependency bump is in the same PR (your "bump everything that needs to be bumped"): @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. utils has to move with the adapter - 5.1.0 pins utils 4.0.0 exactly, so leaving the CLI on 3.7.2 nests a second copy of the classes that cross the CLI/adapter boundary - and utils 4.0.0 is the release whose barrel stops re-exporting ./fs, which is what #1484 prepared. npm outdated now reports no @sasjs/* rows.

Verified for the bump: npm ci exit 0, npm run build exit 0, mocked suite identical to the 4.19.4 baseline (87 suites / 671 tests, 650 passed, the same two doxygen: not found failures), both audit gates exit 0, prettier clean.

The branch is rebased onto main after #1484 merged, so the diff is four commits: the OIDC npm step, the pin, the bumps, and this one.

sasjs-dev Bot added 2 commits October 16, 2026 12:23
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).

@sasjs-dev sasjs-dev Bot left a comment

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

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.

@allanbowe
allanbowe merged commit e1bf90b into main Oct 16, 2026
2 checks passed
@allanbowe
allanbowe deleted the fix/oidc-publish branch October 16, 2026 13:15
allanbowe pushed a commit to sasjs/vscode-extension that referenced this pull request Oct 18, 2026
…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>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant