Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
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 || '' }}"
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): Using github.event.pull_request.* unguarded can fail on non-PR events.

This job runs on both push and PR events, but github.event.pull_request only exists for PRs. On a push, accessing github.event.pull_request.labels or .number will fail expression evaluation. Please guard this with a check like github.event_name == 'pull_request' (or a ternary that returns an empty value when not a PR) so push workflows don’t break.

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'))
uses: actions/cache@v5
with:
path: ${{ steps.cache-paths.outputs.GOMODCACHE }}
Comment on lines +24 to 27
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: Condition uses github.event.pull_request.* without guarding against non-PR events.

The contains(github.event.pull_request.labels.*.name, 'ci-save-cache') expression will still be evaluated on non-PR events, where github.event.pull_request is undefined, which can break push workflows. Please guard the contains(...) call (e.g., by checking github.event_name == 'pull_request' first or using a nested ternary) so pull_request is only accessed for PR events.

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'))) }}
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
2 changes: 1 addition & 1 deletion .github/workflows/scanner-db-integration-tests.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -36,7 +36,7 @@ jobs:
- name: Cache Go dependencies
uses: ./.github/actions/cache-go-dependencies
with:
save: false # ~62 MB, test-dominated, no critical path speedup
save: true # Now worth saving: -buildvcs=false makes test caches stable across commits

- name: Is Postgres ready
run: pg_isready -h 127.0.0.1
Expand Down
4 changes: 2 additions & 2 deletions .github/workflows/style.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -42,7 +42,7 @@ jobs:
- name: Cache Go dependencies
uses: ./.github/actions/cache-go-dependencies
with:
save: false # ~752 MB, style-dominated, no critical path speedup
save: false # check-generated-files modifies the workspace, breaking post-job hashFiles

- name: Check Generated
run: scripts/ci/jobs/check-generated.sh
Expand Down Expand Up @@ -112,7 +112,7 @@ jobs:
- name: Cache Go dependencies
uses: ./.github/actions/cache-go-dependencies
with:
save: false # ~2,183 MB, style-dominated, no critical path speedup
save: true # Now worth saving: -buildvcs=false makes caches stable across commits

- name: Cache UI dependencies
uses: ./.github/actions/cache-ui-dependencies
Expand Down
10 changes: 5 additions & 5 deletions .github/workflows/unit-tests.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -43,7 +43,7 @@ jobs:
- name: Cache Go dependencies
uses: ./.github/actions/cache-go-dependencies
with:
save: false # ~2,000 MB, test-dominated, no critical path speedup
save: true # Now worth saving: -buildvcs=false makes test caches stable across commits

- name: Go Unit Tests
run: ${{ matrix.gotags }} make go-unit-tests
Expand Down Expand Up @@ -125,7 +125,7 @@ jobs:
- name: Cache Go dependencies
uses: ./.github/actions/cache-go-dependencies
with:
save: false # ~913 MB, test-dominated, no critical path speedup
save: true # Now worth saving: -buildvcs=false makes test caches stable across commits

- name: Is Postgres ready
run: pg_isready -h 127.0.0.1
Expand Down Expand Up @@ -187,7 +187,7 @@ jobs:
- name: Cache Go dependencies
uses: ./.github/actions/cache-go-dependencies
with:
save: false # ~610 MB, test-dominated, no critical path speedup
save: true # Now worth saving: -buildvcs=false makes test caches stable across commits

- name: Is Postgres ready
run: pg_isready -h 127.0.0.1
Expand Down Expand Up @@ -310,7 +310,7 @@ jobs:
- name: Cache Go dependencies
uses: ./.github/actions/cache-go-dependencies
with:
save: false # ~1,163 MB, test-dominated, no critical path speedup
save: true # Now worth saving: -buildvcs=false makes test caches stable across commits

- uses: ./.github/actions/handle-tagged-build

Expand Down Expand Up @@ -412,7 +412,7 @@ jobs:
- name: Cache Go dependencies
uses: ./.github/actions/cache-go-dependencies
with:
save: false # ~626 MB, test-dominated, no critical path speedup
save: true # Now worth saving: -buildvcs=false makes test caches stable across commits

- name: Login to Quay.io
uses: docker/login-action@v3
Expand Down
4 changes: 4 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -76,6 +76,10 @@ shellcheck-reports
# Snyk
.dccache

# Generated version data (written by go-tool.sh, like Go's zbootstrap.go)
pkg/version/internal/zversion.go
/VERSION

# Konflux builds download scanner vuln files to the code repo.
# These files need to be ignored in order for `make tag` return a clean version string.
repository-to-cpe.json
Expand Down
15 changes: 9 additions & 6 deletions pkg/version/internal/version_data.go
Original file line number Diff line number Diff line change
@@ -1,14 +1,17 @@
package internal

// Version variables with fallback defaults for ad-hoc builds (e.g. `go build`
// without the build infrastructure). When building via go-tool.sh, these are
// overridden by the generated zversion.go init() function.
var (
// MainVersion is the Rox version.
MainVersion string //XDef:STABLE_MAIN_VERSION
MainVersion string
// CollectorVersion is the collector version to be used by default.
CollectorVersion string //XDef:STABLE_COLLECTOR_VERSION
CollectorVersion string
// FactVersion is the fact version to be used by default.
FactVersion string //XDef:STABLE_FACT_VERSION
FactVersion string
// 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
ScannerVersion string
// GitShortSha is the short git commit SHA.
GitShortSha string
)
3 changes: 3 additions & 0 deletions scanner/.gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,9 @@ nohup.out
# Vim swap files
*.swp

# Generated version data (written by Makefile, like Go's zbootstrap.go)
internal/version/zversion.go

# Go mod
vendor

Expand Down
30 changes: 27 additions & 3 deletions scanner/Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -48,10 +48,10 @@ GOOS := $(HOST_OS)
GO_BUILD_FLAGS = CGO_ENABLED=$(CGO_ENABLED) GOOS=$(GOOS) GOARCH=$(GOARCH)
GO_BUILD_CMD = $(GO_BUILD_FLAGS) go build \
-trimpath \
-ldflags="-X github.com/stackrox/rox/scanner/internal/version.Version=$(TAG) -X github.com/stackrox/rox/scanner/internal/version.VulnerabilityVersion=$(SCANNER_VULNERABILITY_VERSION)" \
-buildvcs=false \
-tags=$(GOTAGS) \
$(RACE_FLAG)
GO_TEST_CMD = $(GO_BUILD_FLAGS) go test
GO_TEST_CMD = $(GO_BUILD_FLAGS) go test -buildvcs=false

DOCKERBUILD := $(CURDIR)/../scripts/docker-build.sh

Expand Down Expand Up @@ -99,6 +99,29 @@ vulnerability-version: VULNERABILITY_VERSION
## Go Builds ##
###############

# Generate version data file (like Go's own zbootstrap.go pattern).
# This replaces the previous -X ldflags for version stamping. By writing
# version info as Go source instead of passing it via ldflags, we avoid
# invalidating the Go build/link cache when only the version changes.
# The file is only written when content changes (skip-if-same).
SCANNER_ZVERSION := internal/version/zversion.go

.PHONY: generate-scanner-version
generate-scanner-version:
$(SILENT)new_content="$$(printf '%s\n' \
'// Code generated by scanner Makefile; DO NOT EDIT.' \
'' \
'package version' \
'' \
'func init() {' \
' Version = "$(TAG)"' \
' VulnerabilityVersion = "$(SCANNER_VULNERABILITY_VERSION)"' \
'}')"; \
if [ -f "$(SCANNER_ZVERSION)" ] && [ "$$(cat "$(SCANNER_ZVERSION)")" = "$$new_content" ]; then \
exit 0; \
fi; \
echo "$$new_content" > "$(SCANNER_ZVERSION)"

build-cmd = $(GO_BUILD_CMD)
build-d := bin

Expand All @@ -113,9 +136,10 @@ clean-build:
@echo "+ $@"
$(SILENT)rm -rf bin/
$(SILENT)rm -f $(build-deps-t)
$(SILENT)rm -f $(SCANNER_ZVERSION)

.PHONY: $(build-t)
$(build-t): $(build-deps-t)
$(build-t): $(build-deps-t) generate-scanner-version
@echo "+ $@"
$(build-cmd) -o $@ ./cmd/$(@F)

Expand Down
6 changes: 5 additions & 1 deletion scanner/internal/version/version.go
Original file line number Diff line number Diff line change
@@ -1,6 +1,10 @@
package version

// Version is set at build time by the latest tag
// Version variables with fallback defaults for ad-hoc builds (e.g. `go build`
// without the build infrastructure). When building via the scanner Makefile,
// these are overridden by the generated zversion.go init() function.

// Version is the scanner version (from the latest git tag).
var Version string

// VulnerabilityVersion is the supported vulnerability schema version.
Expand Down
62 changes: 35 additions & 27 deletions scripts/go-tool.sh
Original file line number Diff line number Diff line change
Expand Up @@ -13,9 +13,7 @@ die() {

RACE="${RACE:-false}"

x_defs=()
x_def_errors=()

# Parse version info from status.sh.
while read -r line || [[ -n "$line" ]]; do
if [[ "$line" =~ ^[[:space:]]*$ ]]; then
continue
Expand All @@ -28,30 +26,40 @@ while read -r line || [[ -n "$line" ]]; do
fi
done < <(cd "${SCRIPT_DIR}/.."; ./status.sh)

while read -r line || [[ -n "$line" ]]; do
if [[ "$line" =~ ^[[:space:]]*$ ]]; then
continue
elif [[ "$line" =~ ^([^:]+):([[:digit:]]+):[[:space:]]*(var[[:space:]]+)?([^[:space:]]+)[[:space:]].*//XDef:([^[:space:]]+)[[:space:]]*$ ]]; then
go_file="${BASH_REMATCH[1]}"
go_line="${BASH_REMATCH[2]}"
go_var="${BASH_REMATCH[4]}"
status_var="${BASH_REMATCH[5]}"

varname="status_${status_var}"
[[ -n "${!varname}" ]] || x_def_errors+=(
"Variable ${go_var} defined in ${go_file}:${go_line} references status var ${status_var} that is not part of the status.sh output"
)
go_package="$(cd "${SCRIPT_DIR}/.."; go list -e "./$(dirname "$go_file")")"

x_defs+=(-X "\"${go_package}.${go_var}=${!varname}\"")
# Generate version data file (like Go's own zbootstrap.go pattern).
# This replaces the previous //XDef: + ldflags mechanism. By writing version
# info as Go source instead of passing it via -X ldflags, we avoid invalidating
# the Go build/link cache when only the version string changes.
# The file is only written when content changes (skip-if-same), so unchanged
# versions produce zero cache churn.
generate_version_file() {
local target="${SCRIPT_DIR}/../pkg/version/internal/zversion.go"
local var
for var in status_STABLE_MAIN_VERSION status_STABLE_COLLECTOR_VERSION \
status_STABLE_FACT_VERSION status_STABLE_SCANNER_VERSION \
status_STABLE_GIT_SHORT_SHA; do
[[ -n "${!var}" ]] || die "${var#status_} is not set in status.sh output"
done
local new_content
new_content="// Code generated by go-tool.sh; DO NOT EDIT.

package internal

func init() {
MainVersion = \"${status_STABLE_MAIN_VERSION}\"
CollectorVersion = \"${status_STABLE_COLLECTOR_VERSION}\"
FactVersion = \"${status_STABLE_FACT_VERSION}\"
ScannerVersion = \"${status_STABLE_SCANNER_VERSION}\"
GitShortSha = \"${status_STABLE_GIT_SHORT_SHA}\"
}"
if [[ -f "$target" ]] && [[ "$(cat "$target")" == "$new_content" ]]; then
return
fi
done < <(git -C "${SCRIPT_DIR}/.." grep -n '//XDef:' -- '*.go')
if [[ "${#x_def_errors[@]}" -gt 0 ]]; then
printf >&2 "%s\n" "${x_def_errors[@]}"
exit 1
fi
echo "$new_content" > "$target"
}
generate_version_file

ldflags=("${x_defs[@]}")
ldflags=()
if [[ "$DEBUG_BUILD" != "yes" ]]; then
ldflags+=(-s -w)
fi
Expand Down Expand Up @@ -102,7 +110,7 @@ function invoke_go_build() {
if [[ "$DEBUG_BUILD" == "yes" ]]; then
gcflags+=(-gcflags "all=-N -l")
fi
invoke_go build -trimpath "${gcflags[@]}" "$@"
invoke_go build -trimpath -buildvcs=false "${gcflags[@]}" "$@"
}

function go_run() (
Expand All @@ -111,7 +119,7 @@ function go_run() (

function go_test() (
unset GOOS
invoke_go test "$@"
invoke_go test -buildvcs=false "$@"
)

case "$TOOL" in
Expand Down
25 changes: 24 additions & 1 deletion status.sh
Original file line number Diff line number Diff line change
@@ -1,6 +1,29 @@
#!/bin/sh

# Note: This requires .git directory in the build context (e.g. builder container)
# Outputs version variables consumed by go-tool.sh to generate zversion.go.
#
# Resolution order (like Go's own findgoversion()):
# 1. BUILD_VERSION_FILE env var pointing to a pre-computed version file
# 2. VERSION file in the repo root
# 3. Live git queries via make targets (requires .git directory)
#
# The file format is one "KEY value" pair per line, e.g.:
# STABLE_MAIN_VERSION 4.11.0-143-g4982da58fd
# STABLE_COLLECTOR_VERSION 4.11.0
# STABLE_FACT_VERSION 0.1.0
# STABLE_SCANNER_VERSION 4.11.0
# STABLE_GIT_SHORT_SHA 4982da58fd

SCRIPT_DIR="$(cd "$(dirname "$0")" && pwd)"

# Check for a pre-computed version file (for CI, Docker builds, or non-git envs).
version_file="${BUILD_VERSION_FILE:-${SCRIPT_DIR}/VERSION}"
if [ -f "$version_file" ]; then
cat "$version_file"
exit 0
fi

# Fall back to live git queries.
echo "STABLE_MAIN_VERSION $(make --quiet --no-print-directory tag)"
echo "STABLE_COLLECTOR_VERSION $(make --quiet --no-print-directory collector-tag)"
echo "STABLE_FACT_VERSION $(make --quiet --no-print-directory fact-tag)"
Expand Down
Loading