Repository navigation
build: Build and run on Node and npm, not Bun - #54
Merged
Merged
Conversation
Bun checks TLS against roots compiled into its binary, so a distrusted root leaves only with a Bun release and a rebuild, and Dependabot cannot read bun.lock, so it never saw the packages behind the direct ranges. Key changes: - Image: node 26.12.1 on Alpine, pinned by digest; npm ci builds it and npm ci --omit=dev installs the runtime dependencies - Lock: package-lock.json built from bun.lock, same versions and hashes except where npm's peer checks needed a change - Pages workflow: setup-node with .nvmrc and the npm cache - Server: keep-alive 75s, above Envoy's 60s idle timeout; SIGTERM closes idle connections and force-closes the rest after 25s
yahyafakhroji
approved these changes
Nov 3, 2026
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Bun checks outbound TLS against root certificates compiled into its binary, so this app drops a distrusted root like eMudhra's only when Bun ships a release and we rebuild. Dependabot also can't read
bun.lock: it saw only the direct ranges inpackage.jsonand none of the ~830 packages they resolve to. This PR removes Bun from the image, the scripts, the Pages workflow and the lock file, and replacesbun.lockwith apackage-lock.jsonthat pins the same tree.Nothing changes on www.cloudvalid.com when this merges. The live site is GitHub Pages, last deployed on 5 March 2026. Every Pages build since then has failed with
The requested module 'js-yaml' does not provide an export named 'default', which #46 tracks. That failure doesn't depend on Bun: this branch reproduces it unchanged under Node and npm, so the Pages deploy stays red until #46 lands. No workflow builds or publishes the Docker image, and nothing in datum-cloud/infra deploys it.What changes
node:26.12.1-alpine3.24, pinned by digest, in place ofoven/bun:1.3-slim.npm ciinstalls the build dependencies, and the production stage runsnpm ci --omit=devinstead of copying the build stage'snode_modules, so devDependencies no longer ship in the runtime image. The bun.lock already pinned sharp'slinuxmuslbinaries, so Alpine is covered.actions/setup-node@v7with.nvmrcand the npm cache, thennpm ciandnpm run build. The shared CI workflow now detects npm frompackage-lock.json.startisnode ./server.mjs, andlintchains its steps withnpm run..gitignoreand.prettierignoredrop their Bun entries.keepAliveTimeoutis 75 s andheadersTimeout76 s. Node's default of 5 s closes idle connections well inside Envoy's 60 s upstream idle timeout, so Envoy could reuse a socket the server was closing and return a 503. On SIGTERM the server stops accepting, closes idle connections, and force-closes the rest after 25 s, inside a 30 s grace period. A second SIGTERM does nothing.After this PR, a repository-wide grep for
bunfinds only "a bunch" in the font demo pages.The lock pins what Bun pinned
This isn't a fresh
npm install. Each package's path, version andintegrityhash came frombun.lock, and the registry manifest for that exact version supplied the dependency and metadata fields. Every one of Bun's 852 hashes matched the registry's.npm install --package-lock-onlythen normalized the lock, adding only thedev,optionalandpeerflags.817 of Bun's 852 entries are in the lock at the same path, version and hash. Bun doesn't enforce peer dependencies, and npm refused the tree as Bun laid it out, so the rest differ in four ways:
@astrojs/markdown-remark: Bun kept 6.3.10 at the top level, which nothing depends on, and nested the 7.2.2 that@astrojs/mdxpins. Astro and Starlight ask for 7.x as a peer, so the lock moves 7.2.2 to the top level and drops 6.3.10 and the 15 packages only it used. Astro now resolves the major it declares; under Bun it would have found 6.3.10.@types/node(dev only): the top-level 17.0.45 fails Vite's@types/nodepeer range, so the 24.13.3 that Bun nested undersitemapmoves to the top level.ajv-draft-04moves underyaml-language-server, its only dependent, so itsajv ^8peer finds the ajv 8 nested there rather than ESLint's ajv 6.typescript-eslintand@typescript-eslint/*(dev only) move from 8.56.1 to 8.66.0, withts-api-utilsfrom 2.4.0 to 2.5.0.eslint-plugin-astro3.x requires>=8.61.0, which no 8.56.1 tree satisfies. 8.66.0 is the version Bun already pinned forastro-eslint-parser, so those nested copies fold into one, and the^8.56.1ranges inpackage.jsonare unchanged.Verified locally
npm cileaves the lock unchanged, andnpm ls --allis clean.npm run lintpasses.prettier --check .flags the same six files it flags on main, none touched here.npm run buildfails atgenerating static routeswith the same js-yaml error as main under Bun (fix(deps): resolve a single compatible js-yaml so the Astro build completes #46).docker build --target dependenciessucceeds. A production-stage image with a stubdistruns on Node v26.12.1, loads sharp, ships no ESLint packages, and returns 200 on/healthz.Keep-Alive: timeout=75, and a connection left idle for 30 s is reused.What Dependabot will see
npm auditreports 1 critical, 18 high, 19 moderate and 3 low findings in the versions Bun pinned, 1 critical and 14 high of them in production dependencies. This PR leaves them alone so the swap stays like-for-like, so expect Dependabot alerts once it merges. #48 covers most of them.Open pull requests this touches
#46 and #48 edit
bun.lock, which this PR deletes, so each will need its change rebuilt againstpackage-lock.json. #47 editsserver.mjsin different lines from this PR.server.mjsstill importsdist/server/entry.mjs, which the static build doesn't emit, so the container can't start until #47 or an equivalent fix lands.Fixes #53
Part of datum-cloud/infra#7480