Skip to content
Open
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
4 changes: 4 additions & 0 deletions bazel/certs/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -53,6 +53,10 @@ By default, `generated_certs` derives the year hermetically from the
`bazel-out/volatile-status.txt` for stamped builds (`stamp = 1`, set
automatically by the macro). No consumer configuration is required.

Year selection runs in a separate stamped action. Certificate generation
consumes only the selected year, so unrelated workspace status changes do
not invalidate cached fixtures or their dependent compilation actions.

Workspaces that want to pin the year from their own
`workspace_status_command` may use `year_status_key` as an optional override
by emitting a line of the form:
Expand Down
28 changes: 21 additions & 7 deletions bazel/certs/certs.bzl
Original file line number Diff line number Diff line change
Expand Up @@ -69,10 +69,10 @@ def generated_certs(
"""
gen_label = str(Label(str(gen)))

year_srcs = []
if year != None:
year_cmd = "YEAR=\"" + str(year) + "\";"
year_arg = "\"" + str(year) + "\""
stamp = 0
else:
year_cmd = " ".join([
"YEAR=$$(sed -n -E 's/^" + year_status_key + " ([0-9]{4})$$/\\1/p' bazel-out/stable-status.txt 2>/dev/null);",
Expand All @@ -82,12 +82,28 @@ def generated_certs(
"fi;",
"if [ -z \"$$YEAR\" ]; then YEAR=$$(date -u +%Y); fi;",
])
year_arg = "\"$$YEAR\""
stamp = 1

# Only the selected year affects certificates. Keep unrelated status
# changes (including BUILD_TIMESTAMP) out of certificate action inputs.
year_file = name + "_epoch_year.txt"
native.genrule(
name = name + "_epoch_year",
outs = [year_file],
cmd = year_cmd + " printf '%s\\n' \"$$YEAR\" > $@",
# Undocumented attr to depend on the workspace status files; see
# https://github.com/bazelbuild/bazel/issues/4942
stamp = 1,
testonly = testonly,
tags = tags,
visibility = visibility,
)
year_srcs = [year_file]
year_cmd = ""
year_arg = "\"$$(cat $(location " + year_file + "))\""

native.genrule(
name = name + "_gen",
srcs = [spec] + srcs,
srcs = [spec] + srcs + year_srcs,
outs = outs,
cmd = " ".join([
year_cmd,
Expand All @@ -105,9 +121,7 @@ def generated_certs(
" exit 1;",
"fi;",
]),
# Undocumented attr to depend on the workspace status files; see
# https://github.com/bazelbuild/bazel/issues/4942
stamp = stamp,
stamp = 0,
testonly = testonly,
tags = tags,
tools = [gen_label],
Expand Down
37 changes: 33 additions & 4 deletions bazel/certs/test/BUILD
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
load("@rules_shell//shell:sh_test.bzl", "sh_test")
load("//certs:certs.bzl", "generated_certs")
load(":certs_analysis_test.bzl", "command_test", "files_test")
load(":certs_analysis_test.bzl", "command_test", "files_test", "inputs_test")

generated_certs(
name = "generated",
Expand Down Expand Up @@ -125,22 +125,51 @@ command_test(

command_test(
name = "stamped_command_test",
target_under_test = ":stamped_gen",
target_under_test = ":stamped_epoch_year",
expected = "STABLE_CERT_EPOCH_YEAR",
)

command_test(
name = "build_timestamp_command_test",
target_under_test = ":stamped_gen",
target_under_test = ":stamped_epoch_year",
expected = "BUILD_TIMESTAMP",
)

command_test(
name = "custom_status_command_test",
target_under_test = ":custom_status_gen",
target_under_test = ":custom_status_epoch_year",
expected = "CUSTOM_CERT_YEAR",
)

inputs_test(
name = "year_status_inputs_test",
expected = [
"stable-status.txt",
"volatile-status.txt",
],
target_under_test = ":stamped_epoch_year",
)

inputs_test(
name = "certificate_inputs_test",
expected = ["stamped_epoch_year.txt"],
forbidden = [
"stable-status.txt",
"volatile-status.txt",
],
target_under_test = ":stamped_gen",
)

inputs_test(
name = "pinned_inputs_test",
forbidden = [
"stable-status.txt",
"volatile-status.txt",
"generated_epoch_year.txt",
],
target_under_test = ":generated_gen",
)

files_test(
name = "runtime_filegroup_test",
target_under_test = ":generated",
Expand Down
19 changes: 19 additions & 0 deletions bazel/certs/test/certs_analysis_test.bzl
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,25 @@ command_test = analysistest.make(
attrs = {"expected": attr.string(mandatory = True)},
)

def _inputs_test_impl(ctx):
env = analysistest.begin(ctx)
actions = [action for action in analysistest.target_actions(env) if action.mnemonic == "Genrule"]
asserts.equals(env, 1, len(actions))
inputs = [f.basename for f in actions[0].inputs.to_list()]
for name in ctx.attr.expected:
asserts.true(env, name in inputs, "missing input: " + name)
for name in ctx.attr.forbidden:
asserts.false(env, name in inputs, "unexpected input: " + name)
return analysistest.end(env)

inputs_test = analysistest.make(
_inputs_test_impl,
attrs = {
"expected": attr.string_list(),
"forbidden": attr.string_list(),
},
)

def _files_test_impl(ctx):
env = analysistest.begin(ctx)
files = sorted([
Expand Down
Loading