[KLC-1927] Skip actions/cache on self-hosted runners to fix tar "Cannot open: File exists" errors#71
[KLC-1927] Skip actions/cache on self-hosted runners to fix tar "Cannot open: File exists" errors#71fbsobreira wants to merge 3 commits into
Conversation
…sions The klever-pipe self-hosted runners persist ~/go/pkg/mod and ./vendor across runs, so actions/cache restores its tarball over files that already exist and emits "/usr/bin/tar: Cannot open: File exists" for every collision, flooding the Actions UI with error annotations even on success. Gate the cache step to GitHub-hosted runners only (runner.environment == 'github-hosted'), where the runner is ephemeral and the cache still helps. On self-hosted runners the step is skipped and the existing cache-hit-gated download/vendor steps regenerate from the persistent dirs. Also drop the legacy enableCrossOsArchive flag.
WalkthroughUpgrade GitHub Actions step major versions across CI and release workflows; refine the Go setup composite action by switching to actions/setup-go@v6, requiring GitHub-hosted runners for dependency caching, updating cache to actions/cache@v5 and removing enableCrossOsArchive, and bumping upload/download and other third-party action majors (upload-artifact, download-artifact, sonarsource, docker tooling, softprops, google auth/upload). ChangesActions and caching updates
Estimated code review effort🎯 3 (Moderate) | ⏱️ ~20 minutes Suggested labels
🚥 Pre-merge checks | ✅ 8✅ Passed checks (8 passed)
✏️ Tip: You can configure your own custom pre-merge checks in the settings. ✨ Finishing Touches🧪 Generate unit tests (beta)
Comment |
There was a problem hiding this comment.
Pull request overview
This PR adjusts the shared Go composite action to avoid noisy tar: Cannot open: File exists cache-restore annotations on persistent self-hosted runners by skipping actions/cache when the runner isn’t GitHub-hosted.
Changes:
- Gate the
actions/cache@v4“Cache Go dependencies” step to GitHub-hosted runners only usingrunner.environment == 'github-hosted'. - Remove the legacy
enableCrossOsArchive: truecache option.
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
Node.js 20 is deprecated on GitHub Actions runners (forced to Node 24 from 2026-06-16, removed 2026-09-16). Bump the actions still on node20 to their latest Node 24 majors: actions/setup-go v5 -> v6 actions/cache v4 -> v5 actions/upload-artifact v5 -> v7 actions/download-artifact v6 -> v8 The klever-pipe self-hosted runner is 2.334.0, above the 2.327.1 minimum these majors require. No params used here changed across the bumps.
Remaining node20 JS actions flagged by the deprecation notice. Bumped to their latest Node 24 majors (inputs we use are unchanged): sonarsource/sonarqube-scan-action v6 -> v8 softprops/action-gh-release v2 -> v3 google-github-actions/auth v2 -> v3 google-github-actions/upload-cloud-storage v2 -> v3 docker/setup-qemu-action v3 -> v4 docker/setup-buildx-action v3 -> v4 docker/login-action v3 -> v4 sonarqube-scan-action v8 enables scanner signature verification by default (skipSignatureVerification now false); auth v3 keeps credentials_json; upload-cloud-storage v3 keeps predefinedAcl/parent; setup-buildx v4 keeps driver-opts. quality-gate-action and twingate are composite (unaffected); golangci-lint-action and actions/checkout are already Node 24.
There was a problem hiding this comment.
Actionable comments posted: 2
Caution
Some comments are outside the diff and can’t be posted inline due to platform limitations.
⚠️ Outside diff range comments (2)
.github/workflows/pr-qa-sec.yaml (1)
126-142:⚠️ Potential issue | 🟠 Major | ⚡ Quick winSet
skipSignatureVerification(or installgpg/dirmngr) forsonarqube-scan-action@v8onklever-pipe
pr-qa-sec.yamlrunssonarsource/sonarqube-scan-action@v8onruns-on: klever-pipe(two scan steps) withoutskipSignatureVerification. In v8 the default isfalse, so the scan enforces Scanner CLI signature verification and requiresgpg+dirmngron self-hosted runners; if either is missing on any runner, the job can hard-fail.🛡️ Fallback if the pool can’t guarantee gpg/dirmngr (apply to both Sonar scan steps)
- name: SonarQube Scan uses: sonarsource/sonarqube-scan-action@v8 env: SONAR_TOKEN: ${{ secrets.SONAR_TOKEN }} SONAR_HOST_URL: ${{ secrets.SONAR_HOST_URL }} with: + skipSignatureVerification: true args: >Prefer installing
gpganddirmngron allklever-piperunners and only useskipSignatureVerification: trueas a compatibility fallback.🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the rest with a brief reason, keep changes minimal, and validate. In @.github/workflows/pr-qa-sec.yaml around lines 126 - 142, The SonarQube scan steps using sonarsource/sonarqube-scan-action@v8 can hard-fail on the self-hosted klever-pipe runners because signature verification requires gpg/dirmngr; update both Sonar scan steps to either install gpg and dirmngr on the runner before the action (e.g., add a prep step that installs gpg + dirmngr) or add the action input skipSignatureVerification: true to both sonarqube-scan-action@v8 usages (preferred only as a fallback) so signature verification won’t hard-fail when gpg/dirmngr are absent..github/workflows/release.yaml (1)
52-56:⚠️ Potential issue | 🟠 Major | ⚖️ Poor tradeoffPass git credentials to the build job’s
go-setup-action(cache miss can break private module fetch).In
.github/workflows/release.yaml(Go Setup, ~lines 52-56), the build matrix runs./.github/actions/go-setup-actionwithoutgit-user/git-pass. The composite action configures authenticated Git access only when both inputs are set, sogo mod tidy/go mod downloadon GitHub-hosted runners can fail when privategithub.com/klever-io/*modules are required and the cache is cold.Although
setup-and-lintpasses credentials, it runs onruns-on: klever-pipe, and the action’s cache step is gated torunner.environment == 'github-hosted', so it won’t populate the cache that the build job relies on.🔐 Proposed fix
- name: Go Setup uses: ./.github/actions/go-setup-action with: go-version: ${{ vars.GO_VERSION || '1.25.7' }} + git-user: ${{ secrets.GIT_USER }} + git-pass: ${{ secrets.GIT_PASS }}🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the rest with a brief reason, keep changes minimal, and validate. In @.github/workflows/release.yaml around lines 52 - 56, The Go setup composite action is invoked without credentials, so private module fetches can fail on cache miss; update the step that uses ./.github/actions/go-setup-action to pass git-user and git-pass inputs (e.g., git-user: ${{ github.actor }} and git-pass: ${{ secrets.GITHUB_TOKEN }}) so the action’s authenticated Git configuration is enabled when running the build; modify the step that contains uses: ./.github/actions/go-setup-action to include these two inputs.
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.
Inline comments:
In @.github/workflows/release-docker.yaml:
- Around line 80-82: The current workflow uses docker/setup-qemu-action@v4 with
platforms: linux/amd64,linux/arm64 which is valid because the action still
accepts a comma-separated platforms input; leave the platforms line as-is but
for supply-chain hardening replace the floating tag docker/setup-qemu-action@v4
with a specific commit SHA (i.e., pin the action) while keeping the platforms
input unchanged.
In @.github/workflows/release.yaml:
- Line 85: Replace mutable action tags with immutable commit SHAs for each
"uses:" entry (e.g., change softprops/action-gh-release@v3 to the specific
commit SHA) and add the human-readable tag as an inline comment for clarity;
update all occurrences called out in the review (the softprops/action-gh-release
usage and the other listed "uses:" lines) so the workflow pins to the exact
commit SHA while keeping the original tag as a comment.
---
Outside diff comments:
In @.github/workflows/pr-qa-sec.yaml:
- Around line 126-142: The SonarQube scan steps using
sonarsource/sonarqube-scan-action@v8 can hard-fail on the self-hosted
klever-pipe runners because signature verification requires gpg/dirmngr; update
both Sonar scan steps to either install gpg and dirmngr on the runner before the
action (e.g., add a prep step that installs gpg + dirmngr) or add the action
input skipSignatureVerification: true to both sonarqube-scan-action@v8 usages
(preferred only as a fallback) so signature verification won’t hard-fail when
gpg/dirmngr are absent.
In @.github/workflows/release.yaml:
- Around line 52-56: The Go setup composite action is invoked without
credentials, so private module fetches can fail on cache miss; update the step
that uses ./.github/actions/go-setup-action to pass git-user and git-pass inputs
(e.g., git-user: ${{ github.actor }} and git-pass: ${{ secrets.GITHUB_TOKEN }})
so the action’s authenticated Git configuration is enabled when running the
build; modify the step that contains uses: ./.github/actions/go-setup-action to
include these two inputs.
🪄 Autofix (Beta)
Fix all unresolved CodeRabbit comments on this PR:
- Push a commit to this branch (recommended)
- Create a new PR with the fixes
ℹ️ Review info
⚙️ Run configuration
Configuration used: Path: .coderabbit.yaml
Review profile: ASSERTIVE
Plan: Pro
Run ID: 6e346c22-bc65-4f80-93de-4d28e0a2bd84
📒 Files selected for processing (3)
.github/workflows/pr-qa-sec.yaml.github/workflows/release-docker.yaml.github/workflows/release.yaml
📜 Review details
⏰ Context from checks skipped due to timeout of 90000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (1)
- GitHub Check: Analyze (go)
🧰 Additional context used
🪛 zizmor (1.25.2)
.github/workflows/release.yaml
[error] 85-85: unpinned action reference (unpinned-uses): action is not pinned to a hash (required by blanket policy)
(unpinned-uses)
[info] 85-85: action functionality is already included by the runner (superfluous-actions): use gh release in a script step
(superfluous-actions)
[error] 106-106: unpinned action reference (unpinned-uses): action is not pinned to a hash (required by blanket policy)
(unpinned-uses)
[error] 111-111: unpinned action reference (unpinned-uses): action is not pinned to a hash (required by blanket policy)
(unpinned-uses)
[error] 118-118: unpinned action reference (unpinned-uses): action is not pinned to a hash (required by blanket policy)
(unpinned-uses)
[error] 125-125: unpinned action reference (unpinned-uses): action is not pinned to a hash (required by blanket policy)
(unpinned-uses)
[error] 132-132: unpinned action reference (unpinned-uses): action is not pinned to a hash (required by blanket policy)
(unpinned-uses)
.github/workflows/release-docker.yaml
[error] 80-80: unpinned action reference (unpinned-uses): action is not pinned to a hash (required by blanket policy)
(unpinned-uses)
[error] 86-86: unpinned action reference (unpinned-uses): action is not pinned to a hash (required by blanket policy)
(unpinned-uses)
[error] 94-94: unpinned action reference (unpinned-uses): action is not pinned to a hash (required by blanket policy)
(unpinned-uses)
.github/workflows/pr-qa-sec.yaml
[error] 127-127: unpinned action reference (unpinned-uses): action is not pinned to a hash (required by blanket policy)
(unpinned-uses)
[error] 145-145: unpinned action reference (unpinned-uses): action is not pinned to a hash (required by blanket policy)
(unpinned-uses)
🔇 Additional comments (8)
.github/workflows/release-docker.yaml (2)
94-97: ⚡ Quick winValidate
docker/login-action@v4input compatibility (username/password).
docker/login-action@v4exists and continues to support thewith.usernameandwith.passwordinputs for authenticating to a container registry—your workflow snippet is aligned with the expected interface.
86-90: ⚡ Quick windocker/setup-buildx-action@v4 is compatible with
driver-opts.driver-optsremains a supported input in v4 and is passed through todocker buildx createas a newline-delimited list, so the multilineimage=moby/buildkit:latest/network=hostconfiguration is still valid..github/workflows/pr-qa-sec.yaml (3)
144-162: Same v8 signature-verification breaking change applies here.The
SonarQube Go detailed scan PRstep has the identical exposure as theSonarQube Scanstep above; whatever resolution is chosen (installgpg/dirmngron the pool, or setskipSignatureVerification: true) must be applied to both.
84-94: LGTM!
112-120:download-artifact@v8is compatible with theupload-artifact@v7producers.The
test-artifactsupload (Line 86) and thelint-resultsupload ingo-setup-lint.yamlboth use the default archive behavior (zipped), and to support direct uploads, download-artifact@v8 no longer attempts to unzip all downloaded files; instead it checks the Content-Type header ahead of unzipping and skips non-zipped files. Since the producers stay zipped, decompression still works. Note that v8 lets you configure behavior on a download hash mismatch via the digest-mismatch parameter, and the default is now error which will fail the workflow run — fail-fast on corruption, which is the desired behavior here..github/workflows/release.yaml (3)
106-108: ⚡ Quick wingoogle-github-actions/auth@v3 keeps
credentials_jsonas a supported input.
The official v3 docs/README and the v3.0.0 release notes still documentcredentials_jsonas the required Service Account Key JSON input forgoogle-github-actions/auth@v3(samewith: credentials_json: ...pattern) with no documented breaking change for this field, so the workflow snippet should remain compatible.
85-85: ⚡ Quick winsoftprops/action-gh-release@v3 input compatibility is OK
files,generate_release_notes,draft, andprereleaseare supported inputs insoftprops/action-gh-release@v3and align with the workflow’s usage. The v2→v3 breaking change is the Node runtime upgrade (Node 20 → Node 24); there are no documented functional breaking changes affecting these inputs.
111-111: ⚡ Quick winVerify
google-github-actions/upload-cloud-storage@v3input compatibility (predefinedAcl,parent). [verify_review_comment: critical_fixes_required]
The v3.0.0 release notes mainly call out the Node 24 runner requirement, but there’s no evidence here thatpredefinedAcl(used in all steps) andparent(used only in the last step:parent: false) keep the same schema/semantics in v3. Confirm v3 still supports these inputs and that they apply the same ACL/path behavior; otherwise uploads could end up with incorrect object ACLs and/or different destination path structure.
Problem
Workflows on the self-hosted
klever-piperunners flood the Actions UI with/usr/bin/tar: Cannot open: File existsannotations during cache restore (hundreds of thousands per run), masking real failures. The runners persist~/go/pkg/modand./vendorbetween runs, soactions/cache@v4extracts its tarball over files that already exist and errors on every collision.Change
Cache Go dependenciesstep to ephemeral GitHub-hosted runners only:if: inputs.cache-enabled == 'true' && runner.environment == 'github-hosted'.On self-hosted runners the step is skipped; the existing
cache-hit-gateddownload/vendor steps regenerate from the persistent dirs.
enableCrossOsArchive: trueflag.Why
runner.environmentThe root cause is self-hosted persistence, not the
klever-pipelabel specifically. Gating onrunner.environmentcovers any self-hosted runner and fails safe (a missing value still skips the cache on self-hosted). Ephemeralubuntu/macosjobs keep caching unchanged.Also: Node.js 24 runtime bumps
Node.js 20 is deprecated on GitHub Actions runners (forced to Node 24 from 2026-06-16, removed 2026-09-16). Bumped every action still on node20 to its latest Node 24 major. Inputs we use are unchanged across the bumps.
GitHub-owned:
actions/setup-goactions/cacheactions/upload-artifactactions/download-artifactThird-party:
sonarsource/sonarqube-scan-actionsoftprops/action-gh-releasegoogle-github-actions/authgoogle-github-actions/upload-cloud-storagedocker/setup-qemu-actiondocker/setup-buildx-actiondocker/login-actionThese majors require Actions Runner ≥ 2.327.1;
klever-pipeis on 2.334.0. Already Node 24 and left as-is:actions/checkout@v6,golangci/golangci-lint-action@v9. Composite (unaffected):sonarsource/sonarqube-quality-gate-action,twingate/github-action.Notable behavior changes verified safe for our usage:
sonarqube-scan-action@v8enables scanner signature verification by default;auth@v3retainscredentials_json;upload-cloud-storage@v3retainspredefinedAcl/parent;setup-buildx@v4retainsdriver-opts.Notes for reviewers
klever-pipeis a multi-runner pool, so standalone creds-less jobs (release-docker → build-multi-arch,push → validate-and-build,pr-qa-sec → test) rely on each runner's persistent module dirs after the cache change. The common case is unaffected. If a new privateklever-io/*module is added and a creds-less job lands on a runner that lacks it, passGIT_USER/GIT_PASSto that job'sgo-setup-actionstep.Verification
release-docker.yamlonklever-pipe→ 0Cannot open: File existsannotationsgo-setup-lint.yaml(PR / workflow_call) → 0 annotationsSummary
This PR updates CI to skip the GitHub Actions cache restore on self-hosted runners and bumps several actions to Node.js 24–compatible majors.
What changed
if: inputs.cache-enabled == 'true' && runner.environment == 'github-hosted'
(previously only checked inputs.cache-enabled).
Rationale
Self-hosted klever-pipe runners persist ~/go/pkg/mod and ./vendor between runs. actions/cache was extracting tarballs over existing files on those runners, producing many "/usr/bin/tar: Cannot open: File exists" annotations that hid real failures. Restricting the cache restore to GitHub-hosted runners avoids these noisy tar errors while preserving caching behavior on ephemeral hosted runners. On self-hosted runners, persistent directories continue to be used and the download/vendor steps regenerate dependencies when needed.
Verification checklist (kept)
Impact on blockchain-critical components
Reviewer notes