Skip to content

Install libkrb5-dev in the js-lib publish workflow#675

Merged
AlexGodbehere merged 1 commit into
mainfrom
ago/fix-js-lib-publish
Jul 17, 2026
Merged

Install libkrb5-dev in the js-lib publish workflow#675
AlexGodbehere merged 1 commit into
mainfrom
ago/fix-js-lib-publish

Conversation

@AlexGodbehere

Copy link
Copy Markdown
Contributor

What failed

The js/gssapi/v2.1.0 release (run 29016308920, 2026-07-09) failed in the
js-lib / publish job, so @amrc-factoryplus/gssapi was never published to
npm (npm view @amrc-factoryplus/gssapi returns E404 for all versions). That
404 broke the v6.0.0-rc.2 release: acs-admin's vite build cannot resolve the
@amrc-factoryplus/gssapi import in
@amrc-factoryplus/service-client/lib/deps.js (service-client depends on
@amrc-factoryplus/gssapi: ^2.1.0).

Root cause

js-lib.yaml runs npm install in the library directory before
npm publish. For lib/js-gssapi (a native addon), npm install runs the
package's install script, cmake-js compile. The CMake configure step
requires the MIT Kerberos development files:

  • CMakeLists.txt does find_path(KRB5_INCLUDE_DIR krb5.h ...) and
    find_library for krb5, com_err, and gssapi_krb5, with a
    FATAL_ERROR if the libraries are not found.
  • The sources include <krb5.h>, <gssapi/gssapi.h> and
    <gssapi/gssapi_krb5.h>.

On Ubuntu these are all provided by libkrb5-dev, which is not
preinstalled on GitHub's ubuntu-latest runner images (only the runtime
libkrb5-3 is present, which has neither the headers nor the unversioned
.so symlinks that find_library needs). So the configure step fails and
the publish never happens.

Ruled out: a broken tarball. dist/index.js and dist/index.d.ts are
committed to git (git ls-files lib/js-gssapi), and npm pack --dry-run
packs all 12 expected files (dist, CMakeLists.txt, src/*).

The fix

Add a step to js-lib.yaml that installs libkrb5-dev before npm install.
This is a no-op cost for pure-JS libraries, so the workflow stays generic for
all js/<lib>/vSEMVER releases.

How this was verified

  • npm install of a copy of lib/js-gssapi on a machine with Kerberos dev
    headers available compiles and links cleanly, confirming the code builds
    fine once the headers exist and the failure is environmental.
  • YAML syntax of the edited workflow validated.
  • The full publish path can only be truly exercised by a release tag (the
    workflow is workflow_call from release.yaml and needs NPM_TOKEN).

Follow-up after merge (not part of this PR)

Reusable workflows resolve at the tag ref, so the existing js/gssapi/v2.1.0
tag would still use the old workflow. After merging:

  1. Cut a new js/gssapi/v2.1.1 release from main to publish
    @amrc-factoryplus/gssapi to npm.
  2. Re-run the failed v6.0.0-rc.2 jobs once the package resolves.

🤖 Generated with Claude Code

The js-lib publish workflow runs npm install in the library directory
before npm publish. For lib/js-gssapi this runs the package's install
script, cmake-js compile, which needs the MIT Kerberos development
files (krb5.h, gssapi/gssapi.h, libkrb5, libgssapi_krb5, libcom_err).
GitHub's ubuntu-latest runners do not ship libkrb5-dev, so the CMake
configure step fails and the js/gssapi/v2.1.0 release never published
@amrc-factoryplus/gssapi to npm. That 404 then broke the v6.0.0-rc.2
release: acs-admin's vite build cannot resolve the import from
@amrc-factoryplus/service-client/lib/deps.js.

Install libkrb5-dev before npm install. This is a no-op for pure-JS
libraries, so the workflow stays generic.
@AlexGodbehere
AlexGodbehere merged commit cca1d63 into main Jul 17, 2026
1 check passed
@AlexGodbehere
AlexGodbehere deleted the ago/fix-js-lib-publish branch July 17, 2026 08:50
AlexGodbehere added a commit that referenced this pull request Jul 17, 2026
AlexGodbehere added a commit that referenced this pull request Jul 17, 2026
…kes effect (#676)

## What was broken

`v6.0.0-rc.2`'s release failed: the `acs-admin` image build errored with

```
[vite]: Rollup failed to resolve import "@amrc-factoryplus/gssapi" from
  /app/acs-admin/node_modules/@amrc-factoryplus/service-client/lib/deps.js
```

which fail-fast-cancelled the other 18 JS image builds and skipped the
chart release.

## Root cause

Two separate defects, both introduced by 42a88e0 ("Prefer
@amrc-factoryplus/gssapi over gssapi.js for GSS"):

1. **The browser build.** `acs-admin` is the only bundled build in the
tree, and `vite.config.js` aliases native GSS out of it (`'gssapi.js':
EMPTY`). 42a88e0 introduced a *second* bare specifier,
`@amrc-factoryplus/gssapi`, into `deps.js` — a module that gets bundled
— without adding it to that alias list. `v5.1.0` and `v6.0.0-rc.1` are
byte-identical here and built fine; rc.1 predates the vendoring by 3h40m
and its `acs-admin` job passed.

2. **The fork was never installed.** It was declared as a *registry*
dependency (`^2.1.0`) of a package that is not on npm. `bun
install`/`npm install` logged the 404 as a warning and skipped it (it is
optional), so `deps.js` fell through its `.catch()` to upstream
`gssapi.js` — **with** credential delegation. #674's delegation fix has
therefore been inert since it merged.

The npm 404 was never the cause of the build failure. In the same rc.2
run, `acs-edge` (npm, same `deps.js` via `file:`) built successfully.

## The fix

- `acs-admin/vite.config.js`: alias `@amrc-factoryplus/gssapi` to the
empty stub, next to the existing `gssapi.js` entry. This alone unblocks
the build — aliases intercept the specifier before node resolution, so
the package need not be installed. It is also correct on its own merits:
without it, an installed fork would drag the native addon loader
(`bindings`, `file-uri-to-path`) into the browser bundle.
- The 16 in-tree services that use GSS via `service-client` declare
`"@amrc-factoryplus/gssapi": "file:../lib/js-gssapi"` in
`optionalDependencies`, which is what actually installs the fork and
makes #674 live. A `file:` ref declared *by* a `file:`-linked package
does not install — npm resolves the nested path relative to the copied
location, hits ENOENT, and silently skips it. `optionalDependencies`
(not `dependencies`) matches how `gssapi.js` is declared and keeps `npm
install` working without krb5 headers.
- Excluded: `acs-admin` (browser; the alias handles it), `acs-edge`
(never imports `service-client`), `acs-example-service` (not built).
- Reverts #675. Its premise was wrong: `js/gssapi/v2.1.0` did not fail
on missing Kerberos headers, it failed in 2s at workflow evaluation with
`Secret NPM_TOKEN is required, but not provided`. No step ever ran.
`js/gssapi/v2.1.1`, cut *with* the libkrb5-dev step, failed identically.
The repo has no Actions secrets, and the js-lib workflow has never
published anything — it was created 2025-06-16, four days *after*
service-client 1.6.0 went to npm. The npm route is abandoned; the fork
stays in-tree.

## Verification

- rc.2's failure reproduced locally byte-identically, then `built in
22.14s` with the alias. The bundled GSS import compiles to
`import('./emptyModule-...js')`, giving the browser the same `GSS ===
{}` it has had since before the fork — no behaviour change.
- No native code in the bundle: `node-gssapi` and `file-uri-to-path`
both 0 matches.
- The real fork installs and compiles via `npm install --install-links`
(`build/Release/node-gssapi.node` present, true GSS surface). The
js-build base image already installs `krb5-dev` explicitly "to build
gssapi.js", so the fork builds wherever `gssapi.js` already does.
- With the per-service declaration, `deps.js` resolves the fork rather
than upstream, even with `gssapi.js` also installed.
- `acs-i3x` jest: 13 suites, 342 tests passing.

## How to test

1. Merge and cut `v6.0.0-rc.3`.
2. Confirm the `acs-admin` build passes and the chart release runs.
3. In a built service image, confirm
`node_modules/@amrc-factoryplus/gssapi/build/Release/node-gssapi.node`
exists.
4. On a cluster, confirm the KDC no longer logs a refused `TGT NOT
FORWARDABLE` request per token/MQTT connect.

## Known gaps

- `acs-edge` imports `@amrc-factoryplus/utilities`, not
`service-client`, so edge agents keep the upstream delegating
`gssapi.js`. If edge principals contribute to the KDC storm, this does
not resolve it for them.
- Registry consumers of `service-client` (`acs-mcp`, `acs-visualiser`,
`historian-uns`, `lib/js-sparkplug-app`) resolve the published copy and
keep delegating.

## Release notes

Fixes the `acs-admin` image build, which broke in v6.0.0-rc.2. The GSS
fork that removes Kerberos credential delegation is now actually
installed in the services that use it, so the fix released in #674 takes
effect.
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