Skip to content

JS-2022 - Fix npm cache never being saved due to lookup-only mode#7494

Merged
nathsou merged 4 commits into
masterfrom
fix/ci-npm-cache-miss-fallback
Jul 8, 2026
Merged

JS-2022 - Fix npm cache never being saved due to lookup-only mode#7494
nathsou merged 4 commits into
masterfrom
fix/ci-npm-cache-miss-fallback

Conversation

@nathsou

@nathsou nathsou commented Jul 8, 2026

Copy link
Copy Markdown
Contributor

Summary

Test plan

When a branch changes package-lock.json (e.g. a new-rule PR adding a
devDependency, or a Renovate bump), the npm cache is keyed on the
lockfile hash. The gh-action_cache save step skips uploading a cache
entry under that hash whenever the freshly installed content matches
what's already cached for the default branch, relying on cross-branch
fallback restores to cover it later. But the fallback lookup reuses
the same (branch-specific) hash suffix instead of the default branch's
own hash, so it misses whenever the lockfile actually differs from
master - leaving jobs like prepare_rspec_rule_data with no
node_modules at all and failing with "tsx: not found".

Add a conditional npm ci fallback (mirroring the existing
populate_npm_cache pattern) to every job that only restores the npm
cache, so a miss no longer breaks the build.
@nathsou nathsou requested a review from a team July 8, 2026 07:51
@hashicorp-vault-sonar-prod hashicorp-vault-sonar-prod Bot changed the title Fix CI npm cache miss leaving node_modules empty on branches JS-2022 Fix CI npm cache miss leaving node_modules empty on branches Jul 8, 2026
@hashicorp-vault-sonar-prod

hashicorp-vault-sonar-prod Bot commented Jul 8, 2026

Copy link
Copy Markdown

JS-2022

@github-actions

github-actions Bot commented Jul 8, 2026

Copy link
Copy Markdown
Contributor

Ruling Report

Code no longer flagged (2 issues)

S8784

vitest/test/typescript/failing/fail.test-d.ts:15

    13 |   })
    14 | 
>   15 |   expectTypeOf(1).toBeVoid()
    16 | })
    17 | 

vitest/test/typescript/test-d/test.test-d.ts:49

    47 | })
    48 | 
>   49 | expectTypeOf({ wolk: 'true' }).toHaveProperty('wolk')
    50 | 

nathsou added a commit that referenced this pull request Jul 8, 2026
The floating v1 tag now resolves to a commit (8d5f45db5f, "Skip
duplicate S3 cache save when content matches the default-branch
fallback", merged 2026-06-30) that skips saving the npm cache under a
branch's own lockfile-hash key whenever content matches master's, and
relies on a fallback restore that doesn't account for a differing
lockfile hash - leaving node_modules empty on any branch that changes
package-lock.json (like this one, which adds eslint-plugin-testing-library).

v1.7.1 predates that change. Pinning here as a test to confirm this
is really the regression before deciding between reverting to a
pinned version repo-wide vs. the npm-ci-fallback approach in #7494.
@nathsou nathsou removed the request for review from a team July 8, 2026 08:01
@nathsou nathsou self-assigned this Jul 8, 2026
@nathsou nathsou marked this pull request as draft July 8, 2026 08:01
nathsou added 2 commits July 8, 2026 10:30
Confirmed on PR #7488 that pinning to v1.7.1 (the release before
8d5f45db5f, "Skip duplicate S3 cache save when content matches the
default-branch fallback", merged into the gh-action_cache v1 branch on
2026-06-30) resolves the cache-miss/"tsx: not found" failure directly,
without needing a fallback install step. That commit is the actual
regression: it skips saving an npm cache entry under a branch's own
lockfile-hash key whenever content matches master's, relying on a
fallback restore that doesn't account for a differing lockfile hash -
so restore-only jobs end up with no node_modules at all whenever a
branch's lockfile actually differs from master (e.g. a new
devDependency, or a Renovate bump).

Pinning to v1.7.1 undoes the regression directly instead of working
around its effects.
@nathsou nathsou changed the title JS-2022 Fix CI npm cache miss leaving node_modules empty on branches Pin gh-action_cache to v1.7.1 to fix CI npm cache miss Jul 8, 2026
nathsou added a commit that referenced this pull request Jul 8, 2026
That pin was only pushed here to validate the CI cache-miss root cause
(confirmed - see #7494). The real fix belongs in build.yml on master
via #7494, not duplicated per-PR; this branch will pick it up on the
next rebase/merge once #7494 lands.
@nathsou nathsou marked this pull request as ready for review July 8, 2026 08:48
@nathsou nathsou changed the title Pin gh-action_cache to v1.7.1 to fix CI npm cache miss JS-2022 - Pin gh-action_cache to v1.7.1 to fix CI npm cache miss Jul 8, 2026
@vdiez

vdiez commented Jul 8, 2026

Copy link
Copy Markdown
Contributor

we should probably consider using https://github.com/actions/cache directly instead of relying on sonarsource cache action, like we do with the orchestrator cache. I don't think SonarJS benefits/needs S3 caching done by sonarsource cache

@erwan-leforestier-sonarsource

Copy link
Copy Markdown
Contributor

The issue I fixed yesterday was similar to yours but it was for test coverage files cache, and not for node_modules cache. Here is the link to my PR if you want to have a look: #7481

From what I understood by investigating this issue with codex, this is due to the use of the lookup_only: true flag used in our workflows, that was not properly working before but it's now properly working since the fix in SonarSource/gh-action_cache, the same commit you mentioned: SonarSource/gh-action_cache@8d5f45d

Purpose of this flag is to say "just check that the cache exist but don't read from it and don't save anything in it". Before their fix, it was always reading the cache so we ended up with files available. Now it's breaking because files are not available anymore.

In my other PR, I fixed it by removing this flag which does a normal restore, so it's kind of "Read it from the cache, but if it fails then run tests to generate the test coverage file and populate the cache with it" and I've also added an explicit upload artifacts inside jobs that require these artifacts (in my case, only "Next SonarQube Analysis" needed it).
You probably want the same in your case, "try restore node_modules from the cache but if it fails, run npm i and populate the cache".

All of this to say that downgrading to gh-action_cache is not a good idea because it's not a bug on their side, it's a bug they actually fixed and it will remain like this so there is no upstream fix to expect, this is an issue on our side.

If you're in a hurry, I'm ok downgrading to v1.7 for now but we should at least open a ticket to properly fix our CI later.

lookup-only: true on populate_npm_cache's cache step means the action
never actually saves node_modules under the branch key (mode=lookup:
"no restore, no save"), same latent bug already fixed for the JS
coverage cache in #7481. It only appeared to work when a branch's
lockfile hash matched master's, via the fallback-exact-key path.

Drop lookup-only so the step does a normal restore-or-install, letting
the action's post-step genuinely save under the branch's own key.
Downstream jobs (build, test_js, test_js_win, prepare_rspec_rule_data)
already do a plain restore against that same key and get a real hit
once it's actually populated - no need to pin gh-action_cache back.
@nathsou

nathsou commented Jul 8, 2026

Copy link
Copy Markdown
Contributor Author

@erwan-leforestier-sonarsource good catch, and thanks for the pointer to #7481 — you were right, this is the same latent-bug pattern.

populate_npm_cache's "Cache NPM dependencies" step was passing lookup-only: true. With the fixed action behavior, that forces mode=lookup (no restore, no save), so the job was never actually saving a branch-scoped node_modules cache entry — it only looked like it worked when a branch's lockfile hash happened to match master's (served via the fallback-exact-key path). Different lockfile hash → no save ever happened → downstream restore-only jobs had nothing to restore.

Dropped lookup-only: true and left it as a normal restore-or-install, same spirit as your coverage-cache fix (just without the artifact-upload step, since the existing downstream jobs already do plain restores against the same key and node_modules is too big to want as a workflow artifact). gh-action_cache stays on @v1, no pin needed.

Validated by merging this fix into #7488 (real lockfile diff there): Prepare RSPEC rule data failed with the original tsx: not found beforehand, and went green afterward along with the rest of the pipeline. Pushed the updated PR description too.

Still agree a tracking ticket for auditing other lookup-only usages in build.yml is worthwhile — will file one, though test_js_win's marker-file check (js-test-win-...) looks like a legitimate lookup-only use since it never needs to restore the marker's content, so I don't think that one needs to change.

@sonarqube-next

sonarqube-next Bot commented Jul 8, 2026

Copy link
Copy Markdown

Quality Gate passed Quality Gate passed

Issues
0 New issues
0 Fixed issues
0 Accepted issues

Measures
0 Security Hotspots
0 Dependency risks
No data about Coverage
No data about Duplication

See analysis details on SonarQube

@nathsou nathsou changed the title JS-2022 - Pin gh-action_cache to v1.7.1 to fix CI npm cache miss JS-2022 - Fix npm cache never being saved due to lookup-only mode Jul 8, 2026
@nathsou nathsou merged commit fe0b1c8 into master Jul 8, 2026
43 checks passed
@nathsou nathsou deleted the fix/ci-npm-cache-miss-fallback branch July 8, 2026 12:44
@gitar-bot

gitar-bot Bot commented Jul 8, 2026

Copy link
Copy Markdown
Code Review 👍 Approved with suggestions 0 resolved / 1 findings

Pins gh-action_cache to v1.7.1 to resolve CI cache misses caused by a downstream regression. Please update the PR title and description to reflect the current implementation state.

💡 Quality: PR title/description no longer matches the actual change

🔗 link

The PR title ("Pin gh-action_cache to v1.7.1") and the summary describe pinning every gh-action_cache usage to v1.7.1. However, the final commit (cc638ba) reverses that approach: all usages remain on the floating @v1 tag and the actual fix is the removal of lookup-only: true from the populate_npm_cache step (net PR diff vs master is only that one deleted line). A reviewer approving based on the current title/summary would expect the opposite of what the code does, and the git history/PR description will be misleading later. Please update the title and summary to reflect the real fix — removing lookup-only: true so the populate job installs and saves node_modules under the branch key instead of relying on the regressed cross-branch fallback restore. Also note the summary's premise that @v1 still contains the regression: confirm downstream jobs are unaffected now that population, rather than the action version, is what changed.

🤖 Prompt for agents
Code Review: Pins `gh-action_cache` to `v1.7.1` to resolve CI cache misses caused by a downstream regression. Please update the PR title and description to reflect the current implementation state.

1. 💡 Quality: PR title/description no longer matches the actual change

   The PR title ("Pin gh-action_cache to v1.7.1") and the summary describe pinning every `gh-action_cache` usage to `v1.7.1`. However, the final commit (`cc638ba`) reverses that approach: all usages remain on the floating `@v1` tag and the actual fix is the removal of `lookup-only: true` from the `populate_npm_cache` step (net PR diff vs master is only that one deleted line). A reviewer approving based on the current title/summary would expect the opposite of what the code does, and the git history/PR description will be misleading later. Please update the title and summary to reflect the real fix — removing `lookup-only: true` so the populate job installs and saves `node_modules` under the branch key instead of relying on the regressed cross-branch fallback restore. Also note the summary's premise that `@v1` still contains the regression: confirm downstream jobs are unaffected now that population, rather than the action version, is what changed.

Options

Auto-apply is off → Gitar will not commit updates to this branch.
Display: compact → Showing less information.

Comment with these commands to change the behavior for this request:

Auto-apply Compact
gitar auto-apply:on         
gitar display:verbose         

Was this helpful? React with 👍 / 👎 | Gitar

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.

3 participants