treewide: fix nostamp
Previously, --nostamp did not disable all stamping with commit info,
which meant that metropolis e2e tests ran on CI even if no change was
made to metropolis code. Now, --config:nostamp does this properly.
The Bazel --nostamp flag is supposed to disable stamping. Ideally, this
means that the workspace status script is not executed. But we can't do
that because the metropolis version is required (e.g. for compatibility
checks), and we currently obtain the version from git tags. Another
option is to check whether the --nostamp flag is set in the status
script, and omit any git commit info in this case. But I didn't find a
way to access the --nostamp flag from the status script, so instead, the
--config:nostamp flag is introduced and replaces --nostamp.
Versions without git info are marked with a "-nostamp" suffix.
I adjusted //version to handle this case.
Change-Id: I34e1b59b908074e8d4234013358b6be41899570a
Reviewed-on: https://review.monogon.dev/c/monogon/+/4169
Tested-by: Jenkins CI
Reviewed-by: Tim Windelschmidt <tim@monogon.tech>
diff --git a/.bazelrc b/.bazelrc
index bcee473..cfeb312 100644
--- a/.bazelrc
+++ b/.bazelrc
@@ -102,6 +102,10 @@
# Set workspace status file and stamp
build --stamp --workspace_status_command=./build/print-workspace-status.py
+# The --nostamp Bazel flag does not work in this repo; instead use
+# --config=nostamp to disable stamping with commit info.
+build:nostamp --workspace_status_command="./build/print-workspace-status.py --nostamp"
+
# Assume a 10k IOPS device (average NVMe) and 64GiB of RAM for test scheduling.
test --local_resources=iops=10000 --local_resources=ram=64000
diff --git a/.bazelrc.ci b/.bazelrc.ci
index 81ba128..42a816d 100644
--- a/.bazelrc.ci
+++ b/.bazelrc.ci
@@ -15,4 +15,4 @@
build --experimental_disk_cache_gc_max_size=150G
# Disable stamping for cache determinism
-build --nostamp
+build --config=nostamp
diff --git a/build/print-workspace-status.py b/build/print-workspace-status.py
index b765e0c..f03b244 100755
--- a/build/print-workspace-status.py
+++ b/build/print-workspace-status.py
@@ -20,6 +20,7 @@
# means there is no such thing as a 'version' for the monorepo by itself,
# only within the context of some product.
+import argparse
from dataclasses import dataclass
import re
import subprocess
@@ -27,25 +28,32 @@
from typing import Optional
+parser = argparse.ArgumentParser()
+parser.add_argument("--nostamp", action="store_true")
+args = parser.parse_args()
+
# Variables to output. These will be printed to stdout at the end of the script
# runtime, sorted by key.
variables: dict[str, str] = {}
-# Git build tree status: clean or dirty.
-git_tree_state: str = "clean"
-git_status = subprocess.check_output(["git", "status", "--porcelain"])
-if git_status.decode().strip() != "":
- git_tree_state = "dirty"
+git_tree_state: str = "unknown"
-# Git commit hash.
-git_commit: str = (
- subprocess.check_output(["git", "rev-parse", "HEAD^{commit}"]).decode().strip()
-)
+if not args.nostamp:
+ # Git build tree status: clean or dirty.
+ git_tree_state = "clean"
+ git_status = subprocess.check_output(["git", "status", "--porcelain"])
+ if git_status.decode().strip() != "":
+ git_tree_state = "dirty"
-# Git commit date.
-git_commit_date: str = (
- subprocess.check_output(["git", "show", "--pretty=format:%cI", "--no-patch", "HEAD"]).decode().strip()
-)
+ # Git commit hash.
+ git_commit: str = (
+ subprocess.check_output(["git", "rev-parse", "HEAD^{commit}"]).decode().strip()
+ )
+
+ # Git commit date.
+ git_commit_date: str = (
+ subprocess.check_output(["git", "show", "--pretty=format:%cI", "--no-patch", "HEAD"]).decode().strip()
+ )
# Git tags pointing at this commit.
git_tags_b: [bytes] = subprocess.check_output(
@@ -53,11 +61,15 @@
).split(b"\n")
git_tags: [str] = [t.decode().strip() for t in git_tags_b if t.decode().strip() != ""]
-variables["STABLE_MONOGON_gitCommit"] = git_commit
-variables["STABLE_MONOGON_gitTreeState"] = git_tree_state
+if not args.nostamp:
+ variables["STABLE_MONOGON_gitCommit"] = git_commit
+ variables["STABLE_MONOGON_gitTreeState"] = git_tree_state
-copyright_year = git_commit_date.partition("-")[0]
-copyright_line = f"Copyright 2020-{copyright_year} The Monogon Project Authors"
+if args.nostamp:
+ copyright_line = "Copyright The Monogon Project Authors"
+else:
+ copyright_year = git_commit_date.partition("-")[0]
+ copyright_line = f"Copyright 2020-{copyright_year} The Monogon Project Authors"
variables["STABLE_MONOGON_copyright"] = copyright_line
# Per product. Each product has it's own semver-style version number, which is
@@ -123,6 +135,8 @@
version = parse_tag(tag, product)
if version is None:
continue
+ if args.nostamp:
+ break
# Found the latest tag for this product. Augment it with the
# devXXX identifier and add it to our versions.
count = (
@@ -136,18 +150,22 @@
if version is None:
# This product never had a release! Use v0.0.0 as a fallback.
version = Version(product, "v0.0.0", [])
- # ... and count the number of all commits ever to use as the devXXX
- # prerelease identifier.
- count = (
- subprocess.check_output(["git", "rev-list", "HEAD", "--count"])
- .decode()
- .strip()
- )
- version.prerelease.append(f"dev{count}")
+ if not args.nostamp:
+ # ... and count the number of all commits ever to use as the devXXX
+ # prerelease identifier.
+ count = (
+ subprocess.check_output(["git", "rev-list", "HEAD", "--count"])
+ .decode()
+ .strip()
+ )
+ version.prerelease.append(f"dev{count}")
- version.prerelease.append(f"g{git_commit[:8]}")
- if git_tree_state == "dirty":
- version.prerelease.append("dirty")
+ if args.nostamp:
+ version.prerelease.append("nostamp")
+ else:
+ version.prerelease.append(f"g{git_commit[:8]}")
+ if git_tree_state == "dirty":
+ version.prerelease.append("dirty")
variables[f"STABLE_MONOGON_{product}_version"] = str(version)
diff --git a/version/stampgo/main.go b/version/stampgo/main.go
index 7aaa91d..3f8502c 100644
--- a/version/stampgo/main.go
+++ b/version/stampgo/main.go
@@ -30,7 +30,6 @@
var (
rePrereleaseCommitOffset = regexp.MustCompile(`^dev([0-9]+)$`)
- rePrereleaseDirty = regexp.MustCompile(`^dirty$`)
rePrereleaseGitHash = regexp.MustCompile(`^g[0-9a-f]+$`)
)
@@ -83,28 +82,26 @@
log.Fatalf("Failed to read workspace status file: %v", err)
}
- commitHash := values["STABLE_MONOGON_gitCommit"]
- if commitHash == "" {
- log.Fatalf("No git commit in workspace status")
- }
- if len(commitHash) < 8 {
- log.Fatalf("Git commit hash too short")
- }
- buildTreeState := spec.Version_GitInformation_BUILD_TREE_STATE_INVALID
- switch values["STABLE_MONOGON_gitTreeState"] {
- case "clean":
- buildTreeState = spec.Version_GitInformation_BUILD_TREE_STATE_CLEAN
- case "dirty":
- buildTreeState = spec.Version_GitInformation_BUILD_TREE_STATE_DIRTY
- default:
- log.Fatalf("Invalid git tree state %q", values["STABLE_MONOGON_gitTreeState"])
- }
+ version := &spec.Version{}
- version := &spec.Version{
- GitInformation: &spec.Version_GitInformation{
+ commitHash := values["STABLE_MONOGON_gitCommit"]
+ if commitHash != "" {
+ if len(commitHash) < 8 {
+ log.Fatalf("Git commit hash too short")
+ }
+ buildTreeState := spec.Version_GitInformation_BUILD_TREE_STATE_INVALID
+ switch values["STABLE_MONOGON_gitTreeState"] {
+ case "clean":
+ buildTreeState = spec.Version_GitInformation_BUILD_TREE_STATE_CLEAN
+ case "dirty":
+ buildTreeState = spec.Version_GitInformation_BUILD_TREE_STATE_DIRTY
+ default:
+ log.Fatalf("Invalid git tree state %q", values["STABLE_MONOGON_gitTreeState"])
+ }
+ version.GitInformation = &spec.Version_GitInformation{
CommitHash: commitHash[:8],
BuildTreeState: buildTreeState,
- },
+ }
}
productVersion := values["STABLE_MONOGON_"+flagProduct+"_version"]
@@ -119,22 +116,24 @@
}
// Parse prerelease strings (v1.2.3-foo-bar -> [foo, bar])
for _, el := range v.PreRelease.Slice() {
- // Skip empty slices which happens when there's a semver string with no
- // prerelease data.
- if el == "" {
- continue
- }
preCommitOffset := rePrereleaseCommitOffset.FindStringSubmatch(el)
- preDirty := rePrereleaseDirty.FindStringSubmatch(el)
preGitHash := rePrereleaseGitHash.FindStringSubmatch(el)
switch {
+ case el == "":
+ // Skip empty slices which happens when there's a semver string with no
+ // prerelease data.
+ case el == "nostamp":
+ // Ignore field, we have it from the global monorepo state.
case preCommitOffset != nil:
offset, err := strconv.ParseUint(preCommitOffset[1], 10, 64)
if err != nil {
log.Fatalf("Invalid commit offset value: %v", err)
}
+ if version.GitInformation == nil {
+ log.Fatalf("Have git offset but no git commit")
+ }
version.GitInformation.CommitsSinceRelease = offset
- case preDirty != nil:
+ case el == "dirty":
// Ignore field, we have it from the global monorepo state.
case preGitHash != nil:
// Ignore field, we have it from the global monorepo state.
diff --git a/version/version.go b/version/version.go
index 999854e..2929684 100644
--- a/version/version.go
+++ b/version/version.go
@@ -33,6 +33,8 @@
if git.BuildTreeState != spec.Version_GitInformation_BUILD_TREE_STATE_CLEAN {
prerelease = append(prerelease, "dirty")
}
+ } else {
+ prerelease = append(prerelease, "nostamp")
}
if len(prerelease) > 0 {