fix pipeline

g
This commit is contained in:
Jake Runyan 2026-08-23 01:29:12 -07:00
parent fc9739c504
commit 8f7c051f85
6 changed files with 17596 additions and 8 deletions

3
.gitignore vendored
View File

@ -2,7 +2,8 @@
/node_modules
/.pnp
.pnp.js
package-lock.json
# package-lock.json is committed on purpose: CI installs with `npm ci`, so the
# lock file is what keeps image builds reproducible across new upstream releases.
# testing
/coverage

View File

@ -1,13 +1,27 @@
# Base images are pinned by digest, not by floating tag: an upstream rebuild of
# node:20-alpine or nginx:alpine must never change what CI builds. The tag next
# to the digest is documentation only — Docker resolves the digest.
# To move to a newer base: docker buildx imagetools inspect node:20-alpine
# and copy the reported digest here.
# Shared dependency layer, reused by the ci and build targets.
FROM node:20-alpine AS deps
# node 24.19.0 (active LTS; 20.x is end-of-life) / npm 11.17.0. The npm major
# must match the one that writes package-lock.json locally, or `npm ci` rejects
# the lock as out of sync.
FROM node:24.19.0-alpine@sha256:d32cdf619f63fe0471182d08996dd516c6275bb5fd31ae06e55a570bd9e1ad43 AS deps
WORKDIR /app
COPY package.json ./
RUN npm install
# package-lock.json is committed, and `npm ci` installs exactly what it pins.
# `npm install` would re-resolve the tree at build time, which is how a
# TypeScript 7 release silently broke the lint stage in build #12.
COPY package.json package-lock.json ./
RUN npm ci
# Lint target, used by CI (docker build --target ci).
FROM deps AS ci
COPY . .
RUN npx eslint src --max-warnings=0
# `npm run lint` uses the eslint from the locked tree; bare `npx eslint` would
# fall back to fetching a copy from the registry if it were ever missing.
RUN npm run lint
# Production build target: bundles the static site.
FROM deps AS build
@ -15,7 +29,8 @@ COPY . .
RUN npm run build
# Serve the static bundle with nginx.
FROM nginx:alpine
# nginx 1.31.4
FROM nginx:1.31.4-alpine@sha256:db35bfc6b2951e7f8a72db5db120288c127ffaeeb4a6d4b95a26fead017d5913
COPY --from=build /app/build /usr/share/nginx/html
EXPOSE 80
# Liveness probe. Use 127.0.0.1 (not localhost): nginx listens IPv4-only and

3
Jenkinsfile vendored
View File

@ -26,7 +26,8 @@ pipeline {
sh '''
set -eu
: "${DISCORD_WEBHOOK:?required credential discord-pws-builds-channel-webhook is missing}"
for f in Dockerfile package.json docker-compose.yml; do
# package-lock.json is required: the image installs with `npm ci`.
for f in Dockerfile package.json package-lock.json docker-compose.yml; do
[ -f "$f" ] || { echo "ERROR: required file '$f' not found at repo root" >&2; exit 1; }
done
docker compose config -q

View File

@ -35,3 +35,23 @@ npm start
```
docker compose down && docker system prune -af && docker compose build && docker compose up -d && docker logs -f jakeswestcoast
```
## Reproducible builds
CI builds must not change because something upstream published a new version.
Three things are pinned, and all three need to stay that way:
1. **`package-lock.json` is committed** and the image installs with `npm ci`, not
`npm install`. Never add it back to `.gitignore`.
2. **Base images are pinned by digest** in the [Dockerfile](Dockerfile). To move to a newer
base, run `docker buildx imagetools inspect node:24-alpine` (or `nginx:alpine`)
and paste the reported digest, updating the version in the tag and comment too.
3. **TypeScript is pinned to 4.9.5**, in both `devDependencies` and `overrides`.
`react-scripts@5` only supports TypeScript `^3.2.1 || ^4`; transitive packages
ask for a much wider range, so without the pin npm hoists whatever the latest
TypeScript is and the ESLint plugins fail to load against its API.
The npm major version that writes the lock file has to match the one in the
image (currently 11.x, from `node:24-alpine`), or `npm ci` rejects the lock as
out of sync. If you regenerate the lock with a different npm, bump the base
image to a Node release carrying the same npm major.

17544
package-lock.json generated Normal file

File diff suppressed because it is too large Load Diff

View File

@ -11,11 +11,18 @@
"react-scripts": "5.0.1",
"web-vitals": "^4.2.4"
},
"devDependencies": {
"typescript": "4.9.5"
},
"overrides": {
"typescript": "4.9.5"
},
"scripts": {
"start": "react-scripts start",
"build": "react-scripts build",
"test": "react-scripts test",
"eject": "react-scripts eject"
"eject": "react-scripts eject",
"lint": "eslint src --max-warnings=0"
},
"eslintConfig": {
"extends": [