Skip to content

[DEVEX-907] Make setup-node conditional in action-pre-commit to preserve baked pre-commit cache#198

Draft
HammerZhaoTuro wants to merge 2 commits into
mainfrom
f/devex-907_make_setup-node_conditional_in_action-pre-commit_to_preserve_baked_pre-c
Draft

[DEVEX-907] Make setup-node conditional in action-pre-commit to preserve baked pre-commit cache#198
HammerZhaoTuro wants to merge 2 commits into
mainfrom
f/devex-907_make_setup-node_conditional_in_action-pre-commit_to_preserve_baked_pre-c

Conversation

@HammerZhaoTuro

@HammerZhaoTuro HammerZhaoTuro commented Jul 15, 2026

Copy link
Copy Markdown
Contributor

Summary

DEVEX-907: Make setup-node conditional in action-pre-commit to preserve baked pre-commit cache

Description

Problem

open-turo/action-pre-commit@v3 unconditionally runs actions/setup-node@v6 (defaulting to Node 24), even though the runner image (turo/actions-runner) already ships Node 22. This causes pre-commit's node language cache to miss for hooks like mirrors-prettier — despite the environments being successfully pre-built into the image (confirmed: 78/79 environments built, only cspell-cli failed).

Pre-commit resolves the cache directory name using get_default_version(), which returns "system" or "default" depending on how Node is found on PATH. When setup-node installs Node 24 into /opt/hostedtoolcache (an emptyDir volume on k8s runners), it changes what pre-commit finds on PATH, flipping the resolved cache key and creating a directory name mismatch with the baked node_env-system environment.

Observed: mirrors-prettier reinstalls from scratch every run (~40-80s wasted), despite being cached in the image.

Impact: ~449 repos use mirrors-prettier@v3.1.0. Other affected node hooks include older commitlint versions without language_version: system and mirrors-eslint.

Scope: lint job only

setup-node runs inside action-pre-commit, which runs only in the lint job of the k8s-tooling reusable workflow. Each job runs on a separate k8s pod — other jobs (test, kustomize-diff, kyverno-test) and separate workflows (release) are completely unaffected.

Within the lint job, the only consumers of Node are the pre-commit hooks themselves (prettier, commitlint, eslint). Node version requirements for all hooks are satisfied by Node 22:

  • prettier@3.1.0 — requires Node >= 14
  • @commitlint/cli@^21 — requires Node >= 22.12.0
  • eslint@9.39.x — requires Node >= 18.18.0

Hook output is deterministic by tool version, not Node runtime. Node 22 vs 24 produces identical formatting/linting results.

Change

Make setup-node conditional — skip it when node is already on PATH, matching the existing pattern for Python. Added NODE_BIN detection to the "Version files" step and gated both "Determine node version" and "Setup node" on env.NODE_BIN == ''.

When the runner image already has Node (e.g. turo/actions-runner with Node 22), both steps are skipped and pre-commit sees the same system Node used during image build — cache keys match. When Node is absent, setup-node runs as before (fallback).

Why this is safe

  1. Only the lint job is affected, and only the pre-commit hooks within it use Node. No other jobs or workflows see this change.
  2. Hook output is Node-version-independent. Prettier, commitlint, and eslint produce identical results on Node 22 vs 24.
  3. The pattern already exists for Python in the same action. Node follows the same convention.
  4. All hooks work on Node 22. The highest requirement is @commitlint/cli@^21 needing Node >= 22.12.0, which the baked runner image (Node 22.23.x) satisfies.
  5. Side benefit: Skipping setup-node saves ~50MB download per run. /opt/hostedtoolcache is an emptyDir volume destroyed when the pod exits, so every setup-node call downloads Node fresh.

Independent safety assessment

Full assessment (artifact) — covers setup-node side effects, blast radius, edge cases (GitHub-hosted runners, .node-version files, npm install in commitlint sub-action, external consumers), and expression semantics.

Validation plan

  • Run a before/after comparison on dunlop-deployments (same approach as DEVEX-868)
  • Confirm mirrors-prettier cache hits (no [INFO] Installing environment in logs)
  • Verify commitlint still passes
  • Spot-check a non-deployment repo that uses the reusable workflow

References

Fixes DEVEX-907

Changes

  • fix: make setup-node conditional to preserve baked pre-commit cache (+9/-0)

🚀 PR created with fotingo

Skip `actions/setup-node` when `node` is already on PATH, matching the
existing pattern for Python. This prevents setup-node from installing a
different Node version that changes pre-commit's cache key, causing
baked hook environments (e.g. mirrors-prettier) to miss and reinstall
from scratch on every run.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
@github-actions

github-actions Bot commented Jul 15, 2026

Copy link
Copy Markdown

Release notes preview

Below is a preview of the release notes if your PR gets merged.


3.6.2 (2026-07-15)

Miscellaneous

  • deps: update actions/checkout action to v7 (cf9c6ed)
  • deps: update all non-major dependencies (7d1989b)
  • deps: update dependency open-turo/renovate-config to v1.21.1 (e3fa877)
  • deps: update pre-commit hook alessandrojcm/commitlint-pre-commit-hook to v9.26.0 (d13582e)
  • deps: update pre-commit hook pre-commit/mirrors-eslint to v10.6.0 (dd9d887)

Bug Fixes

  • make setup-node conditional to preserve baked pre-commit cache (2b2270a)

Tests

  • point commitlint sub-action to feature branch (d13819f)

Avoids double action download during testing. Will be updated to @v4
when the release is cut.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant