mirror of
https://github.com/runyanjake/jakeswestcoast.git
synced 2026-09-25 13:18:40 -07:00
fix pipeline
g
This commit is contained in:
parent
fc9739c504
commit
8f7c051f85
3
.gitignore
vendored
3
.gitignore
vendored
@ -2,7 +2,8 @@
|
|||||||
/node_modules
|
/node_modules
|
||||||
/.pnp
|
/.pnp
|
||||||
.pnp.js
|
.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
|
# testing
|
||||||
/coverage
|
/coverage
|
||||||
|
|||||||
25
Dockerfile
25
Dockerfile
@ -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.
|
# 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
|
WORKDIR /app
|
||||||
COPY package.json ./
|
# package-lock.json is committed, and `npm ci` installs exactly what it pins.
|
||||||
RUN npm install
|
# `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).
|
# Lint target, used by CI (docker build --target ci).
|
||||||
FROM deps AS ci
|
FROM deps AS ci
|
||||||
COPY . .
|
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.
|
# Production build target: bundles the static site.
|
||||||
FROM deps AS build
|
FROM deps AS build
|
||||||
@ -15,7 +29,8 @@ COPY . .
|
|||||||
RUN npm run build
|
RUN npm run build
|
||||||
|
|
||||||
# Serve the static bundle with nginx.
|
# 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
|
COPY --from=build /app/build /usr/share/nginx/html
|
||||||
EXPOSE 80
|
EXPOSE 80
|
||||||
# Liveness probe. Use 127.0.0.1 (not localhost): nginx listens IPv4-only and
|
# Liveness probe. Use 127.0.0.1 (not localhost): nginx listens IPv4-only and
|
||||||
|
|||||||
3
Jenkinsfile
vendored
3
Jenkinsfile
vendored
@ -26,7 +26,8 @@ pipeline {
|
|||||||
sh '''
|
sh '''
|
||||||
set -eu
|
set -eu
|
||||||
: "${DISCORD_WEBHOOK:?required credential discord-pws-builds-channel-webhook is missing}"
|
: "${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; }
|
[ -f "$f" ] || { echo "ERROR: required file '$f' not found at repo root" >&2; exit 1; }
|
||||||
done
|
done
|
||||||
docker compose config -q
|
docker compose config -q
|
||||||
|
|||||||
20
README.md
20
README.md
@ -35,3 +35,23 @@ npm start
|
|||||||
```
|
```
|
||||||
docker compose down && docker system prune -af && docker compose build && docker compose up -d && docker logs -f jakeswestcoast
|
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
17544
package-lock.json
generated
Normal file
File diff suppressed because it is too large
Load Diff
@ -11,11 +11,18 @@
|
|||||||
"react-scripts": "5.0.1",
|
"react-scripts": "5.0.1",
|
||||||
"web-vitals": "^4.2.4"
|
"web-vitals": "^4.2.4"
|
||||||
},
|
},
|
||||||
|
"devDependencies": {
|
||||||
|
"typescript": "4.9.5"
|
||||||
|
},
|
||||||
|
"overrides": {
|
||||||
|
"typescript": "4.9.5"
|
||||||
|
},
|
||||||
"scripts": {
|
"scripts": {
|
||||||
"start": "react-scripts start",
|
"start": "react-scripts start",
|
||||||
"build": "react-scripts build",
|
"build": "react-scripts build",
|
||||||
"test": "react-scripts test",
|
"test": "react-scripts test",
|
||||||
"eject": "react-scripts eject"
|
"eject": "react-scripts eject",
|
||||||
|
"lint": "eslint src --max-warnings=0"
|
||||||
},
|
},
|
||||||
"eslintConfig": {
|
"eslintConfig": {
|
||||||
"extends": [
|
"extends": [
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user