#236: pin the Node version #257
@ -86,7 +86,7 @@ jobs:
|
|||||||
- name: Set up Node.js
|
- name: Set up Node.js
|
||||||
uses: actions/setup-node@v4
|
uses: actions/setup-node@v4
|
||||||
with:
|
with:
|
||||||
node-version: 22
|
node-version-file: .node-version
|
||||||
cache: pnpm
|
cache: pnpm
|
||||||
|
|
||||||
- name: Install dependencies
|
- name: Install dependencies
|
||||||
|
|||||||
@ -58,13 +58,46 @@ jobs:
|
|||||||
exit 1
|
exit 1
|
||||||
fi
|
fi
|
||||||
|
|
||||||
|
# One authoritative Node version (issue #236): `.node-version` is the
|
||||||
|
# pin; every Dockerfile image tag and the engines floor must match it
|
||||||
|
# exactly, and workflows select Node only through node-version-file.
|
||||||
|
# Raising Node = update .node-version, every `FROM node:` tag and the
|
||||||
|
# engines floor in ONE commit (procedure: docs/architecture/operations.md
|
||||||
|
# §Update strategy). The bracketed grep pattern keeps this step from
|
||||||
|
# matching its own source (same trick as the secret fence above).
|
||||||
|
- name: Node version pin is consistent
|
||||||
|
run: |
|
||||||
|
set -euo pipefail
|
||||||
|
ver="$(cat .node-version)"
|
||||||
|
echo "pinned Node version: $ver"
|
||||||
|
bad=0
|
||||||
|
for f in apps/*/Dockerfile; do
|
||||||
|
if grep '^FROM node:' "$f" | grep -v "node:${ver}-alpine"; then
|
||||||
|
echo "$f pins a different Node image than node:${ver}-alpine"
|
||||||
|
bad=1
|
||||||
|
fi
|
||||||
|
done
|
||||||
|
if grep -rn "node-version[:] " .gitea/workflows; then
|
||||||
|
echo "workflows must use node-version-file, not a literal version"
|
||||||
|
bad=1
|
||||||
|
fi
|
||||||
|
if grep -rnE 'node:[0-9][^ ]*-alpine' .gitea/workflows | grep -v "node:${ver}-alpine"; then
|
||||||
|
echo "a workflow references a different node image than node:${ver}-alpine"
|
||||||
|
bad=1
|
||||||
|
fi
|
||||||
|
if ! grep -q "\"node\": \">=${ver}\"" package.json; then
|
||||||
|
echo "package.json engines floor does not match ${ver}"
|
||||||
|
bad=1
|
||||||
|
fi
|
||||||
|
exit "$bad"
|
||||||
|
|
||||||
- name: Set up pnpm
|
- name: Set up pnpm
|
||||||
uses: pnpm/action-setup@v4
|
uses: pnpm/action-setup@v4
|
||||||
|
|
||||||
- name: Set up Node.js
|
- name: Set up Node.js
|
||||||
uses: actions/setup-node@v4
|
uses: actions/setup-node@v4
|
||||||
with:
|
with:
|
||||||
node-version: 22
|
node-version-file: .node-version
|
||||||
cache: pnpm
|
cache: pnpm
|
||||||
|
|
||||||
- name: Install dependencies
|
- name: Install dependencies
|
||||||
@ -119,7 +152,7 @@ jobs:
|
|||||||
- name: Set up Node.js
|
- name: Set up Node.js
|
||||||
uses: actions/setup-node@v4
|
uses: actions/setup-node@v4
|
||||||
with:
|
with:
|
||||||
node-version: 22
|
node-version-file: .node-version
|
||||||
cache: pnpm
|
cache: pnpm
|
||||||
|
|
||||||
- name: Install dependencies
|
- name: Install dependencies
|
||||||
@ -594,7 +627,7 @@ jobs:
|
|||||||
- name: Set up Node.js
|
- name: Set up Node.js
|
||||||
uses: actions/setup-node@v4
|
uses: actions/setup-node@v4
|
||||||
with:
|
with:
|
||||||
node-version: 22
|
node-version-file: .node-version
|
||||||
cache: pnpm
|
cache: pnpm
|
||||||
|
|
||||||
- name: Install dependencies
|
- name: Install dependencies
|
||||||
|
|||||||
@ -55,7 +55,7 @@ jobs:
|
|||||||
} > comment.md
|
} > comment.md
|
||||||
# JSON-encode via a node container — the runner image guarantees
|
# JSON-encode via a node container — the runner image guarantees
|
||||||
# only git/curl/docker, not python or node.
|
# only git/curl/docker, not python or node.
|
||||||
docker run --rm -i node:22.15-alpine node -e \
|
docker run --rm -i node:22.15.1-alpine node -e \
|
||||||
'const fs=require("fs");process.stdout.write(JSON.stringify({body:fs.readFileSync(0,"utf8")}))' \
|
'const fs=require("fs");process.stdout.write(JSON.stringify({body:fs.readFileSync(0,"utf8")}))' \
|
||||||
< comment.md > comment.json
|
< comment.md > comment.json
|
||||||
curl -sf -X POST \
|
curl -sf -X POST \
|
||||||
|
|||||||
@ -54,7 +54,7 @@ jobs:
|
|||||||
echo '_No database migrations in this release._'
|
echo '_No database migrations in this release._'
|
||||||
fi
|
fi
|
||||||
} > notes.md
|
} > notes.md
|
||||||
TAG=$TAG docker run --rm -i -e TAG node:22.15-alpine node -e \
|
TAG=$TAG docker run --rm -i -e TAG node:22.15.1-alpine node -e \
|
||||||
'const fs=require("fs");const body=fs.readFileSync(0,"utf8");process.stdout.write(JSON.stringify({tag_name:process.env.TAG,name:process.env.TAG,body}))' \
|
'const fs=require("fs");const body=fs.readFileSync(0,"utf8");process.stdout.write(JSON.stringify({tag_name:process.env.TAG,name:process.env.TAG,body}))' \
|
||||||
< notes.md > release.json
|
< notes.md > release.json
|
||||||
curl -sf -X POST \
|
curl -sf -X POST \
|
||||||
|
|||||||
1
.node-version
Normal file
1
.node-version
Normal file
@ -0,0 +1 @@
|
|||||||
|
22.15.1
|
||||||
@ -1,7 +1,7 @@
|
|||||||
# Build context is the repository root (workspace build):
|
# Build context is the repository root (workspace build):
|
||||||
# docker build -f apps/api/Dockerfile .
|
# docker build -f apps/api/Dockerfile .
|
||||||
|
|
||||||
FROM node:22.15-alpine AS build
|
FROM node:22.15.1-alpine AS build
|
||||||
WORKDIR /repo
|
WORKDIR /repo
|
||||||
RUN npm install -g pnpm@11
|
RUN npm install -g pnpm@11
|
||||||
COPY pnpm-workspace.yaml pnpm-lock.yaml package.json tsconfig.base.json ./
|
COPY pnpm-workspace.yaml pnpm-lock.yaml package.json tsconfig.base.json ./
|
||||||
@ -23,7 +23,7 @@ RUN pnpm install --frozen-lockfile --filter @dorfteich/api... \
|
|||||||
&& cp -r apps/api/dist /out/dist \
|
&& cp -r apps/api/dist /out/dist \
|
||||||
&& cp -r /repo/fonts /out/fonts
|
&& cp -r /repo/fonts /out/fonts
|
||||||
|
|
||||||
FROM node:22.15-alpine
|
FROM node:22.15.1-alpine
|
||||||
ARG APP_VERSION=0.0.0-dev
|
ARG APP_VERSION=0.0.0-dev
|
||||||
# Default the data dirs to the writable, node-owned locations created below, so
|
# Default the data dirs to the writable, node-owned locations created below, so
|
||||||
# the image works out of the box even where compose does not set them; compose
|
# the image works out of the box even where compose does not set them; compose
|
||||||
|
|||||||
@ -1,7 +1,7 @@
|
|||||||
# Build context is the repository root (workspace build):
|
# Build context is the repository root (workspace build):
|
||||||
# docker build -f apps/backup/Dockerfile .
|
# docker build -f apps/backup/Dockerfile .
|
||||||
|
|
||||||
FROM node:22.15-alpine AS build
|
FROM node:22.15.1-alpine AS build
|
||||||
WORKDIR /repo
|
WORKDIR /repo
|
||||||
RUN npm install -g pnpm@11
|
RUN npm install -g pnpm@11
|
||||||
COPY pnpm-workspace.yaml pnpm-lock.yaml package.json tsconfig.base.json ./
|
COPY pnpm-workspace.yaml pnpm-lock.yaml package.json tsconfig.base.json ./
|
||||||
@ -14,7 +14,7 @@ RUN pnpm install --frozen-lockfile --filter @dorfteich/backup... \
|
|||||||
&& pnpm --filter @dorfteich/backup deploy --prod --legacy /out \
|
&& pnpm --filter @dorfteich/backup deploy --prod --legacy /out \
|
||||||
&& cp -r apps/backup/dist /out/dist
|
&& cp -r apps/backup/dist /out/dist
|
||||||
|
|
||||||
FROM node:22.15-alpine
|
FROM node:22.15.1-alpine
|
||||||
ARG APP_VERSION=0.0.0-dev
|
ARG APP_VERSION=0.0.0-dev
|
||||||
ENV NODE_ENV=production APP_VERSION=${APP_VERSION} \
|
ENV NODE_ENV=production APP_VERSION=${APP_VERSION} \
|
||||||
# Baked-in volume paths (self-sufficient without compose env, like the
|
# Baked-in volume paths (self-sufficient without compose env, like the
|
||||||
|
|||||||
@ -1,7 +1,7 @@
|
|||||||
# Build context is the repository root (workspace build):
|
# Build context is the repository root (workspace build):
|
||||||
# docker build -f apps/collab/Dockerfile .
|
# docker build -f apps/collab/Dockerfile .
|
||||||
|
|
||||||
FROM node:22.15-alpine AS build
|
FROM node:22.15.1-alpine AS build
|
||||||
WORKDIR /repo
|
WORKDIR /repo
|
||||||
RUN npm install -g pnpm@11
|
RUN npm install -g pnpm@11
|
||||||
COPY pnpm-workspace.yaml pnpm-lock.yaml package.json tsconfig.base.json ./
|
COPY pnpm-workspace.yaml pnpm-lock.yaml package.json tsconfig.base.json ./
|
||||||
@ -14,7 +14,7 @@ RUN pnpm install --frozen-lockfile --filter @dorfteich/collab... \
|
|||||||
&& pnpm --filter @dorfteich/collab deploy --prod --legacy /out \
|
&& pnpm --filter @dorfteich/collab deploy --prod --legacy /out \
|
||||||
&& cp -r apps/collab/dist /out/dist
|
&& cp -r apps/collab/dist /out/dist
|
||||||
|
|
||||||
FROM node:22.15-alpine
|
FROM node:22.15.1-alpine
|
||||||
ARG APP_VERSION=0.0.0-dev
|
ARG APP_VERSION=0.0.0-dev
|
||||||
ENV NODE_ENV=production APP_VERSION=${APP_VERSION}
|
ENV NODE_ENV=production APP_VERSION=${APP_VERSION}
|
||||||
WORKDIR /app
|
WORKDIR /app
|
||||||
|
|||||||
@ -1,7 +1,7 @@
|
|||||||
# Build context is the repository root (workspace build):
|
# Build context is the repository root (workspace build):
|
||||||
# docker build -f apps/web/Dockerfile .
|
# docker build -f apps/web/Dockerfile .
|
||||||
|
|
||||||
FROM node:22.15-alpine AS build
|
FROM node:22.15.1-alpine AS build
|
||||||
ARG APP_VERSION=0.0.0-dev
|
ARG APP_VERSION=0.0.0-dev
|
||||||
WORKDIR /repo
|
WORKDIR /repo
|
||||||
RUN npm install -g pnpm@11
|
RUN npm install -g pnpm@11
|
||||||
|
|||||||
@ -169,6 +169,16 @@ not a copy of the purged page.
|
|||||||
- **Base image / dependency hygiene**: monthly dependency-update story
|
- **Base image / dependency hygiene**: monthly dependency-update story
|
||||||
(renovate-style batch PR); security advisories for pinned images tracked
|
(renovate-style batch PR); security advisories for pinned images tracked
|
||||||
in the release checklist.
|
in the release checklist.
|
||||||
|
- **Toolchain pin (issue #236)**: `.node-version` is the single
|
||||||
|
authoritative Node version. CI/CD select Node exclusively via
|
||||||
|
`node-version-file`, every Dockerfile pins `node:<version>-alpine`, and
|
||||||
|
the `engines.node` floor in `package.json` states the same version
|
||||||
|
(open-ended upwards — a newer local Node keeps working; reproducibility
|
||||||
|
rests on the images and CI, not the laptop). An early CI step fails on
|
||||||
|
any drift between those places. Raising Node (e.g. for a security fix):
|
||||||
|
update `.node-version`, all four Dockerfiles and the engines floor in
|
||||||
|
ONE commit and let CI confirm. pnpm is pinned the same way via
|
||||||
|
`packageManager`.
|
||||||
|
|
||||||
## Capacity & limits (initial values, instance-tunable)
|
## Capacity & limits (initial values, instance-tunable)
|
||||||
|
|
||||||
|
|||||||
@ -255,7 +255,7 @@ fehlten — als Issues angelegt:
|
|||||||
· 1 AT · #234 (M24, I-23)
|
· 1 AT · #234 (M24, I-23)
|
||||||
- [x] `page_links.target_slug`-Residuum nach Purge entscheiden
|
- [x] `page_links.target_slug`-Residuum nach Purge entscheiden
|
||||||
· 0,5 AT · #235 (M24, I-24)
|
· 0,5 AT · #235 (M24, I-24)
|
||||||
- [ ] Node-Version pinnen — Voraussetzung für #219 · 0,5 AT · #236 (M25, I-26)
|
- [x] Node-Version pinnen — Voraussetzung für #219 · 0,5 AT · #236 (M25, I-26)
|
||||||
|
|
||||||
Ohne eigenes Issue: IndexedDB-Kopie auf Endgeräten (I-25) — als
|
Ohne eigenes Issue: IndexedDB-Kopie auf Endgeräten (I-25) — als
|
||||||
Akzeptanzkriterium in #226 (Abgrenzungserklärung) und #231
|
Akzeptanzkriterium in #226 (Abgrenzungserklärung) und #231
|
||||||
|
|||||||
@ -5,7 +5,7 @@
|
|||||||
"description": "Dorfteich — an open-source wiki system with real-time collaboration",
|
"description": "Dorfteich — an open-source wiki system with real-time collaboration",
|
||||||
"license": "MIT",
|
"license": "MIT",
|
||||||
"engines": {
|
"engines": {
|
||||||
"node": ">=22"
|
"node": ">=22.15.1"
|
||||||
},
|
},
|
||||||
"packageManager": "pnpm@11.9.0",
|
"packageManager": "pnpm@11.9.0",
|
||||||
"scripts": {
|
"scripts": {
|
||||||
|
|||||||
Loading…
Reference in New Issue
Block a user