parent
de5274835b
commit
f688d17cfb
4
.bazelrc
4
.bazelrc
|
@ -23,6 +23,10 @@ build --enable_runfiles
|
|||
|
||||
common --enable_platform_specific_config
|
||||
|
||||
# For testing our --stamp behavior.
|
||||
# Normally users would use a --workspace_status_command with a script that calls `git describe`.
|
||||
build --embed_label=v1.2.3
|
||||
|
||||
# Turn off legacy external runfiles on all platforms except Windows.
|
||||
# This allows our users to turn on this flag as well, which is a performance win.
|
||||
# Skylib's diff_test implementation for Windows depends on legacy external
|
||||
|
|
|
@ -86,6 +86,19 @@ jq(
|
|||
],
|
||||
filter = "{ deps: split("\n") | map(select(. | length > 0)) }",
|
||||
)
|
||||
|
||||
# With --stamp, causes properties to be replaced by version control info.
|
||||
jq(
|
||||
name = "stamped",
|
||||
srcs = ["package.json"],
|
||||
filter = "|".join([
|
||||
# Don't directly reference $STAMP as it's only set when stamping
|
||||
# This 'as' syntax results in $stamp being null in unstamped builds.
|
||||
"$ARGS.named.STAMP as $stamp",
|
||||
# Provide a default using the "alternative operator" in case $stamp is null.
|
||||
".version = ($stamp.BUILD_EMBED_LABEL // "<unstamped>")",
|
||||
]),
|
||||
)
|
||||
```
|
||||
|
||||
|
||||
|
@ -96,7 +109,7 @@ jq(
|
|||
| :------------- | :------------- | :------------- |
|
||||
| <a id="jq-name"></a>name | Name of the rule | none |
|
||||
| <a id="jq-srcs"></a>srcs | List of input files | none |
|
||||
| <a id="jq-filter"></a>filter | Filter expression (https://stedolan.github.io/jq/manual/#Basicfilters) | <code>None</code> |
|
||||
| <a id="jq-filter"></a>filter | Filter expression (https://stedolan.github.io/jq/manual/#Basicfilters). Subject to stamp variable replacements, see [Stamping](./stamping.md). When stamping is enabled, a variable named "STAMP" will be available in the filter.<br><br>Be careful to write the filter so that it handles unstamped builds, as in the example above. | <code>None</code> |
|
||||
| <a id="jq-filter_file"></a>filter_file | File containing filter expression (alternative to <code>filter</code>) | <code>None</code> |
|
||||
| <a id="jq-args"></a>args | Additional args to pass to jq | <code>[]</code> |
|
||||
| <a id="jq-out"></a>out | Name of the output json file; defaults to the rule name plus ".json" | <code>None</code> |
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
<!-- Generated with Stardoc: http://skydoc.bazel.build -->
|
||||
|
||||
Version Stamping
|
||||
# Version Stamping
|
||||
|
||||
Bazel is generally only a build tool, and is unaware of your version control system.
|
||||
However, when publishing releases, you may want to embed version information in the resulting distribution.
|
||||
|
@ -23,7 +23,8 @@ They will usually say something like "subject to stamp variable replacements".
|
|||
|
||||
## Stamping with a Workspace status script
|
||||
|
||||
To define additional statuses, pass the `--workspace_status_command` argument to `bazel`.
|
||||
To define additional statuses, pass the `--workspace_status_command` flag to `bazel`.
|
||||
This slows down every build, so you should avoid passing this flag unless you need to stamp this build.
|
||||
The value of this flag is a path to a script that prints space-separated key/value pairs, one per line, such as
|
||||
|
||||
```bash
|
||||
|
@ -68,9 +69,9 @@ def _rule_impl(ctx):
|
|||
inputs = []
|
||||
stamp = maybe_stamp(ctx)
|
||||
if stamp:
|
||||
args.add("--volatile_status_file", stamp.volatile_status)
|
||||
args.add("--stable_status_file", stamp.stable_status)
|
||||
inputs.extend([stamp.volatile_status, stamp.stable_status])
|
||||
args.add("--volatile_status_file", stamp.volatile_status_file.path)
|
||||
args.add("--stable_status_file", stamp.stable_status_file.path)
|
||||
inputs.extend([stamp.volatile_status_file, stamp.stable_status_file])
|
||||
|
||||
# ... call actions which parse the stamp files and do something with the values ...
|
||||
```
|
||||
|
|
20
lib/jq.bzl
20
lib/jq.bzl
|
@ -85,12 +85,30 @@ def jq(name, srcs, filter = None, filter_file = None, args = [], out = None, **k
|
|||
],
|
||||
filter = "{ deps: split(\"\\n\") | map(select(. | length > 0)) }",
|
||||
)
|
||||
|
||||
# With --stamp, causes properties to be replaced by version control info.
|
||||
jq(
|
||||
name = "stamped",
|
||||
srcs = ["package.json"],
|
||||
filter = "|".join([
|
||||
# Don't directly reference $STAMP as it's only set when stamping
|
||||
# This 'as' syntax results in $stamp being null in unstamped builds.
|
||||
"$ARGS.named.STAMP as $stamp",
|
||||
# Provide a default using the "alternative operator" in case $stamp is null.
|
||||
".version = ($stamp.BUILD_EMBED_LABEL // \"<unstamped>\")",
|
||||
]),
|
||||
)
|
||||
```
|
||||
|
||||
Args:
|
||||
name: Name of the rule
|
||||
srcs: List of input files
|
||||
filter: Filter expression (https://stedolan.github.io/jq/manual/#Basicfilters)
|
||||
filter: Filter expression (https://stedolan.github.io/jq/manual/#Basicfilters).
|
||||
Subject to stamp variable replacements, see [Stamping](./stamping.md).
|
||||
When stamping is enabled, a variable named "STAMP" will be available in the filter.
|
||||
|
||||
Be careful to write the filter so that it handles unstamped builds, as in the example above.
|
||||
|
||||
filter_file: File containing filter expression (alternative to `filter`)
|
||||
args: Additional args to pass to jq
|
||||
out: Name of the output json file; defaults to the rule name plus ".json"
|
||||
|
|
|
@ -7,6 +7,11 @@ exports_files(
|
|||
visibility = ["//docs:__pkg__"],
|
||||
)
|
||||
|
||||
exports_files(
|
||||
["parse_status_file.jq"],
|
||||
visibility = ["//visibility:public"],
|
||||
)
|
||||
|
||||
bzl_library(
|
||||
name = "copy_common",
|
||||
srcs = ["copy_common.bzl"],
|
||||
|
@ -103,6 +108,7 @@ bzl_library(
|
|||
bzl_library(
|
||||
name = "jq",
|
||||
srcs = ["jq.bzl"],
|
||||
deps = ["//lib:stamping"],
|
||||
)
|
||||
|
||||
bzl_library(
|
||||
|
|
|
@ -1,6 +1,8 @@
|
|||
"""Implementation for jq rule"""
|
||||
|
||||
_jq_attrs = {
|
||||
load("//lib:stamping.bzl", "STAMP_ATTRS", "maybe_stamp")
|
||||
|
||||
_jq_attrs = dict({
|
||||
"srcs": attr.label_list(
|
||||
allow_files = True,
|
||||
mandatory = True,
|
||||
|
@ -10,7 +12,11 @@ _jq_attrs = {
|
|||
"filter_file": attr.label(allow_single_file = True),
|
||||
"args": attr.string_list(),
|
||||
"out": attr.output(),
|
||||
}
|
||||
"_parse_status_file_filter": attr.label(
|
||||
allow_single_file = True,
|
||||
default = Label("//lib/private:parse_status_file.jq"),
|
||||
),
|
||||
}, **STAMP_ATTRS)
|
||||
|
||||
def _jq_impl(ctx):
|
||||
jq_bin = ctx.toolchains["@aspect_bazel_lib//lib:jq_toolchain_type"].jqinfo.bin
|
||||
|
@ -32,6 +38,34 @@ def _jq_impl(ctx):
|
|||
args = args + ["--from-file '%s'" % ctx.file.filter_file.path]
|
||||
inputs.append(ctx.file.filter_file)
|
||||
|
||||
stamp = maybe_stamp(ctx)
|
||||
if stamp:
|
||||
# create an action that gives a JSON representation of the stamp keys
|
||||
stamp_json = ctx.actions.declare_file("_%s_stamp.json" % ctx.label.name)
|
||||
ctx.actions.run_shell(
|
||||
tools = [jq_bin],
|
||||
inputs = [stamp.stable_status_file, stamp.volatile_status_file, ctx.file._parse_status_file_filter],
|
||||
outputs = [stamp_json],
|
||||
command = "{jq} -s -R -f {filter} {stable} {volatile} > {out}".format(
|
||||
jq = jq_bin.path,
|
||||
filter = ctx.file._parse_status_file_filter.path,
|
||||
stable = stamp.stable_status_file.path,
|
||||
volatile = stamp.volatile_status_file.path,
|
||||
out = stamp_json.path,
|
||||
),
|
||||
mnemonic = "ConvertStatusToJson",
|
||||
)
|
||||
inputs.append(stamp_json)
|
||||
|
||||
# jq says of --argfile:
|
||||
# > Do not use. Use --slurpfile instead.
|
||||
# > (This option is like --slurpfile, but when the file has just one text,
|
||||
# > then that is used, else an array of texts is used as in --slurpfile.)
|
||||
# However there's no indication that it's deprecated. Maybe it's a style convention.
|
||||
# For our purposes, "$STAMP.BUILD_TIMESTAMP" looks a lot more sensible in a BUILD file
|
||||
# than "$STAMP[0].BUILD_TIMESTAMP".
|
||||
args = args + ["--argfile", "STAMP", stamp_json.path]
|
||||
|
||||
cmd = "{jq} {args} {filter} {sources} > {out}".format(
|
||||
jq = jq_bin.path,
|
||||
args = " ".join(args),
|
||||
|
|
|
@ -0,0 +1,5 @@
|
|||
[
|
||||
split("\n")[] # Convert lines to array
|
||||
| capture("(?<key>[^\\s]+)\\s+(?<value>.*)"; "x") # capture {"key": [everything before first whitespace], "value": [remainder of line]}
|
||||
]
|
||||
| from_entries # Convert [{"key": "a", "value": "b"}] to map {"a": "b"}
|
|
@ -1,4 +1,4 @@
|
|||
"""Version Stamping
|
||||
"""# Version Stamping
|
||||
|
||||
Bazel is generally only a build tool, and is unaware of your version control system.
|
||||
However, when publishing releases, you may want to embed version information in the resulting distribution.
|
||||
|
@ -21,7 +21,8 @@ They will usually say something like "subject to stamp variable replacements".
|
|||
|
||||
## Stamping with a Workspace status script
|
||||
|
||||
To define additional statuses, pass the `--workspace_status_command` argument to `bazel`.
|
||||
To define additional statuses, pass the `--workspace_status_command` flag to `bazel`.
|
||||
This slows down every build, so you should avoid passing this flag unless you need to stamp this build.
|
||||
The value of this flag is a path to a script that prints space-separated key/value pairs, one per line, such as
|
||||
|
||||
```bash
|
||||
|
@ -66,9 +67,9 @@ def _rule_impl(ctx):
|
|||
inputs = []
|
||||
stamp = maybe_stamp(ctx)
|
||||
if stamp:
|
||||
args.add("--volatile_status_file", stamp.volatile_status)
|
||||
args.add("--stable_status_file", stamp.stable_status)
|
||||
inputs.extend([stamp.volatile_status, stamp.stable_status])
|
||||
args.add("--volatile_status_file", stamp.volatile_status_file.path)
|
||||
args.add("--stable_status_file", stamp.stable_status_file.path)
|
||||
inputs.extend([stamp.volatile_status_file, stamp.stable_status_file])
|
||||
|
||||
# ... call actions which parse the stamp files and do something with the values ...
|
||||
```
|
||||
|
|
|
@ -1,5 +1,6 @@
|
|||
load("//lib/tests/jq:diff_test.bzl", "diff_test")
|
||||
load("//lib:jq.bzl", "jq")
|
||||
load("//lib:testing.bzl", "assert_contains")
|
||||
|
||||
exports_files([
|
||||
"a_pretty.json",
|
||||
|
@ -95,6 +96,39 @@ diff_test(
|
|||
file2 = ":case_filter_file",
|
||||
)
|
||||
|
||||
# Filter that uses a stamp variable
|
||||
[
|
||||
jq(
|
||||
name = ("" if stamp else "un") + "stamped",
|
||||
srcs = ["a.json"],
|
||||
filter = "|".join([
|
||||
# Don't directly reference $STAMP as it's only set when stamping
|
||||
"$ARGS.named.STAMP as $stamp",
|
||||
# Provide a default using the "alternative operator"
|
||||
".foo = ($stamp.BUILD_EMBED_LABEL // \"<unstamped>\")",
|
||||
".value = ($stamp.BUILD_TIMESTAMP // 1 | tonumber)",
|
||||
]),
|
||||
stamp = stamp,
|
||||
)
|
||||
for stamp in [
|
||||
0,
|
||||
1,
|
||||
]
|
||||
]
|
||||
|
||||
assert_contains(
|
||||
name = "check_stamped",
|
||||
actual = "stamped.json",
|
||||
# v1.2.3 comes from the --embed_label flag in .bazelrc
|
||||
expected = """foo": "v1.2.3""",
|
||||
)
|
||||
|
||||
assert_contains(
|
||||
name = "check_unstamped",
|
||||
actual = "unstamped.json",
|
||||
expected = """foo": "<unstamped>""",
|
||||
)
|
||||
|
||||
# Call jq within a genrule
|
||||
genrule(
|
||||
name = "case_genrule",
|
||||
|
|
Loading…
Reference in New Issue