Skip to content

Bazel tooling used by all Airy Bazel workspaces.

License

Notifications You must be signed in to change notification settings

airyhq/bazel-tools

Repository files navigation

Airy Bazel-tools

Bazel tooling used by all Airy Bazel workspaces.

Installation

To install, add this snippet to your WORKSPACE:

load("@bazel_tools//tools/build_defs/repo:git.bzl", "git_repository")
git_repository(
    name = "com_github_airyhq_bazel_tools",
    branch = "main",
    remote = "https://github.com/airyhq/bazel-tools.git"
)

load("@com_github_airyhq_bazel_tools//:repositories.bzl", "airy_bazel_tools_dependencies", "airy_jvm_deps")
airy_bazel_tools_dependencies()

# Required for Java Checkstyle
load("@rules_jvm_external//:defs.bzl", "maven_install")

maven_install(
    artifacts = YOUR_JVM_ARTIFACTS_LIST + airy_jvm_deps,
    # ...
)

Code formatting

We use language specific linters:

Prettier

Prerequisite: prettier is installed using rules_nodejs

Checking a set of Type- or Javascript source files:

load("@com_github_airyhq_bazel_tools//lint:prettier.bzl", "prettier")

prettier(
    name = "prettier",
    config = "//:.prettierrc.json",
    srcs = ["index.js"], # Defaults to all js,jsx,ts,tsx,scss,css files
    ignore = "//:.prettierignore", # Defaults to lint/.prettierignore
)

Both rules will add a :prettier test target to your package, which can be run like so:

bazel test //my/package:prettier

To try fixing prettier issues you instantiate the prettier_fix rule in your root BUILD file:

load("@com_github_airyhq_bazel_tools//lint:prettier.bzl", "fix_prettier")

fix_prettier(
    name = "fix_prettier",
    config = "//:.prettierrc.json", # Defaults to lint/.prettierrc.json
    ignore = "//:.prettierignore", # Defaults to lint/.prettierignore
)

Run it like so:

bazel run //:fix_prettier

Eslint

Checking a set of Type- or Javascript source files:

load("@com_github_airyhq_bazel_tools//lint:eslint.bzl", "eslint")

eslint(
    name = "eslint",
    config = "//:.eslint.json",
    srcs = ["index.ts"], # Defaults to all js,jsx,ts,tsx,scss,css files in package
    ignore = "//:.eslintignore", # Defaults to lint/.eslintignore
)

This rule will add an :eslint test target to your package, which can be run like so:

bazel test //my/package:eslint

Checkstyle

Checking a set of Java source files:

load("@com_github_airyhq_bazel_tools//lint:checkstyle.bzl", "checkstyle")

checkstyle(
    name = "checkstyle",
    srcs = ["src/main/java/airy/core/Main.java"], #  Defaults to all .java files in package
    config = "//:checkstyle.xml" # Defaults to lint/checkstyle.xml
)

Both rules will add a :checkstyle test target to your package, which can be run like so:

bazel test //my/package:checkstyle

Buildifier

Buildifier is used for linting Bazel BUILD and .bzl files.

Macro to check all starlark source files in a package:

load("@com_github_airyhq_bazel_tools//lint:buildifier.bzl", "check_pkg")

check_pkg()

To try fixing buildifier lint issues you can run:

bazel run @com_github_airyhq_bazel_tools//lint:fix_buildifier

These two rules are a very shallow wrapper of buildifier, but we package them for convenience. If you are looking to use its extensive API you can replace this implementation with your own.

Shellcheck

Shellcheck gives warnings and suggestions for bash/sh shell scripts.

Macro to check all scripts including subdirectories ending with .sh:

load("@com_github_airyhq_bazel_tools//lint:shellcheck.bzl", "shellcheck")

shellcheck()

Alternatively you can pass a glob of shellscript files with the scripts parameter.

Web builds

For web builds we use the rules_nodejs repository. You have to install the development dependencies listed in the package.json to use the web rules.

ts_web_library

This is a thin wrapper around the ts_project provided by rules_nodejs. It also aggregates asset dependencies so that they are available to downstream bundling.

load("@com_github_airyhq_bazel_tools//web:typescript.bzl", "ts_web_library")

ts_web_library(
    name = "mylib",
    srcs = ["index.ts"],
    deps = [
        "//my/web/library:ts_lib",
        "@npm//react",
        "@npm//@types/react",
    ],
    data = ["assets/logo.svg"]
)

Parameters:

  • name Unique name of the rule. This will also be used as the js module name so that you can import it like so import {someFunction} from 'mylib'.
  • srcs (optional) Your components source files. By default we glob all .ts and .tsx files.
  • deps (optional) Node module dependencies required to compile the library.
  • data (optional) Files needed as imports to your typescript files. By default we glob typical web file extensions.
  • tsconfig (optional) It's possible to extend tsconfigs (https://www.npmjs.com/package/@bazel/typescript#ts_config)
  • lint_rule (optional) by default this is set to check_pkg(). Setting this flag to None, will disable linting for this package.

web_app

Bundles your web resources using webpack and adds a target *_server that you can use for running a webpack server with hot code reloading.

bazel run //my/web/package:bundle_server
load("@com_github_airyhq_bazel_tools//web:web_app.bzl", "web_app")

web_app(
    name = "bundle",
    app_lib = ":app",
    static_assets = "//my/web/package/public",
    entry = "my/web/package/src/index.js",
    index = ":index.html",
    dev_index = ":dev_index.html",
    dev_tsconfig = "//:tsconfig.json",
    output = {
        "publicPath": "/blog/"
    },
    module_deps = module_deps,
    webpack_prod_config = ":webpack.prod.config.js",
    webpack_dev_config = ":webpack.dev.config.js",
)

Parameters:

  • name Unique name of the build rule. The dev server rule will be called name_server
  • static_assets (optional) Filegroup (list of files) that should be copied "as is" to the webroot. Files need to be in a folder called 'public'.
  • entry Relative path to your compiled index.js
  • index index.html file used for the build
  • dev_tsconfig (optional) Defaults to tsconfig.json, which has to include a mapping of modules to paths using compilerOptions.paths.
  • output (optional) Dictionary that gets applied to the webpack output https://webpack.js.org/configuration/output/
  • aliases (optional) applied to webpack alias
  • show_bundle_report If set to true generates a static bundle size report
  • dev_index (optional) index.html file used for the devserver (defaults to index)
  • module_deps (optional) app_lib dependencies on ts_web_library targets

web_library

load("@com_github_airyhq_bazel_tools//web:web_library.bzl", "web_library")

web_library(
    name = "bundle",
    app_lib = ":app",
entry = "my/web/package/src/index.js",
    module_deps = ["//package/lib:ts_web_lib_target"],
    output = {
        "publicPath": "/blog/"
    }
)

Parameters:

Java

avro_java_library

This rule takes Avro schema definition files .avsc and compiles them to a Jar using the Avro tools

load("@com_github_airyhq_bazel_tools//java:avro.bzl", "avro_java_library")

avro_java_library(
    name = "user", 
    srcs = ["user.avsc"]
)

# Example Usage
java_library(
    name = "mylib",
    deps = [":user"],
)

Parameters:

  • name Unique name of the generated java library.
  • srcs Avro definition files to compile. If you leave this empty it will default to ["{name}.avsc"].

junit5

This is an opinionated wrapper around the Bazel built-in java_test. It requires that the test path starts with src/java/test and that the test package name is the same as the file path. I.e. a test file in package com.package needs to be located in src/test/java/com/package/.

load("@com_github_airyhq_bazel_tools//java:junit5.bzl", "junit5")

junit5(
    file = "src/java/test/com/package/Test.java", 
    size = "small",
)

Parameters:

  • file Relative file path of the test file

For more options see the Bazel java_test rule

Helm

Currently the helm rule set supports: downloading the helm binary as a repository rule, helm template in a form of test rule and helm push to a Chartmuseum helm repository.

For downloading the helm binary, add this to your WORKSPACES file:

load("@com_github_airyhq_bazel_tools//helm:helm.bzl", "helm_tool")

helm_tool(
    name = "helm_binary",
)

The chart needs to be packaged before it can be processed by Bazel. To do that, add this to your BUILD file in the directory where the Chart.yaml file resides:

load("@rules_pkg//:pkg.bzl", "pkg_tar")

filegroup(
    name = "files",
    srcs = glob([
        "**/*.yaml",
        "**/*.tpl",
    ]),
)

pkg_tar(
    name = "package",
    srcs = [":files"],
    extension = "tgz",
    strip_prefix = "./",
)

For running a test with helm template, add this to your BUILD file, in the same directory:

load("@com_github_airyhq_bazel_tools//helm:helm.bzl", "helm_template_test")

helm_template_test(
    name = "template",
    chart = ":package",
)

Then run:

bazel test //.../helm-chart:template

Parameters:

  • name Unique name of the rule.
  • _helm_binary Location of the Helm binary to be used (Defaults to the binary downloaded with the repository rule).
  • chart A tgz archive containing the Helm chart.

For pushing to a Chartmuseum helm repository, add this to your BUILD file, in the same directory:

load("@com_github_airyhq_bazel_tools//helm:helm.bzl", "helm_push")
helm_push(
    name = "push_testing",
    repository_url = "https://testing.helm.airy.co",
    repository_name = "airy",
    auth = "none",
    chart = chart,
)
helm_push(
    name = "push",
    repository_url = "https://helm.airy.co",
    repository_name = "airy",
    auth = "basic",
    chart = chart,
)

Then run:

bazel run //.../helm-chart:push

Parameters:

  • name Unique name of the rule.
  • _helm_binary Location of the Helm binary to be used (Defaults to the binary downloaded with the repository rule).
  • chart A tgz archive containing the Helm chart.
  • repository_url The URL of the repository where the Helm chart is pushed.
  • repository_name The name of the temporary repoository added by Bazel.
  • auth Authentication type for the Helm repository (currently only none and basic are supported).
  • _push_script_template A script that is used and templated for running helm push.
  • version A string containing the version of the Helm chart.
  • version_file An alternative to providing the version, a file can be used containing the version as a first line.

Note that only basic auth is supported at the moment. If you are using it, you must export HELM_REPO_USERNAME and HELM_REPO_PASSWORD with the username and the password of your Chartmuseum helm repository.

Minikube

Currently the Minikube rule set supports starting (creating) and stopping (destroying) a Minikube Kubernetes cluster.

For downloading the Minikube binary, add this to your WORKSPACE file:

load("@com_github_airyhq_bazel_tools//minikube:minikube.bzl", "minikube_tool")

minikube_tool(
    name = "minikube_binary",
)

For creating a Kubernetes cluster add this to your BUILD file:

load("@com_github_airyhq_bazel_tools//minikube:minikube.bzl", "minikube_start")

minikube_start(
    name = "minikube-start",
)

Then run:

bazel run //.../infrastructure:minikube-start

Parameters:

  • name Unique name of the rule.
  • _minikube_binary (optional) Location of the Minikube binary to be used (Defaults to the binary downloaded with the repository rule).
  • profile (optional) The Minikube profile [default: airy-core].
  • driver (optional) The Minikube driver [default: docker].
  • cpus (optional) The number of CPU cores for the Kubernetes node [default: 4].
  • memory (optional) The amount of memory of the Kubernetes node [default: 7168].
  • ingress_port (optional) The NodePort to be opened for the Ingress Controller [default: 80].

For destroying a Kubernetes cluster add this to your BUILD file:

load("@com_github_airyhq_bazel_tools//minikube:minikube.bzl", "minikube_stop")

minikube_stop(
    name = "minikube-stop",
)

Then run:

bazel run //.../infrastructure:minikube-stop

Parameters:

  • name Unique name of the rule.
  • _minikube_binary (optional) Location of the Minikube binary to be used (Defaults to the binary downloaded with the repository rule).
  • profile (optional) The Minikube profile [default: airy-core].

Aspects

We provide a simple aspect that helps discover the output groups of a target. It can be used like so:

bazel build --nobuild //path/to:target  --aspects=@com_github_airyhq_bazel_tools//aspects:outputs.bzl%output_group_query_aspect

How to contribute

We welcome (and love) every form of contribution! Good entry points to the project are:

If you're still not sure where to start, open a new issue and we'll gladly help you get started.

Code of Conduct

To ensure a safe experience and a welcoming community, the project adheres to the contributor convenant code of conduct.

Airy Open Source

At Airy we ❤️ Open Source. Check out our other projects over at docs.airy.co.