diff --git a/.aspect/bazelrc/BUILD.bazel b/.aspect/bazelrc/BUILD.bazel new file mode 100644 index 0000000..3622b92 --- /dev/null +++ b/.aspect/bazelrc/BUILD.bazel @@ -0,0 +1,15 @@ +"Aspect bazelrc presets; see https://docs.aspect.build/guides/bazelrc" + +load("@aspect_bazel_lib//lib:bazelrc_presets.bzl", "write_aspect_bazelrc_presets") + +write_aspect_bazelrc_presets( + name = "update_aspect_bazelrc_presets", + presets = [ + "bazel8", + "convenience", + "correctness", + "debug", + "javascript", + "performance", + ], +) diff --git a/.aspect/bazelrc/bazel8.bazelrc b/.aspect/bazelrc/bazel8.bazelrc new file mode 100644 index 0000000..e01f897 --- /dev/null +++ b/.aspect/bazelrc/bazel8.bazelrc @@ -0,0 +1 @@ +# No Bazel 8 specific flag presets yet. diff --git a/.aspect/bazelrc/convenience.bazelrc b/.aspect/bazelrc/convenience.bazelrc new file mode 100644 index 0000000..796675a --- /dev/null +++ b/.aspect/bazelrc/convenience.bazelrc @@ -0,0 +1,28 @@ +# Attempt to build & test every target whose prerequisites were successfully built. +# Docs: https://bazel.build/docs/user-manual#keep-going +build --keep_going + +# Output test errors to stderr so users don't have to `cat` or open test failure log files when test +# fail. This makes the log noisier in exchange for reducing the time-to-feedback on test failures for +# users. +# Docs: https://bazel.build/docs/user-manual#test-output +test --test_output=errors + +# Show the output files created by builds that requested more than one target. This helps users +# locate the build outputs in more cases +# Docs: https://bazel.build/docs/user-manual#show-result +build --show_result=20 + +# Bazel picks up host-OS-specific config lines from bazelrc files. For example, if the host OS is +# Linux and you run bazel build, Bazel picks up lines starting with build:linux. Supported OS +# identifiers are `linux`, `macos`, `windows`, `freebsd`, and `openbsd`. Enabling this flag is +# equivalent to using `--config=linux` on Linux, `--config=windows` on Windows, etc. +# Docs: https://bazel.build/reference/command-line-reference#flag--enable_platform_specific_config +common --enable_platform_specific_config + +# Output a heap dump if an OOM is thrown during a Bazel invocation +# (including OOMs due to `--experimental_oom_more_eagerly_threshold`). +# The dump will be written to `/.heapdump.hprof`. +# You may need to configure CI to capture this artifact and upload for later use. +# Docs: https://bazel.build/reference/command-line-reference#flag--heap_dump_on_oom +common --heap_dump_on_oom diff --git a/.aspect/bazelrc/correctness.bazelrc b/.aspect/bazelrc/correctness.bazelrc new file mode 100644 index 0000000..e550193 --- /dev/null +++ b/.aspect/bazelrc/correctness.bazelrc @@ -0,0 +1,64 @@ +# Do not upload locally executed action results to the remote cache. +# This should be the default for local builds so local builds cannot poison the remote cache. +# It should be flipped to `--remote_upload_local_results` on CI +# by using `--bazelrc=.aspect/bazelrc/ci.bazelrc`. +# Docs: https://bazel.build/reference/command-line-reference#flag--remote_upload_local_results +build --noremote_upload_local_results + +# Don't allow network access for build actions in the sandbox. +# Ensures that you don't accidentally make non-hermetic actions/tests which depend on remote +# services. +# Developers should tag targets with `tags=["requires-network"]` to opt-out of the enforcement. +# Docs: https://bazel.build/reference/command-line-reference#flag--sandbox_default_allow_network +build --sandbox_default_allow_network=false + +# Warn if a test's timeout is significantly longer than the test's actual execution time. +# Bazel's default for test_timeout is medium (5 min), but most tests should instead be short (1 min). +# While a test's timeout should be set such that it is not flaky, a test that has a highly +# over-generous timeout can hide real problems that crop up unexpectedly. +# For instance, a test that normally executes in a minute or two should not have a timeout of +# ETERNAL or LONG as these are much, much too generous. +# Docs: https://bazel.build/docs/user-manual#test-verbose-timeout-warnings +test --test_verbose_timeout_warnings + +# Allow the Bazel server to check directory sources for changes. Ensures that the Bazel server +# notices when a directory changes, if you have a directory listed in the srcs of some target. +# Recommended when using +# [copy_directory](https://github.com/bazel-contrib/bazel-lib/blob/main/docs/copy_directory.md) and +# [rules_js](https://github.com/aspect-build/rules_js) since npm package are source directories +# inputs to copy_directory actions. +# Docs: https://bazel.build/reference/command-line-reference#flag--host_jvm_args +startup --host_jvm_args=-DBAZEL_TRACK_SOURCE_DIRECTORIES=1 + +# Allow exclusive tests to run in the sandbox. Fixes a bug where Bazel doesn't enable sandboxing for +# tests with `tags=["exclusive"]`. +# Docs: https://bazel.build/reference/command-line-reference#flag--incompatible_exclusive_test_sandboxed +test --incompatible_exclusive_test_sandboxed + +# Use a static value for `PATH` and does not inherit `LD_LIBRARY_PATH`. Doesn't let environment +# variables like `PATH` sneak into the build, which can cause massive cache misses when they change. +# Use `--action_env=ENV_VARIABLE` if you want to inherit specific environment variables from the +# client, but note that doing so can prevent cross-user caching if a shared cache is used. +# Docs: https://bazel.build/reference/command-line-reference#flag--incompatible_strict_action_env +build --incompatible_strict_action_env + +# Do not automatically create `__init__.py` files in the runfiles of Python targets. Fixes the wrong +# default that comes from Google's internal monorepo by using `__init__.py` to delimit a Python +# package. Precisely, when a `py_binary` or `py_test` target has `legacy_create_init` set to `auto (the +# default), it is treated as false if and only if this flag is set. See +# https://github.com/bazelbuild/bazel/issues/10076. +# Docs: https://bazel.build/reference/command-line-reference#flag--incompatible_default_to_explicit_init_py +build --incompatible_default_to_explicit_init_py + +# Set default value of `allow_empty` to `False` in `glob()`. This prevents a common mistake when +# attempting to use `glob()` to match files in a subdirectory that is opaque to the current package +# because it contains a BUILD file. See https://github.com/bazelbuild/bazel/issues/8195. +# Docs: https://bazel.build/reference/command-line-reference#flag--incompatible_disallow_empty_glob +common --incompatible_disallow_empty_glob + +# Always download coverage files for tests from the remote cache. By default, coverage files are not +# downloaded on test result cache hits when --remote_download_minimal is enabled, making it impossible +# to generate a full coverage report. +# Docs: https://bazel.build/reference/command-line-reference#flag--experimental_fetch_all_coverage_outputs +# detching remote cache results +test --experimental_fetch_all_coverage_outputs diff --git a/.aspect/bazelrc/debug.bazelrc b/.aspect/bazelrc/debug.bazelrc new file mode 100644 index 0000000..bfb0bdd --- /dev/null +++ b/.aspect/bazelrc/debug.bazelrc @@ -0,0 +1,19 @@ +############################################################ +# Use `bazel test --config=debug` to enable these settings # +############################################################ + +# Stream stdout/stderr output from each test in real-time. +# Docs: https://bazel.build/docs/user-manual#test-output +test:debug --test_output=streamed + +# Run one test at a time. +# Docs: https://bazel.build/reference/command-line-reference#flag--test_strategy +test:debug --test_strategy=exclusive + +# Prevent long running tests from timing out. +# Docs: https://bazel.build/docs/user-manual#test-timeout +test:debug --test_timeout=9999 + +# Always run tests even if they have cached results. +# Docs: https://bazel.build/docs/user-manual#cache-test-results +test:debug --nocache_test_results diff --git a/.aspect/bazelrc/javascript.bazelrc b/.aspect/bazelrc/javascript.bazelrc new file mode 100644 index 0000000..ace9d60 --- /dev/null +++ b/.aspect/bazelrc/javascript.bazelrc @@ -0,0 +1,11 @@ +# Aspect recommended Bazel flags when using Aspect's JavaScript rules: https://github.com/aspect-build/rules_js +# Docs for Node.js flags: https://nodejs.org/en/docs/guides/debugging-getting-started/#command-line-options + +# Support for debugging Node.js tests. Use bazel run with `--config=debug` to turn on the NodeJS +# inspector agent. The node process will break before user code starts and wait for the debugger to +# connect. Pass the --inspect-brk option to all tests which enables the node inspector agent. See +# https://nodejs.org/de/docs/guides/debugging-getting-started/#command-line-options for more +# details. +# Docs: https://nodejs.org/en/docs/guides/debugging-getting-started/#command-line-options +run:debug -- --node_options=--inspect-brk +test:debug --test_env=NODE_OPTIONS=--inspect-brk diff --git a/.aspect/bazelrc/performance.bazelrc b/.aspect/bazelrc/performance.bazelrc new file mode 100644 index 0000000..56749dd --- /dev/null +++ b/.aspect/bazelrc/performance.bazelrc @@ -0,0 +1,19 @@ +# Directories used by sandboxed non-worker execution may be reused to avoid unnecessary setup costs. +# Save time on Sandbox creation and deletion when many of the same kind of action run during the +# build. +# No longer experimental in Bazel 6: https://github.com/bazelbuild/bazel/commit/c1a95501a5611878e5cc43a3cc531f2b9e47835b +# Docs: https://bazel.build/reference/command-line-reference#flag--reuse_sandbox_directories +build --experimental_reuse_sandbox_directories + +# Avoid creating a runfiles tree for binaries or tests until it is needed. +# Docs: https://bazel.build/reference/command-line-reference#flag--build_runfile_links +# See https://github.com/bazelbuild/bazel/issues/6627 +# +# This may break local workflows that `build` a binary target, then run the resulting program +# outside of `bazel run`. In those cases, the script will need to call +# `bazel build --build_runfile_links //my/binary:target` and then execute the resulting program. +build --nobuild_runfile_links + +# Needed prior to Bazel 8; see +# https://github.com/bazelbuild/bazel/issues/20577 +coverage --build_runfile_links diff --git a/.aspect/cli/config.yaml b/.aspect/cli/config.yaml new file mode 100644 index 0000000..5f04fe8 --- /dev/null +++ b/.aspect/cli/config.yaml @@ -0,0 +1,3 @@ +configure: + languages: + javascript: true diff --git a/.aspect/workflows/bazelrc b/.aspect/workflows/bazelrc new file mode 100644 index 0000000..db6b8ce --- /dev/null +++ b/.aspect/workflows/bazelrc @@ -0,0 +1,66 @@ +# Set this flag to enable re-tries of failed tests on CI. +# When any test target fails, try one or more times. This applies regardless of whether the "flaky" +# tag appears on the target definition. +# This is a tradeoff: legitimately failing tests will take longer to report, +# but we can paper over flaky tests that pass most of the time. +# The alternative is to mark every flaky test with the `flaky = True` attribute, but this requires +# the buildcop to make frequent code edits. +# Not recommended for local builds so that the flakiness is observed during development and thus +# is more likely to get fixed. +# Note that when passing after the first attempt, Bazel will give a special "FLAKY" status. +# Docs: https://bazel.build/docs/user-manual#flaky-test-attempts +test --flaky_test_attempts=2 + +# Announce all announces command options read from the bazelrc file(s) when starting up at the +# beginning of each Bazel invocation. This is very useful on CI to be able to inspect what Bazel rc +# settings are being applied on each run. +# Docs: https://bazel.build/docs/user-manual#announce-rc +build --announce_rc + +# Add a timestamp to each message generated by Bazel specifying the time at which the message was +# displayed. +# Docs: https://bazel.build/docs/user-manual#show-timestamps +build --show_timestamps + +# Only show progress every 30 seconds on CI. +# We want to find a compromise between printing often enough to show that the build isn't stuck, +# but not so often that we produce a long log file that requires a lot of scrolling. +# https://bazel.build/reference/command-line-reference#flag--show_progress_rate_limit +build --show_progress_rate_limit=30 + +# Use cursor controls in screen output. +# Docs: https://bazel.build/docs/user-manual#curses +build --curses=yes + +# Use colors to highlight output on the screen. Set to `no` if your CI does not display colors. +# Docs: https://bazel.build/docs/user-manual#color +build --color=yes + +# The terminal width in columns. Configure this to override the default value based on what your CI system renders. +# Docs: https://github.com/bazelbuild/bazel/blob/1af61b21df99edc2fc66939cdf14449c2661f873/src/main/java/com/google/devtools/build/lib/runtime/UiOptions.java#L151 +build --terminal_columns=143 + +###################################### +# Generic remote cache configuration # +###################################### + +# Only download remote outputs of top level targets to the local machine. +# Docs: https://bazel.build/reference/command-line-reference#flag--remote_download_toplevel +build --remote_download_toplevel + +# The maximum amount of time to wait for remote execution and cache calls. +# https://bazel.build/reference/command-line-reference#flag--remote_timeout +build --remote_timeout=3600 + +# Upload locally executed action results to the remote cache. +# Docs: https://bazel.build/reference/command-line-reference#flag--remote_upload_local_results +build --remote_upload_local_results + +# Fall back to standalone local execution strategy if remote execution fails. If the grpc remote +# cache connection fails, it will fail the build, add this so it falls back to the local cache. +# Docs: https://bazel.build/reference/command-line-reference#flag--remote_local_fallback +build --remote_local_fallback + +# Fixes builds hanging on CI that get the TCP connection closed without sending RST packets. +# Docs: https://bazel.build/reference/command-line-reference#flag--grpc_keepalive_time +build --grpc_keepalive_time=30s \ No newline at end of file diff --git a/.aspect/workflows/config.yaml b/.aspect/workflows/config.yaml new file mode 100644 index 0000000..4ccdcdf --- /dev/null +++ b/.aspect/workflows/config.yaml @@ -0,0 +1,13 @@ +# See https://docs.aspect.build/workflows/configuration +tasks: + # - format: + # queue: aspect-medium + - buildifier: + queue: aspect-medium + - configure: + queue: aspect-medium + - test: + - finalization: + queue: aspect-small +notifications: + github: {} diff --git a/.bazeliskrc b/.bazeliskrc new file mode 100644 index 0000000..5ca935b --- /dev/null +++ b/.bazeliskrc @@ -0,0 +1,2 @@ +BAZELISK_BASE_URL=https://static.aspect.build/aspect +USE_BAZEL_VERSION=aspect/2024.51.11 \ No newline at end of file diff --git a/.bazelrc b/.bazelrc new file mode 100644 index 0000000..b991a19 --- /dev/null +++ b/.bazelrc @@ -0,0 +1,13 @@ +# Import Aspect bazelrc presets +import %workspace%/.aspect/bazelrc/bazel8.bazelrc +import %workspace%/.aspect/bazelrc/convenience.bazelrc +import %workspace%/.aspect/bazelrc/correctness.bazelrc +import %workspace%/.aspect/bazelrc/debug.bazelrc +import %workspace%/.aspect/bazelrc/javascript.bazelrc +import %workspace%/.aspect/bazelrc/performance.bazelrc + +# honor the setting of `skipLibCheck` in the tsconfig.json file +common --@aspect_rules_ts//ts:skipLibCheck=honor_tsconfig + +# Use "tsc" as the transpiler when ts_project has no `transpiler` set. +common --@aspect_rules_ts//ts:default_to_tsc_transpiler \ No newline at end of file diff --git a/.bazelversion b/.bazelversion new file mode 100644 index 0000000..fa5fce0 --- /dev/null +++ b/.bazelversion @@ -0,0 +1 @@ +8.0.0 \ No newline at end of file diff --git a/.github/workflows/ci.yaml b/.github/workflows/ci.yaml deleted file mode 100644 index 15e34f2..0000000 --- a/.github/workflows/ci.yaml +++ /dev/null @@ -1,46 +0,0 @@ -name: CI - -on: - push: - branches: [main] - pull_request: - branches: [main] - - # Allows you to run this workflow manually from the Actions tab - workflow_dispatch: - -jobs: - test: - runs-on: ubuntu-latest - steps: - - uses: actions/checkout@v4 - - uses: pnpm/action-setup@v4 - with: - version: 8 - run_install: false - - uses: actions/setup-node@v4 - with: - node-version: 20 - cache: pnpm - - run: pnpm install --frozen-lockfile - - run: pnpm run build - - run: pnpm run test - - e2e: - runs-on: ubuntu-latest - # Don't run e2es on PRs from forks as it requires access to secrets - # when using `pull_request`. - # See https://securitylab.github.com/research/github-actions-preventing-pwn-requests - if: ${{ github.event_name == 'push' || github.event.pull_request.head.repo.full_name == 'bazel-contrib/publish-to-bcr' }} - steps: - - uses: actions/checkout@v4 - - uses: pnpm/action-setup@v4 - with: - version: 8 - run_install: false - - uses: actions/setup-node@v4 - with: - node-version: 20 - cache: pnpm - - run: pnpm install --frozen-lockfile - - run: pnpm run e2e diff --git a/.gitignore b/.gitignore index bb11fa8..148c4ca 100644 --- a/.gitignore +++ b/.gitignore @@ -1,5 +1,5 @@ -build -dist +bazel-* +MODULE.bazel.lock node_modules .DS_Store .terraform diff --git a/.pre-commit-config.yaml b/.pre-commit-config.yaml index 05c66cf..7206449 100644 --- a/.pre-commit-config.yaml +++ b/.pre-commit-config.yaml @@ -11,9 +11,13 @@ repos: - id: commitizen stages: [commit-msg] - repo: https://github.com/pre-commit/mirrors-prettier - rev: "v2.7.1" + rev: 'v2.7.1' hooks: - id: prettier additional_dependencies: - prettier@2.7.1 - prettier-plugin-organize-imports@3.1.1 + - repo: https://github.com/keith/pre-commit-buildifier + rev: 8.0.0 + hooks: + - id: buildifier-lint diff --git a/.prettierrc.cjs b/.prettierrc.cjs new file mode 100644 index 0000000..0cb93e6 --- /dev/null +++ b/.prettierrc.cjs @@ -0,0 +1,16 @@ +/* eslint-env node */ + +module.exports = { + trailingComma: 'es5', + tabWidth: 4, + semi: true, + singleQuote: true, + overrides: [ + { + files: ['**/*.yaml', '**/*.yml', '**/*.json'], + options: { + tabWidth: 2, + }, + }, + ], +}; diff --git a/BUILD.bazel b/BUILD.bazel new file mode 100644 index 0000000..a4c0c41 --- /dev/null +++ b/BUILD.bazel @@ -0,0 +1,79 @@ +load("@aspect_rules_js//js:defs.bzl", "js_library") +load("@buildifier_prebuilt//:rules.bzl", "buildifier") +load("@npm//:defs.bzl", "npm_link_all_packages") +load("//bazel/ts:defs.bzl", "ts_config", "ts_project") + +exports_files( + [ + "babel.config.json", + "pnpm-lock.yaml", + ], + visibility = ["//:__subpackages__"], +) + +npm_link_all_packages(name = "node_modules") + +ts_project( + name = "root", + srcs = [ + "jest.setup.ts", + ], + visibility = ["//src:__subpackages__"], + deps = [ + ":node_modules/@jest/globals", + ":node_modules/jest-extended", + "//:node_modules/@types/jest", # keep + ], +) + +ts_config( + name = "tsconfig", + src = "tsconfig.json", + visibility = [ + "//e2e:__subpackages__", + "//src:__subpackages__", + ], +) + +js_library( + name = "package_json", + srcs = ["package.json"], + visibility = ["//:__subpackages__"], +) + +js_library( + name = "jest_config", + srcs = [ + "jest.config.js", + ], + visibility = ["//:__subpackages__"], + deps = [ + "//:node_modules/babel-jest", + "//:root", + ], +) + +buildifier( + name = "buildifier", + exclude_patterns = ["./.git/*"], + lint_mode = "fix", + mode = "fix", +) + +buildifier( + name = "buildifier.check", + exclude_patterns = ["./.git/*"], + lint_mode = "warn", + mode = "diff", +) + +alias( + name = "format", + actual = "//tools/format", +) + +js_library( + name = "prettierrc", + srcs = [".prettierrc.cjs"], + visibility = ["//visibility:public"], +) diff --git a/MODULE.bazel b/MODULE.bazel new file mode 100644 index 0000000..fb9d2d3 --- /dev/null +++ b/MODULE.bazel @@ -0,0 +1,84 @@ +bazel_dep(name = "aspect_bazel_lib", version = "2.11.0") +bazel_dep(name = "aspect_rules_jest", version = "0.22.0") +bazel_dep(name = "aspect_rules_js", version = "2.1.2") +bazel_dep(name = "aspect_rules_lint", version = "1.0.7") +bazel_dep(name = "aspect_rules_ts", version = "3.3.2") +bazel_dep( + name = "buildifier_prebuilt", + version = "8.0.0", +) +bazel_dep(name = "platforms", version = "0.0.10") +bazel_dep(name = "rules_multitool", version = "0.12.0") +bazel_dep(name = "rules_nodejs", version = "6.3.2") +bazel_dep(name = "rules_pkg", version = "1.0.1") +bazel_dep(name = "toolchains_llvm", version = "1.2.0") +bazel_dep(name = "xz", version = "5.4.5.bcr.5") + +# FIXME: Remove when a new `toolchains_llvm` has been released. +git_override( + module_name = "toolchains_llvm", + commit = "bda1c9fbf232b682c30d039f8e4a5e3cf3025d0f", + remote = "https://github.com/bazel-contrib/toolchains_llvm", +) + +multitool = use_extension("@rules_multitool//multitool:extension.bzl", "multitool") +multitool.hub(lockfile = "//tools:tools.lock.json") +use_repo(multitool, "multitool") + +node = use_extension("@rules_nodejs//nodejs:extensions.bzl", "node", dev_dependency = True) +node.toolchain(node_version = "20.18.0") + +pnpm = use_extension("@aspect_rules_js//npm:extensions.bzl", "pnpm") +pnpm.pnpm( + name = "pnpm", + pnpm_version = "8.15.9", +) + +# Allows developers to use the matching pnpm version, for example: +# bazel run -- @pnpm//:pnpm install --dir $PWD --lockfile-only +use_repo(pnpm, "pnpm") + +npm = use_extension("@aspect_rules_js//npm:extensions.bzl", "npm", dev_dependency = True) +npm.npm_translate_lock( + name = "npm", + bins = { + "@google-cloud/functions-framework": [ + "functions-framework=build/src/main.js", + ], + }, + npmrc = "//:.npmrc", + pnpm_lock = "//:pnpm-lock.yaml", +) +use_repo(npm, "npm") + +rules_ts_ext = use_extension("@aspect_rules_ts//ts:extensions.bzl", "ext", dev_dependency = True) +rules_ts_ext.deps( + ts_version_from = "//:package.json", +) +use_repo(rules_ts_ext, "npm_typescript") + +llvm = use_extension("@toolchains_llvm//toolchain/extensions:llvm.bzl", "llvm") +llvm.toolchain( + libclang_rt = { + "@libclang_rt-wasm32-wasi//:libclang_rt.builtins-wasm32.a": "wasm32-unknown-unknown/libclang_rt.builtins.a", + }, + llvm_versions = { + "": "19.1.0", + }, + stdlib = {"wasm32": "libc"}, +) +llvm.sysroot( + label = "@wasi-sysroot//sysroots/wasm32-wasip2", + targets = ["wasm32"], +) +use_repo(llvm, "llvm_toolchain") + +register_toolchains("@llvm_toolchain//:all") + +wasi_sysroot = use_repo_rule("//src/infrastructure/xzdec:wasm.bzl", "wasi_sysroot") + +wasm32_libclang_rt = use_repo_rule("//src/infrastructure/xzdec:wasm.bzl", "wasm32_libclang_rt") + +wasi_sysroot(name = "wasi-sysroot") + +wasm32_libclang_rt(name = "libclang_rt-wasm32-wasi") diff --git a/REPO.bazel b/REPO.bazel new file mode 100644 index 0000000..a66307e --- /dev/null +++ b/REPO.bazel @@ -0,0 +1,5 @@ +"""Global repository settings. + +See https://bazel.build/rules/lib/globals/repo +""" +ignore_directories(["**/node_modules"]) diff --git a/WORKSPACE b/WORKSPACE new file mode 100644 index 0000000..34dcc17 --- /dev/null +++ b/WORKSPACE @@ -0,0 +1,2 @@ +# This file should be removed once this issue is fixed: +# https://github.com/bazel-contrib/bazel-gazelle/issues/2012 diff --git a/bazel/jest/BUILD.bazel b/bazel/jest/BUILD.bazel new file mode 100644 index 0000000..e69de29 diff --git a/bazel/jest/defs.bzl b/bazel/jest/defs.bzl new file mode 100644 index 0000000..3a8511f --- /dev/null +++ b/bazel/jest/defs.bzl @@ -0,0 +1,38 @@ +""" +Defaults for jest tests +""" + +load("@aspect_bazel_lib//lib:copy_file.bzl", "copy_file") +load("@aspect_rules_jest//jest:defs.bzl", _jest_test = "jest_test") + +def jest_test(name, **kwargs): + """Defaults for jest_test. + + Args: + name: Name of the jest_test target + **kwargs: Additional attributes to pass to the jest_test rule + """ + + # Tell jest to use babel to transform ESM into commonjs before + # running tests, because testing ESM in jest is a nightmare. + # The location of the babel config file must be next to the jest + # root in order to work, so copy it here. + copy_file( + name = "{}__babel_config".format(name), + src = "//:babel.config.json", + out = "babel.config.json", + ) + + data = kwargs.pop("data", []) + + _jest_test( + name = name, + config = "//:jest_config", + data = data + [ + "babel.config.json", + "//:node_modules/@babel/preset-env", + "//:package_json", + ], + node_modules = "//:node_modules", + **kwargs + ) diff --git a/bazel/ts/BUILD.bazel b/bazel/ts/BUILD.bazel new file mode 100644 index 0000000..e69de29 diff --git a/bazel/ts/defs.bzl b/bazel/ts/defs.bzl new file mode 100644 index 0000000..755d004 --- /dev/null +++ b/bazel/ts/defs.bzl @@ -0,0 +1,27 @@ +""" +Defaults for Typescript projects +""" + +load("@aspect_rules_ts//ts:defs.bzl", _ts_config = "ts_config", _ts_project = "ts_project") + +ts_config = _ts_config + +def ts_project(name, **kwargs): + """Defaults for ts_project. + + Args: + name: Name of the ts_project target + **kwargs: Additional attributes to pass to the ts_project rule + """ + + tsconfig = kwargs.pop("tsconfig", "//:tsconfig") + + _ts_project( + name = name, + declaration = True, + source_map = True, + allow_js = True, + tsconfig = {"include": ["**/*.ts"]}, + extends = tsconfig, + **kwargs + ) diff --git a/deployment/README.md b/deployment/README.md index 7d6dbe1..0fb86c0 100644 --- a/deployment/README.md +++ b/deployment/README.md @@ -43,28 +43,16 @@ You can create the bucket manually, or you can set it up using the [remote state Note that this is a standalone root terraform module that is separate from the rest of the terraform managed resources due to limitations with terraform and not being able to pass the bucket dynamically as a backend. -### Initialize terraform backend +### Initialize terraform state -Change to the environment directory and initialize the backend. - -```shell -cd deployment/environments/dev -terraform init -``` - -### Build the app - -```shell -pnpm install -pnpm run build +```bash +(cd deployment/environments/dev && bazel run terraform -- init) ``` ### Deploy the app -Run terraform apply to deploy the application. - -```shell -terraform apply +```bash +(cd deployment/environments/dev && bazel run terraform -- apply) ``` ### Setup webhook @@ -125,29 +113,19 @@ the fake BCR. Follow these steps if an environment has already been setup and deployed to a Google Cloud Platform project. -### Initialize terraform backend +### Initialize terraform state If the environment is already deployed then the terraform state bucket should exist. Find and take note of the bucket id. -Change to the directory of the environment you want to deploy to and initialize the backend. +Change to the directory of the environment you want to deploy to and initialize the terraform state. -```shell -cd deployment/environments/dev -terraform init -``` - -### Build the app - -```shell -pnpm install -pnpm run build +```bash +(cd deployment/environments/dev && bazel run terraform -- init) ``` ### Deploy the app -Run terraform apply to deploy the application. - -```shell -terraform apply +```bash +(cd deployment/environments/dev && bazel run terraform -- apply) ``` diff --git a/deployment/environments/dev/BUILD.bazel b/deployment/environments/dev/BUILD.bazel new file mode 100644 index 0000000..df602a7 --- /dev/null +++ b/deployment/environments/dev/BUILD.bazel @@ -0,0 +1,8 @@ +load("//tools:terraform.bzl", "terraform") + +terraform( + name = "terraform", + data = [ + "//src:cloudfunction", + ], +) diff --git a/deployment/environments/prod/BUILD.bazel b/deployment/environments/prod/BUILD.bazel new file mode 100644 index 0000000..df602a7 --- /dev/null +++ b/deployment/environments/prod/BUILD.bazel @@ -0,0 +1,8 @@ +load("//tools:terraform.bzl", "terraform") + +terraform( + name = "terraform", + data = [ + "//src:cloudfunction", + ], +) diff --git a/deployment/modules/webhook/main.tf b/deployment/modules/webhook/main.tf index 8f76e1a..9c315fb 100644 --- a/deployment/modules/webhook/main.tf +++ b/deployment/modules/webhook/main.tf @@ -20,16 +20,10 @@ resource "google_storage_bucket" "source_archive_bucket" { location = local.region } -data "archive_file" "publish_to_bcr_function_archive" { - type = "zip" - source_dir = "../../../dist/publish-to-bcr" - output_path = "../../../dist/publish-to-bcr.zip" -} - resource "google_storage_bucket_object" "publish_to_bcr_function_bucket_object" { - name = "source.${data.archive_file.publish_to_bcr_function_archive.output_md5}" + name = "source.${filemd5("${path.module}/../../../bazel-bin/src/cloudfunction.zip")}" bucket = google_storage_bucket.source_archive_bucket.name - source = data.archive_file.publish_to_bcr_function_archive.output_path + source = "${path.module}/../../../bazel-bin/src/cloudfunction.zip" } resource "google_cloudfunctions_function" "publish_to_bcr_function" { diff --git a/e2e/BUILD.bazel b/e2e/BUILD.bazel new file mode 100644 index 0000000..427eba6 --- /dev/null +++ b/e2e/BUILD.bazel @@ -0,0 +1,41 @@ +load("//bazel/jest:defs.bzl", "jest_test") +load("//bazel/ts:defs.bzl", "ts_project") + +ts_project( + name = "e2e_tests", + testonly = True, + srcs = ["e2e.spec.ts"], + data = glob(["fixtures/**/*"]) + [ + # e2e tests run a cloud function emulator which runs on the + # distribution package. The emulator (unlike GCP) doesn't install + # deps from the included pnpm-lock.yaml file. For simplicity just + # link all node_modules so that the emulation can resolve its deps. + "//:node_modules", + ], + deps = [ + "//:node_modules/@octokit/core", + "//:node_modules/@octokit/webhooks-types", + "//:node_modules/@types/imapflow", + "//:node_modules/@types/mailparser", + "//:node_modules/@types/node", + "//:node_modules/@types/nodemailer", + "//:node_modules/imapflow", + "//:node_modules/mailparser", + "//:node_modules/mockttp", + "//:node_modules/nodemailer", + "//:node_modules/simple-git", + "//e2e/helpers", + "//e2e/stubs", + "//src/infrastructure", + ], +) + +jest_test( + name = "test", + timeout = "moderate", + data = [ + ":e2e_tests", + ], + snapshots = ["__snapshots__/e2e.spec.js.snap"], + tags = ["requires-network"], +) diff --git a/e2e/__snapshots__/e2e.spec.js.snap b/e2e/__snapshots__/e2e.spec.js.snap new file mode 100644 index 0000000..b397bbc --- /dev/null +++ b/e2e/__snapshots__/e2e.spec.js.snap @@ -0,0 +1,581 @@ +// Jest Snapshot v1, https://goo.gl/fbAQLP + +exports[`e2e tests [snapshot] empty strip prefix 1`] = ` +"---------------------------------------------------- +modules/no-prefix/1.0.0/MODULE.bazel +---------------------------------------------------- +module( + name = "no-prefix", + version = "1.0.0", +) + +---------------------------------------------------- +modules/no-prefix/1.0.0/presubmit.yml +---------------------------------------------------- +bcr_test_module: + module_path: "e2e/bzlmod" + matrix: + platform: ["debian10", "macos", "ubuntu2004", "windows"] + bazel: [6.x, 7.x] + tasks: + run_tests: + name: "Run test module" + platform: \${{ platform }} + bazel: \${{ bazel }} + test_targets: + - "//..." + +---------------------------------------------------- +modules/no-prefix/1.0.0/source.json +---------------------------------------------------- +{ + "integrity": "sha256-bJ2Xfwra9b+xS7zKSEpP0ammXllsZPkJNgwRT59E6to=", + "url": "https://github.com/testorg/no-prefix/archive/refs/tags/v1.0.0.tar.gz" +} + +---------------------------------------------------- +modules/no-prefix/metadata.json +---------------------------------------------------- +{ + "homepage": "https://github.com/testorg/no-prefix", + "maintainers": [ + { + "name": "Foo McBar", + "email": "foo@test.org", + "github": "foobar" + } + ], + "repository": [ + "github:testorg/no-prefix" + ], + "versions": [ + "1.0.0" + ], + "yanked_versions": {} +} + +" +`; + +exports[`e2e tests [snapshot] error email for incorrect strip prefix 1`] = ` +"TO: releaser@test.org, foo@test.org +SUBJECT: Publish to BCR + +Failed to publish entry for testorg/versioned@v1.0.0 to the Bazel Central Registry. + +Could not find MODULE.bazel in release archive at ./versioned-1.0.0/MODULE.bazel. +Is the strip prefix in source.template.json correct? (currently it's 'versioned-1.0.0') + + +" +`; + +exports[`e2e tests [snapshot] error email for incorrect strip prefix in multi module repo 1`] = ` +"TO: releaser@test.org, foo@test.org, moo@test.org +SUBJECT: Publish to BCR + +Failed to publish entry for testorg/multi-module@v1.0.0 to the Bazel Central Registry. + +Failed to download release archive from http://localhost:8001/testorg/multi-module/releases/download/v1.0.0.tar.gz. Received status 503 + + +" +`; + +exports[`e2e tests [snapshot] missing strip prefix 1`] = ` +"---------------------------------------------------- +modules/empty-prefix/1.0.0/MODULE.bazel +---------------------------------------------------- +module( + name = "empty-prefix", + version = "1.0.0", +) + +---------------------------------------------------- +modules/empty-prefix/1.0.0/presubmit.yml +---------------------------------------------------- +bcr_test_module: + module_path: "e2e/bzlmod" + matrix: + platform: ["debian10", "macos", "ubuntu2004", "windows"] + bazel: [6.x, 7.x] + tasks: + run_tests: + name: "Run test module" + platform: \${{ platform }} + bazel: \${{ bazel }} + test_targets: + - "//..." + +---------------------------------------------------- +modules/empty-prefix/1.0.0/source.json +---------------------------------------------------- +{ + "integrity": "sha256-5TYQ+giuNTh5YplxFIAEcr2X96ht90LJpehveS4++G0=", + "strip_prefix": "", + "url": "https://github.com/testorg/empty-prefix/archive/refs/tags/v1.0.0.tar.gz" +} + +---------------------------------------------------- +modules/empty-prefix/metadata.json +---------------------------------------------------- +{ + "homepage": "https://github.com/testorg/empty-prefix", + "maintainers": [ + { + "name": "Foo McBar", + "email": "foo@test.org", + "github": "foobar" + } + ], + "repository": [ + "github:testorg/empty-prefix" + ], + "versions": [ + "1.0.0" + ], + "yanked_versions": {} +} + +" +`; + +exports[`e2e tests [snapshot] multiple modules 1`] = ` +"---------------------------------------------------- +modules/module/1.0.0/MODULE.bazel +---------------------------------------------------- +module( + name = "module", + version = "1.0.0", +) + +---------------------------------------------------- +modules/module/1.0.0/presubmit.yml +---------------------------------------------------- +bcr_test_module: + module_path: "e2e/bzlmod" + matrix: + platform: ["debian10", "macos", "ubuntu2004", "windows"] + bazel: [6.x, 7.x] + tasks: + run_tests: + name: "Run test module" + platform: \${{ platform }} + bazel: \${{ bazel }} + test_targets: + - "//..." + +---------------------------------------------------- +modules/module/1.0.0/source.json +---------------------------------------------------- +{ + "integrity": "sha256-TNq18BsxVczY1FA2lJkWLBXMhQAkYloc8qAZcjPH+40=", + "strip_prefix": "multi-module-1.0.0", + "url": "https://github.com/testorg/multi-module/releases/download/v1.0.0.tar.gz" +} + +---------------------------------------------------- +modules/module/metadata.json +---------------------------------------------------- +{ + "homepage": "https://github.com/testorg/multi-module", + "maintainers": [ + { + "name": "Foo McBar", + "email": "foo@test.org", + "github": "foobar" + } + ], + "repository": [ + "github:testorg/multi-module" + ], + "versions": [ + "1.0.0" + ], + "yanked_versions": {} +} + +---------------------------------------------------- +modules/submodule/1.0.0/MODULE.bazel +---------------------------------------------------- +module( + name = "submodule", + version = "1.0.0", +) + +---------------------------------------------------- +modules/submodule/1.0.0/presubmit.yml +---------------------------------------------------- +bcr_test_module: + module_path: "e2e/bzlmod" + matrix: + platform: ["debian10", "macos", "ubuntu2004", "windows"] + bazel: [6.x, 7.x] + tasks: + run_tests: + name: "Run test module" + platform: \${{ platform }} + bazel: \${{ bazel }} + test_targets: + - "//..." + +---------------------------------------------------- +modules/submodule/1.0.0/source.json +---------------------------------------------------- +{ + "integrity": "sha256-TNq18BsxVczY1FA2lJkWLBXMhQAkYloc8qAZcjPH+40=", + "strip_prefix": "multi-module-1.0.0/submodule", + "url": "https://github.com/testorg/multi-module/releases/download/v1.0.0.tar.gz" +} + +---------------------------------------------------- +modules/submodule/metadata.json +---------------------------------------------------- +{ + "homepage": "https://github.com/testorg/multi-module", + "maintainers": [ + { + "name": "Foo McBar", + "email": "foo@test.org", + "github": "foobar" + }, + { + "name": "Moo Cow", + "email": "moo@test.org", + "github": "moocow" + } + ], + "repository": [ + "github:testorg/multi-module" + ], + "versions": [ + "1.0.0" + ], + "yanked_versions": {} +} + +" +`; + +exports[`e2e tests [snapshot] ruleset with tarball release archive 1`] = ` +"---------------------------------------------------- +modules/tarball/1.0.0/MODULE.bazel +---------------------------------------------------- +module( + name = "tarball", + version = "1.0.0", +) + +---------------------------------------------------- +modules/tarball/1.0.0/presubmit.yml +---------------------------------------------------- +bcr_test_module: + module_path: "e2e/bzlmod" + matrix: + platform: ["debian10", "macos", "ubuntu2004", "windows"] + bazel: [6.x, 7.x] + tasks: + run_tests: + name: "Run test module" + platform: \${{ platform }} + bazel: \${{ bazel }} + test_targets: + - "//..." + +---------------------------------------------------- +modules/tarball/1.0.0/source.json +---------------------------------------------------- +{ + "integrity": "sha256-YFE/8KavtapcwFusSXdOrUk8aXATwtdEgZgDEgiZZ/U=", + "strip_prefix": "tarball-1.0.0", + "url": "https://github.com/testorg/tarball/archive/refs/tags/v1.0.0.tar.gz" +} + +---------------------------------------------------- +modules/tarball/metadata.json +---------------------------------------------------- +{ + "homepage": "https://github.com/testorg/tarball", + "maintainers": [ + { + "name": "Foo McBar", + "email": "foo@test.org", + "github": "foobar" + } + ], + "repository": [ + "github:testorg/tarball" + ], + "versions": [ + "1.0.0" + ], + "yanked_versions": {} +} + +" +`; + +exports[`e2e tests [snapshot] ruleset with unversioned module in source 1`] = ` +"---------------------------------------------------- +modules/unversioned/1.0.0/MODULE.bazel +---------------------------------------------------- +module( + name = "unversioned", + version = "1.0.0", +) + +---------------------------------------------------- +modules/unversioned/1.0.0/patches/module_dot_bazel_version.patch +---------------------------------------------------- +=================================================================== +--- a/MODULE.bazel ++++ b/MODULE.bazel +@@ -1,3 +1,4 @@ + module( + name = "unversioned", ++ version = "1.0.0", + ) + +---------------------------------------------------- +modules/unversioned/1.0.0/presubmit.yml +---------------------------------------------------- +bcr_test_module: + module_path: "e2e/bzlmod" + matrix: + platform: ["debian10", "macos", "ubuntu2004", "windows"] + bazel: [6.x, 7.x] + tasks: + run_tests: + name: "Run test module" + platform: \${{ platform }} + bazel: \${{ bazel }} + test_targets: + - "//..." + +---------------------------------------------------- +modules/unversioned/1.0.0/source.json +---------------------------------------------------- +{ + "integrity": "sha256-Q0ySwS1iZvzII/KXwZoxaWE2lLpp6ZrS7uMd4xLVdg4=", + "strip_prefix": "unversioned-1.0.0", + "url": "https://github.com/testorg/unversioned/archive/refs/tags/v1.0.0.tar.gz", + "patches": { + "module_dot_bazel_version.patch": "sha256-6+XCBXtNxFGKuL182vqWxZkECRxHLHSe1gd+hfpnL8A=" + }, + "patch_strip": 1 +} + +---------------------------------------------------- +modules/unversioned/metadata.json +---------------------------------------------------- +{ + "homepage": "https://github.com/testorg/unversioned", + "maintainers": [ + { + "name": "Foo McBar", + "email": "foo@test.org", + "github": "foobar" + } + ], + "repository": [ + "github:testorg/unversioned" + ], + "versions": [ + "1.0.0" + ], + "yanked_versions": {} +} + +" +`; + +exports[`e2e tests [snapshot] ruleset with versioned module in source 1`] = ` +"---------------------------------------------------- +modules/versioned/1.0.0/MODULE.bazel +---------------------------------------------------- +module( + name = "versioned", + version = "1.0.0", +) + +---------------------------------------------------- +modules/versioned/1.0.0/presubmit.yml +---------------------------------------------------- +bcr_test_module: + module_path: "e2e/bzlmod" + matrix: + platform: ["debian10", "macos", "ubuntu2004", "windows"] + bazel: [6.x, 7.x] + tasks: + run_tests: + name: "Run test module" + platform: \${{ platform }} + bazel: \${{ bazel }} + test_targets: + - "//..." + +---------------------------------------------------- +modules/versioned/1.0.0/source.json +---------------------------------------------------- +{ + "integrity": "sha256-iVWytRu1iuiPYMIOTOSooeY0dESDK71QNkGQPFbxzeM=", + "strip_prefix": "versioned-1.0.0", + "url": "https://github.com/testorg/versioned/archive/refs/tags/v1.0.0.tar.gz" +} + +---------------------------------------------------- +modules/versioned/metadata.json +---------------------------------------------------- +{ + "homepage": "https://github.com/testorg/versioned", + "maintainers": [ + { + "name": "Foo McBar", + "email": "foo@test.org", + "github": "foobar" + } + ], + "repository": [ + "github:testorg/versioned" + ], + "versions": [ + "1.0.0" + ], + "yanked_versions": {} +} + +" +`; + +exports[`e2e tests [snapshot] ruleset with zero-versioned module in source 1`] = ` +"---------------------------------------------------- +modules/zero-versioned/1.0.0/MODULE.bazel +---------------------------------------------------- +module( + name = "zero-versioned", + version = "1.0.0", +) + +---------------------------------------------------- +modules/zero-versioned/1.0.0/patches/module_dot_bazel_version.patch +---------------------------------------------------- +=================================================================== +--- a/MODULE.bazel ++++ b/MODULE.bazel +@@ -1,4 +1,4 @@ + module( + name = "zero-versioned", +- version = "0.0.0", ++ version = "1.0.0", + ) + +---------------------------------------------------- +modules/zero-versioned/1.0.0/presubmit.yml +---------------------------------------------------- +bcr_test_module: + module_path: "e2e/bzlmod" + matrix: + platform: ["debian10", "macos", "ubuntu2004", "windows"] + bazel: [6.x, 7.x] + tasks: + run_tests: + name: "Run test module" + platform: \${{ platform }} + bazel: \${{ bazel }} + test_targets: + - "//..." + +---------------------------------------------------- +modules/zero-versioned/1.0.0/source.json +---------------------------------------------------- +{ + "integrity": "sha256-OHSXEuWyo2djYr8CjWMT9dq38TDS9P/vIzNBfLQ5E+Q=", + "strip_prefix": "zero-versioned-1.0.0", + "url": "https://github.com/testorg/zero-versioned/archive/refs/tags/v1.0.0.tar.gz", + "patches": { + "module_dot_bazel_version.patch": "sha256-KpbuC1vv5mfhdTs5nnTl3/pH7Y/6JCnD1b1XLsqyOAo=" + }, + "patch_strip": 1 +} + +---------------------------------------------------- +modules/zero-versioned/metadata.json +---------------------------------------------------- +{ + "homepage": "https://github.com/testorg/zero-versioned", + "maintainers": [ + { + "name": "Foo McBar", + "email": "foo@test.org", + "github": "foobar" + } + ], + "repository": [ + "github:testorg/zero-versioned" + ], + "versions": [ + "1.0.0" + ], + "yanked_versions": {} +} + +" +`; + +exports[`e2e tests [snapshot] ruleset with zip release archive 1`] = ` +"---------------------------------------------------- +modules/zip/1.0.0/MODULE.bazel +---------------------------------------------------- +module( + name = "zip", + version = "1.0.0", +) + +---------------------------------------------------- +modules/zip/1.0.0/presubmit.yml +---------------------------------------------------- +bcr_test_module: + module_path: "e2e/bzlmod" + matrix: + platform: ["debian10", "macos", "ubuntu2004", "windows"] + bazel: [6.x, 7.x] + tasks: + run_tests: + name: "Run test module" + platform: \${{ platform }} + bazel: \${{ bazel }} + test_targets: + - "//..." + +---------------------------------------------------- +modules/zip/1.0.0/source.json +---------------------------------------------------- +{ + "integrity": "sha256-Ko4V5xPneq+Bq8C4EKMXUCnbzjrTTUaFLwC4ckVz3go=", + "strip_prefix": "zip-1.0.0", + "url": "https://github.com/testorg/zip/archive/refs/tags/v1.0.0.zip" +} + +---------------------------------------------------- +modules/zip/metadata.json +---------------------------------------------------- +{ + "homepage": "https://github.com/testorg/zip", + "maintainers": [ + { + "name": "Foo McBar", + "email": "foo@test.org", + "github": "foobar" + } + ], + "repository": [ + "github:testorg/zip" + ], + "versions": [ + "1.0.0" + ], + "yanked_versions": {} +} + +" +`; diff --git a/e2e/fixtures/empty-prefix/MODULE.bazel b/e2e/fixtures/empty-prefix/MODULE.bazel index 3e93f38..d00556f 100644 --- a/e2e/fixtures/empty-prefix/MODULE.bazel +++ b/e2e/fixtures/empty-prefix/MODULE.bazel @@ -1,4 +1,4 @@ module( name = "empty-prefix", version = "1.0.0", -) \ No newline at end of file +) diff --git a/e2e/fixtures/fixed-releaser/MODULE.bazel b/e2e/fixtures/fixed-releaser/MODULE.bazel index 7807409..cf8b95e 100644 --- a/e2e/fixtures/fixed-releaser/MODULE.bazel +++ b/e2e/fixtures/fixed-releaser/MODULE.bazel @@ -1,4 +1,4 @@ module( name = "fixed-releaser", version = "1.0.0", -) \ No newline at end of file +) diff --git a/e2e/fixtures/multi-module/MODULE.bazel b/e2e/fixtures/multi-module/MODULE.bazel index 8dca550..defb129 100644 --- a/e2e/fixtures/multi-module/MODULE.bazel +++ b/e2e/fixtures/multi-module/MODULE.bazel @@ -1,4 +1,4 @@ module( name = "module", version = "1.0.0", -) \ No newline at end of file +) diff --git a/e2e/fixtures/multi-module/submodule/MODULE.bazel b/e2e/fixtures/multi-module/submodule/MODULE.bazel index ac5522a..5356b29 100644 --- a/e2e/fixtures/multi-module/submodule/MODULE.bazel +++ b/e2e/fixtures/multi-module/submodule/MODULE.bazel @@ -1,4 +1,4 @@ module( name = "submodule", version = "1.0.0", -) \ No newline at end of file +) diff --git a/e2e/fixtures/no-prefix/MODULE.bazel b/e2e/fixtures/no-prefix/MODULE.bazel index 79b58be..4fa4165 100644 --- a/e2e/fixtures/no-prefix/MODULE.bazel +++ b/e2e/fixtures/no-prefix/MODULE.bazel @@ -1,4 +1,4 @@ module( name = "no-prefix", version = "1.0.0", -) \ No newline at end of file +) diff --git a/e2e/fixtures/tarball/MODULE.bazel b/e2e/fixtures/tarball/MODULE.bazel index 1da5802..2dcce6c 100644 --- a/e2e/fixtures/tarball/MODULE.bazel +++ b/e2e/fixtures/tarball/MODULE.bazel @@ -1,4 +1,4 @@ module( name = "tarball", version = "1.0.0", -) \ No newline at end of file +) diff --git a/e2e/fixtures/unversioned/MODULE.bazel b/e2e/fixtures/unversioned/MODULE.bazel index 93d4911..848d23d 100644 --- a/e2e/fixtures/unversioned/MODULE.bazel +++ b/e2e/fixtures/unversioned/MODULE.bazel @@ -1,3 +1,3 @@ module( - name = "unversioned" + name = "unversioned", ) diff --git a/e2e/fixtures/versioned/MODULE.bazel b/e2e/fixtures/versioned/MODULE.bazel index 8f2136a..c4b763d 100644 --- a/e2e/fixtures/versioned/MODULE.bazel +++ b/e2e/fixtures/versioned/MODULE.bazel @@ -1,4 +1,4 @@ module( name = "versioned", version = "1.0.0", -) \ No newline at end of file +) diff --git a/e2e/fixtures/zip/MODULE.bazel b/e2e/fixtures/zip/MODULE.bazel index 7a1c481..aac8703 100644 --- a/e2e/fixtures/zip/MODULE.bazel +++ b/e2e/fixtures/zip/MODULE.bazel @@ -1,4 +1,4 @@ module( name = "zip", version = "1.0.0", -) \ No newline at end of file +) diff --git a/e2e/helpers/BUILD.bazel b/e2e/helpers/BUILD.bazel new file mode 100644 index 0000000..6fb828a --- /dev/null +++ b/e2e/helpers/BUILD.bazel @@ -0,0 +1,30 @@ +load("//bazel/ts:defs.bzl", "ts_project") + +ts_project( + name = "helpers", + srcs = [ + "archive.ts", + "email.ts", + "fixture.ts", + "types.ts", + "webhook.ts", + ], + visibility = ["//e2e:__subpackages__"], + deps = [ + "//:node_modules/@octokit/webhooks-methods", + "//:node_modules/@octokit/webhooks-types", + "//:node_modules/@types/archiver", + "//:node_modules/@types/imapflow", + "//:node_modules/@types/mailparser", + "//:node_modules/@types/node", + "//:node_modules/@types/nodemailer", + "//:node_modules/@types/tar", + "//:node_modules/archiver", + "//:node_modules/axios", + "//:node_modules/imapflow", + "//:node_modules/mailparser", + "//:node_modules/nodemailer", + "//:node_modules/simple-git", + "//:node_modules/tar", + ], +) diff --git a/e2e/helpers/fixture.ts b/e2e/helpers/fixture.ts index 6ac70ca..5f9c871 100644 --- a/e2e/helpers/fixture.ts +++ b/e2e/helpers/fixture.ts @@ -1,19 +1,11 @@ import { User } from "@octokit/webhooks-types"; import fs from "node:fs"; -import os from "node:os"; import path from "node:path"; import simpleGit, { SimpleGit } from "simple-git"; -export const FIXTURES_PATH = path.join( - __dirname, - "..", - "..", - "..", - "e2e", - "fixtures" -); +export const FIXTURES_PATH = path.join("e2e", "fixtures"); export const PREPARED_FIXTURES_PATH = fs.mkdtempSync( - os.tmpdir() + path.sep + "fixtures-" + process.env.TEST_TMPDIR + path.sep + "fixtures-" ); export enum Fixture { diff --git a/e2e/stubs/BUILD.bazel b/e2e/stubs/BUILD.bazel new file mode 100644 index 0000000..79c9b0c --- /dev/null +++ b/e2e/stubs/BUILD.bazel @@ -0,0 +1,24 @@ +load("//bazel/ts:defs.bzl", "ts_project") + +ts_project( + name = "stubs", + srcs = [ + "cloud-functions.ts", + "fake-github.ts", + "fake-secrets.ts", + "stubbed-server.ts", + ], + visibility = ["//e2e:__subpackages__"], + deps = [ + "//:node_modules/@google-cloud/functions-framework", # keep + "//:node_modules/@octokit/webhooks-types", + "//:node_modules/@types/jest", # keep + "//:node_modules/@types/node", + "//:node_modules/@types/nodemailer", + "//:node_modules/mockttp", + "//:node_modules/nodemailer", + "//:node_modules/portfinder", + "//e2e/helpers", + "//src:dist", # keep + ], +) diff --git a/e2e/stubs/cloud-functions.ts b/e2e/stubs/cloud-functions.ts index af79c8b..9d7d91b 100644 --- a/e2e/stubs/cloud-functions.ts +++ b/e2e/stubs/cloud-functions.ts @@ -1,69 +1,68 @@ -import { ChildProcess, spawn } from "child_process"; -import path from "node:path"; -import { TestAccount } from "nodemailer"; -import portfinder from "portfinder"; -import { PREPARED_FIXTURES_PATH } from "../helpers/fixture"; -import { StubbedServer } from "./stubbed-server"; +import { ChildProcess, spawn } from 'child_process'; +import { TestAccount } from 'nodemailer'; +import portfinder from 'portfinder'; +import { PREPARED_FIXTURES_PATH } from '../helpers/fixture'; +import { StubbedServer } from './stubbed-server'; /** * Run the Cloud Functions runtime framework locally. */ export class CloudFunctions implements StubbedServer { - private functionsFrameworkProcess: ChildProcess; - private port: number; + private functionsFrameworkProcess: ChildProcess; + private port: number; - public constructor( - private readonly github: StubbedServer, - private readonly secrets: StubbedServer, - private readonly emailAccount: TestAccount - ) {} + public constructor( + private readonly github: StubbedServer, + private readonly secrets: StubbedServer, + private readonly emailAccount: TestAccount + ) {} - public async start(): Promise { - this.port = await portfinder.getPortPromise(); + public async start(): Promise { + this.port = await portfinder.getPortPromise(); - this.functionsFrameworkProcess = spawn( - "functions-framework", - [ - "--target=handleGithubWebhookEvent", - "--signature-type=http", - `--port=${this.port}`, - ], - { - stdio: "inherit", - cwd: path.join(__dirname, "..", "..", "..", "dist", "publish-to-bcr"), - env: { - ...process.env, - INTEGRATION_TESTING: "1", - PREPARED_FIXTURES_PATH, - SMTP_HOST: this.emailAccount.smtp.host, - SMTP_PORT: this.emailAccount.smtp.port.toString(), - NOTIFICATIONS_EMAIL: this.emailAccount.user, - SECRET_MANAGER_HOST: this.secrets.getHost(), - SECRET_MANAGER_PORT: this.secrets.getPort().toString(), - BAZEL_CENTRAL_REGISTRY: "bazelbuild/bazel-central-registry", - GITHUB_APP_ID: "1234", - GITHUB_BOT_APP_ID: "5678", - GITHUB_API_ENDPOINT: `http://${this.github.getHost()}:${this.github.getPort()}`, - }, - } - ); + this.functionsFrameworkProcess = spawn( + `${process.env.TEST_SRCDIR}/${process.env.TEST_WORKSPACE}/node_modules/.bin/functions-framework`, + [ + '--target=handleGithubWebhookEvent', + '--signature-type=http', + `--port=${this.port}`, + `--source=src/dist`, + ], + { + stdio: 'inherit', + env: { + ...process.env, + INTEGRATION_TESTING: '1', + PREPARED_FIXTURES_PATH, + SMTP_HOST: this.emailAccount.smtp.host, + SMTP_PORT: this.emailAccount.smtp.port.toString(), + NOTIFICATIONS_EMAIL: this.emailAccount.user, + SECRET_MANAGER_HOST: this.secrets.getHost(), + SECRET_MANAGER_PORT: this.secrets.getPort().toString(), + BAZEL_CENTRAL_REGISTRY: 'bazelbuild/bazel-central-registry', + GITHUB_APP_ID: '1234', + GITHUB_BOT_APP_ID: '5678', + GITHUB_API_ENDPOINT: `http://${this.github.getHost()}:${this.github.getPort()}`, + }, + } + ); - // Give the cloud functions service some time to boot up - await new Promise((resolve) => setTimeout(resolve, 1000)); - } - public async shutdown(): Promise { - this.functionsFrameworkProcess.kill(); - } - public async reset(): Promise { - // There is nothing to reset - } - public getHost(): string { - return "localhost"; - } - public getPort(): number { - return this.port; - } - public getBaseUrl(): string { - return `http://${this.getHost()}:${this.getPort()}`; - } + // Give the cloud functions service some time to boot up + await new Promise((resolve) => setTimeout(resolve, 1000)); + } + public async shutdown(): Promise { + this.functionsFrameworkProcess.kill(); + } + public async reset(): Promise { + // There is nothing to reset + } + public getHost(): string { + return 'localhost'; + } + public getPort(): number { + return this.port; + } + public getBaseUrl(): string { + return `http://${this.getHost()}:${this.getPort()}`; + } } diff --git a/jest.config.js b/jest.config.js index 6152dc5..0e8bc22 100644 --- a/jest.config.js +++ b/jest.config.js @@ -3,21 +3,29 @@ * https://jestjs.io/docs/configuration */ +import path from "path"; + export default { // Automatically clear mock calls, instances, contexts and results before every test clearMocks: true, // The root directory that Jest should scan for tests and modules within. - rootDir: "build", + // rootDir: "build", // A list of paths to directories that Jest should use to search for files in. - roots: ["src", "e2e"], + // roots: ["src", "e2e"], // A list of paths to modules that run some code to configure or set up the testing framework before each test - setupFilesAfterEnv: ["./jest.setup.js"], + setupFilesAfterEnv: [ + path.join( + process.env.TEST_SRCDIR, + process.env.TEST_WORKSPACE, + "jest.setup.js" + ), + ], // The path to a module that can resolve test<->snapshot path. - snapshotResolver: "./jest-snapshot-resolver.js", + // snapshotResolver: "./jest-snapshot-resolver.js", // A map from regular expressions to paths to transformers transform: { diff --git a/package.json b/package.json index 1563c7d..0ebc596 100644 --- a/package.json +++ b/package.json @@ -64,14 +64,18 @@ "globby": "^14.0.0", "imapflow": "^1.0.147", "jest": "^29.7.0", + "jest-cli": "^29.7.0", + "jest-junit": "^16.0.0", "jest-extended": "^4.0.2", "jest-mock": "^29.7.0", "mailparser": "3.6.6", "mockttp": "^3.10.0", "portfinder": "^1.0.32", - "typescript": "^5.0.0" + "prettier": "3.4.2", + "typescript": "5.6.3" }, "pnpm": { + "onlyBuiltDependencies": [], "packageExtensions": { "@google-cloud/secret-manager": { "dependencies": { diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index c2bfe1d..da96f90 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -4,6 +4,8 @@ settings: autoInstallPeers: true excludeLinksFromLockfile: false +onlyBuiltDependencies: [] + packageExtensionsChecksum: 3f4e93adca9209d652f9612730512d6a dependencies: @@ -138,9 +140,15 @@ devDependencies: jest: specifier: ^29.7.0 version: 29.7.0(@types/node@18.19.70) + jest-cli: + specifier: ^29.7.0 + version: 29.7.0(@types/node@18.19.70) jest-extended: specifier: ^4.0.2 version: 4.0.2(jest@29.7.0) + jest-junit: + specifier: ^16.0.0 + version: 16.0.0 jest-mock: specifier: ^29.7.0 version: 29.7.0 @@ -153,9 +161,12 @@ devDependencies: portfinder: specifier: ^1.0.32 version: 1.0.32 + prettier: + specifier: 3.4.2 + version: 3.4.2 typescript: - specifier: ^5.0.0 - version: 5.7.3 + specifier: 5.6.3 + version: 5.6.3 packages: @@ -175,8 +186,8 @@ packages: js-tokens: 4.0.0 picocolors: 1.1.1 - /@babel/compat-data@7.26.3: - resolution: {integrity: sha512-nHIxvKPniQXpmQLb0vhY3VaFb3S0YrTAwpOWJZh1wn3oJPjJk9Asva204PsBdmAE8vpzfHudT8DB0scYvy9q0g==} + /@babel/compat-data@7.26.5: + resolution: {integrity: sha512-XvcZi1KWf88RVbF9wn8MN6tYFloU5qX8KjuF3E1PVBmJ9eypXfs4GRiJwLuTZL0iSnJUKn1BFPa5BPZZJyFzPg==} engines: {node: '>=6.9.0'} dev: true @@ -186,14 +197,14 @@ packages: dependencies: '@ampproject/remapping': 2.3.0 '@babel/code-frame': 7.26.2 - '@babel/generator': 7.26.3 - '@babel/helper-compilation-targets': 7.25.9 + '@babel/generator': 7.26.5 + '@babel/helper-compilation-targets': 7.26.5 '@babel/helper-module-transforms': 7.26.0(@babel/core@7.26.0) '@babel/helpers': 7.26.0 - '@babel/parser': 7.26.3 + '@babel/parser': 7.26.5 '@babel/template': 7.25.9 - '@babel/traverse': 7.26.4 - '@babel/types': 7.26.3 + '@babel/traverse': 7.26.5 + '@babel/types': 7.26.5 convert-source-map: 2.0.0 debug: 4.4.0 gensync: 1.0.0-beta.2 @@ -203,12 +214,12 @@ packages: - supports-color dev: true - /@babel/generator@7.26.3: - resolution: {integrity: sha512-6FF/urZvD0sTeO7k6/B15pMLC4CHUv1426lzr3N01aHJTl046uCAh9LXW/fzeXXjPNCJ6iABW5XaWOsIZB93aQ==} + /@babel/generator@7.26.5: + resolution: {integrity: sha512-2caSP6fN9I7HOe6nqhtft7V4g7/V/gfDsC3Ag4W7kEzzvRGKqiv0pu0HogPiZ3KaVSoNDhUws6IJjDjpfmYIXw==} engines: {node: '>=6.9.0'} dependencies: - '@babel/parser': 7.26.3 - '@babel/types': 7.26.3 + '@babel/parser': 7.26.5 + '@babel/types': 7.26.5 '@jridgewell/gen-mapping': 0.3.8 '@jridgewell/trace-mapping': 0.3.25 jsesc: 3.1.0 @@ -218,14 +229,14 @@ packages: resolution: {integrity: sha512-gv7320KBUFJz1RnylIg5WWYPRXKZ884AGkYpgpWW02TH66Dl+HaC1t1CKd0z3R4b6hdYEcmrNZHUmfCP+1u3/g==} engines: {node: '>=6.9.0'} dependencies: - '@babel/types': 7.26.3 + '@babel/types': 7.26.5 dev: true - /@babel/helper-compilation-targets@7.25.9: - resolution: {integrity: sha512-j9Db8Suy6yV/VHa4qzrj9yZfZxhLWQdVnRlXxmKLYlhWUVB1sB2G5sxuWYXk/whHD9iW76PmNzxZ4UCnTQTVEQ==} + /@babel/helper-compilation-targets@7.26.5: + resolution: {integrity: sha512-IXuyn5EkouFJscIDuFF5EsiSolseme1s0CZB+QxVugqJLYmKdxI1VfIBOst0SUu4rnk2Z7kqTwmoO1lp3HIfnA==} engines: {node: '>=6.9.0'} dependencies: - '@babel/compat-data': 7.26.3 + '@babel/compat-data': 7.26.5 '@babel/helper-validator-option': 7.25.9 browserslist: 4.24.4 lru-cache: 5.1.1 @@ -242,9 +253,9 @@ packages: '@babel/helper-annotate-as-pure': 7.25.9 '@babel/helper-member-expression-to-functions': 7.25.9 '@babel/helper-optimise-call-expression': 7.25.9 - '@babel/helper-replace-supers': 7.25.9(@babel/core@7.26.0) + '@babel/helper-replace-supers': 7.26.5(@babel/core@7.26.0) '@babel/helper-skip-transparent-expression-wrappers': 7.25.9 - '@babel/traverse': 7.26.4 + '@babel/traverse': 7.26.5 semver: 6.3.1 transitivePeerDependencies: - supports-color @@ -268,8 +279,8 @@ packages: '@babel/core': ^7.4.0 || ^8.0.0-0 <8.0.0 dependencies: '@babel/core': 7.26.0 - '@babel/helper-compilation-targets': 7.25.9 - '@babel/helper-plugin-utils': 7.25.9 + '@babel/helper-compilation-targets': 7.26.5 + '@babel/helper-plugin-utils': 7.26.5 debug: 4.4.0 lodash.debounce: 4.0.8 resolve: 1.22.10 @@ -281,8 +292,8 @@ packages: resolution: {integrity: sha512-wbfdZ9w5vk0C0oyHqAJbc62+vet5prjj01jjJ8sKn3j9h3MQQlflEdXYvuqRWjHnM12coDEqiC1IRCi0U/EKwQ==} engines: {node: '>=6.9.0'} dependencies: - '@babel/traverse': 7.26.4 - '@babel/types': 7.26.3 + '@babel/traverse': 7.26.5 + '@babel/types': 7.26.5 transitivePeerDependencies: - supports-color dev: true @@ -291,8 +302,8 @@ packages: resolution: {integrity: sha512-tnUA4RsrmflIM6W6RFTLFSXITtl0wKjgpnLgXyowocVPrbYrLUXSBXDgTs8BlbmIzIdlBySRQjINYs2BAkiLtw==} engines: {node: '>=6.9.0'} dependencies: - '@babel/traverse': 7.26.4 - '@babel/types': 7.26.3 + '@babel/traverse': 7.26.5 + '@babel/types': 7.26.5 transitivePeerDependencies: - supports-color dev: true @@ -306,7 +317,7 @@ packages: '@babel/core': 7.26.0 '@babel/helper-module-imports': 7.25.9 '@babel/helper-validator-identifier': 7.25.9 - '@babel/traverse': 7.26.4 + '@babel/traverse': 7.26.5 transitivePeerDependencies: - supports-color dev: true @@ -315,11 +326,11 @@ packages: resolution: {integrity: sha512-FIpuNaz5ow8VyrYcnXQTDRGvV6tTjkNtCK/RYNDXGSLlUD6cBuQTSw43CShGxjvfBTfcUA/r6UhUCbtYqkhcuQ==} engines: {node: '>=6.9.0'} dependencies: - '@babel/types': 7.26.3 + '@babel/types': 7.26.5 dev: true - /@babel/helper-plugin-utils@7.25.9: - resolution: {integrity: sha512-kSMlyUVdWe25rEsRGviIgOWnoT/nfABVWlqt9N19/dIPWViAOW2s9wznP5tURbs/IDuNk4gPy3YdYRgH3uxhBw==} + /@babel/helper-plugin-utils@7.26.5: + resolution: {integrity: sha512-RS+jZcRdZdRFzMyr+wcsaqOmld1/EqTghfaBGQQd/WnRdzdlvSZ//kF7U8VQTxf1ynZ4cjUcYgjVGx13ewNPMg==} engines: {node: '>=6.9.0'} dev: true @@ -332,13 +343,13 @@ packages: '@babel/core': 7.26.0 '@babel/helper-annotate-as-pure': 7.25.9 '@babel/helper-wrap-function': 7.25.9 - '@babel/traverse': 7.26.4 + '@babel/traverse': 7.26.5 transitivePeerDependencies: - supports-color dev: true - /@babel/helper-replace-supers@7.25.9(@babel/core@7.26.0): - resolution: {integrity: sha512-IiDqTOTBQy0sWyeXyGSC5TBJpGFXBkRynjBeXsvbhQFKj2viwJC76Epz35YLU1fpe/Am6Vppb7W7zM4fPQzLsQ==} + /@babel/helper-replace-supers@7.26.5(@babel/core@7.26.0): + resolution: {integrity: sha512-bJ6iIVdYX1YooY2X7w1q6VITt+LnUILtNk7zT78ykuwStx8BauCzxvFqFaHjOpW1bVnSUM1PN1f0p5P21wHxvg==} engines: {node: '>=6.9.0'} peerDependencies: '@babel/core': ^7.0.0 @@ -346,7 +357,7 @@ packages: '@babel/core': 7.26.0 '@babel/helper-member-expression-to-functions': 7.25.9 '@babel/helper-optimise-call-expression': 7.25.9 - '@babel/traverse': 7.26.4 + '@babel/traverse': 7.26.5 transitivePeerDependencies: - supports-color dev: true @@ -355,8 +366,8 @@ packages: resolution: {integrity: sha512-K4Du3BFa3gvyhzgPcntrkDgZzQaq6uozzcpGbOO1OEJaI+EJdqWIMTLgFgQf6lrfiDFo5FU+BxKepI9RmZqahA==} engines: {node: '>=6.9.0'} dependencies: - '@babel/traverse': 7.26.4 - '@babel/types': 7.26.3 + '@babel/traverse': 7.26.5 + '@babel/types': 7.26.5 transitivePeerDependencies: - supports-color dev: true @@ -380,8 +391,8 @@ packages: engines: {node: '>=6.9.0'} dependencies: '@babel/template': 7.25.9 - '@babel/traverse': 7.26.4 - '@babel/types': 7.26.3 + '@babel/traverse': 7.26.5 + '@babel/types': 7.26.5 transitivePeerDependencies: - supports-color dev: true @@ -391,15 +402,15 @@ packages: engines: {node: '>=6.9.0'} dependencies: '@babel/template': 7.25.9 - '@babel/types': 7.26.3 + '@babel/types': 7.26.5 dev: true - /@babel/parser@7.26.3: - resolution: {integrity: sha512-WJ/CvmY8Mea8iDXo6a7RK2wbmJITT5fN3BEkRuFlxVyNx8jOKIIhmC4fSkTcPcf8JyavbBwIe6OpiCOBXt/IcA==} + /@babel/parser@7.26.5: + resolution: {integrity: sha512-SRJ4jYmXRqV1/Xc+TIVG84WjHBXKlxO9sHQnA2Pf12QQEAp1LOh6kDzNHXcUnbH1QI0FDoPPVOt+vyUDucxpaw==} engines: {node: '>=6.0.0'} hasBin: true dependencies: - '@babel/types': 7.26.3 + '@babel/types': 7.26.5 dev: true /@babel/plugin-bugfix-firefox-class-in-computed-class-key@7.25.9(@babel/core@7.26.0): @@ -409,8 +420,8 @@ packages: '@babel/core': ^7.0.0 dependencies: '@babel/core': 7.26.0 - '@babel/helper-plugin-utils': 7.25.9 - '@babel/traverse': 7.26.4 + '@babel/helper-plugin-utils': 7.26.5 + '@babel/traverse': 7.26.5 transitivePeerDependencies: - supports-color dev: true @@ -422,7 +433,7 @@ packages: '@babel/core': ^7.0.0 dependencies: '@babel/core': 7.26.0 - '@babel/helper-plugin-utils': 7.25.9 + '@babel/helper-plugin-utils': 7.26.5 dev: true /@babel/plugin-bugfix-safari-id-destructuring-collision-in-function-expression@7.25.9(@babel/core@7.26.0): @@ -432,7 +443,7 @@ packages: '@babel/core': ^7.0.0 dependencies: '@babel/core': 7.26.0 - '@babel/helper-plugin-utils': 7.25.9 + '@babel/helper-plugin-utils': 7.26.5 dev: true /@babel/plugin-bugfix-v8-spread-parameters-in-optional-chaining@7.25.9(@babel/core@7.26.0): @@ -442,7 +453,7 @@ packages: '@babel/core': ^7.13.0 dependencies: '@babel/core': 7.26.0 - '@babel/helper-plugin-utils': 7.25.9 + '@babel/helper-plugin-utils': 7.26.5 '@babel/helper-skip-transparent-expression-wrappers': 7.25.9 '@babel/plugin-transform-optional-chaining': 7.25.9(@babel/core@7.26.0) transitivePeerDependencies: @@ -456,8 +467,8 @@ packages: '@babel/core': ^7.0.0 dependencies: '@babel/core': 7.26.0 - '@babel/helper-plugin-utils': 7.25.9 - '@babel/traverse': 7.26.4 + '@babel/helper-plugin-utils': 7.26.5 + '@babel/traverse': 7.26.5 transitivePeerDependencies: - supports-color dev: true @@ -477,7 +488,7 @@ packages: '@babel/core': ^7.0.0-0 dependencies: '@babel/core': 7.26.0 - '@babel/helper-plugin-utils': 7.25.9 + '@babel/helper-plugin-utils': 7.26.5 dev: true /@babel/plugin-syntax-bigint@7.8.3(@babel/core@7.26.0): @@ -486,7 +497,7 @@ packages: '@babel/core': ^7.0.0-0 dependencies: '@babel/core': 7.26.0 - '@babel/helper-plugin-utils': 7.25.9 + '@babel/helper-plugin-utils': 7.26.5 dev: true /@babel/plugin-syntax-class-properties@7.12.13(@babel/core@7.26.0): @@ -495,7 +506,7 @@ packages: '@babel/core': ^7.0.0-0 dependencies: '@babel/core': 7.26.0 - '@babel/helper-plugin-utils': 7.25.9 + '@babel/helper-plugin-utils': 7.26.5 dev: true /@babel/plugin-syntax-class-static-block@7.14.5(@babel/core@7.26.0): @@ -505,7 +516,7 @@ packages: '@babel/core': ^7.0.0-0 dependencies: '@babel/core': 7.26.0 - '@babel/helper-plugin-utils': 7.25.9 + '@babel/helper-plugin-utils': 7.26.5 dev: true /@babel/plugin-syntax-import-assertions@7.26.0(@babel/core@7.26.0): @@ -515,7 +526,7 @@ packages: '@babel/core': ^7.0.0-0 dependencies: '@babel/core': 7.26.0 - '@babel/helper-plugin-utils': 7.25.9 + '@babel/helper-plugin-utils': 7.26.5 dev: true /@babel/plugin-syntax-import-attributes@7.26.0(@babel/core@7.26.0): @@ -525,7 +536,7 @@ packages: '@babel/core': ^7.0.0-0 dependencies: '@babel/core': 7.26.0 - '@babel/helper-plugin-utils': 7.25.9 + '@babel/helper-plugin-utils': 7.26.5 dev: true /@babel/plugin-syntax-import-meta@7.10.4(@babel/core@7.26.0): @@ -534,7 +545,7 @@ packages: '@babel/core': ^7.0.0-0 dependencies: '@babel/core': 7.26.0 - '@babel/helper-plugin-utils': 7.25.9 + '@babel/helper-plugin-utils': 7.26.5 dev: true /@babel/plugin-syntax-json-strings@7.8.3(@babel/core@7.26.0): @@ -543,7 +554,7 @@ packages: '@babel/core': ^7.0.0-0 dependencies: '@babel/core': 7.26.0 - '@babel/helper-plugin-utils': 7.25.9 + '@babel/helper-plugin-utils': 7.26.5 dev: true /@babel/plugin-syntax-jsx@7.25.9(@babel/core@7.26.0): @@ -553,7 +564,7 @@ packages: '@babel/core': ^7.0.0-0 dependencies: '@babel/core': 7.26.0 - '@babel/helper-plugin-utils': 7.25.9 + '@babel/helper-plugin-utils': 7.26.5 dev: true /@babel/plugin-syntax-logical-assignment-operators@7.10.4(@babel/core@7.26.0): @@ -562,7 +573,7 @@ packages: '@babel/core': ^7.0.0-0 dependencies: '@babel/core': 7.26.0 - '@babel/helper-plugin-utils': 7.25.9 + '@babel/helper-plugin-utils': 7.26.5 dev: true /@babel/plugin-syntax-nullish-coalescing-operator@7.8.3(@babel/core@7.26.0): @@ -571,7 +582,7 @@ packages: '@babel/core': ^7.0.0-0 dependencies: '@babel/core': 7.26.0 - '@babel/helper-plugin-utils': 7.25.9 + '@babel/helper-plugin-utils': 7.26.5 dev: true /@babel/plugin-syntax-numeric-separator@7.10.4(@babel/core@7.26.0): @@ -580,7 +591,7 @@ packages: '@babel/core': ^7.0.0-0 dependencies: '@babel/core': 7.26.0 - '@babel/helper-plugin-utils': 7.25.9 + '@babel/helper-plugin-utils': 7.26.5 dev: true /@babel/plugin-syntax-object-rest-spread@7.8.3(@babel/core@7.26.0): @@ -589,7 +600,7 @@ packages: '@babel/core': ^7.0.0-0 dependencies: '@babel/core': 7.26.0 - '@babel/helper-plugin-utils': 7.25.9 + '@babel/helper-plugin-utils': 7.26.5 dev: true /@babel/plugin-syntax-optional-catch-binding@7.8.3(@babel/core@7.26.0): @@ -598,7 +609,7 @@ packages: '@babel/core': ^7.0.0-0 dependencies: '@babel/core': 7.26.0 - '@babel/helper-plugin-utils': 7.25.9 + '@babel/helper-plugin-utils': 7.26.5 dev: true /@babel/plugin-syntax-optional-chaining@7.8.3(@babel/core@7.26.0): @@ -607,7 +618,7 @@ packages: '@babel/core': ^7.0.0-0 dependencies: '@babel/core': 7.26.0 - '@babel/helper-plugin-utils': 7.25.9 + '@babel/helper-plugin-utils': 7.26.5 dev: true /@babel/plugin-syntax-private-property-in-object@7.14.5(@babel/core@7.26.0): @@ -617,7 +628,7 @@ packages: '@babel/core': ^7.0.0-0 dependencies: '@babel/core': 7.26.0 - '@babel/helper-plugin-utils': 7.25.9 + '@babel/helper-plugin-utils': 7.26.5 dev: true /@babel/plugin-syntax-top-level-await@7.14.5(@babel/core@7.26.0): @@ -627,7 +638,7 @@ packages: '@babel/core': ^7.0.0-0 dependencies: '@babel/core': 7.26.0 - '@babel/helper-plugin-utils': 7.25.9 + '@babel/helper-plugin-utils': 7.26.5 dev: true /@babel/plugin-syntax-typescript@7.25.9(@babel/core@7.26.0): @@ -637,7 +648,7 @@ packages: '@babel/core': ^7.0.0-0 dependencies: '@babel/core': 7.26.0 - '@babel/helper-plugin-utils': 7.25.9 + '@babel/helper-plugin-utils': 7.26.5 dev: true /@babel/plugin-syntax-unicode-sets-regex@7.18.6(@babel/core@7.26.0): @@ -648,7 +659,7 @@ packages: dependencies: '@babel/core': 7.26.0 '@babel/helper-create-regexp-features-plugin': 7.26.3(@babel/core@7.26.0) - '@babel/helper-plugin-utils': 7.25.9 + '@babel/helper-plugin-utils': 7.26.5 dev: true /@babel/plugin-transform-arrow-functions@7.25.9(@babel/core@7.26.0): @@ -658,7 +669,7 @@ packages: '@babel/core': ^7.0.0-0 dependencies: '@babel/core': 7.26.0 - '@babel/helper-plugin-utils': 7.25.9 + '@babel/helper-plugin-utils': 7.26.5 dev: true /@babel/plugin-transform-async-generator-functions@7.25.9(@babel/core@7.26.0): @@ -668,9 +679,9 @@ packages: '@babel/core': ^7.0.0-0 dependencies: '@babel/core': 7.26.0 - '@babel/helper-plugin-utils': 7.25.9 + '@babel/helper-plugin-utils': 7.26.5 '@babel/helper-remap-async-to-generator': 7.25.9(@babel/core@7.26.0) - '@babel/traverse': 7.26.4 + '@babel/traverse': 7.26.5 transitivePeerDependencies: - supports-color dev: true @@ -683,20 +694,20 @@ packages: dependencies: '@babel/core': 7.26.0 '@babel/helper-module-imports': 7.25.9 - '@babel/helper-plugin-utils': 7.25.9 + '@babel/helper-plugin-utils': 7.26.5 '@babel/helper-remap-async-to-generator': 7.25.9(@babel/core@7.26.0) transitivePeerDependencies: - supports-color dev: true - /@babel/plugin-transform-block-scoped-functions@7.25.9(@babel/core@7.26.0): - resolution: {integrity: sha512-toHc9fzab0ZfenFpsyYinOX0J/5dgJVA2fm64xPewu7CoYHWEivIWKxkK2rMi4r3yQqLnVmheMXRdG+k239CgA==} + /@babel/plugin-transform-block-scoped-functions@7.26.5(@babel/core@7.26.0): + resolution: {integrity: sha512-chuTSY+hq09+/f5lMj8ZSYgCFpppV2CbYrhNFJ1BFoXpiWPnnAb7R0MqrafCpN8E1+YRrtM1MXZHJdIx8B6rMQ==} engines: {node: '>=6.9.0'} peerDependencies: '@babel/core': ^7.0.0-0 dependencies: '@babel/core': 7.26.0 - '@babel/helper-plugin-utils': 7.25.9 + '@babel/helper-plugin-utils': 7.26.5 dev: true /@babel/plugin-transform-block-scoping@7.25.9(@babel/core@7.26.0): @@ -706,7 +717,7 @@ packages: '@babel/core': ^7.0.0-0 dependencies: '@babel/core': 7.26.0 - '@babel/helper-plugin-utils': 7.25.9 + '@babel/helper-plugin-utils': 7.26.5 dev: true /@babel/plugin-transform-class-properties@7.25.9(@babel/core@7.26.0): @@ -717,7 +728,7 @@ packages: dependencies: '@babel/core': 7.26.0 '@babel/helper-create-class-features-plugin': 7.25.9(@babel/core@7.26.0) - '@babel/helper-plugin-utils': 7.25.9 + '@babel/helper-plugin-utils': 7.26.5 transitivePeerDependencies: - supports-color dev: true @@ -730,7 +741,7 @@ packages: dependencies: '@babel/core': 7.26.0 '@babel/helper-create-class-features-plugin': 7.25.9(@babel/core@7.26.0) - '@babel/helper-plugin-utils': 7.25.9 + '@babel/helper-plugin-utils': 7.26.5 transitivePeerDependencies: - supports-color dev: true @@ -743,10 +754,10 @@ packages: dependencies: '@babel/core': 7.26.0 '@babel/helper-annotate-as-pure': 7.25.9 - '@babel/helper-compilation-targets': 7.25.9 - '@babel/helper-plugin-utils': 7.25.9 - '@babel/helper-replace-supers': 7.25.9(@babel/core@7.26.0) - '@babel/traverse': 7.26.4 + '@babel/helper-compilation-targets': 7.26.5 + '@babel/helper-plugin-utils': 7.26.5 + '@babel/helper-replace-supers': 7.26.5(@babel/core@7.26.0) + '@babel/traverse': 7.26.5 globals: 11.12.0 transitivePeerDependencies: - supports-color @@ -759,7 +770,7 @@ packages: '@babel/core': ^7.0.0-0 dependencies: '@babel/core': 7.26.0 - '@babel/helper-plugin-utils': 7.25.9 + '@babel/helper-plugin-utils': 7.26.5 '@babel/template': 7.25.9 dev: true @@ -770,7 +781,7 @@ packages: '@babel/core': ^7.0.0-0 dependencies: '@babel/core': 7.26.0 - '@babel/helper-plugin-utils': 7.25.9 + '@babel/helper-plugin-utils': 7.26.5 dev: true /@babel/plugin-transform-dotall-regex@7.25.9(@babel/core@7.26.0): @@ -781,7 +792,7 @@ packages: dependencies: '@babel/core': 7.26.0 '@babel/helper-create-regexp-features-plugin': 7.26.3(@babel/core@7.26.0) - '@babel/helper-plugin-utils': 7.25.9 + '@babel/helper-plugin-utils': 7.26.5 dev: true /@babel/plugin-transform-duplicate-keys@7.25.9(@babel/core@7.26.0): @@ -791,7 +802,7 @@ packages: '@babel/core': ^7.0.0-0 dependencies: '@babel/core': 7.26.0 - '@babel/helper-plugin-utils': 7.25.9 + '@babel/helper-plugin-utils': 7.26.5 dev: true /@babel/plugin-transform-duplicate-named-capturing-groups-regex@7.25.9(@babel/core@7.26.0): @@ -802,7 +813,7 @@ packages: dependencies: '@babel/core': 7.26.0 '@babel/helper-create-regexp-features-plugin': 7.26.3(@babel/core@7.26.0) - '@babel/helper-plugin-utils': 7.25.9 + '@babel/helper-plugin-utils': 7.26.5 dev: true /@babel/plugin-transform-dynamic-import@7.25.9(@babel/core@7.26.0): @@ -812,7 +823,7 @@ packages: '@babel/core': ^7.0.0-0 dependencies: '@babel/core': 7.26.0 - '@babel/helper-plugin-utils': 7.25.9 + '@babel/helper-plugin-utils': 7.26.5 dev: true /@babel/plugin-transform-exponentiation-operator@7.26.3(@babel/core@7.26.0): @@ -822,7 +833,7 @@ packages: '@babel/core': ^7.0.0-0 dependencies: '@babel/core': 7.26.0 - '@babel/helper-plugin-utils': 7.25.9 + '@babel/helper-plugin-utils': 7.26.5 dev: true /@babel/plugin-transform-export-namespace-from@7.25.9(@babel/core@7.26.0): @@ -832,7 +843,7 @@ packages: '@babel/core': ^7.0.0-0 dependencies: '@babel/core': 7.26.0 - '@babel/helper-plugin-utils': 7.25.9 + '@babel/helper-plugin-utils': 7.26.5 dev: true /@babel/plugin-transform-for-of@7.25.9(@babel/core@7.26.0): @@ -842,7 +853,7 @@ packages: '@babel/core': ^7.0.0-0 dependencies: '@babel/core': 7.26.0 - '@babel/helper-plugin-utils': 7.25.9 + '@babel/helper-plugin-utils': 7.26.5 '@babel/helper-skip-transparent-expression-wrappers': 7.25.9 transitivePeerDependencies: - supports-color @@ -855,9 +866,9 @@ packages: '@babel/core': ^7.0.0-0 dependencies: '@babel/core': 7.26.0 - '@babel/helper-compilation-targets': 7.25.9 - '@babel/helper-plugin-utils': 7.25.9 - '@babel/traverse': 7.26.4 + '@babel/helper-compilation-targets': 7.26.5 + '@babel/helper-plugin-utils': 7.26.5 + '@babel/traverse': 7.26.5 transitivePeerDependencies: - supports-color dev: true @@ -869,7 +880,7 @@ packages: '@babel/core': ^7.0.0-0 dependencies: '@babel/core': 7.26.0 - '@babel/helper-plugin-utils': 7.25.9 + '@babel/helper-plugin-utils': 7.26.5 dev: true /@babel/plugin-transform-literals@7.25.9(@babel/core@7.26.0): @@ -879,7 +890,7 @@ packages: '@babel/core': ^7.0.0-0 dependencies: '@babel/core': 7.26.0 - '@babel/helper-plugin-utils': 7.25.9 + '@babel/helper-plugin-utils': 7.26.5 dev: true /@babel/plugin-transform-logical-assignment-operators@7.25.9(@babel/core@7.26.0): @@ -889,7 +900,7 @@ packages: '@babel/core': ^7.0.0-0 dependencies: '@babel/core': 7.26.0 - '@babel/helper-plugin-utils': 7.25.9 + '@babel/helper-plugin-utils': 7.26.5 dev: true /@babel/plugin-transform-member-expression-literals@7.25.9(@babel/core@7.26.0): @@ -899,7 +910,7 @@ packages: '@babel/core': ^7.0.0-0 dependencies: '@babel/core': 7.26.0 - '@babel/helper-plugin-utils': 7.25.9 + '@babel/helper-plugin-utils': 7.26.5 dev: true /@babel/plugin-transform-modules-amd@7.25.9(@babel/core@7.26.0): @@ -910,7 +921,7 @@ packages: dependencies: '@babel/core': 7.26.0 '@babel/helper-module-transforms': 7.26.0(@babel/core@7.26.0) - '@babel/helper-plugin-utils': 7.25.9 + '@babel/helper-plugin-utils': 7.26.5 transitivePeerDependencies: - supports-color dev: true @@ -923,7 +934,7 @@ packages: dependencies: '@babel/core': 7.26.0 '@babel/helper-module-transforms': 7.26.0(@babel/core@7.26.0) - '@babel/helper-plugin-utils': 7.25.9 + '@babel/helper-plugin-utils': 7.26.5 transitivePeerDependencies: - supports-color dev: true @@ -936,9 +947,9 @@ packages: dependencies: '@babel/core': 7.26.0 '@babel/helper-module-transforms': 7.26.0(@babel/core@7.26.0) - '@babel/helper-plugin-utils': 7.25.9 + '@babel/helper-plugin-utils': 7.26.5 '@babel/helper-validator-identifier': 7.25.9 - '@babel/traverse': 7.26.4 + '@babel/traverse': 7.26.5 transitivePeerDependencies: - supports-color dev: true @@ -951,7 +962,7 @@ packages: dependencies: '@babel/core': 7.26.0 '@babel/helper-module-transforms': 7.26.0(@babel/core@7.26.0) - '@babel/helper-plugin-utils': 7.25.9 + '@babel/helper-plugin-utils': 7.26.5 transitivePeerDependencies: - supports-color dev: true @@ -964,7 +975,7 @@ packages: dependencies: '@babel/core': 7.26.0 '@babel/helper-create-regexp-features-plugin': 7.26.3(@babel/core@7.26.0) - '@babel/helper-plugin-utils': 7.25.9 + '@babel/helper-plugin-utils': 7.26.5 dev: true /@babel/plugin-transform-new-target@7.25.9(@babel/core@7.26.0): @@ -974,17 +985,17 @@ packages: '@babel/core': ^7.0.0-0 dependencies: '@babel/core': 7.26.0 - '@babel/helper-plugin-utils': 7.25.9 + '@babel/helper-plugin-utils': 7.26.5 dev: true - /@babel/plugin-transform-nullish-coalescing-operator@7.25.9(@babel/core@7.26.0): - resolution: {integrity: sha512-ENfftpLZw5EItALAD4WsY/KUWvhUlZndm5GC7G3evUsVeSJB6p0pBeLQUnRnBCBx7zV0RKQjR9kCuwrsIrjWog==} + /@babel/plugin-transform-nullish-coalescing-operator@7.26.5(@babel/core@7.26.0): + resolution: {integrity: sha512-OHqczNm4NTQlW1ghrVY43FPoiRzbmzNVbcgVnMKZN/RQYezHUSdjACjaX50CD3B7UIAjv39+MlsrVDb3v741FA==} engines: {node: '>=6.9.0'} peerDependencies: '@babel/core': ^7.0.0-0 dependencies: '@babel/core': 7.26.0 - '@babel/helper-plugin-utils': 7.25.9 + '@babel/helper-plugin-utils': 7.26.5 dev: true /@babel/plugin-transform-numeric-separator@7.25.9(@babel/core@7.26.0): @@ -994,7 +1005,7 @@ packages: '@babel/core': ^7.0.0-0 dependencies: '@babel/core': 7.26.0 - '@babel/helper-plugin-utils': 7.25.9 + '@babel/helper-plugin-utils': 7.26.5 dev: true /@babel/plugin-transform-object-rest-spread@7.25.9(@babel/core@7.26.0): @@ -1004,8 +1015,8 @@ packages: '@babel/core': ^7.0.0-0 dependencies: '@babel/core': 7.26.0 - '@babel/helper-compilation-targets': 7.25.9 - '@babel/helper-plugin-utils': 7.25.9 + '@babel/helper-compilation-targets': 7.26.5 + '@babel/helper-plugin-utils': 7.26.5 '@babel/plugin-transform-parameters': 7.25.9(@babel/core@7.26.0) dev: true @@ -1016,8 +1027,8 @@ packages: '@babel/core': ^7.0.0-0 dependencies: '@babel/core': 7.26.0 - '@babel/helper-plugin-utils': 7.25.9 - '@babel/helper-replace-supers': 7.25.9(@babel/core@7.26.0) + '@babel/helper-plugin-utils': 7.26.5 + '@babel/helper-replace-supers': 7.26.5(@babel/core@7.26.0) transitivePeerDependencies: - supports-color dev: true @@ -1029,7 +1040,7 @@ packages: '@babel/core': ^7.0.0-0 dependencies: '@babel/core': 7.26.0 - '@babel/helper-plugin-utils': 7.25.9 + '@babel/helper-plugin-utils': 7.26.5 dev: true /@babel/plugin-transform-optional-chaining@7.25.9(@babel/core@7.26.0): @@ -1039,7 +1050,7 @@ packages: '@babel/core': ^7.0.0-0 dependencies: '@babel/core': 7.26.0 - '@babel/helper-plugin-utils': 7.25.9 + '@babel/helper-plugin-utils': 7.26.5 '@babel/helper-skip-transparent-expression-wrappers': 7.25.9 transitivePeerDependencies: - supports-color @@ -1052,7 +1063,7 @@ packages: '@babel/core': ^7.0.0-0 dependencies: '@babel/core': 7.26.0 - '@babel/helper-plugin-utils': 7.25.9 + '@babel/helper-plugin-utils': 7.26.5 dev: true /@babel/plugin-transform-private-methods@7.25.9(@babel/core@7.26.0): @@ -1063,7 +1074,7 @@ packages: dependencies: '@babel/core': 7.26.0 '@babel/helper-create-class-features-plugin': 7.25.9(@babel/core@7.26.0) - '@babel/helper-plugin-utils': 7.25.9 + '@babel/helper-plugin-utils': 7.26.5 transitivePeerDependencies: - supports-color dev: true @@ -1077,7 +1088,7 @@ packages: '@babel/core': 7.26.0 '@babel/helper-annotate-as-pure': 7.25.9 '@babel/helper-create-class-features-plugin': 7.25.9(@babel/core@7.26.0) - '@babel/helper-plugin-utils': 7.25.9 + '@babel/helper-plugin-utils': 7.26.5 transitivePeerDependencies: - supports-color dev: true @@ -1089,7 +1100,7 @@ packages: '@babel/core': ^7.0.0-0 dependencies: '@babel/core': 7.26.0 - '@babel/helper-plugin-utils': 7.25.9 + '@babel/helper-plugin-utils': 7.26.5 dev: true /@babel/plugin-transform-regenerator@7.25.9(@babel/core@7.26.0): @@ -1099,7 +1110,7 @@ packages: '@babel/core': ^7.0.0-0 dependencies: '@babel/core': 7.26.0 - '@babel/helper-plugin-utils': 7.25.9 + '@babel/helper-plugin-utils': 7.26.5 regenerator-transform: 0.15.2 dev: true @@ -1111,7 +1122,7 @@ packages: dependencies: '@babel/core': 7.26.0 '@babel/helper-create-regexp-features-plugin': 7.26.3(@babel/core@7.26.0) - '@babel/helper-plugin-utils': 7.25.9 + '@babel/helper-plugin-utils': 7.26.5 dev: true /@babel/plugin-transform-reserved-words@7.25.9(@babel/core@7.26.0): @@ -1121,7 +1132,7 @@ packages: '@babel/core': ^7.0.0-0 dependencies: '@babel/core': 7.26.0 - '@babel/helper-plugin-utils': 7.25.9 + '@babel/helper-plugin-utils': 7.26.5 dev: true /@babel/plugin-transform-shorthand-properties@7.25.9(@babel/core@7.26.0): @@ -1131,7 +1142,7 @@ packages: '@babel/core': ^7.0.0-0 dependencies: '@babel/core': 7.26.0 - '@babel/helper-plugin-utils': 7.25.9 + '@babel/helper-plugin-utils': 7.26.5 dev: true /@babel/plugin-transform-spread@7.25.9(@babel/core@7.26.0): @@ -1141,7 +1152,7 @@ packages: '@babel/core': ^7.0.0-0 dependencies: '@babel/core': 7.26.0 - '@babel/helper-plugin-utils': 7.25.9 + '@babel/helper-plugin-utils': 7.26.5 '@babel/helper-skip-transparent-expression-wrappers': 7.25.9 transitivePeerDependencies: - supports-color @@ -1154,7 +1165,7 @@ packages: '@babel/core': ^7.0.0-0 dependencies: '@babel/core': 7.26.0 - '@babel/helper-plugin-utils': 7.25.9 + '@babel/helper-plugin-utils': 7.26.5 dev: true /@babel/plugin-transform-template-literals@7.25.9(@babel/core@7.26.0): @@ -1164,7 +1175,7 @@ packages: '@babel/core': ^7.0.0-0 dependencies: '@babel/core': 7.26.0 - '@babel/helper-plugin-utils': 7.25.9 + '@babel/helper-plugin-utils': 7.26.5 dev: true /@babel/plugin-transform-typeof-symbol@7.25.9(@babel/core@7.26.0): @@ -1174,7 +1185,7 @@ packages: '@babel/core': ^7.0.0-0 dependencies: '@babel/core': 7.26.0 - '@babel/helper-plugin-utils': 7.25.9 + '@babel/helper-plugin-utils': 7.26.5 dev: true /@babel/plugin-transform-unicode-escapes@7.25.9(@babel/core@7.26.0): @@ -1184,7 +1195,7 @@ packages: '@babel/core': ^7.0.0-0 dependencies: '@babel/core': 7.26.0 - '@babel/helper-plugin-utils': 7.25.9 + '@babel/helper-plugin-utils': 7.26.5 dev: true /@babel/plugin-transform-unicode-property-regex@7.25.9(@babel/core@7.26.0): @@ -1195,7 +1206,7 @@ packages: dependencies: '@babel/core': 7.26.0 '@babel/helper-create-regexp-features-plugin': 7.26.3(@babel/core@7.26.0) - '@babel/helper-plugin-utils': 7.25.9 + '@babel/helper-plugin-utils': 7.26.5 dev: true /@babel/plugin-transform-unicode-regex@7.25.9(@babel/core@7.26.0): @@ -1206,7 +1217,7 @@ packages: dependencies: '@babel/core': 7.26.0 '@babel/helper-create-regexp-features-plugin': 7.26.3(@babel/core@7.26.0) - '@babel/helper-plugin-utils': 7.25.9 + '@babel/helper-plugin-utils': 7.26.5 dev: true /@babel/plugin-transform-unicode-sets-regex@7.25.9(@babel/core@7.26.0): @@ -1217,7 +1228,7 @@ packages: dependencies: '@babel/core': 7.26.0 '@babel/helper-create-regexp-features-plugin': 7.26.3(@babel/core@7.26.0) - '@babel/helper-plugin-utils': 7.25.9 + '@babel/helper-plugin-utils': 7.26.5 dev: true /@babel/preset-env@7.26.0(@babel/core@7.26.0): @@ -1226,10 +1237,10 @@ packages: peerDependencies: '@babel/core': ^7.0.0-0 dependencies: - '@babel/compat-data': 7.26.3 + '@babel/compat-data': 7.26.5 '@babel/core': 7.26.0 - '@babel/helper-compilation-targets': 7.25.9 - '@babel/helper-plugin-utils': 7.25.9 + '@babel/helper-compilation-targets': 7.26.5 + '@babel/helper-plugin-utils': 7.26.5 '@babel/helper-validator-option': 7.25.9 '@babel/plugin-bugfix-firefox-class-in-computed-class-key': 7.25.9(@babel/core@7.26.0) '@babel/plugin-bugfix-safari-class-field-initializer-scope': 7.25.9(@babel/core@7.26.0) @@ -1243,7 +1254,7 @@ packages: '@babel/plugin-transform-arrow-functions': 7.25.9(@babel/core@7.26.0) '@babel/plugin-transform-async-generator-functions': 7.25.9(@babel/core@7.26.0) '@babel/plugin-transform-async-to-generator': 7.25.9(@babel/core@7.26.0) - '@babel/plugin-transform-block-scoped-functions': 7.25.9(@babel/core@7.26.0) + '@babel/plugin-transform-block-scoped-functions': 7.26.5(@babel/core@7.26.0) '@babel/plugin-transform-block-scoping': 7.25.9(@babel/core@7.26.0) '@babel/plugin-transform-class-properties': 7.25.9(@babel/core@7.26.0) '@babel/plugin-transform-class-static-block': 7.26.0(@babel/core@7.26.0) @@ -1268,7 +1279,7 @@ packages: '@babel/plugin-transform-modules-umd': 7.25.9(@babel/core@7.26.0) '@babel/plugin-transform-named-capturing-groups-regex': 7.25.9(@babel/core@7.26.0) '@babel/plugin-transform-new-target': 7.25.9(@babel/core@7.26.0) - '@babel/plugin-transform-nullish-coalescing-operator': 7.25.9(@babel/core@7.26.0) + '@babel/plugin-transform-nullish-coalescing-operator': 7.26.5(@babel/core@7.26.0) '@babel/plugin-transform-numeric-separator': 7.25.9(@babel/core@7.26.0) '@babel/plugin-transform-object-rest-spread': 7.25.9(@babel/core@7.26.0) '@babel/plugin-transform-object-super': 7.25.9(@babel/core@7.26.0) @@ -1306,8 +1317,8 @@ packages: '@babel/core': ^7.0.0-0 || ^8.0.0-0 <8.0.0 dependencies: '@babel/core': 7.26.0 - '@babel/helper-plugin-utils': 7.25.9 - '@babel/types': 7.26.3 + '@babel/helper-plugin-utils': 7.26.5 + '@babel/types': 7.26.5 esutils: 2.0.3 dev: true @@ -1323,27 +1334,27 @@ packages: engines: {node: '>=6.9.0'} dependencies: '@babel/code-frame': 7.26.2 - '@babel/parser': 7.26.3 - '@babel/types': 7.26.3 + '@babel/parser': 7.26.5 + '@babel/types': 7.26.5 dev: true - /@babel/traverse@7.26.4: - resolution: {integrity: sha512-fH+b7Y4p3yqvApJALCPJcwb0/XaOSgtK4pzV6WVjPR5GLFQBRI7pfoX2V2iM48NXvX07NUxxm1Vw98YjqTcU5w==} + /@babel/traverse@7.26.5: + resolution: {integrity: sha512-rkOSPOw+AXbgtwUga3U4u8RpoK9FEFWBNAlTpcnkLFjL5CT+oyHNuUUC/xx6XefEJ16r38r8Bc/lfp6rYuHeJQ==} engines: {node: '>=6.9.0'} dependencies: '@babel/code-frame': 7.26.2 - '@babel/generator': 7.26.3 - '@babel/parser': 7.26.3 + '@babel/generator': 7.26.5 + '@babel/parser': 7.26.5 '@babel/template': 7.25.9 - '@babel/types': 7.26.3 + '@babel/types': 7.26.5 debug: 4.4.0 globals: 11.12.0 transitivePeerDependencies: - supports-color dev: true - /@babel/types@7.26.3: - resolution: {integrity: sha512-vN5p+1kl59GVKMvTHt55NzzmYVxprfJD+ql7U9NFIfKCBkYE55LYtS+WtPlaYOyzydrKI8Nezd+aZextrd+FMA==} + /@babel/types@7.26.5: + resolution: {integrity: sha512-L6mZmwFDK6Cjh1nRCLXpa6no13ZIioJDz7mdkzHv399pThrTa/k0nUlNaenOeh2kWu/iaOQYElEpKPUswUa9Vg==} engines: {node: '>=6.9.0'} dependencies: '@babel/helper-string-parser': 7.25.9 @@ -1809,7 +1820,6 @@ packages: /@nestjs/core@10.4.15(@nestjs/common@10.4.15)(reflect-metadata@0.2.2)(rxjs@7.8.1): resolution: {integrity: sha512-UBejmdiYwaH6fTsz2QFBlC1cJHM+3UDeLZN+CiP9I1fRv2KlBZsmozGLbV5eS1JAVWJB4T5N5yQ0gjN8ZvcS2w==} - requiresBuild: true peerDependencies: '@nestjs/common': ^10.0.0 '@nestjs/microservices': ^10.0.0 @@ -2183,8 +2193,8 @@ packages: /@types/babel__core@7.20.5: resolution: {integrity: sha512-qoQprZvz5wQFJwMDqeseRXWv3rqMvhgpbXFfVyWhbx9X47POIA6i/+dXefEmZKoAgOaTdaIgNSMqMIU61yRyzA==} dependencies: - '@babel/parser': 7.26.3 - '@babel/types': 7.26.3 + '@babel/parser': 7.26.5 + '@babel/types': 7.26.5 '@types/babel__generator': 7.6.8 '@types/babel__template': 7.4.4 '@types/babel__traverse': 7.20.6 @@ -2193,20 +2203,20 @@ packages: /@types/babel__generator@7.6.8: resolution: {integrity: sha512-ASsj+tpEDsEiFr1arWrlN6V3mdfjRMZt6LtK/Vp/kreFLnr5QH5+DhvD5nINYZXzwJvXeGq+05iUXcAzVrqWtw==} dependencies: - '@babel/types': 7.26.3 + '@babel/types': 7.26.5 dev: true /@types/babel__template@7.4.4: resolution: {integrity: sha512-h/NUaSyG5EyxBIp8YRxo4RMe2/qQgvyowRwVMzhYhBCONbW8PUsg4lkFMrhgZhUe5z3L3MiLDuvyJ/CaPa2A8A==} dependencies: - '@babel/parser': 7.26.3 - '@babel/types': 7.26.3 + '@babel/parser': 7.26.5 + '@babel/types': 7.26.5 dev: true /@types/babel__traverse@7.20.6: resolution: {integrity: sha512-r1bzfrm0tomOI8g1SzvCaQHo6Lcv6zu0EA+W2kHrt8dyrHQxGzBBL4kdkzIS+jBMV+EYcMAEAqXqYaLJq5rOZg==} dependencies: - '@babel/types': 7.26.3 + '@babel/types': 7.26.5 dev: true /@types/body-parser@1.19.5: @@ -2414,7 +2424,6 @@ packages: /@types/yauzl@2.10.3: resolution: {integrity: sha512-oJoftv0LSuaDZE3Le4DbKX+KS9G36NzOeSap90UIK0yMA/NhKJhqlSGtNDORNRaIbQfzjXDrQa0ytJ6mNRGz/Q==} - requiresBuild: true dependencies: '@types/node': 18.19.70 dev: false @@ -2622,7 +2631,7 @@ packages: resolution: {integrity: sha512-Y1IQok9821cC9onCx5otgFfRm7Lm+I+wwxOx738M/WLPZ9Q42m4IG5W0FNX8WLL2gYMZo3JkuXIH2DOpWM+qwA==} engines: {node: '>=8'} dependencies: - '@babel/helper-plugin-utils': 7.25.9 + '@babel/helper-plugin-utils': 7.26.5 '@istanbuljs/load-nyc-config': 1.1.0 '@istanbuljs/schema': 0.1.3 istanbul-lib-instrument: 5.2.1 @@ -2636,7 +2645,7 @@ packages: engines: {node: ^14.15.0 || ^16.10.0 || >=18.0.0} dependencies: '@babel/template': 7.25.9 - '@babel/types': 7.26.3 + '@babel/types': 7.26.5 '@types/babel__core': 7.20.5 '@types/babel__traverse': 7.20.6 dev: true @@ -2646,7 +2655,7 @@ packages: peerDependencies: '@babel/core': ^7.4.0 || ^8.0.0-0 <8.0.0 dependencies: - '@babel/compat-data': 7.26.3 + '@babel/compat-data': 7.26.5 '@babel/core': 7.26.0 '@babel/helper-define-polyfill-provider': 0.6.3(@babel/core@7.26.0) semver: 6.3.1 @@ -2719,9 +2728,8 @@ packages: resolution: {integrity: sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw==} dev: true - /bare-events@2.5.3: - resolution: {integrity: sha512-pCO3aoRJ0MBiRMu8B7vUga0qL3L7gO1+SW7ku6qlSsMLwuhaawnuvZDyzJY/kyC63Un0XAB0OPUcfF1eTO/V+Q==} - requiresBuild: true + /bare-events@2.5.4: + resolution: {integrity: sha512-+gFfDkR8pj4/TrWCGUGWmJIkBwuxPS5F+a5yWjOHQt2hHvNZd5YLzadjmDUtFmMM4y429bnKLa8bYBMHcYdnQA==} dev: true optional: true @@ -3626,7 +3634,6 @@ packages: resolution: {integrity: sha512-5xoDfX+fL7faATnagmWPpbFtwh/R77WmMMqqHGS65C3vvB0YHrgF+B1YmZ3441tMj5n63k0212XNoJwzlhffQw==} engines: {node: ^8.16.0 || ^10.6.0 || >=11.0.0} os: [darwin] - requiresBuild: true dev: true optional: true @@ -4173,7 +4180,7 @@ packages: engines: {node: '>=8'} dependencies: '@babel/core': 7.26.0 - '@babel/parser': 7.26.3 + '@babel/parser': 7.26.5 '@istanbuljs/schema': 0.1.3 istanbul-lib-coverage: 3.2.2 semver: 6.3.1 @@ -4186,7 +4193,7 @@ packages: engines: {node: '>=10'} dependencies: '@babel/core': 7.26.0 - '@babel/parser': 7.26.3 + '@babel/parser': 7.26.5 '@istanbuljs/schema': 0.1.3 istanbul-lib-coverage: 3.2.2 semver: 7.6.3 @@ -4430,6 +4437,16 @@ packages: fsevents: 2.3.3 dev: true + /jest-junit@16.0.0: + resolution: {integrity: sha512-A94mmw6NfJab4Fg/BlvVOUXzXgF0XIH6EmTgJ5NDPp4xoKq0Kr7sErb+4Xs9nZvu58pJojz5RFGpqnZYJTrRfQ==} + engines: {node: '>=10.12.0'} + dependencies: + mkdirp: 1.0.4 + strip-ansi: 6.0.1 + uuid: 8.3.2 + xml: 1.0.1 + dev: true + /jest-leak-detector@29.7.0: resolution: {integrity: sha512-kYA8IJcSYtST2BY9I+SMC32nDpBT3J2NvWJx8+JCuCdl/CR1I4EKUJROiP8XtCcxqgTTBGJNdbB1A8XRKbTetw==} engines: {node: ^14.15.0 || ^16.10.0 || >=18.0.0} @@ -4603,10 +4620,10 @@ packages: engines: {node: ^14.15.0 || ^16.10.0 || >=18.0.0} dependencies: '@babel/core': 7.26.0 - '@babel/generator': 7.26.3 + '@babel/generator': 7.26.5 '@babel/plugin-syntax-jsx': 7.25.9(@babel/core@7.26.0) '@babel/plugin-syntax-typescript': 7.25.9(@babel/core@7.26.0) - '@babel/types': 7.26.3 + '@babel/types': 7.26.5 '@jest/expect-utils': 29.7.0 '@jest/transform': 29.7.0 '@jest/types': 29.6.3 @@ -5085,7 +5102,6 @@ packages: resolution: {integrity: sha512-vVqVZQyf3WLx2Shd0qJ9xuvqgAyKPLAiqITEtqW0oIUjzo3PePDd6fW9iFz30ef7Ysp/oiWqbhszeGWW2T6Gzw==} engines: {node: '>=10'} hasBin: true - dev: false /mockttp@3.15.5: resolution: {integrity: sha512-Efhz6RcAga1Zn93W5XWOwUSvIq9NNhJHig4gCCm6whemDKgt7aYalhrGIi7sdK7Cn7ipbG3x9n3ux+TljB+o6w==} @@ -5442,6 +5458,12 @@ packages: engines: {node: '>= 0.4'} dev: false + /prettier@3.4.2: + resolution: {integrity: sha512-e9MewbtFo+Fevyuxn/4rrcDAaq0IYxPGLvObpQjiZBMAzB9IGmzlnG9RZy3FFas+eBMu2vA0CszMeduow5dIuQ==} + engines: {node: '>=14'} + hasBin: true + dev: true + /pretty-format@28.1.3: resolution: {integrity: sha512-8gFb/To0OmxHR9+ZTb14Df2vNxdGCX8g1xWGUTqUw5TiZvcQf5sHKObd5UcPyLLyowNwDAMTF3XWOG1B6mxl1Q==} engines: {node: ^12.13.0 || ^14.15.0 || ^16.10.0 || >=17.0.0} @@ -5492,7 +5514,6 @@ packages: /protobufjs@7.4.0: resolution: {integrity: sha512-mRUWCc3KUU4w1jU8sGxICXH/gNS94DvI1gxqDvBzhj1JpcsimQkYiOJfwsPUykUI5ZaspFbSgmBLER8IrQ3tqw==} engines: {node: '>=12.0.0'} - requiresBuild: true dependencies: '@protobufjs/aspromise': 1.1.2 '@protobufjs/base64': 1.1.2 @@ -6036,7 +6057,7 @@ packages: queue-tick: 1.0.1 text-decoder: 1.2.3 optionalDependencies: - bare-events: 2.5.3 + bare-events: 2.5.4 dev: true /string-length@4.0.2: @@ -6226,8 +6247,8 @@ packages: engines: {node: '>=6.0.0', npm: '>=3.0.0'} dev: true - /typescript@5.7.3: - resolution: {integrity: sha512-84MVSjMEHP+FQRPy3pX9sTVV/INIex71s9TL2Gm5FG/WG1SqXeKyZ0k7/blY/4FdOzI12CBy1vGc4og/eus0fw==} + /typescript@5.6.3: + resolution: {integrity: sha512-hjcS1mhfuyi4WW8IWtjP7brDrG2cuDZukyrYrSauoXGNgx0S7zceP07adYkJycEr56BOUTNPzbInooiN3fn1qw==} engines: {node: '>=14.17'} hasBin: true dev: true @@ -6422,6 +6443,10 @@ packages: optional: true dev: true + /xml@1.0.1: + resolution: {integrity: sha512-huCv9IH9Tcf95zuYCsQraZtWnJvBtLVE0QHMOs8bWyZAFZNDcYjsPq1nEx8jKA9y+Beo9v+7OBPRisQTjinQMw==} + dev: true + /xtend@4.0.2: resolution: {integrity: sha512-LKYU1iAXJXUgAXn9URjiu+MWhyUXHsvfp7mcuYm9dSUKK0/CjtrUwFAxD82/mCWbtLsGjFIad0wIsod4zrTAEQ==} engines: {node: '>=0.4'} diff --git a/src/BUILD.bazel b/src/BUILD.bazel new file mode 100644 index 0000000..6cee1bf --- /dev/null +++ b/src/BUILD.bazel @@ -0,0 +1,24 @@ +load("@aspect_bazel_lib//lib:copy_to_directory.bzl", "copy_to_directory") +load("@rules_pkg//pkg:zip.bzl", "pkg_zip") + +copy_to_directory( + name = "dist", + srcs = [ + "//:package_json", + "//:pnpm-lock.yaml", + "//src/application", + "//src/application/webhook", + "//src/domain", + "//src/infrastructure", + "//src/infrastructure/xzdec", + "//src/infrastructure/xzdec:xzdec_wasm_gz", + ], + visibility = ["//e2e:__subpackages__"], +) + +pkg_zip( + name = "cloudfunction", + srcs = ["dist"], + strip_prefix = "dist", + visibility = ["//deployment/environments:__subpackages__"], +) diff --git a/src/application/BUILD.bazel b/src/application/BUILD.bazel new file mode 100644 index 0000000..2b8d956 --- /dev/null +++ b/src/application/BUILD.bazel @@ -0,0 +1,22 @@ +load("//bazel/ts:defs.bzl", "ts_project") + +ts_project( + name = "application", + srcs = [ + "notifications.ts", + "octokit.ts", + "release-event-handler.ts", + ], + visibility = [ + "//src:__pkg__", + "//src/application:__subpackages__", + ], + deps = [ + "//:node_modules/@nestjs/common", + "//:node_modules/@octokit/rest", + "//:node_modules/@octokit/webhooks", + "//:node_modules/@octokit/webhooks-types", + "//src/domain", + "//src/infrastructure", + ], +) diff --git a/src/application/webhook/BUILD.bazel b/src/application/webhook/BUILD.bazel new file mode 100644 index 0000000..46e0c03 --- /dev/null +++ b/src/application/webhook/BUILD.bazel @@ -0,0 +1,24 @@ +load("//bazel/ts:defs.bzl", "ts_project") + +ts_project( + name = "webhook", + srcs = [ + "app.module.ts", + "index.ts", + "main.ts", + "providers.ts", + ], + visibility = ["//src:__pkg__"], + deps = [ + "//:node_modules/@google-cloud/functions-framework", + "//:node_modules/@nestjs/common", + "//:node_modules/@nestjs/core", + "//:node_modules/@octokit/rest", + "//:node_modules/@octokit/webhooks", + "//:node_modules/@types/source-map-support", + "//:node_modules/source-map-support", + "//src/application", + "//src/domain", + "//src/infrastructure", + ], +) diff --git a/src/domain/BUILD.bazel b/src/domain/BUILD.bazel new file mode 100644 index 0000000..fea7c4a --- /dev/null +++ b/src/domain/BUILD.bazel @@ -0,0 +1,79 @@ +load("//bazel/jest:defs.bzl", "jest_test") +load("//bazel/ts:defs.bzl", "ts_project") + +ts_project( + name = "domain", + srcs = [ + "config.ts", + "create-entry.ts", + "error.ts", + "find-registry-fork.ts", + "integrity-hash.ts", + "metadata-file.ts", + "module-file.ts", + "publish-entry.ts", + "release-archive.ts", + "repository.ts", + "ruleset-repository.ts", + "source-template.ts", + "user.ts", + "version.ts", + ], + visibility = ["//src:__subpackages__"], + deps = [ + "//:node_modules/@nestjs/common", + "//:node_modules/@types/diff", + "//:node_modules/@types/node", + "//:node_modules/@types/tar", + "//:node_modules/axios", + "//:node_modules/axios-retry", + "//:node_modules/diff", + "//:node_modules/exponential-backoff", + "//:node_modules/extract-zip", + "//:node_modules/tar", + "//:node_modules/yaml", + "//src/infrastructure", + "//src/infrastructure/xzdec", + ], +) + +ts_project( + name = "domain_tests", + testonly = True, + srcs = [ + "create-entry.spec.ts", + "find-registry-fork.spec.ts", + "integrity-hash.spec.ts", + "metadata-file.spec.ts", + "module-file.spec.ts", + "publish-entry.spec.ts", + "release-archive.spec.ts", + "repository.spec.ts", + "ruleset-repository.spec.ts", + "source-template.spec.ts", + "version.spec.ts", + ], + deps = [ + ":domain", + "//:node_modules/@types/diff", + "//:node_modules/@types/jest", # keep + "//:node_modules/@types/node", + "//:node_modules/@types/tar", + "//:node_modules/axios", + "//:node_modules/axios-retry", + "//:node_modules/diff", + "//:node_modules/exponential-backoff", + "//:node_modules/jest-extended", # keep + "//:node_modules/jest-mock", + "//:node_modules/tar", + "//src/infrastructure", + "//src/test", + ], +) + +jest_test( + name = "test", + data = [ + ":domain_tests", + ], +) diff --git a/src/domain/find-registry-fork.spec.ts b/src/domain/find-registry-fork.spec.ts index 21f17a6..f2ad601 100644 --- a/src/domain/find-registry-fork.spec.ts +++ b/src/domain/find-registry-fork.spec.ts @@ -63,7 +63,7 @@ describe("findCandidateForks", () => { mockRepositoryService.getSourceRepository.mockImplementation( async (repository) => { - if (repository.equals(ownerBcrFork)) { + if (repository.owner === ownerBcrFork.owner && repository.name === ownerBcrFork.name) { return CANONICAL_BCR; } return repository; @@ -110,7 +110,7 @@ describe("findCandidateForks", () => { mockRepositoryService.getSourceRepository.mockImplementation( async (repository) => { - if (repository.equals(releaserBcrFork)) { + if (repository.owner === releaserBcrFork.owner && repository.name === releaserBcrFork.name) { return CANONICAL_BCR; } return repository; @@ -161,8 +161,8 @@ describe("findCandidateForks", () => { mockRepositoryService.getSourceRepository.mockImplementation( async (repository) => { if ( - repository.equals(releaserBcrFork) || - repository.equals(ownerBcrFork) + (repository.owner === releaserBcrFork.owner && repository.name === releaserBcrFork.name) || + (repository.owner === ownerBcrFork.owner && repository.name === ownerBcrFork.name) ) { return CANONICAL_BCR; } @@ -172,7 +172,8 @@ describe("findCandidateForks", () => { mockRepositoryService.hasAppInstallation.mockImplementation( async (repository) => - repository.equals(ownerBcrFork) || repository.equals(releaserBcrFork) + (repository.owner === releaserBcrFork.owner && repository.name === releaserBcrFork.name) || + (repository.owner === ownerBcrFork.owner && repository.name === ownerBcrFork.name) ); const forks = await findRegistryForkService.findCandidateForks( @@ -210,7 +211,7 @@ describe("findCandidateForks", () => { mockRepositoryService.getSourceRepository.mockImplementation( async (repository) => { - if (repository.equals(ownerBcrFork)) { + if (repository.owner === ownerBcrFork.owner && repository.name === ownerBcrFork.name) { return new Repository("bazel-central-registry", "not-google"); } return repository; @@ -251,7 +252,7 @@ describe("findCandidateForks", () => { mockRepositoryService.getSourceRepository.mockImplementation( async (repository) => { - if (repository.equals(releaserBcrFork)) { + if (repository.owner === releaserBcrFork.owner && repository.name === releaserBcrFork.name) { return CANONICAL_BCR; } return repository; diff --git a/src/domain/find-registry-fork.ts b/src/domain/find-registry-fork.ts index 44ee887..3631e05 100644 --- a/src/domain/find-registry-fork.ts +++ b/src/domain/find-registry-fork.ts @@ -36,12 +36,12 @@ export class FindRegistryForkService { potentialForkOwners.add(releaser.username); const allForks = ( - await Promise.all( + (await Promise.all( Array.from(potentialForkOwners.values()).map((owner) => this.repositoryService.getForkedRepositoriesByOwner(owner) ) ) - ).reduce((acc, curr) => acc.concat(curr), []); + ).reduce((acc, curr) => acc.concat(curr), [])).map(r => new Repository(r.name, r.owner)); let candidateForks = allForks.filter( (repo) => repo.name === "bazel-central-registry" diff --git a/src/domain/metadata-file.spec.ts b/src/domain/metadata-file.spec.ts index 8c1ba4a..1f68436 100644 --- a/src/domain/metadata-file.spec.ts +++ b/src/domain/metadata-file.spec.ts @@ -1,6 +1,6 @@ +import "jest-extended"; import { mocked } from "jest-mock"; import fs from "node:fs"; -import "../../jest.setup"; import { MetadataFile, MetadataFileError } from "./metadata-file"; jest.mock("node:fs"); diff --git a/src/domain/release-archive.spec.ts b/src/domain/release-archive.spec.ts index e33984b..5ec3c1c 100644 --- a/src/domain/release-archive.spec.ts +++ b/src/domain/release-archive.spec.ts @@ -5,7 +5,6 @@ import fs, { WriteStream } from "node:fs"; import os from "node:os"; import path from "node:path"; import tar from "tar"; -import "../../jest.setup"; import { fakeModuleFile } from "../test/mock-template-files"; import { expectThrownError } from "../test/util"; import { diff --git a/src/infrastructure/BUILD.bazel b/src/infrastructure/BUILD.bazel new file mode 100644 index 0000000..2f9e672 --- /dev/null +++ b/src/infrastructure/BUILD.bazel @@ -0,0 +1,29 @@ +load("//bazel/ts:defs.bzl", "ts_project") + +ts_project( + name = "infrastructure", + srcs = [ + "email.ts", + "git.ts", + "github.ts", + "secrets.ts", + ], + visibility = [ + "//e2e:__pkg__", + "//src:__pkg__", + "//src/application:__subpackages__", + "//src/domain:__subpackages__", + ], + deps = [ + "//:node_modules/@google-cloud/secret-manager", + "//:node_modules/@nestjs/common", + "//:node_modules/@octokit/auth-app", + "//:node_modules/@octokit/rest", + "//:node_modules/@octokit/types", + "//:node_modules/@types/nodemailer", + "//:node_modules/gcp-metadata", + "//:node_modules/google-auth-library", + "//:node_modules/nodemailer", + "//:node_modules/simple-git", + ], +) diff --git a/src/infrastructure/xzdec/.gitignore b/src/infrastructure/xzdec/.gitignore deleted file mode 100644 index 2f0f755..0000000 --- a/src/infrastructure/xzdec/.gitignore +++ /dev/null @@ -1,2 +0,0 @@ -/bazel-* -/MODULE.bazel.lock diff --git a/src/infrastructure/xzdec/BUILD.bazel b/src/infrastructure/xzdec/BUILD.bazel index 2ae7e30..0a8f5f9 100644 --- a/src/infrastructure/xzdec/BUILD.bazel +++ b/src/infrastructure/xzdec/BUILD.bazel @@ -1,8 +1,8 @@ -load("@aspect_bazel_lib//lib:write_source_files.bzl", "write_source_file") +load("//bazel/ts:defs.bzl", "ts_project") load(":wasm.bzl", "wasm_binary") cc_binary( - name = "xzdec", + name = "xzdec_cc", srcs = ["xzdec.c"], linkopts = [ "-nostdlib", @@ -16,18 +16,24 @@ cc_binary( wasm_binary( name = "xzdec_wasm", out = "xzdec.wasm", - lib = ":xzdec", + lib = ":xzdec_cc", ) genrule( name = "xzdec_wasm_gz", srcs = [":xzdec_wasm"], - outs = ["xzdec_wasm_gz/xzdec.wasm.gz"], + outs = ["xzdec.wasm.gz"], cmd = "cat $< | gzip -9 -k -n > $@", + visibility = ["//src:__pkg__"], ) -write_source_file( - name = "write_xzdec_wasm_gz_to_source_tree", - in_file = ":xzdec_wasm_gz", - out_file = "xzdec.wasm.gz", +ts_project( + name = "xzdec", + srcs = ["xzdec.ts"], + data = [":xzdec_wasm_gz"], + visibility = [ + "//src:__pkg__", + "//src/domain:__subpackages__", + ], + deps = ["//:node_modules/@types/node"], ) diff --git a/src/infrastructure/xzdec/MODULE.bazel b/src/infrastructure/xzdec/MODULE.bazel deleted file mode 100644 index 9aab199..0000000 --- a/src/infrastructure/xzdec/MODULE.bazel +++ /dev/null @@ -1,45 +0,0 @@ -module(name = "publish-to-bcr") - -bazel_dep(name = "aspect_bazel_lib", version = "2.9.3") -bazel_dep(name = "platforms", version = "0.0.10") -bazel_dep(name = "toolchains_llvm", version = "1.2.0") -bazel_dep(name = "xz", version = "5.4.5.bcr.5") - -# https://github.com/bazel-contrib/toolchains_llvm/pull/405 -# -# FIXME: Remove when a new `toolchains_llvm` has been released. -git_override( - module_name = "toolchains_llvm", - commit = "bda1c9fbf232b682c30d039f8e4a5e3cf3025d0f", - remote = "https://github.com/bazel-contrib/toolchains_llvm", -) - -llvm = use_extension("@toolchains_llvm//toolchain/extensions:llvm.bzl", "llvm") -llvm.toolchain( - libclang_rt = { - "@libclang_rt-wasm32-wasi//:libclang_rt.builtins-wasm32.a": "wasm32-unknown-unknown/libclang_rt.builtins.a", - }, - llvm_versions = { - # Pin to an older LLVM version due to a stray Homebrew dependency - # in the macOS build of v19.1.0. - # - # https://github.com/llvm/llvm-project/issues/110070 - "": "18.1.8", - }, - stdlib = {"wasm32": "libc"}, -) -llvm.sysroot( - label = "@wasi-sysroot//sysroots/wasm32-wasip2", - targets = ["wasm32"], -) -use_repo(llvm, "llvm_toolchain") - -register_toolchains("@llvm_toolchain//:all") - -wasi_sysroot = use_repo_rule("//:wasm.bzl", "wasi_sysroot") - -wasm32_libclang_rt = use_repo_rule("//:wasm.bzl", "wasm32_libclang_rt") - -wasi_sysroot(name = "wasi-sysroot") - -wasm32_libclang_rt(name = "libclang_rt-wasm32-wasi") diff --git a/src/infrastructure/xzdec/wasm.bzl b/src/infrastructure/xzdec/wasm.bzl index ff76b24..888e9a7 100644 --- a/src/infrastructure/xzdec/wasm.bzl +++ b/src/infrastructure/xzdec/wasm.bzl @@ -1,8 +1,10 @@ +"Rule for generating a wasm binary" + _WASM_ABIS = [ "wasm32-wasip2", ] -def _platform_transition(settings, attr): +def _platform_transition(_, attr): return {"//command_line_option:platforms": str(attr._platform)} platform_transition = transition( diff --git a/src/infrastructure/xzdec/xzdec.wasm.gz b/src/infrastructure/xzdec/xzdec.wasm.gz deleted file mode 100644 index c3c457b..0000000 Binary files a/src/infrastructure/xzdec/xzdec.wasm.gz and /dev/null differ diff --git a/src/test/BUILD.bazel b/src/test/BUILD.bazel new file mode 100644 index 0000000..fb0d8c1 --- /dev/null +++ b/src/test/BUILD.bazel @@ -0,0 +1,15 @@ +load("//bazel/ts:defs.bzl", "ts_project") + +ts_project( + name = "test", + srcs = [ + "mock-template-files.ts", + "util.ts", + ], + visibility = ["//src/domain:__pkg__"], + deps = [ + "//:node_modules/@types/jest", # keep + "//:node_modules/@types/node", + "//src/domain", + ], +) diff --git a/tools/BUILD.bazel b/tools/BUILD.bazel new file mode 100644 index 0000000..9e376e6 --- /dev/null +++ b/tools/BUILD.bazel @@ -0,0 +1,18 @@ +load(":terraform.bzl", "terraform") + +package(default_visibility = ["//visibility:public"]) + +terraform(name = "terraform") + +sh_library( + name = "shell", + srcs = [ + "tool.sh", + ], +) + +exports_files( + [ + "tool.sh", + ], +) diff --git a/tools/clean.js b/tools/clean.js deleted file mode 100644 index 1690a54..0000000 --- a/tools/clean.js +++ /dev/null @@ -1,5 +0,0 @@ -import fs from "node:fs"; -import { BUILD_DIR, DIST_DIR } from "./config.js"; - -fs.rmSync(BUILD_DIR, { recursive: true, force: true }); -fs.rmSync(DIST_DIR, { recursive: true, force: true }); diff --git a/tools/config.js b/tools/config.js deleted file mode 100644 index 11db70e..0000000 --- a/tools/config.js +++ /dev/null @@ -1,9 +0,0 @@ -import path from "node:path"; -import { fileURLToPath } from "node:url"; - -export const PROJECT_DIR = path.join( - path.dirname(fileURLToPath(import.meta.url)), - ".." -); -export const BUILD_DIR = path.join(PROJECT_DIR, "build"); -export const DIST_DIR = path.join(PROJECT_DIR, "dist"); diff --git a/tools/copy-dist-files.js b/tools/copy-dist-files.js deleted file mode 100644 index 3c1127f..0000000 --- a/tools/copy-dist-files.js +++ /dev/null @@ -1,41 +0,0 @@ -import { globbySync } from "globby"; -import fs from "node:fs"; -import path from "node:path"; -import { DIST_DIR, PROJECT_DIR } from "./config.js"; - -async function main() { - const filesToInclude = getDistributableFiles(); - copyFilesToDist(filesToInclude); -} - -function getDistributableFiles() { - return globbySync( - [ - "package.json", - "pnpm-lock.yaml", - "src/infrastructure/xzdec/xzdec.wasm.gz", - "build/src/**/*.js", - "!build/src/test", - ], - { - cwd: PROJECT_DIR, - } - ); -} - -function copyFilesToDist(files) { - console.info(`Copying distributable files to ${DIST_DIR}`); - files.forEach((file) => { - const src = path.join(PROJECT_DIR, file); - const distFile = file.replace(/^build\/src\//, "").replace(/^src\//, ""); - - const dest = path.join(DIST_DIR, "publish-to-bcr", distFile); - console.info(` => ${file} -> ${distFile}`); - fs.mkdirSync(path.dirname(dest), { recursive: true }); - fs.copyFileSync(src, dest); - }); -} - -(async () => { - await main(); -})(); diff --git a/tools/format/BUILD.bazel b/tools/format/BUILD.bazel new file mode 100644 index 0000000..4723b0c --- /dev/null +++ b/tools/format/BUILD.bazel @@ -0,0 +1,27 @@ +load("@aspect_rules_lint//format:defs.bzl", "format_multirun") +load("@npm//:prettier/package_json.bzl", prettier = "bin") + +package(default_visibility = ["//visibility:public"]) + +prettier.prettier_binary( + name = "prettier", + data = [ + "//:prettierrc", + ], + # Allow the binary to be run outside bazel + env = {"BAZEL_BINDIR": "."}, + fixed_args = [ + # `require` statements in the config file will be resolved relative to its location + # Therefore to make it hermetic, prettier must be pointed at the copy of the config file + # in the runfiles folder rather than the one in the source folder. + "--config=\"$$JS_BINARY__RUNFILES\"/$(rlocationpath //:prettierrc)", + ], +) + +format_multirun( + name = "format", + javascript = ":prettier", + starlark = "@buildifier_prebuilt//:buildifier", + terraform = "@aspect_rules_lint//format:terraform", + yaml = "@aspect_rules_lint//format:yamlfmt", +) diff --git a/tools/terraform.bzl b/tools/terraform.bzl new file mode 100644 index 0000000..f9ef035 --- /dev/null +++ b/tools/terraform.bzl @@ -0,0 +1,12 @@ +"""Terraform tool runnable target with optional data deps that will be built before run""" + +def terraform(name, data = [], **kwargs): + native.sh_binary( + name = name, + srcs = ["//tools:tool.sh"], + args = ["$(rootpath @multitool//tools/terraform)"], + data = ["@multitool//tools/terraform"] + data, + tags = kwargs.pop("tags", ["manual"]), + visibility = kwargs.pop("visibility", ["//:__subpackages__"]), + **kwargs + ) diff --git a/tools/tool.bzl b/tools/tool.bzl new file mode 100644 index 0000000..c253f5d --- /dev/null +++ b/tools/tool.bzl @@ -0,0 +1,38 @@ +"""Makes tool macros for terraform et al""" + +def make_tool(tool, target, data = [], **kwargs): + native.sh_binary( + name = tool, + srcs = ["//tools:tool.sh"], + args = select({ + "//platforms/config:linux_x86_64": ["$(rootpath @{tool}_linux_x86_64{target})".format( + target = target, + tool = tool, + )], + "//platforms/config:macos_aarch64": ["$(rootpath @{tool}_macos_aarch64{target})".format( + target = target, + tool = tool, + )], + "//platforms/config:macos_x86_64": ["$(rootpath @{tool}_macos_x86_64{target})".format( + target = target, + tool = tool, + )], + }), + data = select({ + "//platforms/config:linux_x86_64": ["@{tool}_linux_x86_64{target}".format( + target = target, + tool = tool, + )], + "//platforms/config:macos_aarch64": ["@{tool}_macos_aarch64{target}".format( + target = target, + tool = tool, + )], + "//platforms/config:macos_x86_64": ["@{tool}_macos_x86_64{target}".format( + target = target, + tool = tool, + )], + }) + data, + tags = kwargs.pop("tags", ["manual"]), + visibility = kwargs.pop("visibility", ["//:__subpackages__"]), + **kwargs + ) diff --git a/tools/tool.sh b/tools/tool.sh new file mode 100755 index 0000000..55d3fee --- /dev/null +++ b/tools/tool.sh @@ -0,0 +1,10 @@ +#!/usr/bin/env bash + +set -o errexit -o nounset -o pipefail + +tool="${PWD}/$1" +shift + +cd "${BUILD_WORKING_DIRECTORY}" + +exec "${tool}" "$@" diff --git a/tools/tools.lock.json b/tools/tools.lock.json new file mode 100644 index 0000000..7d58d1a --- /dev/null +++ b/tools/tools.lock.json @@ -0,0 +1,59 @@ +{ + "$schema": "https://raw.githubusercontent.com/theoremlp/rules_multitool/main/lockfile.schema.json", + "multitool": { + "binaries": [ + { + "kind": "archive", + "url": "https://github.com/theoremlp/multitool/releases/download/v0.7.0/multitool-aarch64-apple-darwin.tar.xz", + "file": "multitool-aarch64-apple-darwin/multitool", + "sha256": "691a57ac398fb9d185f4d2e76a406cc8e15d05e900aaaa047ba8d582cc16e7bd", + "os": "macos", + "cpu": "arm64" + }, + { + "kind": "archive", + "url": "https://github.com/theoremlp/multitool/releases/download/v0.7.0/multitool-x86_64-unknown-linux-gnu.tar.xz", + "file": "multitool-x86_64-unknown-linux-gnu/multitool", + "sha256": "b4c979723e26ed2d2f27f11b06fe35b8ab325b69dbdda53bae1e19e2e98c4f46", + "os": "linux", + "cpu": "x86_64" + }, + { + "kind": "archive", + "url": "https://github.com/theoremlp/multitool/releases/download/v0.7.0/multitool-aarch64-unknown-linux-gnu.tar.xz", + "file": "multitool-aarch64-unknown-linux-gnu/multitool", + "sha256": "dfd76e47788cccd17ff48f70d612d24293037ed33a0abb6e8d8317c64e3a184c", + "os": "linux", + "cpu": "arm64" + } + ] + }, + "terraform": { + "binaries": [ + { + "kind": "archive", + "url": "https://releases.hashicorp.com/terraform/1.9.3/terraform_1.9.3_darwin_arm64.zip", + "file": "terraform", + "sha256": "168cfeb339dbbfea6be651573ec168e6ca08bab79a4fc0474681eee1e9a95de9", + "os": "macos", + "cpu": "arm64" + }, + { + "kind": "archive", + "url": "https://releases.hashicorp.com/terraform/1.9.3/terraform_1.9.3_linux_amd64.zip", + "file": "terraform", + "sha256": "e52520cf6d677155e69a8fcfe64054891f4d991802b0d36d4c8b670d60a7e899", + "os": "linux", + "cpu": "x86_64" + }, + { + "kind": "archive", + "url": "https://releases.hashicorp.com/terraform/1.9.3/terraform_1.9.3_linux_arm64.zip", + "file": "terraform", + "sha256": "193ce269aafd5c44f359cd73a75c5cc7aaab924eb5c3601784c1873575828ec7", + "os": "linux", + "cpu": "arm64" + } + ] + } +} diff --git a/tsconfig.json b/tsconfig.json index 7434af5..97c0907 100644 --- a/tsconfig.json +++ b/tsconfig.json @@ -3,7 +3,6 @@ "noImplicitAny": true, "esModuleInterop": true, "sourceMap": true, - "outDir": "build", "module": "es2020", "target": "es2020", "moduleResolution": "node", @@ -11,7 +10,7 @@ "experimentalDecorators": true, "emitDecoratorMetadata": true, "allowJs": true, - "types": ["jest", "node"] + "skipLibCheck": true }, "include": ["src/**/*.ts", "e2e/**/*.ts", "*.js"], "exclude": ["node_modules", "src/**/bazel-*"]