Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
35 commits
Select commit Hold shift + click to select a range
8fdfdfe
perf(ci): disable buildvcs to improve Go build cache efficiency
davdhacs Feb 18, 2026
7173d76
empty commit
davdhacs Feb 19, 2026
046ed05
empty commit
davdhacs Feb 19, 2026
07fcb33
empty commit
davdhacs Feb 19, 2026
2ec9c25
empty commit
davdhacs Feb 19, 2026
3566da5
empty commit
davdhacs Feb 19, 2026
b49ed70
ci: temporarily enable cache saves on test branch
davdhacs Feb 19, 2026
8eb5eba
ci: allow cache saves on PRs with ci-save-cache label
davdhacs Feb 19, 2026
d705061
empty commit
davdhacs Feb 19, 2026
b8dad64
perf(ci): derive GitCommit from MainVersion, remove -X ldflags injection
davdhacs Feb 19, 2026
89e6230
Merge branch 'master' into davdhacs/gha-disable-buildvcs
davdhacs Feb 19, 2026
ee29ef8
empty commit
davdhacs Feb 19, 2026
1edc031
empty commit
davdhacs Feb 19, 2026
7f1a1c0
empty commit
davdhacs Feb 20, 2026
64385e7
empty commit
davdhacs Feb 20, 2026
6526120
empty commit
davdhacs Feb 20, 2026
076db7c
empty commit
davdhacs Feb 20, 2026
2df7925
empty commit
davdhacs Feb 20, 2026
0b0a150
empty commit
davdhacs Feb 20, 2026
d0583a0
Add CI benchmark for go build git index optimization
davdhacs Feb 21, 2026
ad46e0e
Add push trigger for git index benchmark workflow
davdhacs Feb 21, 2026
ab6a92e
Improve benchmark workflow with GOCACHE diagnostics
davdhacs Feb 21, 2026
7586559
Test patched Go in full pre-build-cli and pre-build-go-binaries jobs
davdhacs Feb 21, 2026
87fa2bf
Restructure benchmark: cache patched Go binary, chain cold→warm jobs
davdhacs Feb 21, 2026
32d4edf
Add continue-on-error to all build/timing steps
davdhacs Feb 21, 2026
aa622b6
Add cross-run GOCACHE reuse + diagnostics for cache misses
davdhacs Feb 21, 2026
11b555f
empty commit
davdhacs Feb 21, 2026
44d6bd7
empty commit
davdhacs Feb 21, 2026
59ba12c
always run
davdhacs Feb 21, 2026
ff1adfe
empty commit
davdhacs Feb 21, 2026
5ff4ce2
empty commit
davdhacs Feb 21, 2026
9e1a72f
Gate all optimizations behind GONOBITINDEX + fair baseline comparison
davdhacs Feb 21, 2026
098af8d
empty commit
davdhacs Feb 21, 2026
a77834e
empty commit
davdhacs Feb 21, 2026
b23a670
empty commit
davdhacs Feb 21, 2026
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
15 changes: 8 additions & 7 deletions .github/actions/cache-go-dependencies/action.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -14,37 +14,38 @@ runs:
echo "GOCACHE=$(go env GOCACHE)" >> "$GITHUB_OUTPUT"
echo "GOMODCACHE=$(go env GOMODCACHE)" >> "$GITHUB_OUTPUT"
echo "GOARCH=$(go env GOARCH)" >> "$GITHUB_OUTPUT"
echo "TAG=$(date +%Yw%U)" >> "$GITHUB_OUTPUT"
TAG="${{ contains(github.event.pull_request.labels.*.name, 'ci-save-cache') && github.event.pull_request.number || '' }}"
echo "TAG=${TAG:-$(date +%Yw%U)}" >> "$GITHUB_OUTPUT"
shell: bash

# Save caches only on pushes to the default branch.
# All other events (PRs, etc.) restore only.
# Save caches on pushes to the default branch, or on PRs with the
# ci-save-cache label (for testing cache-affecting changes on branches).
- name: Cache Go Dependencies (save)
if: inputs.save == 'true' && (github.event_name == 'push' && github.ref_name == github.event.repository.default_branch)
if: inputs.save == 'true' && (github.event_name == 'push' && github.ref_name == github.event.repository.default_branch || contains(github.event.pull_request.labels.*.name, 'ci-save-cache'))
Comment on lines 23 to +24
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

issue (bug_risk): Referencing github.event.pull_request on non-PR events can break the workflow expression.

On push events, github.event.pull_request is undefined, and accessing its properties can cause the workflow condition to error. To avoid failures on pushes, wrap the label check in an event guard, e.g.:

if: inputs.save == 'true' && (
  (github.event_name == 'push' && github.ref_name == github.event.repository.default_branch) ||
  (github.event_name == 'pull_request' && contains(github.event.pull_request.labels.*.name, 'ci-save-cache'))
)

This preserves the intended behavior without touching github.event.pull_request when it doesn’t exist.

uses: actions/cache@v5
with:
path: ${{ steps.cache-paths.outputs.GOMODCACHE }}
key: go-mod-v1-${{ hashFiles('**/go.sum') }}
restore-keys: go-mod-v1-

- name: Cache Go Dependencies (restore)
if: ${{ !(inputs.save == 'true' && (github.event_name == 'push' && github.ref_name == github.event.repository.default_branch)) }}
if: ${{ !(inputs.save == 'true' && (github.event_name == 'push' && github.ref_name == github.event.repository.default_branch || contains(github.event.pull_request.labels.*.name, 'ci-save-cache'))) }}
Comment on lines 31 to +32
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

suggestion (bug_risk): The restore condition has the same pull_request access risk and is hard to reason about with the negation.

To avoid undefined access and keep the logic easier to validate, consider reusing the guarded save condition and inverting it for restore, e.g.:

if: ${{ !(inputs.save == 'true' && (
  (github.event_name == 'push' && github.ref_name == github.event.repository.default_branch) ||
  (github.event_name == 'pull_request' && contains(github.event.pull_request.labels.*.name, 'ci-save-cache'))
)) }}

This keeps restore as the exact inverse of the guarded save condition while only evaluating github.event.pull_request for PR events.

Suggested implementation:

    - name: Cache Go Dependencies (save)
      if: inputs.save == 'true' && ((github.event_name == 'push' && github.ref_name == github.event.repository.default_branch) || (github.event_name == 'pull_request' && contains(github.event.pull_request.labels.*.name, 'ci-save-cache')))
      uses: actions/cache@v5

    - name: Cache Go Dependencies (restore)
      if: ${{ !(inputs.save == 'true' && ((github.event_name == 'push' && github.ref_name == github.event.repository.default_branch) || (github.event_name == 'pull_request' && contains(github.event.pull_request.labels.*.name, 'ci-save-cache')))) }}
      uses: actions/cache/restore@v5

uses: actions/cache/restore@v5
with:
path: ${{ steps.cache-paths.outputs.GOMODCACHE }}
key: go-mod-v1-${{ hashFiles('**/go.sum') }}
restore-keys: go-mod-v1-

- name: Cache Go Build (save)
if: inputs.save == 'true' && (github.event_name == 'push' && github.ref_name == github.event.repository.default_branch)
if: inputs.save == 'true' && (github.event_name == 'push' && github.ref_name == github.event.repository.default_branch || contains(github.event.pull_request.labels.*.name, 'ci-save-cache'))
uses: actions/cache@v5
with:
path: ${{ steps.cache-paths.outputs.GOCACHE }}
key: go-build-v1-${{ github.job }}-${{ steps.cache-paths.outputs.GOARCH }}-${{ steps.cache-paths.outputs.TAG }}
restore-keys: go-build-v1-${{ github.job }}-${{ steps.cache-paths.outputs.GOARCH }}-

- name: Cache Go Build (restore)
if: ${{ !(inputs.save == 'true' && (github.event_name == 'push' && github.ref_name == github.event.repository.default_branch)) }}
if: ${{ !(inputs.save == 'true' && (github.event_name == 'push' && github.ref_name == github.event.repository.default_branch || contains(github.event.pull_request.labels.*.name, 'ci-save-cache'))) }}
uses: actions/cache/restore@v5
with:
path: ${{ steps.cache-paths.outputs.GOCACHE }}
Expand Down
333 changes: 333 additions & 0 deletions .github/workflows/test-go-gitindex.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,333 @@
name: Test Go Git Index Optimization

on:
workflow_dispatch:
push:
branches:
- 'davdhacs/gha-disable-buildvcs'

defaults:
run:
shell: bash

jobs:

# ==================================================================
# Build patched Go toolchain (cached by patch hash)
# ==================================================================
build-patched-go:
runs-on: ubuntu-latest
container:
image: quay.io/stackrox-io/apollo-ci:stackrox-test-0.5.2
volumes:
- /usr:/mnt/usr
- /opt:/mnt/opt
steps:
- name: Checkout
uses: actions/checkout@v6

- name: Cache patched Go toolchain
id: go-cache
uses: actions/cache@v5
with:
path: /tmp/go-patched
key: patched-go-v1-${{ hashFiles('scripts/go-gitindex.patch') }}

- name: Build patched Go toolchain
if: steps.go-cache.outputs.cache-hit != 'true'
run: |
set -euo pipefail
echo "::group::Clone Go 1.25.7"
git clone --depth=1 --branch go1.25.7 https://go.googlesource.com/go /tmp/go-patched 2>&1
echo "::endgroup::"

echo "::group::Apply patch"
cd /tmp/go-patched
git apply "$GITHUB_WORKSPACE/scripts/go-gitindex.patch"
echo "::endgroup::"

echo "::group::Build Go toolchain"
cd /tmp/go-patched/src
GOROOT_BOOTSTRAP="$(go env GOROOT)" ./make.bash 2>&1 | tail -5
echo "::endgroup::"

- name: Verify patched Go
continue-on-error: true
run: |
echo "Patched Go: $(/tmp/go-patched/bin/go version)"
echo "Compiler SHA256:"
sha256sum "/tmp/go-patched/pkg/tool/linux_amd64/compile" 2>/dev/null || true

# ==================================================================
# BASELINE: patched Go binary, all optimizations DISABLED
# Same compiler binary + fresh per-run cache = fair comparison
# ==================================================================
pre-build-go-binaries:
needs: build-patched-go
runs-on: ubuntu-latest
container:
image: quay.io/stackrox-io/apollo-ci:stackrox-test-0.5.2
volumes:
- /usr:/mnt/usr
- /opt:/mnt/opt
env:
GONOBITINDEX: "1"
steps:
- name: Checkout
uses: actions/checkout@v6
with:
fetch-depth: 0

- uses: ./.github/actions/job-preamble
with:
gcp-account: ${{ secrets.GCP_SERVICE_ACCOUNT_STACKROX_CI }}

- name: Restore patched Go toolchain
uses: actions/cache/restore@v5
with:
path: /tmp/go-patched
key: patched-go-v1-${{ hashFiles('scripts/go-gitindex.patch') }}

- name: Set patched Go as default
run: |
echo "/tmp/go-patched/bin" >> "$GITHUB_PATH"
echo "GOROOT=/tmp/go-patched" >> "$GITHUB_ENV"

# Restore GOCACHE with per-run key (fresh cache, not stale weekly)
- name: Restore GOCACHE
id: baseline-gocache
uses: actions/cache/restore@v5
with:
path: /github/home/.cache/go-build
key: baseline-gocache-v1-${{ hashFiles('scripts/go-gitindex.patch') }}-${{ github.run_id }}
restore-keys: |
baseline-gocache-v1-${{ hashFiles('scripts/go-gitindex.patch') }}-

- name: Restore GOMODCACHE
uses: actions/cache/restore@v5
with:
path: /github/home/go/pkg/mod
key: go-mod-v1-${{ hashFiles('**/go.sum') }}
restore-keys: go-mod-v1-

- name: Download Go modules
run: make deps --always-make

- name: Record environment
continue-on-error: true
run: |
echo "Go: $(go version)"
echo "GONOBITINDEX: ${GONOBITINDEX}"
echo "GOCACHE: $(go env GOCACHE)"
echo "GOCACHE restored: ${{ steps.baseline-gocache.outputs.cache-hit || 'prefix-match-or-miss' }}"
echo "GOCACHE matched key: ${{ steps.baseline-gocache.outputs.cache-matched-key || 'none' }}"
echo "GOCACHE size: $(du -sh "$(go env GOCACHE)" 2>/dev/null | cut -f1 || echo 'empty')"
echo "Compiler SHA256:"
sha256sum "$(go env GOROOT)/pkg/tool/$(go env GOOS)_$(go env GOARCH)/compile" 2>/dev/null || true

- name: "Build Go Binaries (baseline, optimizations DISABLED)"
continue-on-error: true
run: |
time GOOS=linux GOARCH=amd64 CGO_ENABLED=1 make build-prep main-build-nodeps GOFLAGS="-v" 2>&1 | tee /tmp/build1.log
echo "Packages compiled: $(grep -c '^[a-z]' /tmp/build1.log 2>/dev/null || echo 0)"

- name: "Rebuild (known-warm)"
continue-on-error: true
run: |
time GOOS=linux GOARCH=amd64 CGO_ENABLED=1 make build-prep main-build-nodeps 2>&1

- name: "Warm build timing (baseline, 3 runs)"
continue-on-error: true
run: |
for i in 1 2 3; do
echo "--- run $i ---"
time GOOS=linux GOARCH=amd64 CGO_ENABLED=1 make build-prep main-build-nodeps 2>&1
done

- name: Save GOCACHE
uses: actions/cache/save@v5
continue-on-error: true
with:
path: /github/home/.cache/go-build
key: baseline-gocache-v1-${{ hashFiles('scripts/go-gitindex.patch') }}-${{ github.run_id }}

# ==================================================================
# PATCHED GO: cold build — populates GOCACHE, saves it
# ==================================================================
patched-go-cold-build:
needs: build-patched-go
runs-on: ubuntu-latest
container:
image: quay.io/stackrox-io/apollo-ci:stackrox-test-0.5.2
volumes:
- /usr:/mnt/usr
- /opt:/mnt/opt
steps:
- name: Checkout
uses: actions/checkout@v6
with:
fetch-depth: 0

- uses: ./.github/actions/job-preamble
with:
gcp-account: ${{ secrets.GCP_SERVICE_ACCOUNT_STACKROX_CI }}

- name: Restore patched Go toolchain
uses: actions/cache/restore@v5
with:
path: /tmp/go-patched
key: patched-go-v1-${{ hashFiles('scripts/go-gitindex.patch') }}

- name: Set patched Go as default
run: |
echo "/tmp/go-patched/bin" >> "$GITHUB_PATH"
echo "GOROOT=/tmp/go-patched" >> "$GITHUB_ENV"

# Restore GOCACHE: exact match for this run, or prefix match from previous run
- name: Restore GOCACHE
id: gocache-restore
uses: actions/cache/restore@v5
with:
path: /github/home/.cache/go-build
key: patched-gocache-v1-${{ hashFiles('scripts/go-gitindex.patch') }}-${{ github.run_id }}
restore-keys: |
patched-gocache-v1-${{ hashFiles('scripts/go-gitindex.patch') }}-

- name: Restore GOMODCACHE
uses: actions/cache/restore@v5
with:
path: /github/home/go/pkg/mod
key: go-mod-v1-${{ hashFiles('**/go.sum') }}
restore-keys: go-mod-v1-

- name: Download Go modules
run: make deps --always-make

- name: Record environment
continue-on-error: true
run: |
echo "Go: $(go version)"
echo "GOCACHE: $(go env GOCACHE)"
echo "GOCACHE restored: ${{ steps.gocache-restore.outputs.cache-hit || 'prefix-match-or-miss' }}"
echo "GOCACHE matched key: ${{ steps.gocache-restore.outputs.cache-matched-key || 'none' }}"
echo "GOCACHE size: $(du -sh "$(go env GOCACHE)" 2>/dev/null | cut -f1 || echo 'empty')"
echo "Compiler SHA256:"
sha256sum "$(go env GOROOT)/pkg/tool/$(go env GOOS)_$(go env GOARCH)/compile" 2>/dev/null || true

- name: "Build Go Binaries (patched Go)"
continue-on-error: true
run: |
echo "=== Build (patched Go) ==="
time GOOS=linux GOARCH=amd64 CGO_ENABLED=1 make build-prep main-build-nodeps GOFLAGS="-v" 2>&1 | tee /tmp/build1.log
echo "Packages compiled: $(grep -c '^[a-z]' /tmp/build1.log 2>/dev/null || echo 0)"

- name: "Rebuild (known-warm, same job)"
continue-on-error: true
run: |
echo "=== Known-warm rebuild ==="
time GOOS=linux GOARCH=amd64 CGO_ENABLED=1 make build-prep main-build-nodeps 2>&1

- name: "GOCACHE after build"
continue-on-error: true
run: |
GOCACHE="$(go env GOCACHE)"
echo "GOCACHE size: $(du -sh "$GOCACHE" 2>/dev/null | cut -f1)"
echo "Total files: $(find "$GOCACHE" -type f 2>/dev/null | wc -l)"

# Save with run-specific key (unique, so save always works)
- name: Save GOCACHE
uses: actions/cache/save@v5
continue-on-error: true
with:
path: /github/home/.cache/go-build
key: patched-gocache-v1-${{ hashFiles('scripts/go-gitindex.patch') }}-${{ github.run_id }}

# ==================================================================
# PATCHED GO: warm build — restores GOCACHE from cold build
# Same Go binary + same GOCACHE = should be a cache hit
# ==================================================================
patched-go-warm-build:
needs: patched-go-cold-build
runs-on: ubuntu-latest
container:
image: quay.io/stackrox-io/apollo-ci:stackrox-test-0.5.2
volumes:
- /usr:/mnt/usr
- /opt:/mnt/opt
steps:
- name: Checkout
uses: actions/checkout@v6
with:
fetch-depth: 0

- uses: ./.github/actions/job-preamble
with:
gcp-account: ${{ secrets.GCP_SERVICE_ACCOUNT_STACKROX_CI }}

- name: Restore patched Go toolchain
uses: actions/cache/restore@v5
with:
path: /tmp/go-patched
key: patched-go-v1-${{ hashFiles('scripts/go-gitindex.patch') }}

- name: Set patched Go as default
run: |
echo "/tmp/go-patched/bin" >> "$GITHUB_PATH"
echo "GOROOT=/tmp/go-patched" >> "$GITHUB_ENV"

# Restore this run's GOCACHE from the cold build job
- name: Restore GOCACHE from cold build
uses: actions/cache/restore@v5
with:
path: /github/home/.cache/go-build
key: patched-gocache-v1-${{ hashFiles('scripts/go-gitindex.patch') }}-${{ github.run_id }}

- name: Restore GOMODCACHE
uses: actions/cache/restore@v5
with:
path: /github/home/go/pkg/mod
key: go-mod-v1-${{ hashFiles('**/go.sum') }}
restore-keys: go-mod-v1-

- name: Download Go modules
run: make deps --always-make

- name: Record environment
continue-on-error: true
run: |
echo "Go: $(go version)"
echo "GOCACHE: $(go env GOCACHE)"
echo "GOCACHE size: $(du -sh "$(go env GOCACHE)" 2>/dev/null | cut -f1 || echo 'empty')"
echo "Compiler SHA256:"
sha256sum "$(go env GOROOT)/pkg/tool/$(go env GOOS)_$(go env GOARCH)/compile" 2>/dev/null || true

- name: "Build Go Binaries (patched Go, restored GOCACHE)"
continue-on-error: true
run: |
echo "=== Build with restored GOCACHE ==="
time GOOS=linux GOARCH=amd64 CGO_ENABLED=1 make build-prep main-build-nodeps GOFLAGS="-v" 2>&1 | tee /tmp/build1.log
echo "Packages compiled (cache misses): $(grep -c '^[a-z]' /tmp/build1.log 2>/dev/null || echo 0)"

- name: "Rebuild (known-warm)"
continue-on-error: true
run: |
echo "=== Known-warm rebuild ==="
time GOOS=linux GOARCH=amd64 CGO_ENABLED=1 make build-prep main-build-nodeps 2>&1

- name: "Warm build timing (git index ENABLED, 3 runs)"
continue-on-error: true
run: |
for i in 1 2 3; do
echo "--- run $i ---"
time GOOS=linux GOARCH=amd64 CGO_ENABLED=1 make build-prep main-build-nodeps 2>&1
done

- name: "Warm build timing (git index DISABLED, 3 runs)"
continue-on-error: true
env:
GONOBITINDEX: "1"
run: |
for i in 1 2 3; do
echo "--- run $i ---"
time GOOS=linux GOARCH=amd64 CGO_ENABLED=1 make build-prep main-build-nodeps 2>&1
done
2 changes: 0 additions & 2 deletions pkg/version/internal/version_data.go
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,4 @@ var (
FactVersion string //XDef:STABLE_FACT_VERSION
// ScannerVersion is the scanner version to be used with this Rox version.
ScannerVersion string //XDef:STABLE_SCANNER_VERSION
// GitShortSha is the (short) Git SHA that was built.
GitShortSha string //XDef:STABLE_GIT_SHORT_SHA
)
1 change: 0 additions & 1 deletion pkg/version/testutils/set_version.go
Original file line number Diff line number Diff line change
Expand Up @@ -33,7 +33,6 @@ func SetVersion(t *testing.T, version version.Versions) {
internal.MainVersion = version.MainVersion
internal.ScannerVersion = version.ScannerVersion
internal.CollectorVersion = version.CollectorVersion
internal.GitShortSha = version.GitCommit
internal.FactVersion = version.FactVersion
}

Expand Down
Loading
Loading