From 18bfd2d225242a9991c6e70c4e2fc86e1e87dc00 Mon Sep 17 00:00:00 2001 From: JuanCF Date: Tue, 25 Aug 2026 00:03:03 -0600 Subject: [PATCH 1/2] chore: move CI and the image build to Node 24 LTS Node 20 reached the end of its life and GitHub's runners now warn on actions that declare a node20 runtime. Separately, CI built and tested the frontend on Node 20 while the Docker image built it on Node 22, so the version validated in CI was never the version shipped. Move everything to Node 24, the current active LTS (Node 22 dropped to maintenance in October 2025): - lint.yml and release.yml: node-version 20 -> 24. - Dockerfile: node:22-slim -> node:24-slim, so the image builds the SPA on the same version CI tests it on. - Bump every action one major to its node24 runtime, re-resolving the pinned SHAs in docker-publish.yml: checkout v5.1.0, setup-qemu v4.2.0, setup-buildx v4.3.0, login v4.6.0, metadata v6.2.0, build-push v7.3.0, plus setup-python v6, setup-node v5 and action-gh-release v3. Verified against node:24-slim: tsc -b and eslint are clean, all 169 frontend tests pass, and the image builds. The resulting image digest is byte-identical to the Node 22 build, so the toolchain moves without changing the shipped artifact. --- .github/workflows/docker-publish.yml | 14 +++++++------- .github/workflows/lint.yml | 12 ++++++------ .github/workflows/release.yml | 22 +++++++++++----------- Dockerfile | 2 +- 4 files changed, 25 insertions(+), 25 deletions(-) diff --git a/.github/workflows/docker-publish.yml b/.github/workflows/docker-publish.yml index 20aee31..6317306 100644 --- a/.github/workflows/docker-publish.yml +++ b/.github/workflows/docker-publish.yml @@ -35,7 +35,7 @@ jobs: outputs: is-latest: ${{ steps.newest.outputs.is-latest }} steps: - - uses: actions/checkout@11d5960a326750d5838078e36cf38b85af677262 # v4.4.0 + - uses: actions/checkout@fbc6f3992d24b796d5a048ff273f7fcc4a7b6c09 # v5.1.0 with: fetch-depth: 0 persist-credentials: false @@ -73,20 +73,20 @@ jobs: contents: read packages: write steps: - - uses: actions/checkout@11d5960a326750d5838078e36cf38b85af677262 # v4.4.0 + - uses: actions/checkout@fbc6f3992d24b796d5a048ff273f7fcc4a7b6c09 # v5.1.0 with: persist-credentials: false - name: Set up QEMU - uses: docker/setup-qemu-action@c7c53464625b32c7a7e944ae62b3e17d2b600130 # v3.7.0 + uses: docker/setup-qemu-action@96fe6ef7f33517b61c61be40b68a1882f3264fb8 # v4.2.0 - name: Set up Buildx - uses: docker/setup-buildx-action@8d2750c68a42422c14e847fe6c8ac0403b4cbd6f # v3.12.0 + uses: docker/setup-buildx-action@37fe631027851001ddb9b187196cc803df7f5f0e # v4.3.0 # Pull requests build for validation only; nothing is pushed. - name: Log in to GHCR if: github.event_name != 'pull_request' - uses: docker/login-action@c94ce9fb468520275223c153574b00df6fe4bcc9 # v3.7.0 + uses: docker/login-action@dbcb813823bdd20940b903addbd779551569679f # v4.6.0 with: registry: ${{ env.REGISTRY }} username: ${{ github.actor }} @@ -97,7 +97,7 @@ jobs: # main -> :main (rolling development build) - name: Derive image tags id: meta - uses: docker/metadata-action@c299e40c65443455700f0fdfc63efafe5b349051 # v5.10.0 + uses: docker/metadata-action@dc802804100637a589fabce1cb79ff13a1411302 # v6.2.0 with: images: ${{ env.REGISTRY }}/${{ env.IMAGE_NAME }} # latest=false disables the automatic "any semver tag wins :latest" @@ -117,7 +117,7 @@ jobs: org.opencontainers.image.description=Web UI for managing Network UPS Tools (NUT) - name: Build and push - uses: docker/build-push-action@10e90e3645eae34f1e60eeb005ba3a3d33f178e8 # v6.19.2 + uses: docker/build-push-action@53b7df96c91f9c12dcc8a07bcb9ccacbed38856a # v7.3.0 with: context: . # Pull requests validate on amd64 only; emulated arm64 roughly diff --git a/.github/workflows/lint.yml b/.github/workflows/lint.yml index acc2b15..3bea61f 100644 --- a/.github/workflows/lint.yml +++ b/.github/workflows/lint.yml @@ -12,7 +12,7 @@ jobs: lint-shell: runs-on: ubuntu-latest steps: - - uses: actions/checkout@v4 + - uses: actions/checkout@v5 - name: Install tools run: sudo apt-get install -y shellcheck shfmt @@ -27,10 +27,10 @@ jobs: lint-python: runs-on: ubuntu-latest steps: - - uses: actions/checkout@v4 + - uses: actions/checkout@v5 - name: Set up Python - uses: actions/setup-python@v5 + uses: actions/setup-python@v6 with: python-version: '3.11' @@ -47,12 +47,12 @@ jobs: test-frontend: runs-on: ubuntu-latest steps: - - uses: actions/checkout@v4 + - uses: actions/checkout@v5 - name: Set up Node.js - uses: actions/setup-node@v4 + uses: actions/setup-node@v5 with: - node-version: '20' + node-version: '24' - name: Install dependencies run: cd src/frontend && npm ci diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml index 067e4ba..e99fe86 100644 --- a/.github/workflows/release.yml +++ b/.github/workflows/release.yml @@ -9,7 +9,7 @@ jobs: check-tag-branch: runs-on: ubuntu-latest steps: - - uses: actions/checkout@v4 + - uses: actions/checkout@v5 with: fetch-depth: 0 persist-credentials: false @@ -30,7 +30,7 @@ jobs: permissions: contents: read steps: - - uses: actions/checkout@v4 + - uses: actions/checkout@v5 with: persist-credentials: false @@ -49,12 +49,12 @@ jobs: permissions: contents: read steps: - - uses: actions/checkout@v4 + - uses: actions/checkout@v5 with: persist-credentials: false - name: Set up Python - uses: actions/setup-python@v5 + uses: actions/setup-python@v6 with: python-version: '3.11' @@ -74,14 +74,14 @@ jobs: permissions: contents: read steps: - - uses: actions/checkout@v4 + - uses: actions/checkout@v5 with: persist-credentials: false - name: Set up Node.js - uses: actions/setup-node@v4 + uses: actions/setup-node@v5 with: - node-version: '20' + node-version: '24' - name: Install dependencies run: cd src/frontend && npm ci @@ -95,14 +95,14 @@ jobs: permissions: contents: write steps: - - uses: actions/checkout@v4 + - uses: actions/checkout@v5 with: persist-credentials: false - name: Set up Node.js - uses: actions/setup-node@v4 + uses: actions/setup-node@v5 with: - node-version: '20' + node-version: '24' - name: Build frontend run: cd src/frontend && npm ci && npm run build @@ -111,7 +111,7 @@ jobs: run: make build-tarball - name: Create GitHub Release - uses: softprops/action-gh-release@v2 + uses: softprops/action-gh-release@v3 with: files: nutwatch.tar.gz generate_release_notes: true diff --git a/Dockerfile b/Dockerfile index 792585a..26efd49 100644 --- a/Dockerfile +++ b/Dockerfile @@ -6,7 +6,7 @@ # Pinned to the build host's architecture: the SPA and the backend sources it # is copied alongside are both arch-independent, so there is no reason to run # npm under QEMU emulation when cross-building the arm64 image. -FROM --platform=$BUILDPLATFORM node:22-slim AS frontend-builder +FROM --platform=$BUILDPLATFORM node:24-slim AS frontend-builder # Build the React SPA. Vite writes to ../backend/static, so we copy the # backend tree into the same relative location before building. WORKDIR /build/src/frontend From 341151217cfefdbc655da84c7cb7b19775635de4 Mon Sep 17 00:00:00 2001 From: JuanCF Date: Tue, 25 Aug 2026 00:05:18 -0600 Subject: [PATCH 2/2] chore: add .nvmrc pinning the frontend to Node 24 Gives nvm, fnm and asdf users the same Node version CI and the Docker image build use, so `nvm use` in src/frontend matches what the SPA is actually tested and built on. --- src/frontend/.nvmrc | 1 + 1 file changed, 1 insertion(+) create mode 100644 src/frontend/.nvmrc diff --git a/src/frontend/.nvmrc b/src/frontend/.nvmrc new file mode 100644 index 0000000..a45fd52 --- /dev/null +++ b/src/frontend/.nvmrc @@ -0,0 +1 @@ +24