bazel: add tidy and check

Signed-off-by: Paul Meyer <49727155+katexochen@users.noreply.github.com>
This commit is contained in:
Paul Meyer 2023-03-13 18:33:31 +01:00
parent 9b3af5af76
commit 02c97fac03
12 changed files with 267 additions and 111 deletions

View File

@ -1,37 +0,0 @@
name: Bazel unit tests and linting
on:
workflow_dispatch:
push:
branches:
- main
- "release/**"
paths:
- "**.bzl"
- "**.bazel"
- ".github/workflows/test-bazel.yml"
pull_request:
paths:
- "**.bzl"
- "**.bazel"
- ".github/workflows/test-bazel.yml"
jobs:
bazel-test:
name: Bazel tests
runs-on: ubuntu-22.04
steps:
- name: Checkout
uses: actions/checkout@ac593985615ec2ede58e132d2e21d2b1cbd6127c # v3.3.0
with:
ref: ${{ !github.event.pull_request.head.repo.fork && github.head_ref || '' }}
- name: Run buildifier
shell: bash
run: |
bazelisk test //:buildifier-check
# TODO(malt3): Find workflows to run bazel unit tests
# - name: Run unit tests
# shell: bash
# run: bazelisk test --test_output=all ...

View File

@ -1,4 +1,4 @@
name: Go mod tidy check
name: tidy-and-check
on:
workflow_dispatch:
@ -19,8 +19,8 @@ on:
- ".github/workflows/test-tidy.yml"
jobs:
gotidycheck:
name: Go mod tidy check
tidycheck:
name: tidy and check
runs-on: ubuntu-22.04
steps:
- name: Checkout
@ -32,9 +32,11 @@ jobs:
- name: Run Bazel tidy
shell: bash
run: |
bazelisk run //bazel/ci:tidy
bazelisk run //:gazelle-check
run: bazelisk run //:tidy
- name: Run Bazel check
shell: bash
run: bazelisk run //:check
- name: Check if tidy made modifications
id: tidycheck

View File

@ -1,34 +1,20 @@
load("@bazel_gazelle//:def.bzl", "gazelle")
load("@bazeldnf//:def.bzl", "bazeldnf")
load("@com_github_bazelbuild_buildtools//buildifier:def.bzl", "buildifier", "buildifier_test")
# gazelle:map_kind go_test go_test //bazel/go:go_test.bzl
# gazelle:prefix github.com/edgelesssys/constellation/v2
gazelle(name = "gazelle")
gazelle(
name = "gazelle-check",
command = "fix",
mode = "diff",
)
exports_files([
"WORKSPACE.bazel",
])
bazeldnf(name = "bazeldnf")
buildifier_test(
name = "buildifier-check",
timeout = "short",
lint_mode = "warn",
lint_warnings = ["all"],
mode = "diff",
no_sandbox = True,
verbose = True,
workspace = "WORKSPACE.bazel",
alias(
name = "tidy",
actual = "//bazel/ci:tidy",
)
buildifier(
name = "buildifier-fix",
lint_mode = "fix",
lint_warnings = ["all"],
mode = "fix",
verbose = True,
alias(
name = "check",
actual = "//bazel/ci:check",
)
# gazelle:map_kind go_test go_test //bazel/go:go_test.bzl
# gazelle:prefix github.com/edgelesssys/constellation/v2

View File

@ -92,9 +92,7 @@ add_test(NAME integration-license COMMAND bash -c "go test -tags integration" WO
# format
#
add_custom_target(format
COMMAND bash -c "${BAZEL} run //:buildifier-fix"
COMMAND bash -c "${BAZEL} run //:gazelle"
COMMAND bash -c "${BAZEL} run //bazel/ci:tidy"
COMMAND bash -c "${BAZEL} run //:tidy"
COMMAND bash -c "shfmt -i 2 -s -w -sr $(shfmt -f ${CMAKE_SOURCE_DIR} | grep -v helm/charts/cilium)"
COMMAND bash -c "gofumpt -l -w ${CMAKE_SOURCE_DIR}"
VERBATIM

View File

@ -11,7 +11,7 @@ load("@bazel_gazelle//:deps.bzl", "gazelle_dependencies")
load("@io_bazel_rules_go//go:deps.bzl", "go_register_toolchains", "go_rules_dependencies")
load("//bazel/toolchains:go_module_deps.bzl", "go_dependencies")
# gazelle:repository_macro toolchains/go_module_deps.bzl%go_dependencies
# gazelle:repository_macro bazel/toolchains/go_module_deps.bzl%go_dependencies
go_dependencies()
go_rules_dependencies()
@ -135,3 +135,9 @@ oci_register_toolchains(
crane_version = LATEST_CRANE_VERSION,
zot_version = LATEST_ZOT_VERSION,
)
# Multirun
load("//bazel/toolchains:multirun_deps.bzl", "multirun_deps")
multirun_deps()

View File

@ -1,12 +1,86 @@
sh_binary(
name = "tidy",
srcs = ["tidy.sh"],
load("@bazel_gazelle//:def.bzl", "gazelle")
load("@com_github_ash2k_bazel_tools//multirun:def.bzl", "multirun")
load("@com_github_bazelbuild_buildtools//buildifier:def.bzl", "buildifier", "buildifier_test")
load(":def.bzl", "sh_template")
gazelle(name = "gazelle_generate")
gazelle(
name = "gazelle_check",
command = "fix",
mode = "diff",
)
gazelle(
name = "gazelle_update_repos",
args = [
"-from_file=go.work",
"-to_macro=bazel/toolchains/go_module_deps.bzl%go_dependencies",
"-build_file_proto_mode=disable_global",
"-build_file_generation=on",
"-prune",
],
command = "update-repos",
)
buildifier_test(
name = "buildifier_check",
timeout = "short",
lint_mode = "warn",
lint_warnings = ["all"],
mode = "diff",
no_sandbox = True,
verbose = True,
workspace = "//:WORKSPACE.bazel",
)
buildifier(
name = "buildifier_fix",
lint_mode = "fix",
lint_warnings = ["all"],
mode = "fix",
verbose = True,
)
sh_library(
name = "base_lib",
srcs = [
"lib.bash",
],
)
sh_template(
name = "go_mod_tidy",
data = [
"@bazel_gazelle//cmd/gazelle",
":base_lib",
"@go_sdk//:bin/go",
],
env = {
"GAZELLE": "$(location @bazel_gazelle//cmd/gazelle)",
"GO": "$(location @go_sdk//:bin/go)",
substitutions = {
"@@BASE_LIB@@": "$(location :base_lib)",
"@@GO@@": "$(location @go_sdk//:bin/go)",
},
template = "tidy.sh.in",
)
multirun(
name = "tidy",
commands = [
# execute sequentially
":go_mod_tidy",
":gazelle_update_repos",
":gazelle_generate",
":buildifier_fix",
],
visibility = ["//visibility:public"],
)
multirun(
name = "check",
testonly = True,
commands = [
":gazelle_check",
":buildifier_check",
],
jobs = 0,
visibility = ["//visibility:public"],
)

65
bazel/ci/def.bzl Normal file
View File

@ -0,0 +1,65 @@
"""Bazel rules for CI and dev tooling"""
load("@bazel_skylib//lib:shell.bzl", "shell")
def _sh_template_impl(ctx):
out_file = ctx.actions.declare_file(ctx.label.name + ".bash")
substitutions = {}
for k, v in ctx.attr.substitutions.items():
sub = ctx.expand_location(v, ctx.attr.data)
sub = shell.quote(sub)
substitutions[k] = sub
ctx.actions.expand_template(
template = ctx.file.template,
output = out_file,
substitutions = substitutions,
is_executable = True,
)
return [DefaultInfo(
files = depset([out_file]),
executable = out_file,
)]
_sh_template = rule(
implementation = _sh_template_impl,
attrs = {
"data": attr.label_list(
allow_files = True,
),
"substitutions": attr.string_dict(),
"template": attr.label(
allow_single_file = True,
),
},
)
def sh_template(name, **kwargs):
"""Build a sh_binary from a template
Args:
name: name
**kwargs: **kwargs
"""
script_name = name + "-script"
tags = kwargs.get("tags", [])
data = kwargs.get("data", [])
substitutions = kwargs.pop("substitutions", [])
template = kwargs.pop("template", [])
_sh_template(
name = script_name,
tags = tags,
data = data,
substitutions = substitutions,
template = template,
)
native.sh_binary(
name = name,
srcs = [script_name],
**kwargs
)

62
bazel/ci/lib.bash Executable file
View File

@ -0,0 +1,62 @@
#!/usr/bin/env bash
set -euo pipefail
set -o errtrace
shopt -s inherit_errexit
function printErr {
echo -e "\033[0;31mERROR:\033[0m ${1}"
}
function _exitHandler {
local exit_code=$1
if [[ ${exit_code} -ne 0 ]]; then
printErr "$0: exit status ${exit_code}"
fi
}
function _errorHandler {
local line=$1
local linecallfunc=$2
local command="$3"
local funcstack="$4"
printErr "$0: '${command}' failed at line ${line}"
if [[ ${funcstack} != "::" ]]; then
echo -ne "\tin ${funcstack} "
if [[ ${linecallfunc} != "" ]]; then
echo "called at line ${linecallfunc}"
else
echo
fi
fi
}
_exitHandlers=()
_errorHandlers=()
function registerExitHandler {
_exitHandlers+=("$1")
}
function registerErrorHandler {
_errorHandler+=("$1")
}
function _callExitHandlers {
_exitHandlers+=(_exitHandler) # Add our handler last.
for h in "${_exitHandlers[@]}"; do
${h} "$@"
done
}
function _callErrorHandlers {
_errorHandlers+=(_errorHandler) # Add our handler last.
for h in "${_errorHandlers[@]}"; do
${h} "$@"
done
}
trap '_callErrorHandlers $LINENO $BASH_LINENO "$BASH_COMMAND" $(printf "::%s" ${FUNCNAME[@]:-})' ERR
trap '_callExitHandlers $?' EXIT

View File

@ -1,23 +0,0 @@
#!/usr/bin/env bash
set -euo pipefail
shopt -s inherit_errexit
# shellcheck disable=SC2153
gazelle=$(realpath "${GAZELLE}")
go=$(realpath "${GO}")
cd "${BUILD_WORKSPACE_DIRECTORY}"
submodules=$(${go} list -f '{{.Dir}}' -m)
for mod in ${submodules}; do
${go} mod tidy -C "${mod}"
done
${gazelle} update-repos \
-from_file=go.work \
-to_macro=toolchains/go_module_deps.bzl%go_dependencies \
-build_file_proto_mode=disable_global \
-build_file_generation=on \
-prune

18
bazel/ci/tidy.sh.in Executable file
View File

@ -0,0 +1,18 @@
#!/usr/bin/env bash
lib=$(realpath @@BASE_LIB@@)
go=$(realpath @@GO@@)
# shellcheck source=lib.bash
if ! source "${lib}"; then
echo "Error: could not find import"
exit 1
fi
cd "${BUILD_WORKSPACE_DIRECTORY}" || exit 1
submodules=$(${go} list -f '{{.Dir}}' -m)
for mod in ${submodules}; do
${go} mod tidy -C "${mod}"
done

View File

@ -0,0 +1,10 @@
"""multirun_deps"""
load("@bazel_tools//tools/build_defs/repo:git.bzl", "git_repository")
def multirun_deps():
git_repository(
name = "com_github_ash2k_bazel_tools",
commit = "4e045b9b4e3e613970ab68941b556a356239d433",
remote = "https://github.com/ash2k/bazel-tools.git",
)

View File

@ -96,9 +96,7 @@ After updating a dependency, you will have to run `bazel run //:gazelle-update-r
Bazel is the primary build system for this project. It is used to build all Go code and will be used to build all artifacts in the future.
Still, we aim to keep the codebase compatible with `go build` and `go test` as well.
Whenever Go code is changed, you will have to run `bazel run //:gazelle` to regenerate the Bazel build files for Go code.
The CI will check if the Bazel build files are up to date with `bazel run //:gazelle-check`.
Optionally, you can use [autogazelle](https://github.com/bazelbuild/bazel-gazelle/tree/master/cmd/autogazelle) to regenerate the Bazel build files automatically on save. This is not tested and might not work properly.
Whenever Go code is changed, you will have to run `bazel run //:tidy` to regenerate the Bazel build files for Go code.
## Bazel commands
@ -111,11 +109,8 @@ Optionally, you can use [autogazelle](https://github.com/bazelbuild/bazel-gazell
* `bazel run --run_under="cd $PWD &&" //cli:cli_oss -- create -c 1 -w 1` - build + run a target with arguments in current working directory
* `bazel cquery --output=files //subfolder:target` - get location of a build artifact
* `bazel test //...` - run all tests
* `bazel run //:gazelle` - regenerate Bazel build files for Go code
* `bazel run //:gazelle-check` - check if Bazel build files for Go code are up to date
* `bazel run //:gazelle-update-repos` - update Bazel workspace with changes from `go.mod` and `go.sum` files
* `bazel run //:buildifier-fix` - format Bazel build files
* `bazel test //:buildifier-check` - lint Bazel build files
* `bazel run //:tidy` - tidy, format and generate
* `bazel run //:check` - execute checks and linters
## Editor integration