diff --git a/.bazelrc b/.bazelrc index d1f17d7..3bca248 100644 --- a/.bazelrc +++ b/.bazelrc @@ -1,12 +1,18 @@ +############################################################################### +## Bazel Configuration Flags +## +## `.bazelrc` is a Bazel configuration file. +## https://bazel.build/docs/best-practices#bazelrc-file +############################################################################### + test --test_output=errors +test --verbose_failures # Fix the excessive rebuilding when using anything that depends on protobuf rules # See https://github.com/bazelbuild/buildtools/issues/744 common --incompatible_strict_action_env common --enable_bzlmod -try-import user.bazelrc - # To update these lines, execute # `bazel run @rules_bazel_integration_test//tools:update_deleted_packages` build --deleted_packages=examples/check_glob,examples/optional_attributes @@ -15,3 +21,26 @@ query --deleted_packages=examples/check_glob,examples/optional_attributes # Enable the aspect build --aspects=//shellcheck:shellcheck_aspect.bzl%shellcheck_aspect build --output_groups=+shellcheck_checks + +############################################################################### +## Incompatibility flags +############################################################################### + +# https://github.com/bazelbuild/bazel/issues/8195 +build --incompatible_disallow_empty_glob=true + +# https://github.com/bazelbuild/bazel/issues/12821 +build --nolegacy_external_runfiles + +# https://github.com/bazelbuild/bazel/issues/23043. +build --incompatible_autoload_externally= + +############################################################################### +## Custom user flags +## +## This should always be the last thing in the `.bazelrc` file to ensure +## consistent behavior when setting flags in that file as `.bazelrc` files are +## evaluated top to bottom. +############################################################################### + +try-import user.bazelrc diff --git a/.bcr/presubmit.yml b/.bcr/presubmit.yml index 04562e0..179e1ef 100644 --- a/.bcr/presubmit.yml +++ b/.bcr/presubmit.yml @@ -2,7 +2,12 @@ bcr_test_module: module_path: "examples/check_glob" matrix: - platform: ["debian10", "macos", "ubuntu2004"] + platform: + - "debian10" + - "macos" + - "macos_arm64" + - "ubuntu2004" + - "ubuntu2004_arm64" bazel: [7.*, 8.*, 9.*] tasks: run_tests: diff --git a/.gitattributes b/.gitattributes new file mode 100644 index 0000000..4ebdb96 --- /dev/null +++ b/.gitattributes @@ -0,0 +1,2 @@ +*.sh text eol=lf +.shellcheckrc text eol=lf diff --git a/.github/workflows/workflow.yml b/.github/workflows/workflow.yml index 70b4030..2944da6 100644 --- a/.github/workflows/workflow.yml +++ b/.github/workflows/workflow.yml @@ -19,17 +19,17 @@ jobs: include: - os: macos-latest - os: ubuntu-latest + - os: ubuntu-24.04-arm + - os: windows-latest steps: - uses: actions/checkout@v6 - - name: Test fetch - run: bazel fetch //... - - name: Test run: bazel test //... - name: Create release archive and notes + if: startswith(runner.os, 'Windows') != true # Set by GH actions, see # https://docs.github.com/en/actions/learn-github-actions/environment-variables#default-environment-variables run: ./ci/package.sh "${{ github.ref_name }}" diff --git a/shellcheck/internal/aspect_runner.bat b/shellcheck/internal/aspect_runner.bat index fbc3752..b9c96d5 100755 --- a/shellcheck/internal/aspect_runner.bat +++ b/shellcheck/internal/aspect_runner.bat @@ -1,6 +1,5 @@ -#!/bin/sh +@ECHO OFF -set -eu - -echo "" > "${SHELLCHECK_ASPECT_OUTPUT}" -exec $@ +echo "" > "%SHELLCHECK_ASPECT_OUTPUT%" +call %* +exit /b %ERRORLEVEL% diff --git a/shellcheck/internal/aspect_runner.sh b/shellcheck/internal/aspect_runner.sh index fbc3752..cfa6466 100755 --- a/shellcheck/internal/aspect_runner.sh +++ b/shellcheck/internal/aspect_runner.sh @@ -3,4 +3,4 @@ set -eu echo "" > "${SHELLCHECK_ASPECT_OUTPUT}" -exec $@ +exec "$@" diff --git a/shellcheck/internal/rules.bzl b/shellcheck/internal/rules.bzl index 99ad658..98e012c 100644 --- a/shellcheck/internal/rules.bzl +++ b/shellcheck/internal/rules.bzl @@ -9,15 +9,21 @@ _SHELL_CONTENT = """\ set -eu -{shellcheck} {args} +"{shellcheck}" {args}{post} """ _BATCH_CONTENT = """\ @ECHO OFF -{shellcheck} {args} +"{shellcheck}" {args}{post} """ +def _quote_for_shell(value): + return "\"{}\"".format(value.replace("\"", "\\\"")) + +def _quote_for_batch(value): + return "\"{}\"".format(value.replace("\"", "\"\"")) + def shellcheck_test_impl(ctx, expect_fail = False): """The implementation of the `shellcheck_test` rule. @@ -48,21 +54,27 @@ def shellcheck_test_impl(ctx, expect_fail = False): shellcheck_rc = toolchain.shellcheckrc.short_path srcs = [f.short_path for f in ctx.files.data] if is_windows: - shellcheck_path.replace("/", "\\") - shellcheck_rc.replace("/", "\\") + shellcheck_path = shellcheck_path.replace("/", "\\") + shellcheck_rc = shellcheck_rc.replace("/", "\\") srcs = [src.replace("/", "\\") for src in srcs] - cmd.append("--rcfile={}".format(shellcheck_rc)) - cmd.extend(srcs) + if is_windows: + cmd.append("--rcfile={}".format(_quote_for_batch(shellcheck_rc))) + cmd.extend([_quote_for_batch(src) for src in srcs]) + else: + cmd.append("--rcfile={}".format(_quote_for_shell(shellcheck_rc))) + cmd.extend([_quote_for_shell(src) for src in srcs]) + post = "" if expect_fail: - cmd.append("|| exit 0; exit 1") + post = " && exit /b 1 || exit /b 0" if is_windows else " || exit 0\nexit 1" ctx.actions.write( output = executable, content = (_BATCH_CONTENT if is_windows else _SHELL_CONTENT).format( shellcheck = shellcheck_path, args = " ".join(cmd), + post = post, ), is_executable = True, ) @@ -148,6 +160,12 @@ _shellcheck_srcs_aspect = aspect( implementation = _shellcheck_srcs_aspect_impl, ) +def _unix_path_arg(value): + return value.path + +def _windows_path_arg(value): + return value.path.replace("/", "\\") + def _shellcheck_aspect_impl(target, ctx): if target.label.workspace_root.startswith("external"): return [] @@ -177,6 +195,9 @@ def _shellcheck_aspect_impl(target, ctx): return [] toolchain = ctx.toolchains[TOOLCHAIN_TYPE] + is_windows = ctx.target_platform_has_constraint( + ctx.attr._windows_constraint[platform_common.ConstraintValueInfo], + ) inputs_direct = [toolchain.shellcheckrc] + getattr(ctx.rule.files, "data", []) inputs_transitive = [src_info.srcs, src_info.transitive_srcs] @@ -188,15 +209,21 @@ def _shellcheck_aspect_impl(target, ctx): ]) format = ctx.attr._format[BuildSettingInfo].value - severity = ctx.attr._format[BuildSettingInfo].value + severity = ctx.attr._severity[BuildSettingInfo].value output = ctx.actions.declare_file("{}.shellcheck.ok".format(target.label.name)) tools = depset([toolchain.shellcheck], transitive = [toolchain.all_files]) + shellcheck_path = toolchain.shellcheck.path + shellcheck_rc_path = toolchain.shellcheckrc.path + if is_windows: + shellcheck_path = shellcheck_path.replace("/", "\\") + shellcheck_rc_path = shellcheck_rc_path.replace("/", "\\") + args = ctx.actions.args() - args.add(toolchain.shellcheck) - args.add(toolchain.shellcheckrc, format = "--rcfile=%s") + args.add(shellcheck_path) + args.add(shellcheck_rc_path, format = "--rcfile=%s") args.add_all(src_info.source_paths, format_each = "--source-path=%s") if format: @@ -205,7 +232,7 @@ def _shellcheck_aspect_impl(target, ctx): if severity: args.add(severity, format = "--severity=%s") - args.add_all(srcs) + args.add_all(srcs, map_each = _windows_path_arg if is_windows else _unix_path_arg) ctx.actions.run( mnemonic = "Shellcheck", @@ -240,6 +267,9 @@ shellcheck_aspect = aspect( "_severity": attr.label( default = Label("//shellcheck/settings:severity"), ), + "_windows_constraint": attr.label( + default = Label("@platforms//os:windows"), + ), }, toolchains = [TOOLCHAIN_TYPE], requires = [_shellcheck_srcs_aspect],