diff --git a/.bazelignore b/.bazelignore index 1e107f52..5eaaac1d 100644 --- a/.bazelignore +++ b/.bazelignore @@ -1 +1,2 @@ -examples +examples/ +.git/ diff --git a/.bazelrc b/.bazelrc index 0d5d6565..6e777ef2 100644 --- a/.bazelrc +++ b/.bazelrc @@ -1,4 +1,51 @@ -build --nolegacy_external_runfiles -build --verbose_failures -test --test_output=errors +######################## +# Import bazelrc presets +import %workspace%/tools/preset.bazelrc +# Don’t want to push a rules author to update their deps if not needed. +# https://bazel.build/reference/command-line-reference#flag--check_direct_dependencies +# https://bazelbuild.slack.com/archives/C014RARENH0/p1691158021917459?thread_ts=1691156601.420349&cid=C014RARENH0 +common --config=ruleset + +# Bazel settings that apply to this repository. +# Take care to document any settings that you expect users to apply. +# Settings that apply only to CI are in .github/workflows/ci.bazelrc + +# Required until this is the default; expected in Bazel 7 +common --enable_bzlmod + +# C++17 is required by protobuf and abseil-cpp +build --cxxopt=-std=c++17 +build --host_cxxopt=-std=c++17 + +# Ensure that the MODULE.bazel.lock file is complete and committed. +# This is an important security measure: it ensures that developers on the +# same rule set download dependencies at the same versions with the same bits. +# This setting does not affect modules that depend on this module. +# +# When updating dependencies, use --lockfile_mode=refresh, for example: +# bazel mod tidy --lockfile_mode=refresh +# +# When testing different versions of Bazel, use --lockfile_mode=update or +# --lockfile_mode=off. The lock file format changes over time, and different +# versions of Bazel may expect different syntax. Bazel also implicitly requires +# some modules, and different versions have different dependencies, which +# also affects the contents of the lock file. +common --lockfile_mode=off + +# This directory is configured in GitHub actions to be persisted between runs. +# We do not enable the repository cache to cache downloaded external artifacts +# as these are generally faster to download again than to fetch them from the +# GitHub actions cache. +common:ci --disk_cache=~/.cache/bazel + +common --@protobuf//bazel/toolchains:prefer_prebuilt_protoc + +# Load any settings specific to the current user. +# .bazelrc.user should appear in .gitignore so that settings are not shared with team members +# This needs to be last statement in this +# config, as the user configuration should be able to overwrite flags from this file. +# See https://docs.bazel.build/versions/master/best-practices.html#bazelrc +# (Note that we use .bazelrc.user so the file appears next to .bazelrc in directory listing, +# rather than user.bazelrc as suggested in the Bazel docs) +try-import %workspace%/.bazelrc.user \ No newline at end of file diff --git a/.bazelversion b/.bazelversion index f22d756d..93c8ddab 100644 --- a/.bazelversion +++ b/.bazelversion @@ -1 +1 @@ -6.5.0 +7.6.0 diff --git a/.bcr/metadata.template.json b/.bcr/metadata.template.json new file mode 100644 index 00000000..8a7ddb56 --- /dev/null +++ b/.bcr/metadata.template.json @@ -0,0 +1,20 @@ +{ + "homepage": "https://github.com/adobe/rules_gitops", + "maintainers": [ + { + "name": "Nick Schaap", + "email": "schaap@adobe.com", + "github": "nickschaap", + "github_user_id": 4684894 + }, + { + "name": "Konstantin Zadorozhny", + "email": "zadorozh@adobe.com", + "github": "kzadorozhny", + "github_user_id": 1616702 + } + ], + "repository": ["github:adobe/rules_gitops"], + "versions": [], + "yanked_versions": {} +} \ No newline at end of file diff --git a/.bcr/presubmit.yml b/.bcr/presubmit.yml new file mode 100644 index 00000000..eedb1e3c --- /dev/null +++ b/.bcr/presubmit.yml @@ -0,0 +1,12 @@ +bcr_test_module: + module_path: '.' + matrix: + bazel: ['7.x', '8.x', '9.x'] + platform: ['debian10', 'macos', 'ubuntu2004'] + tasks: + run_tests: + name: 'Run test module' + bazel: ${{ bazel }} + platform: ${{ platform }} + test_targets: + - '//...' \ No newline at end of file diff --git a/.bcr/source.template.json b/.bcr/source.template.json new file mode 100644 index 00000000..afe0f67a --- /dev/null +++ b/.bcr/source.template.json @@ -0,0 +1,6 @@ +{ + "integrity": "**leave this alone**", + "strip_prefix": "{REPO}-{VERSION}", + "docs_url": "https://github.com/{OWNER}/{REPO}/releases/download/{TAG}/{REPO}-{TAG}.docs.tar.gz", + "url": "https://github.com/{OWNER}/{REPO}/releases/download/{TAG}/{REPO}-{TAG}.tar.gz" +} \ No newline at end of file diff --git a/.fasterci/config.yaml b/.fasterci/config.yaml deleted file mode 100644 index bbf4ddbe..00000000 --- a/.fasterci/config.yaml +++ /dev/null @@ -1,40 +0,0 @@ -# configure vscode yaml support https://marketplace.visualstudio.com/items?itemName=redhat.vscode-yaml -# yaml-language-server: $schema=https://fasterci.com/config.schema.json -workflows: - - - &build_workflow - name: Faster CI / build (6.5.0) - env: - USE_BAZEL_VERSION: "6.5.0" - image: us.gcr.io/fasterci/bazelbuilder:5e59f651dbb5 - on: - push: - branches: - - main - pull_request: - branches: - - "**" - from-branches-ignore: - # will ignore PRs from renovate bot, since the bot is not a repository collaborator - - "renovate/**" - steps: - - name: Build & test - bazel: - build_targets: - - //... - test_targets: - - //... - - name: Build & test examples - working-directory: examples - bazel: - build_targets: - - //... - test_targets: - - //... - - name: Check - run: bazel run //:buildifier-check - - - <<: *build_workflow - name: Faster CI / build (5.4.1) - env: - USE_BAZEL_VERSION: "5.4.1" diff --git a/.gitattributes b/.gitattributes new file mode 100644 index 00000000..b38e6a24 --- /dev/null +++ b/.gitattributes @@ -0,0 +1,8 @@ +################################# +# Configuration for 'git archive' +# See https://git-scm.com/docs/git-archive#ATTRIBUTES + +# Don't include examples in the distribution artifact, to reduce size. +# You may want to add additional exclusions for folders or files that users don't need. +examples export-ignore +tests export-ignore \ No newline at end of file diff --git a/.github/ISSUE_TEMPLATE.md b/.github/ISSUE_TEMPLATE.md index 25798e24..cd0ac456 100644 --- a/.github/ISSUE_TEMPLATE.md +++ b/.github/ISSUE_TEMPLATE.md @@ -25,19 +25,6 @@ > Replace this line with your answer. -### Snippet of the `WORKSPACE` file that includes rules_gitops rules. - -> Replace this line with your answer. - -### Have you found anything relevant by searching the web? - -> Replace these lines with your answer. -> -> Places to look: -> - StackOverflow: http://stackoverflow.com/questions/tagged/bazel -> - GitHub issues: https://github.com/bazelbuild/bazel/issues -> - Slack: https://bazelbuild.slack.com - ### Any other information, logs, or outputs that you want to share? > Replace these lines with your answer. diff --git a/.github/workflows/ci.yaml b/.github/workflows/ci.yaml index 877d30d8..a8cba60e 100644 --- a/.github/workflows/ci.yaml +++ b/.github/workflows/ci.yaml @@ -14,8 +14,9 @@ jobs: strategy: matrix: bazel-version: - - 6.5.0 - - 5.4.1 + - 7.6.0 + - 8.5.0 + - 9.0.0 env: USE_BAZEL_VERSION: ${{ matrix.bazel-version }} steps: @@ -35,49 +36,16 @@ jobs: mkdir -p "${TOOLS_DIR}/bin/" curl -Ls -o "${TOOLS_DIR}/bin/bazel" "https://github.com/bazelbuild/bazelisk/releases/download/v1.14.0/bazelisk-linux-amd64" chmod +x "${TOOLS_DIR}/bin/bazel" - curl -Ls -o "${TOOLS_DIR}/bin/buildifier" "https://github.com/bazelbuild/buildtools/releases/download/0.29.0/buildifier" - chmod +x "${TOOLS_DIR}/bin/buildifier" - curl -Ls -o "${TOOLS_DIR}/bin/kind" "https://github.com/kubernetes-sigs/kind/releases/download/v0.29.0/kind-linux-amd64" - chmod +x "${TOOLS_DIR}/bin/kind" echo "${TOOLS_DIR}/bin" >> $GITHUB_PATH - - name: Setup kind cluster - run: | - ./create_kind_cluster.sh - - name: Build - run: | - bazel build //... - - name: Check - # run downloaded version of buildifier to reduce uncached build times - # see: bazel run //:buildifier-check - run: | - find . -type f \(\ - -name '*.bzl' \ - -o -name '*.sky' \ - -o -name BUILD \ - -o -name BUILD.bazel \ - -o -name WORKSPACE \ - -o -name WORKSPACE.bazel \ - \) | xargs buildifier \ - -mode=check \ - -lint=warn \ - --warnings=-module-docstring,-function-docstring,-function-docstring-header,-function-docstring-args,-function-docstring-return,-print \ - || { - buildifier_exit_code=$? - echo "Error: failed buildifier checks. Please run \"bazel run //:buildifier-fix\" and commit the changes." - exit $buildifier_exit_code - } - name: Test run: | - bazel test //... - - name: Build examples - run: | - cd examples - bazel build //... - - name: Test examples + bazel --output_base=~/.bazel/ test //... --config=ci + - name: Build helloworld run: | - cd examples - bazel test //... - - name: E2E + cd examples/helloworld + bazel --output_base=~/.bazel/ build //... + - name: Build legacy docker + if: matrix.bazel-version == '7.6.0' run: | - cd examples - ./e2e-test.sh + cd examples/legacy_docker + bazel --output_base=~/.bazel/ build //... diff --git a/.github/workflows/conventional-commits.yaml b/.github/workflows/conventional-commits.yaml new file mode 100644 index 00000000..e10b72a5 --- /dev/null +++ b/.github/workflows/conventional-commits.yaml @@ -0,0 +1,21 @@ +# This helps the tag.yaml action to automatically create new releases +# +# tag.yaml requires all commits to follow the conventional commit pattern so that it can +# automatically derive the next release version based on the commit history + +name: Verify PR title/description +on: + pull_request_target: + types: + - opened + - edited + - synchronize +permissions: + pull-requests: read +jobs: + check: + runs-on: ubuntu-latest + steps: + - uses: amannn/action-semantic-pull-request@v5 + env: + GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} \ No newline at end of file diff --git a/.github/workflows/publish.yaml b/.github/workflows/publish.yaml new file mode 100644 index 00000000..a5cfe20c --- /dev/null +++ b/.github/workflows/publish.yaml @@ -0,0 +1,35 @@ +# Publish new releases to Bazel Central Registry. +name: Publish to BCR +on: + # Run the publish workflow after a successful release + # Will be triggered from the release.yaml workflow + workflow_call: + inputs: + tag_name: + required: true + type: string + secrets: + publish_token: + required: true + # In case of problems, let release engineers retry by manually dispatching + # the workflow from the GitHub UI + workflow_dispatch: + inputs: + tag_name: + description: git tag being released + required: true + type: string +jobs: + publish: + uses: bazel-contrib/publish-to-bcr/.github/workflows/publish.yaml@v1.0.0 + with: + tag_name: ${{ inputs.tag_name }} + # GitHub repository which is a fork of the upstream where the Pull Request will be opened. + registry_fork: adobe/bazel-central-registry + permissions: + attestations: write + contents: write + id-token: write + secrets: + # Necessary to push to the BCR fork, and to open a pull request against a registry + publish_token: ${{ secrets.publish_token || secrets.BCR_PUBLISH_TOKEN }} \ No newline at end of file diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml index 4a632e12..3b2fa7ff 100644 --- a/.github/workflows/release.yml +++ b/.github/workflows/release.yml @@ -1,87 +1,34 @@ # Cut a release whenever a new tag is pushed to the repo. -# You should use an annotated tag, like `git tag -a v1.2.3` -# and put the release notes into the commit message for the tag. name: Release - on: + # Can be triggered from the tag.yaml workflow + workflow_call: + inputs: + tag_name: + required: true + type: string + secrets: + publish_token: + required: true + # Or, developers can manually push a tag from their clone push: tags: - "v*.*.*" - +permissions: + id-token: write + attestations: write + contents: write jobs: - build: - runs-on: ubuntu-24.04 - env: - USE_BAZEL_VERSION: 6.5.0 - steps: - - name: Checkout - uses: actions/checkout@v3 - - name: Mount Bazel cache - uses: actions/cache@v4 - with: - path: ~/.cache/bazel - key: bazel-${{ env.USE_BAZEL_VERSION }}-${{ github.sha }} - restore-keys: | - bazel-${{ env.USE_BAZEL_VERSION }}- - bazel- - - name: Setup build tools - run: | - TOOLS_DIR="${HOME}/.cache/tools" - mkdir -p "${TOOLS_DIR}/bin/" - curl -Ls -o "${TOOLS_DIR}/bin/bazel" "https://github.com/bazelbuild/bazelisk/releases/download/v1.14.0/bazelisk-linux-amd64" - chmod +x "${TOOLS_DIR}/bin/bazel" - curl -Ls -o "${TOOLS_DIR}/bin/buildifier" "https://github.com/bazelbuild/buildtools/releases/download/0.29.0/buildifier" - chmod +x "${TOOLS_DIR}/bin/buildifier" - curl -Ls -o "${TOOLS_DIR}/bin/kind" "https://github.com/kubernetes-sigs/kind/releases/download/v0.29.0/kind-linux-amd64" - chmod +x "${TOOLS_DIR}/bin/kind" - echo "${TOOLS_DIR}/bin" >> $GITHUB_PATH - - name: Setup kind cluster - run: | - ./create_kind_cluster.sh - - name: Build - run: | - bazel build //... - - name: Check - # run downloaded version of buildifier to reduce uncached build times - # see: bazel run //:buildifier-check - run: | - find . -type f \(\ - -name '*.bzl' \ - -o -name '*.sky' \ - -o -name BUILD \ - -o -name BUILD.bazel \ - -o -name WORKSPACE \ - -o -name WORKSPACE.bazel \ - \) | xargs buildifier \ - -mode=check \ - -lint=warn \ - --warnings=-module-docstring,-function-docstring,-function-docstring-header,-function-docstring-args,-function-docstring-return,-print \ - || { - buildifier_exit_code=$? - echo "Error: failed buildifier checks. Please run \"bazel run //:buildifier-fix\" and commit the changes." - exit $buildifier_exit_code - } - - name: Test - run: | - bazel test //... - - name: Build examples - run: | - cd examples - bazel build //... - - name: Test examples - run: | - cd examples - bazel test //... - - name: E2E - run: | - cd examples - ./e2e-test.sh - - name: Prepare workspace snippet - run: .github/workflows/workspace_snippet.sh ${{ env.GITHUB_REF_NAME }} > release_notes.txt - - name: Release - uses: softprops/action-gh-release@v1 - with: - prerelease: true - # Use GH feature to populate the changelog automatically - generate_release_notes: true - body_path: release_notes.txt + release: + uses: bazel-contrib/.github/.github/workflows/release_ruleset.yaml@v7.2.2 + with: + release_files: rules_gitops-*.tar.gz + prerelease: false + tag_name: ${{ inputs.tag_name || github.ref_name }} + publish: + needs: release + uses: ./.github/workflows/publish.yaml + with: + tag_name: ${{ inputs.tag_name || github.ref_name }} + secrets: + publish_token: ${{ secrets.publish_token || secrets.BCR_PUBLISH_TOKEN }} \ No newline at end of file diff --git a/.github/workflows/release_prep.sh b/.github/workflows/release_prep.sh new file mode 100755 index 00000000..da4c2181 --- /dev/null +++ b/.github/workflows/release_prep.sh @@ -0,0 +1,36 @@ +#!/usr/bin/env bash + +set -o errexit -o nounset -o pipefail + +# Argument provided by reusable workflow caller, see +# https://github.com/bazel-contrib/.github/blob/d197a6427c5435ac22e56e33340dff912bc9334e/.github/workflows/release_ruleset.yaml#L72 +TAG=$1 +# The prefix is chosen to match what GitHub generates for source archives +# This guarantees that users can easily switch from a released artifact to a source archive +# with minimal differences in their code (e.g. strip_prefix remains the same) +PREFIX="rules_gitops-${TAG:1}" +ARCHIVE="rules_gitops-$TAG.tar.gz" + +# NB: configuration for 'git archive' is in /.gitattributes +git archive --format=tar --prefix=${PREFIX}/ ${TAG} | gzip > $ARCHIVE +SHA=$(shasum -a 256 $ARCHIVE | awk '{print $1}') + +# Add generated API docs to the release, see https://github.com/bazelbuild/bazel-central-registry/issues/5593 +docs="$(mktemp -d)"; targets="$(mktemp)" +bazel --output_base="$docs" query --output=label --output_file="$targets" 'kind("starlark_doc_extract rule", //...)' +bazel --output_base="$docs" build --target_pattern_file="$targets" +tar --create --auto-compress \ + --directory "$(bazel --output_base="$docs" info bazel-bin)" \ + --file "$GITHUB_WORKSPACE/${ARCHIVE%.tar.gz}.docs.tar.gz" . + +cat << EOF +## Using Bzlmod with Bazel 6 or greater + +1. (Bazel 6 only) Enable with \`common --enable_bzlmod\` in \`.bazelrc\`. +2. Add to your \`MODULE.bazel\` file: + +\`\`\`starlark +bazel_dep(name = "rules_gitops", version = "${TAG:1}") +\`\`\` + +EOF diff --git a/.github/workflows/workspace_snippet.sh b/.github/workflows/workspace_snippet.sh deleted file mode 100755 index d1d3a235..00000000 --- a/.github/workflows/workspace_snippet.sh +++ /dev/null @@ -1,26 +0,0 @@ -#!/usr/bin/env bash - -set -o errexit -o nounset -o pipefail - -TAG=${GITHUB_REF_NAME} -PREFIX="rules_gitops-${TAG:1}" -SHA=$(git archive --format=tar --prefix=${PREFIX}/ ${TAG} | gzip | shasum -a 256 | awk '{print $1}') - -cat << EOF - -WORKSPACE snippet: - -\`\`\`starlark - -load("@bazel_tools//tools/build_defs/repo:http.bzl", "http_archive") - -http_archive( - name = "com_adobe_rules_gitops", - sha256 = "${SHA}", - strip_prefix = "${PREFIX}", - urls = ["https://github.com/adobe/rules_gitops/archive/refs/tags/${TAG}.tar.gz"], -) -EOF - -awk '/---SNIP---/{f=1;next}/---END_SNIP---/{f=0}f' examples/WORKSPACE -echo "\`\`\`" diff --git a/.gitignore b/.gitignore index 1833df43..b4eccf98 100644 --- a/.gitignore +++ b/.gitignore @@ -4,3 +4,4 @@ .DS_Store Thumbs.db bazel-* +.bazelrc.user diff --git a/BUILD b/BUILD deleted file mode 100644 index d4718a48..00000000 --- a/BUILD +++ /dev/null @@ -1,64 +0,0 @@ -# Copyright 2020 Adobe. All rights reserved. -# This file is licensed to you under the Apache License, Version 2.0 (the "License"); -# you may not use this file except in compliance with the License. You may obtain a copy -# of the License at http://www.apache.org/licenses/LICENSE-2.0 - -# Unless required by applicable law or agreed to in writing, software distributed under -# the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR REPRESENTATIONS -# OF ANY KIND, either express or implied. See the License for the specific language -# governing permissions and limitations under the License. - -# gazelle:build_tags darwin,linux -# gazelle:exclude examples -# gazelle:proto disable_global - -load("@bazel_gazelle//:def.bzl", "gazelle") -load("@com_github_bazelbuild_buildtools//buildifier:def.bzl", "buildifier") - -licenses(["notice"]) # Apache 2.0 - -exports_files(["WORKSPACE"]) - -# gazelle:prefix github.com/adobe/rules_gitops -gazelle( - name = "gazelle", - build_tags = [ - "integration", - "debug", - ], - command = "fix", - extra_args = [ - "-build_file_name", - "BUILD,BUILD.bazel", - ], -) - -buildifier( - name = "buildifier", - lint_mode = "warn", - lint_warnings = [ - "-module-docstring", - "-function-docstring", - "-function-docstring-header", - "-function-docstring-args", - "-function-docstring-return", - ], -) - -buildifier( - name = "buildifier-fix", - lint_mode = "fix", -) - -buildifier( - name = "buildifier-check", - lint_mode = "warn", - lint_warnings = [ - "-module-docstring", - "-function-docstring", - "-function-docstring-header", - "-function-docstring-args", - "-function-docstring-return", - ], - mode = "check", -) diff --git a/BUILD.bazel b/BUILD.bazel new file mode 100644 index 00000000..e77ceaad --- /dev/null +++ b/BUILD.bazel @@ -0,0 +1,66 @@ +# Copyright 2026 Adobe. All rights reserved. +# This file is licensed to you under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. You may obtain a copy +# of the License at http://www.apache.org/licenses/LICENSE-2.0 + +# Unless required by applicable law or agreed to in writing, software distributed under +# the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR REPRESENTATIONS +# OF ANY KIND, either express or implied. See the License for the specific language +# governing permissions and limitations under the License. + +# gazelle:exclude examples +# gazelle:map_kind bzl_library bzl_library @bazel_lib//:bzl_library.bzl + +load("@buildifier_prebuilt//:rules.bzl", "buildifier", "buildifier_test") +load("@gazelle//:def.bzl", "DEFAULT_LANGUAGES", "gazelle", "gazelle_binary") +load("@package_metadata//licenses/rules:license.bzl", "license") +load("@package_metadata//purl:purl.bzl", "purl") +load("@package_metadata//rules:package_metadata.bzl", "package_metadata") +load("//kustomize:defs.bzl", "kustomize_binary") + +buildifier( + name = "buildifier.fix", + exclude_patterns = ["./.git/*"], + lint_mode = "fix", + mode = "fix", +) + +buildifier_test( + name = "buildifier_test", + exclude_patterns = ["./.git/*"], + lint_mode = "warn", + mode = "check", + no_sandbox = True, + workspace = ":MODULE.bazel", +) + +package_metadata( + name = "package_metadata", + purl = purl.bazel( + module_name(), + module_version(), + ), + visibility = ["//visibility:public"], +) + +license( + name = "license", + kind = "@package_metadata//licenses/spdx:Apache-2.0", + text = "LICENSE", +) + +gazelle_binary( + name = "gazelle_bin", + languages = DEFAULT_LANGUAGES + [ + "@bazel_skylib_gazelle_plugin//bzl", + ], +) + +gazelle( + name = "gazelle", + gazelle = "gazelle_bin", +) + +kustomize_binary( + name = "kustomize_bin", +) diff --git a/COPYRIGHT b/COPYRIGHT index 7aeab94c..a05a31ad 100644 --- a/COPYRIGHT +++ b/COPYRIGHT @@ -1,4 +1,4 @@ -© Copyright 2015-2020 Adobe. All rights reserved. +© Copyright 2015-2026 Adobe. All rights reserved. Adobe holds the copyright for all the files found in this repository. diff --git a/MODULE.bazel b/MODULE.bazel new file mode 100644 index 00000000..60da8748 --- /dev/null +++ b/MODULE.bazel @@ -0,0 +1,60 @@ +module( + name = "rules_gitops", + compatibility_level = 0, +) + +bazel_dep(name = "platforms", version = "1.0.0") +bazel_dep(name = "package_metadata", version = "0.0.6") +bazel_dep(name = "protobuf", version = "33.4") +bazel_dep(name = "rules_go", version = "0.59.0") +bazel_dep(name = "rules_shell", version = "0.6.1") + +go_sdk = use_extension("@rules_go//go:extensions.bzl", "go_sdk") +go_sdk.download(version = "1.24.12") + +bazel_dep(name = "gazelle", version = "0.47.0") + +go_deps = use_extension("@gazelle//:extensions.bzl", "go_deps") +go_deps.from_file(go_mod = "//:go.mod") +use_repo(go_deps, "com_github_ghodss_yaml", "com_github_golang_protobuf", "com_github_google_go_cmp", "com_github_google_go_github_v32", "com_github_xanzy_go_gitlab", "io_k8s_api", "io_k8s_apimachinery", "io_k8s_client_go", "io_k8s_sigs_kind", "org_golang_x_oauth2") + +bazel_dep(name = "bazel_skylib", version = "1.8.2") +bazel_dep(name = "bazel_lib", version = "3.0.0") +bazel_dep(name = "bazelrc-preset.bzl", version = "1.6.0") + +kustomize = use_extension("//kustomize:defs.bzl", "kustomize") +use_repo(kustomize, "kustomize") + +register_toolchains("@kustomize//toolchains:all") + +kubectl = use_extension("//kubectl:defs.bzl", "kubectl") +use_repo(kubectl, "kubectl") + +register_toolchains("@kubectl//toolchains:all") + +bazel_dep(name = "rules_img", version = "0.3.3") + +# Dev Dependencies +bazel_dep(name = "bazel_skylib_gazelle_plugin", version = "1.8.2", dev_dependency = True) +bazel_dep(name = "buildifier_prebuilt", version = "8.2.1", dev_dependency = True) + +pull = use_repo_rule("@rules_img//img:pull.bzl", "pull") + +pull( + name = "alpine", + dev_dependency = True, + digest = "sha256:51183f2cfa6320055da30872f211093f9ff1d3cf06f39a0bdb212314c5dc7375", + layer_handling = "lazy", + registries = [ + "mirror.gcr.io", + "index.docker.io", + ], + repository = "library/alpine", + tag = "3.23", +) + +preset = use_repo_rule("//tools:preset.bzl", "preset") + +preset( + name = "preset.bzl", +) diff --git a/README.md b/README.md index a2bd2b0b..13522153 100644 --- a/README.md +++ b/README.md @@ -1,364 +1,128 @@ # Bazel GitOps Rules -![CI](https://github.com/adobe/rules_gitops/workflows/CI/badge.svg?branch=master&event=push) +![CI](https://github.com/adobe/rules_gitops/workflows/CI/badge.svg?branch=main&event=push) -Bazel GitOps Rules provides tooling to bridge the gap between Bazel (for hermetic, reproducible, container builds) and continuous, git-operation driven, deployments. Users author standard kubernetes manifests and kustomize overlays for their services. Bazel GitOps Rules handles image push and substitution, applies necessary kustomizations, and handles content addressed substitutions of all object references (configmaps, secrets, etc). Bazel targets are exposed for applying the rendered manifest directly to a Kubernetes cluster, or into version control facilitating deployment via Git operations. +Bazel GitOps Rules provides tooling to bridge the gap between Bazel (for hermetic, reproducible, container builds) and continuous, git-operation driven, deployments. Users author standard Kubernetes manifests and kustomize overlays for their services. Bazel GitOps Rules handles image push and substitution, applies necessary kustomizations, and handles content addressed substitutions of all object references (configmaps, secrets, etc). Bazel targets are exposed for applying the rendered manifest directly to a Kubernetes cluster, or into version control facilitating deployment via Git operations. -Bazel GitOps Rules is an alternative to [rules_k8s](https://github.com/bazelbuild/rules_k8s). The main differences are: +## Features -* Utilizes and integrates the full set of [Kustomize](https://kustomize.io/) capabilities for generating manifests. -* Implements GitOps target. -* Supports personal namespace deployments. -* Provides integration test setup utility. -* Speeds up deployments iterations: - * The results manifests are rendered without pushing containers. - * Pushes all the images in parallel. -* Provides an utility that creates GitOps pull requests. +- **Kustomize Integration**: Full [Kustomize](https://kustomize.io/) capabilities for generating and transforming manifests +- **GitOps Workflow**: Native support for Git-based deployment workflows with automatic PR creation +- **Container Image Management**: Seamless integration with [rules_img](https://github.com/bazel-contrib/rules_img) for building and pushing container images +- **Namespace Deployments**: Support for personal and team namespace deployments +- **Integration Testing**: Built-in utilities for Kubernetes integration test setup +- **Toolchain Support**: Managed kustomize and kubectl toolchains via Bzlmod +## Ruleset Overview -## Rules +The ruleset is organized into the following modules: -* [k8s_deploy](#k8s_deploy) -* [k8s_test_setup](#k8s_test_setup) +| Module | Description | +|--------|-------------| +| `@rules_gitops//gitops:defs.bzl` | Core deployment rules (`k8s_deploy`, `gitops`) for rendering manifests and managing deployments | +| `@rules_gitops//kustomize:defs.bzl` | Kustomize rules and toolchain for manifest transformation | +| `@rules_gitops//kubectl:defs.bzl` | Kubectl toolchain for cluster interactions | +| `@rules_gitops//testing:defs.bzl` | Integration testing utilities (`k8s_test_setup`, `k8s_test_namespace`) | +| `@rules_gitops//adapters:providers.bzl` | `K8sPushInfo` provider for container image integration | +| `@rules_gitops//adapters:rules_img.bzl` | Adapter for [rules_img](https://github.com/bazel-contrib/rules_img) container images | +## Getting Started -## Guides +### Installation -* [Base Manifests and Overlays](#base-manifests-and-overlays) -* [Generating Configmaps](#generating-configmaps) -* [Injecting Docker Images](#injecting-docker-images) -* [Adding Dependencies](#adding-dependencies) -* [GitOps and Deployment](#gitops-and-deployment) -* [Integration Testing Support](#integration-testing-support) - - - -## Installation - -From the release you wish to use: - -copy the WORKSPACE snippet into your `WORKSPACE` file. +Add `rules_gitops` to your `MODULE.bazel`: +```starlark +bazel_dep(name = "rules_gitops", version = "1.0.0") +``` - -## k8s_deploy +### Toolchain Setup -The `k8s_deploy` creates rules that produce the `.apply` and `.gitops` targets `k8s_deploy` is defined in [k8s.bzl](./skylib/k8s.bzl). `k8s_deploy` takes the files listed in the `manifests`, `patches`, and `configmaps_srcs` attributes and combines (**renders**) them into one YAML file. This happens when you `bazel build` or `bazel run` a target created by the `k8s_deploy`. The file is created at `bazel-bin/path/to/package/name.yaml`. When you run a `.apply` target, it runs `kubectl apply` on this file. When you run a `.gitops` target, it copies this file to -the appropriate location in the same os separate repository. +The ruleset provides managed toolchains for kustomize and kubectl. To use custom versions, configure the extensions in your `MODULE.bazel`: -For example, let's look at the [example's k8s_deploy](./examples/helloworld/BUILD). We can peek at the file containing the rendered K8s manifests: -```bash -cd examples -bazel run //helloworld:mynamespace.show -``` -When you run `bazel run ///helloworld:mynamespace.apply`, it applies this file into your personal (`{BUILD_USER}`) namespace. Viewing the rendered files with `.show` can be useful for debugging issues with invalid or misconfigured manifests. - -| Parameter | Default | Description -| ------------------------- | -------------- | ----------- -| ***cluster*** | `None` | The name of the cluster in which these manifests will be applied. -| ***namespace*** | `None` | The target namespace to assign to all manifests. Any namespace value in the source manifests will be replaced or added if not specified. -| ***user*** | `{BUILD_USER}` | The user passed to kubectl in .apply rule. Must exist in users ~/.kube/config -| ***configmaps_srcs*** | `None` | A list of files (of any type) that will be combined into configmaps. See [Generating Configmaps](#generating-configmaps). -| ***configmaps_renaming*** | `None` | Configmaps/Secrets renaming policy. Could be None or 'hash'. 'hash' renaming policy is used to add a unique suffix to the generated configmap or secret name. All references to the configmap or secret in other manifests will be replaced with the generated name. -| ***secrets_srcs*** | `None` | A list of files (of any type) that will be combined into a secret similar to configmaps. -| ***manifests*** | `glob(['*.yaml','*.yaml.tpl'])` | A list of base manifests. See [Base Manifests and Overlays](#base-manifests-and-overlays). -| ***name_prefix*** | `None` | Adds prefix to the names of all resources defined in manifests. -| ***name_suffix*** | `None` | Adds suffix to the names of all resources defined in manifests. -| ***patches*** | `None` | A list of patch files to overlay the base manifests. See [Base Manifests and Overlays](#base-manifests-and-overlays). -| ***image_name_patches*** | `None` | A dict of image names that will be replaced with new ones. See [kustomization images](https://kubectl.docs.kubernetes.io/references/kustomize/kustomization/images/). -| ***image_tag_patches*** | `None` | A dict of image names which tags be replaced with new ones. See [kustomization images](https://kubectl.docs.kubernetes.io/references/kustomize/kustomization/images/). -| ***substitutions*** | `None` | Does parameter substitution in all the manifests (including configmaps). This should generally be limited to "CLUSTER" and "NAMESPACE" only. Any other replacements should be done with overlays. -| ***configurations*** | `[]` | A list of files with [kustomize configurations](https://github.com/kubernetes-sigs/kustomize/blob/master/examples/transformerconfigs/README.md). -| ***prefix_suffix_app_labels*** | `False` | Add the bundled configuration file allowing adding suffix and prefix to labels `app` and `app.kubernetes.io/name` and respective selector in Deployment. -| ***common_labels*** | `{}` | A map of labels that should be added to all objects and object templates. -| ***common_annotations*** | `{}` | A map of annotations that should be added to all objects and object templates. -| ***start_tag*** | `"{{"` | The character start sequence used for substitutions. -| ***end_tag*** | `"}}"` | The character end sequence used for substitutions. -| ***deps*** | `[]` | A list of dependencies used to drive `k8s_deploy` functionality (i.e. `deps_aliases`). -| ***deps_aliases*** | `{}` | A dict of labels of file dependencies. File dependency contents are available for template expansion in manifests as `{{imports.