From 543582f60037e78ef65f116cfe1b437110a14884 Mon Sep 17 00:00:00 2001 From: Paul Johnston Date: Sun, 5 Oct 2025 13:29:24 -0600 Subject: [PATCH] Add golden tests --- .bcr/presubmit.yml | 2 +- .github/workflows/ci.yaml | 6 +- .github/workflows/release_ruleset.yaml | 4 +- MODULE.bazel | 2 +- examples/helloworld/BUILD.bazel | 13 ++-- examples/helloworld/index.js.golden | 15 ++++ rules/testing.bzl | 102 +++++++++++++++++++++++++ 7 files changed, 131 insertions(+), 13 deletions(-) create mode 100755 examples/helloworld/index.js.golden create mode 100644 rules/testing.bzl diff --git a/.bcr/presubmit.yml b/.bcr/presubmit.yml index c6a2300..b19745d 100644 --- a/.bcr/presubmit.yml +++ b/.bcr/presubmit.yml @@ -8,5 +8,5 @@ bcr_test_module: name: "Build module" platform: ${{ platform }} bazel: ${{ bazel }} - build_targets: + test_targets: - "//..." diff --git a/.github/workflows/ci.yaml b/.github/workflows/ci.yaml index 660dda7..6fbee1f 100644 --- a/.github/workflows/ci.yaml +++ b/.github/workflows/ci.yaml @@ -25,10 +25,10 @@ jobs: disk-cache: true # Share repository cache between workflows. repository-cache: true - - name: bazel build + - name: bazel test run: >- bazelisk --bazelrc=.github/workflows/ci.bazelrc --bazelrc=.bazelrc - build - ... + test + //... diff --git a/.github/workflows/release_ruleset.yaml b/.github/workflows/release_ruleset.yaml index 9494ccd..b790a30 100644 --- a/.github/workflows/release_ruleset.yaml +++ b/.github/workflows/release_ruleset.yaml @@ -93,7 +93,7 @@ jobs: # Fetch built artifacts (if any) from earlier jobs, which the release script may want to read. # Extract into ${GITHUB_WORKSPACE}/artifacts/* - uses: actions/download-artifact@95815c38cf2ff2164869cbab79da8d1f422bc89e # v4.2.1 - + - name: Build release artifacts and prepare release notes run: | if [ ! -f ".github/workflows/release_prep.sh" ]; then @@ -205,4 +205,4 @@ jobs: tag_name: ${{ inputs.tag_name }} files: | release_files/**/* - attestations/* \ No newline at end of file + attestations/* diff --git a/MODULE.bazel b/MODULE.bazel index 1ebec25..e8f3c5f 100644 --- a/MODULE.bazel +++ b/MODULE.bazel @@ -12,7 +12,7 @@ module( bazel_dep(name = "aspect_rules_js", version = "2.6.0") bazel_dep(name = "aspect_rules_ts", version = "3.7.0") -bazel_dep(name = "bazel_skylib", version = "1.8.1") +bazel_dep(name = "bazel_skylib", version = "1.8.2") bazel_dep(name = "rules_nodejs", version = "6.5.0") # -------------------------------------------------------------------------------- diff --git a/examples/helloworld/BUILD.bazel b/examples/helloworld/BUILD.bazel index ccca023..ae1aba2 100644 --- a/examples/helloworld/BUILD.bazel +++ b/examples/helloworld/BUILD.bazel @@ -1,13 +1,14 @@ load("//rules:defs.bzl", "closure_ts_compile") +load("//rules:testing.bzl", "golden_file_test") closure_ts_compile( name = "lib", srcs = ["index.ts"], ) -# bazel run //examples/helloworld:files.update -# bazel test //examples/helloworld:files.test -# golden_filegroup( -# name = "files", -# srcs = [":index.ts"], -# ) +# bazel test //examples/helloworld:golden_test +# bazel run //examples/helloworld:golden_test.update +golden_file_test( + name = "golden_test", + srcs = [":lib"], +) diff --git a/examples/helloworld/index.js.golden b/examples/helloworld/index.js.golden new file mode 100755 index 0000000..827b0f3 --- /dev/null +++ b/examples/helloworld/index.js.golden @@ -0,0 +1,15 @@ +/** + * @fileoverview added by tsickle + * Generated from: examples/helloworld/index.ts + */ +goog.module('examples.helloworld.index'); +var module = module || { id: 'examples/helloworld/index.ts' }; +goog.require('tslib'); +/** + * @param {string} name + * @return {string} + */ +function sayHello(name) { + return `hello, ${name}!`; +} +exports.sayHello = sayHello; diff --git a/rules/testing.bzl b/rules/testing.bzl new file mode 100644 index 0000000..f5e3357 --- /dev/null +++ b/rules/testing.bzl @@ -0,0 +1,102 @@ +def _golden_file_test_impl(ctx): + outputs = [ctx.outputs.executable] + + content = "\n".join([ + """ +if diff -u {dst} {src}; then + echo "files contents are identical" +else + echo "files differ" + exit 1 +fi +""".format( + src = src.short_path, + dst = src.short_path + ".golden", + ) + for src in ctx.files.srcs + ]) + + ctx.actions.write( + ctx.outputs.executable, + "set -x\n\n" + content, + is_executable = True, + ) + return [ + DefaultInfo( + files = depset(outputs), + runfiles = ctx.runfiles(files = ctx.files.srcs + ctx.files.goldens), + ), + ] + +_golden_file_test = rule( + doc = "Asserts the two files are equal", + implementation = _golden_file_test_impl, + attrs = { + "srcs": attr.label_list( + doc = "the source files under test", + allow_files = True, + mandatory = True, + ), + "goldens": attr.label_list( + doc = "the expected golden files", + allow_files = True, + mandatory = True, + ), + }, + executable = True, + test = True, +) + +def _golden_file_update_impl(ctx): + outputs = [ctx.outputs.executable] + + content = "\n".join([ + """ +cp -f {src} {dst} +echo "Updated golden file: {dst}" +""".format( + src = src.short_path, + dst = "$BUILD_WORKING_DIRECTORY/%s/%s.golden" % (ctx.label.package, src.basename), + ) + for src in ctx.files.srcs + ]) + + ctx.actions.write( + ctx.outputs.executable, + "set -x\n\n" + content, + is_executable = True, + ) + return [ + DefaultInfo( + files = depset(outputs), + runfiles = ctx.runfiles(files = ctx.files.srcs), + ), + ] + +_golden_file_update = rule( + doc = "Asserts the two files are equal", + implementation = _golden_file_update_impl, + attrs = { + "srcs": attr.label_list( + doc = "the source files to update", + allow_files = True, + mandatory = True, + ), + }, + executable = True, +) + +def golden_file_test(name, srcs, **kwargs): + tags = kwargs.get("tags", []) + _golden_file_test( + name = name, + srcs = srcs, + goldens = native.glob(["*.golden"]), + tags = tags, + **kwargs + ) + _golden_file_update( + name = name + ".update", + srcs = srcs, + tags = tags, + )