From 3f5d2cf9365b058bdc504bbf8ba35180f31b88e3 Mon Sep 17 00:00:00 2001 From: Googler Date: Fri, 2 Jun 2023 02:42:00 -0700 Subject: [PATCH 1/2] Add formatted timestamp entries to volatile workspace status file. This change avoids unix timestamp parsing for Starlark rules which will be writing BuildInfo files in the future. PiperOrigin-RevId: 537258769 Change-Id: Ie68bac5d8e365f3251122c4b6367227e1dd0cec8 --- site/en/docs/user-manual.md | 2 ++ .../build/lib/bazel/BazelWorkspaceStatusModule.java | 11 +++++++++++ 2 files changed, 13 insertions(+) diff --git a/site/en/docs/user-manual.md b/site/en/docs/user-manual.md index 4b81b26d29ec4e..e9cf747b47ad0f 100644 --- a/site/en/docs/user-manual.md +++ b/site/en/docs/user-manual.md @@ -1270,6 +1270,8 @@ The contract is: Bazel always outputs the following volatile keys: * `BUILD_TIMESTAMP`: time of the build in seconds since the Unix Epoch (the value of `System.currentTimeMillis()` divided by a thousand) + * `FORMATTED_DATE`: time of the build Formatted as + `yyyy MMM d HH mm ss EEE`(for example 2023 Jun 2 01 44 29 Fri) in UTC. On Linux/macOS you can pass `--workspace_status_command=/bin/true` to disable retrieving workspace status, because `true` does nothing, successfully (exits diff --git a/src/main/java/com/google/devtools/build/lib/bazel/BazelWorkspaceStatusModule.java b/src/main/java/com/google/devtools/build/lib/bazel/BazelWorkspaceStatusModule.java index 0b9ada5de51592..7308d4fddd827a 100644 --- a/src/main/java/com/google/devtools/build/lib/bazel/BazelWorkspaceStatusModule.java +++ b/src/main/java/com/google/devtools/build/lib/bazel/BazelWorkspaceStatusModule.java @@ -62,6 +62,9 @@ import java.io.IOException; import java.io.OutputStream; import java.nio.charset.StandardCharsets; +import java.time.Instant; +import java.time.ZoneOffset; +import java.time.format.DateTimeFormatter; import java.util.Map; import java.util.TreeMap; import javax.annotation.Nullable; @@ -80,6 +83,13 @@ static class BazelWorkspaceStatusAction extends WorkspaceStatusAction { private final String username; private final String hostname; + private static final DateTimeFormatter TIME_FORMAT = + DateTimeFormatter.ofPattern("yyyy MMM d HH mm ss EEE"); + + private static String format(long timestamp) { + return Instant.ofEpochMilli(timestamp).atZone(ZoneOffset.UTC).format(TIME_FORMAT); + } + BazelWorkspaceStatusAction( Artifact stableStatus, Artifact volatileStatus, String username, String hostname) { super( @@ -182,6 +192,7 @@ public ActionResult execute(ActionExecutionContext actionExecutionContext) stableMap.put(BuildInfo.BUILD_USER, username); volatileMap.put( BuildInfo.BUILD_TIMESTAMP, Long.toString(getCurrentTimeMillis(clientEnv) / 1000)); + volatileMap.put("FORMATTED_DATE", format(getCurrentTimeMillis(clientEnv) / 1000 * 1000)); try { Map statusMap = parseWorkspaceStatus(getAdditionalWorkspaceStatus(options, actionExecutionContext)); From c086e6f6b8c3b083223809286094793c5715b259 Mon Sep 17 00:00:00 2001 From: Googler Date: Wed, 13 Sep 2023 10:24:15 -0700 Subject: [PATCH 2/2] Fix a bug where volatile workspace status file might have contained a formatted date different from a timestamp. PiperOrigin-RevId: 565090042 Change-Id: I25d9c97ec562e062fb50c3ded572cc7bbf8a311f --- .../lib/bazel/BazelWorkspaceStatusModule.java | 6 ++--- .../bazel/bazel_workspace_status_test.sh | 22 +++++++++++++++++++ 2 files changed, 25 insertions(+), 3 deletions(-) diff --git a/src/main/java/com/google/devtools/build/lib/bazel/BazelWorkspaceStatusModule.java b/src/main/java/com/google/devtools/build/lib/bazel/BazelWorkspaceStatusModule.java index 7308d4fddd827a..f5e38a793b3a84 100644 --- a/src/main/java/com/google/devtools/build/lib/bazel/BazelWorkspaceStatusModule.java +++ b/src/main/java/com/google/devtools/build/lib/bazel/BazelWorkspaceStatusModule.java @@ -190,9 +190,9 @@ public ActionResult execute(ActionExecutionContext actionExecutionContext) stableMap.put(BuildInfo.BUILD_EMBED_LABEL, options.embedLabel); stableMap.put(BuildInfo.BUILD_HOST, hostname); stableMap.put(BuildInfo.BUILD_USER, username); - volatileMap.put( - BuildInfo.BUILD_TIMESTAMP, Long.toString(getCurrentTimeMillis(clientEnv) / 1000)); - volatileMap.put("FORMATTED_DATE", format(getCurrentTimeMillis(clientEnv) / 1000 * 1000)); + long currentTimeMillis = getCurrentTimeMillis(clientEnv); + volatileMap.put(BuildInfo.BUILD_TIMESTAMP, Long.toString(currentTimeMillis / 1000)); + volatileMap.put("FORMATTED_DATE", format(currentTimeMillis / 1000 * 1000)); try { Map statusMap = parseWorkspaceStatus(getAdditionalWorkspaceStatus(options, actionExecutionContext)); diff --git a/src/test/shell/bazel/bazel_workspace_status_test.sh b/src/test/shell/bazel/bazel_workspace_status_test.sh index 5bb4e03dd0f725..ebac7f696493da 100755 --- a/src/test/shell/bazel/bazel_workspace_status_test.sh +++ b/src/test/shell/bazel/bazel_workspace_status_test.sh @@ -190,6 +190,28 @@ EOF assert_contains "STABLE_NAME bob" bazel-genfiles/ao assert_contains "NUMBER 3" bazel-genfiles/ao + # Test that generated timestamp is the same as its formatted version. + volatile_file="bazel-out/volatile-status.txt" + bazel build --stamp //:a || fail "build failed" + assert_contains "BUILD_TIMESTAMP" $volatile_file + assert_contains "FORMATTED_DATE" $volatile_file + # Read key value pairs. + timestamp_key_value=$(sed "1q;d" $volatile_file) + formatted_timestamp_key_value=$(sed "2q;d" $volatile_file) + # Extract values of the formatted date and timestamp. + timestamp=${timestamp_key_value#* } + formatted_date=${formatted_timestamp_key_value#* } + if [[ $(uname -s) == "Darwin" ]] + then + timestamp_formatted_date=$(date -u -r "$timestamp" +'%Y %b %d %H %M %S %a') + else + timestamp_formatted_date=$(date -u -d "@$timestamp" +'%Y %b %d %H %M %S %a') + fi + + if [[ $timestamp_formatted_date != $formatted_date ]] + then + fail "Timestamp formatted date: $timestamp_formatted_date differs from workspace module provided formatted date: $formatted_date" + fi } function test_env_var_in_workspace_status() {