From dcc85f691d632629fdb4deec308a034e875c2f2b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Artur=20M=C4=99dryga=C5=82?= Date: Fri, 25 Sep 2026 16:15:39 +0200 Subject: [PATCH 1/4] ci: bump actions off the retired node20 runtime in the remaining workflows Same first-node24 majors PR #371 chose for ci.yml/master.yml: checkout@v5, setup-node@v5, upload-artifact@v6, download-artifact@v7, pnpm/action-setup@v5. download-artifact v5's breaking change only affects artifact-ids downloads; these workflows download by name or pattern. Refs DEV-3113 Co-Authored-By: Claude Opus 5.5 --- .github/workflows/e2e-live.yml | 8 ++++---- .github/workflows/e2e-starter-matrix.yml | 8 ++++---- .github/workflows/examples-build.yml | 14 +++++++------- .github/workflows/import-docs.yml | 10 +++++----- .github/workflows/import-starters.yml | 16 ++++++++-------- .github/workflows/server-examples-build.yml | 10 +++++----- 6 files changed, 33 insertions(+), 33 deletions(-) diff --git a/.github/workflows/e2e-live.yml b/.github/workflows/e2e-live.yml index a2df0cd057..bbe61cb027 100644 --- a/.github/workflows/e2e-live.yml +++ b/.github/workflows/e2e-live.yml @@ -87,13 +87,13 @@ jobs: # weekly canary fires (schedule events carry no inputs). BASE_URL: ${{ inputs.base_url || (github.event_name == 'schedule' && 'https://demos.handsontable.com' || '') }} steps: - - uses: actions/checkout@v4 + - uses: actions/checkout@v5 - - uses: pnpm/action-setup@v4 + - uses: pnpm/action-setup@v5 with: package_json_file: runner/package.json - - uses: actions/setup-node@v4 + - uses: actions/setup-node@v5 with: node-version: 22 cache: pnpm @@ -222,7 +222,7 @@ jobs: - name: Upload Playwright report on failure if: failure() - uses: actions/upload-artifact@v4 + uses: actions/upload-artifact@v6 with: name: playwright-report-live # playwright-report/ holds the html report, test-results/ the traces. diff --git a/.github/workflows/e2e-starter-matrix.yml b/.github/workflows/e2e-starter-matrix.yml index 9cdf20bdb0..3d0cc69bae 100644 --- a/.github/workflows/e2e-starter-matrix.yml +++ b/.github/workflows/e2e-starter-matrix.yml @@ -59,13 +59,13 @@ jobs: run: working-directory: runner steps: - - uses: actions/checkout@v4 + - uses: actions/checkout@v5 - - uses: pnpm/action-setup@v4 + - uses: pnpm/action-setup@v5 with: package_json_file: runner/package.json - - uses: actions/setup-node@v4 + - uses: actions/setup-node@v5 with: node-version: 22 cache: pnpm @@ -94,7 +94,7 @@ jobs: - name: Upload matrix report + results if: always() - uses: actions/upload-artifact@v4 + uses: actions/upload-artifact@v6 with: name: starter-matrix # e2e:matrix runs --reporter=list,json — no HTML playwright-report is diff --git a/.github/workflows/examples-build.yml b/.github/workflows/examples-build.yml index 7b1ba157d6..63f37e8ceb 100644 --- a/.github/workflows/examples-build.yml +++ b/.github/workflows/examples-build.yml @@ -76,7 +76,7 @@ jobs: outputs: starters: ${{ steps.find.outputs.starters }} steps: - - uses: actions/checkout@v4 + - uses: actions/checkout@v5 - id: find run: | @@ -114,9 +114,9 @@ jobs: matrix: starter: ${{ fromJSON(needs.discover.outputs.starters) }} steps: - - uses: actions/checkout@v4 + - uses: actions/checkout@v5 - - uses: pnpm/action-setup@v4 + - uses: pnpm/action-setup@v5 with: package_json_file: ${{ matrix.starter }}/package.json @@ -126,7 +126,7 @@ jobs: # signal. 16 cold installs is the cheaper trade. If this is ever added as an # optimization, prove the hit by comparing two consecutive runs — a silent # miss reads exactly like a hit. - - uses: actions/setup-node@v4 + - uses: actions/setup-node@v5 with: node-version: 22 @@ -220,13 +220,13 @@ jobs: matrix: starter: ${{ fromJSON(needs.discover.outputs.starters) }} steps: - - uses: actions/checkout@v4 + - uses: actions/checkout@v5 - - uses: pnpm/action-setup@v4 + - uses: pnpm/action-setup@v5 with: package_json_file: ${{ matrix.starter }}/package.json - - uses: actions/setup-node@v4 + - uses: actions/setup-node@v5 with: node-version: 22 diff --git a/.github/workflows/import-docs.yml b/.github/workflows/import-docs.yml index 1854ae1ffe..f886db36f7 100644 --- a/.github/workflows/import-docs.yml +++ b/.github/workflows/import-docs.yml @@ -64,10 +64,10 @@ jobs: run: working-directory: runner steps: - - uses: actions/checkout@v4 + - uses: actions/checkout@v5 - name: Check out Handsontable docs source - uses: actions/checkout@v4 + uses: actions/checkout@v5 with: repository: handsontable/handsontable ref: ${{ matrix.docs_branch }} @@ -139,7 +139,7 @@ jobs: cp -R "apps/authoring/public/docs-examples/${{ matrix.bucket }}" "$RUNNER_TEMP/docs-examples/${{ matrix.bucket }}" - name: Upload ${{ matrix.bucket }} bucket - uses: actions/upload-artifact@v4 + uses: actions/upload-artifact@v6 with: name: docs-examples-${{ matrix.bucket }} path: ${{ runner.temp }}/docs-examples @@ -153,10 +153,10 @@ jobs: contents: write pull-requests: write steps: - - uses: actions/checkout@v4 + - uses: actions/checkout@v5 - name: Download generated buckets - uses: actions/download-artifact@v4 + uses: actions/download-artifact@v7 with: pattern: docs-examples-* merge-multiple: true diff --git a/.github/workflows/import-starters.yml b/.github/workflows/import-starters.yml index 1bc9265ec1..dc07965588 100644 --- a/.github/workflows/import-starters.yml +++ b/.github/workflows/import-starters.yml @@ -39,7 +39,7 @@ jobs: outputs: matrix: ${{ steps.matrix.outputs.matrix }} steps: - - uses: actions/checkout@v4 + - uses: actions/checkout@v5 - id: matrix name: Build bucket matrix @@ -94,12 +94,12 @@ jobs: steps: # Pipeline code always comes from master; matrix.ref only selects the # examples/ source tree for the bucket. - - uses: actions/checkout@v4 + - uses: actions/checkout@v5 with: ref: master - name: Check out starter sources at ${{ matrix.ref }} - uses: actions/checkout@v4 + uses: actions/checkout@v5 with: ref: ${{ matrix.ref }} path: starter-src @@ -107,7 +107,7 @@ jobs: /examples/** sparse-checkout-cone-mode: false - - uses: actions/setup-node@v4 + - uses: actions/setup-node@v5 with: node-version: 22 @@ -172,7 +172,7 @@ jobs: cp -R "apps/authoring/public/starter-examples/${{ matrix.bucket }}" "$RUNNER_TEMP/starter-examples/${{ matrix.bucket }}" - name: Upload bucket ${{ matrix.bucket }} - uses: actions/upload-artifact@v4 + uses: actions/upload-artifact@v6 with: name: starter-examples-${{ matrix.bucket }} path: ${{ runner.temp }}/starter-examples @@ -186,18 +186,18 @@ jobs: contents: write pull-requests: write steps: - - uses: actions/checkout@v4 + - uses: actions/checkout@v5 with: ref: master - name: Download generated buckets - uses: actions/download-artifact@v4 + uses: actions/download-artifact@v7 with: pattern: starter-examples-* merge-multiple: true path: runner/apps/authoring/public/starter-examples - - uses: actions/setup-node@v4 + - uses: actions/setup-node@v5 with: node-version: 22 diff --git a/.github/workflows/server-examples-build.yml b/.github/workflows/server-examples-build.yml index 9373379992..6d68abd900 100644 --- a/.github/workflows/server-examples-build.yml +++ b/.github/workflows/server-examples-build.yml @@ -54,7 +54,7 @@ jobs: outputs: projects: ${{ steps.find.outputs.projects }} steps: - - uses: actions/checkout@v4 + - uses: actions/checkout@v5 - id: find run: | @@ -88,9 +88,9 @@ jobs: run: working-directory: ${{ matrix.project }} steps: - - uses: actions/checkout@v4 + - uses: actions/checkout@v5 - - uses: actions/setup-node@v4 + - uses: actions/setup-node@v5 with: node-version: 22 cache: npm @@ -121,9 +121,9 @@ jobs: run: working-directory: ${{ matrix.project }} steps: - - uses: actions/checkout@v4 + - uses: actions/checkout@v5 - - uses: actions/setup-node@v4 + - uses: actions/setup-node@v5 with: node-version: 22 cache: npm From f3c8fccbc12548d9d22bd68094bac9b03b5bd691 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Artur=20M=C4=99dryga=C5=82?= Date: Fri, 25 Sep 2026 16:16:17 +0200 Subject: [PATCH 2/4] ci: opt out of setup-node v5 automatic pnpm cache where it does not belong import-starters runs setup-node before pnpm exists (corepack comes after), so the auto-cache fails with "Unable to locate executable file: pnpm". examples-build deliberately runs uncached (installs under RUNNER_TEMP miss a workspace-resolved store silently); v5 would have turned the cache on without a word. Refs DEV-3113 Co-Authored-By: Claude Opus 5.5 --- .github/workflows/examples-build.yml | 6 +++++- .github/workflows/import-starters.yml | 6 ++++++ 2 files changed, 11 insertions(+), 1 deletion(-) diff --git a/.github/workflows/examples-build.yml b/.github/workflows/examples-build.yml index 63f37e8ceb..a431a8f763 100644 --- a/.github/workflows/examples-build.yml +++ b/.github/workflows/examples-build.yml @@ -125,10 +125,12 @@ jobs: # checkout, so an install under RUNNER_TEMP can miss it with no error and no # signal. 16 cold installs is the cheaper trade. If this is ever added as an # optimization, prove the hit by comparing two consecutive runs — a silent - # miss reads exactly like a hit. + # miss reads exactly like a hit. setup-node v5 would otherwise turn that + # cache on by itself from the root package.json `packageManager` field. - uses: actions/setup-node@v5 with: node-version: 22 + package-manager-cache: false - name: Extract the starter outside the repo tree run: | @@ -229,6 +231,8 @@ jobs: - uses: actions/setup-node@v5 with: node-version: 22 + # Same RUNNER_TEMP extraction as the `build` lane — no cache. + package-manager-cache: false - name: Extract the starter outside the repo tree run: | diff --git a/.github/workflows/import-starters.yml b/.github/workflows/import-starters.yml index dc07965588..618fff59ee 100644 --- a/.github/workflows/import-starters.yml +++ b/.github/workflows/import-starters.yml @@ -110,6 +110,9 @@ jobs: - uses: actions/setup-node@v5 with: node-version: 22 + # setup-node v5 auto-enables pnpm caching from the root package.json + # `packageManager` field; pnpm only exists after `corepack enable` below. + package-manager-cache: false - name: Enable corepack (pnpm lockfile resolution) run: corepack enable @@ -200,6 +203,9 @@ jobs: - uses: actions/setup-node@v5 with: node-version: 22 + # setup-node v5 auto-enables pnpm caching from the root package.json + # `packageManager` field; pnpm only exists after `corepack enable` below. + package-manager-cache: false - name: Enable corepack (container context locks) run: corepack enable From a787a5dbabcd03a433feead22cb73a3c1ba7ba83 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Artur=20M=C4=99dryga=C5=82?= Date: Fri, 25 Sep 2026 16:16:42 +0200 Subject: [PATCH 3/4] ci: move create-pull-request to v8.1.1, its first node24 line v7.0.11 is runs.using node20. actionlint cannot resolve SHA pins so it never flagged this; the pin stays a SHA because the job holds contents+PR write. Refs DEV-3113 Co-Authored-By: Claude Opus 5.5 --- .github/workflows/import-docs.yml | 2 +- .github/workflows/import-starters.yml | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/.github/workflows/import-docs.yml b/.github/workflows/import-docs.yml index f886db36f7..18cb91b7dc 100644 --- a/.github/workflows/import-docs.yml +++ b/.github/workflows/import-docs.yml @@ -169,7 +169,7 @@ jobs: - name: Create or update generated-content pull request # SHA-pinned: this job holds contents+PR write permissions, so a retargeted # upstream tag must not be able to run new code here. - uses: peter-evans/create-pull-request@22a9089034f40e5a961c8808d113e2c98fb63676 # v7.0.11 + uses: peter-evans/create-pull-request@5f6978faf089d4d20b00c7766989d076bb2fc7f1 # v8.1.1 with: branch: chore/docs-example-buckets base: ${{ github.ref_name }} diff --git a/.github/workflows/import-starters.yml b/.github/workflows/import-starters.yml index 618fff59ee..45b724820a 100644 --- a/.github/workflows/import-starters.yml +++ b/.github/workflows/import-starters.yml @@ -220,10 +220,10 @@ jobs: node scripts/prepare-container.mjs - name: Create or update generated-content pull request - # Pinned to an immutable SHA (v7.0.11): this job holds contents+PR + # Pinned to an immutable SHA (v8.1.1): this job holds contents+PR # write permissions, so a retargeted upstream tag must not be able to # run new code here. - uses: peter-evans/create-pull-request@22a9089034f40e5a961c8808d113e2c98fb63676 # v7.0.11 + uses: peter-evans/create-pull-request@5f6978faf089d4d20b00c7766989d076bb2fc7f1 # v8.1.1 with: branch: chore/starter-example-buckets base: master From 1ad8a8ac6c46323568ba201d15edfdaa899471ab Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Artur=20M=C4=99dryga=C5=82?= Date: Fri, 25 Sep 2026 16:17:09 +0200 Subject: [PATCH 4/4] ci: annotate the two intentional word splits so actionlint runs clean Refs DEV-3113 Co-Authored-By: Claude Opus 5.5 --- .github/workflows/examples-build.yml | 1 + .github/workflows/server-examples-build.yml | 1 + 2 files changed, 2 insertions(+) diff --git a/.github/workflows/examples-build.yml b/.github/workflows/examples-build.yml index a431a8f763..d28b2843fc 100644 --- a/.github/workflows/examples-build.yml +++ b/.github/workflows/examples-build.yml @@ -275,6 +275,7 @@ jobs: # date" and left 18.0.0 installed. A canary that rebuilds the pinned # version is worse than no canary. `update --latest` moves the lock # (18.0.0 -> 18.1.0 in the same copy) and leaves the spec alone. + # shellcheck disable=SC2086 # $pkgs is a space-separated list; it must split. pnpm update $pkgs --latest - name: Verify the install actually moved to the released version diff --git a/.github/workflows/server-examples-build.yml b/.github/workflows/server-examples-build.yml index 6d68abd900..e59372ca69 100644 --- a/.github/workflows/server-examples-build.yml +++ b/.github/workflows/server-examples-build.yml @@ -141,6 +141,7 @@ jobs: process.stdout.write(w ? w + '@latest' : ''); ") echo "Installing handsontable@latest $wrapper" + # shellcheck disable=SC2086 # $wrapper may be empty; quoting it would pass "". npm install handsontable@latest $wrapper - name: Report resolved Handsontable version