Skip to content
Draft
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
13 changes: 13 additions & 0 deletions .github/actions/cache-go-dependencies/action.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -54,3 +54,16 @@ runs:
- name: Download Go modules
run: make deps --always-make
shell: bash

- name: Stabilize file mtimes for Go test cache
run: |
# Go's test cache validates inputs by (path, size, mtime) — NOT content.
# git checkout sets all mtimes to "now", which differs between CI runs,
# causing every test to miss the cache. Setting a fixed mtime makes the
# test cache hit across runs when file content hasn't changed.
#
# Risk: if a non-.go testdata file changes content but not size between
# commits, the test cache could return a stale result. This is extremely
# rare and Go's own test cache has the same inherent limitation.
git ls-files -z | xargs -0 touch -t 200101010000
shell: bash
1 change: 1 addition & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -80,3 +80,4 @@ shellcheck-reports
# These files need to be ignored in order for `make tag` return a clean version string.
repository-to-cpe.json
container-name-repos-map.json
pkg/version/internal/zversion.go
1 change: 1 addition & 0 deletions VERSION
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
4.11.x
2 changes: 1 addition & 1 deletion make/env.mk
Original file line number Diff line number Diff line change
Expand Up @@ -60,7 +60,7 @@ TAG := $(BUILD_TAG)
endif

ifeq ($(TAG),)
TAG=$(shell git describe --tags --abbrev=10 --dirty --long --exclude '*-nightly-*')
TAG=$(shell git describe --tags --abbrev=10 --dirty --long --exclude '*-nightly-*' 2>/dev/null || cat VERSION 2>/dev/null || echo "0.0.0")
endif

# Set expiration on Quay.io for non-release tags.
Expand Down
25 changes: 13 additions & 12 deletions operator/Dockerfile
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,11 @@ ARG roxpath
WORKDIR ${roxpath}/
ENV GOPATH=/workspace

# Run the build stage as root so COPY'd files are writable (e.g. for
# generating zversion.go). This is safe because only the final binary
# is copied to the runtime image, which runs as non-root (uid 65534).
USER 0

# Copy the Go Modules manifests
COPY go.mod go.mod
COPY go.sum go.sum
Expand All @@ -31,27 +36,23 @@ COPY go.sum go.sum
ENV GOPROXY=https://proxy.golang.org|https://goproxy.io|direct
RUN go mod download || go mod download || go mod download

# Copy operator source
# Copy source files. The go-toolset image runs as uid 1001, so use --chown
# to ensure the build user can write generated files (e.g. zversion.go).
COPY operator/ operator/

# Copy common packages from repo root
COPY pkg/ pkg/
COPY image/ image/

# Copy generated files from repo root.
# Not generating them during this docker build because they anyway need to be generated by the orchestrating makefiles.
COPY generated/ generated/

# Copy scripts/go-build.sh and dependencies.
COPY scripts/ scripts/
COPY operator/build/status.sh status.sh

# This creates a git repo in workdir so that `git grep` command in build.sh can succeed and actually find //XDef-s.
RUN git init && git add .
COPY COLLECTOR_VERSION SCANNER_VERSION FACT_VERSION VERSION ./

# We've been historically building operator without CGO both upstream and downstream.
ENV CGO_ENABLED=0

# BUILD_TAG is set by the smuggled-status-sh mechanism or Konflux pipeline.
# go-tool.sh uses it for the version string when .git is unavailable.
ARG BUILD_TAG
ENV BUILD_TAG=${BUILD_TAG}

# Build the operator binary.
RUN GOOS=linux GOARCH=${TARGET_ARCH} scripts/go-build-file.sh operator/cmd/main.go stackrox-operator

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
)
104 changes: 65 additions & 39 deletions scripts/go-tool.sh
Original file line number Diff line number Diff line change
Expand Up @@ -12,46 +12,61 @@ die() {
}

RACE="${RACE:-false}"

x_defs=()
x_def_errors=()

while read -r line || [[ -n "$line" ]]; do
if [[ "$line" =~ ^[[:space:]]*$ ]]; then
continue
elif [[ "$line" =~ ^([^[:space:]]+)[[:space:]]+(.*)[[:space:]]*$ ]]; then
var="${BASH_REMATCH[1]}"
def="${BASH_REMATCH[2]}"
eval "status_${var}=$(printf '%q' "$def")"
REPO_ROOT="${SCRIPT_DIR}/.."

# Read version data from committed files.
COLLECTOR_VERSION="$(cat "${REPO_ROOT}/COLLECTOR_VERSION")" || die "Missing COLLECTOR_VERSION"
SCANNER_VERSION="$(cat "${REPO_ROOT}/SCANNER_VERSION")" || die "Missing SCANNER_VERSION"
FACT_VERSION="$(cat "${REPO_ROOT}/FACT_VERSION")" || die "Missing FACT_VERSION"
BASE_VERSION="$(cat "${REPO_ROOT}/VERSION")" || die "Missing VERSION"

# Generate version data file. Tests use only the base tag (stable across
# commits) to keep ActionIDs stable for test result caching. Builds get
# the full git-describe version with commit count and SHA.
generate_version_file() {
local target="${REPO_ROOT}/pkg/version/internal/zversion.go"
local main_version git_short_sha

if [[ "$TOOL" == "test" ]]; then
# Base tag only (e.g. "4.11.x") — stable across commits.
main_version="${BASE_VERSION}"
git_short_sha=""
elif [[ -n "${BUILD_TAG:-}" ]]; then
# Konflux/release builds set BUILD_TAG to the full version string.
# Use it directly (the Docker build context has no .git directory).
main_version="${BUILD_TAG}"
git_short_sha="$(echo "$BUILD_TAG" | grep -oP 'g\K[0-9a-f]+$' || echo "")"
else
die "Malformed status.sh output line ${line}"
# Full format matching git describe (e.g. "4.11.x-193-g7257553280").
local commit_count
git_short_sha="$(cd "${REPO_ROOT}"; git rev-parse --short HEAD 2>/dev/null || echo "")"
commit_count="$(cd "${REPO_ROOT}"; git rev-list --count "${BASE_VERSION}..HEAD" 2>/dev/null || echo "0")"
main_version="${BASE_VERSION}-${commit_count}-g${git_short_sha}"
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}\"")

local new_content
new_content="// Code generated by go-tool.sh; DO NOT EDIT.

package internal

func init() {
MainVersion = \"${main_version}\"
CollectorVersion = \"${COLLECTOR_VERSION}\"
FactVersion = \"${FACT_VERSION}\"
ScannerVersion = \"${SCANNER_VERSION}\"
GitShortSha = \"${git_short_sha}\"
}"
if [[ -f "$target" ]] && [[ "$(cat "$target")" == "$new_content" ]]; then
# Pin mtime to fixed past date for test cache stability.
touch -t 200101010000 "$target"
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"
touch -t 200101010000 "$target"
}
generate_version_file

ldflags=("${x_defs[@]}")
ldflags=()
if [[ "$DEBUG_BUILD" != "yes" ]]; then
ldflags+=(-s -w)
fi
Expand Down Expand Up @@ -88,7 +103,18 @@ function go_build() (
mkdir -p "$output"

echo >&2 "Compiling Go source in ${dirs[*]} to ${output}"
invoke_go_build -o "$output" "${dirs[@]}"
local total
total=$(go list -deps "${dirs[@]}" 2>/dev/null | wc -l | tr -d ' ')
local compiled_count=/tmp/go-build-compiled-count
invoke_go_build -o "$output" "${dirs[@]}" 2> >(tee >(wc -l | tr -d ' ' > "$compiled_count") >&2)
wait
local compiled
compiled=$(cat "$compiled_count" 2>/dev/null | tr -d ' ')
local cached=$((total - compiled))
echo >&2 "Build cache: ${cached}/${total} deps cached ($compiled compiled)"
if [[ "$total" -gt 0 ]] && [[ $((cached * 100 / total)) -lt 50 ]]; then
echo >&2 "WARNING: Build cache hit rate below 50% (${cached}/${total}). Significant code changes invalidate the cached build — expect slower compilation."
fi
)

function go_build_file() {
Expand All @@ -102,7 +128,7 @@ function invoke_go_build() {
if [[ "$DEBUG_BUILD" == "yes" ]]; then
gcflags+=(-gcflags "all=-N -l")
fi
invoke_go build -trimpath "${gcflags[@]}" "$@"
invoke_go build -v -trimpath -buildvcs=false "${gcflags[@]}" "$@"
}

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

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

case "$TOOL" in
Expand Down
2 changes: 1 addition & 1 deletion tests/roxctl/bats-tests/helpers.bash
Original file line number Diff line number Diff line change
Expand Up @@ -29,7 +29,7 @@ any_version='[0-9]+\.[0-9]+\.'

delete-outdated-binaries() {
local roxctl_ver="${1}"
current_tag="$(git describe --tags --abbrev=10 --dirty --long --exclude '*-nightly-*')"
current_tag="$(git describe --tags --abbrev=10 --dirty --long --exclude '*-nightly-*' 2>/dev/null || cat VERSION 2>/dev/null || echo "0.0.0")"
echo "Roxctl version='${roxctl_ver}'" >&3
echo "Current tag ='${current_tag}'" >&3
if [[ "${current_tag}" != "${roxctl_ver}" ]]; then
Expand Down
Loading