From d9daf5f51599f2d173c37ecad68de7623cb1e348 Mon Sep 17 00:00:00 2001 From: Jawed khelil Date: Tue, 16 Jun 2026 08:45:00 +0200 Subject: [PATCH] ci(dependabot): add generated config for active release branches Implement the same dependabot generation pattern used by tektoncd/pipeline: - .github/dependabot.config.yml: human-editable source of truth listing ecosystems and active release branches - hack/generate-dependabot.go: Go generator that produces dependabot.yml from the config - hack/generate-dependabot.sh: shell wrapper that refreshes release branches from releases.md and calls the generator - .github/workflows/dependabot-regen.yml: weekly workflow that auto-regenerates and opens a PR on drift - .github/dependabot.yml: regenerated from config; covers main (all updates) and release-v0.20.x, release-v0.25.x, release-v0.26.x, release-v0.27.x (patch-only) Signed-off-by: Jawed khelil Assisted-by: Claude Sonnet 4.6 (via Cursor) Co-authored-by: Cursor --- .github/dependabot.config.yml | 64 ++++++ .github/dependabot.yml | 260 ++++++++++++++++++++++--- .github/workflows/dependabot-regen.yml | 114 +++++++++++ hack/generate-dependabot.go | 182 +++++++++++++++++ hack/generate-dependabot.sh | 40 ++++ releases.md | 26 ++- 6 files changed, 653 insertions(+), 33 deletions(-) create mode 100644 .github/dependabot.config.yml create mode 100644 .github/workflows/dependabot-regen.yml create mode 100644 hack/generate-dependabot.go create mode 100755 hack/generate-dependabot.sh diff --git a/.github/dependabot.config.yml b/.github/dependabot.config.yml new file mode 100644 index 0000000000..8510541dea --- /dev/null +++ b/.github/dependabot.config.yml @@ -0,0 +1,64 @@ +# Dependabot configuration +# This file defines the base configuration and branches for dependabot updates. +# The actual .github/dependabot.yml is generated from this file. +# +# Automated regeneration: +# - A GitHub Actions workflow runs weekly to regenerate dependabot.yml +# - If changes are detected, it automatically creates a PR +# - See: .github/workflows/dependabot-regen.yml +# +# Manual regeneration: +# 1. Edit the 'ecosystems' section to change what packages to monitor +# 2. Edit the 'release-branches' section to add/remove branches +# 3. Run: ./hack/generate-dependabot.sh + +# List of release branches to monitor (in addition to main branch) +# These should be active LTS release branches +# Check releases.md for the current list of supported releases +release-branches: + - release-v0.27.x + - release-v0.26.x + - release-v0.25.x + - release-v0.20.x +# Package ecosystems to monitor +# Each ecosystem will be configured for: +# - main branch: all updates (major, minor, patch) +# - release branches: patch updates only +ecosystems: + - package-ecosystem: gomod + directory: / + schedule: + interval: daily + labels: + - ok-to-test + - dependencies + - release-note-none + - kind/misc + ignore: + - dependency-name: "k8s.io/*" + update-types: + - version-update:semver-major + - version-update:semver-minor + groups: + all: + patterns: + - "*" + cooldown: + default-days: 7 + semver-major-days: 30 + semver-minor-days: 7 + semver-patch-days: 3 + - package-ecosystem: github-actions + directory: / + schedule: + interval: weekly + labels: + - ok-to-test + - dependencies + - release-note-none + - kind/misc + cooldown: + default-days: 7 + semver-major-days: 30 + semver-minor-days: 7 + semver-patch-days: 3 diff --git a/.github/dependabot.yml b/.github/dependabot.yml index 152cc073d4..e596ac6b5f 100644 --- a/.github/dependabot.yml +++ b/.github/dependabot.yml @@ -1,26 +1,238 @@ +# Generated file - DO NOT EDIT MANUALLY +# This file is generated by hack/generate-dependabot.sh +# +# To update this file: +# 1. Edit .github/dependabot.config.yml +# 2. Run: ./hack/generate-dependabot.sh +# version: 2 updates: - - package-ecosystem: "gomod" - directory: "/" - schedule: - interval: "daily" - labels: - - "ok-to-test" - groups: - all: - patterns: - - "*" - labels: - - "ok-to-test" - - "dependencies" - - "release-note-none" - - "kind/misc" - - package-ecosystem: "github-actions" - directory: "/" - schedule: - interval: "weekly" - labels: - - "ok-to-test" - - "dependencies" - - "release-note-none" - - "kind/misc" + - package-ecosystem: gomod + directory: / + schedule: + interval: daily + labels: + - ok-to-test + - dependencies + - release-note-none + - kind/misc + ignore: + - dependency-name: k8s.io/* + update-types: + - version-update:semver-major + - version-update:semver-minor + groups: + all: + patterns: + - '*' + cooldown: + default-days: 7 + semver-major-days: 30 + semver-minor-days: 7 + semver-patch-days: 3 + - package-ecosystem: github-actions + directory: / + schedule: + interval: weekly + labels: + - ok-to-test + - dependencies + - release-note-none + - kind/misc + cooldown: + default-days: 7 + semver-major-days: 30 + semver-minor-days: 7 + semver-patch-days: 3 + - package-ecosystem: gomod + directory: / + target-branch: release-v0.27.x + schedule: + interval: daily + labels: + - ok-to-test + - dependencies + - release-note-none + - kind/misc + ignore: + - dependency-name: k8s.io/* + update-types: + - version-update:semver-major + - version-update:semver-minor + - dependency-name: '*' + update-types: + - version-update:semver-major + - version-update:semver-minor + groups: + all: + patterns: + - '*' + cooldown: + default-days: 7 + semver-major-days: 30 + semver-minor-days: 7 + semver-patch-days: 3 + - package-ecosystem: github-actions + directory: / + target-branch: release-v0.27.x + schedule: + interval: weekly + labels: + - ok-to-test + - dependencies + - release-note-none + - kind/misc + ignore: + - dependency-name: '*' + update-types: + - version-update:semver-major + - version-update:semver-minor + cooldown: + default-days: 7 + semver-major-days: 30 + semver-minor-days: 7 + semver-patch-days: 3 + - package-ecosystem: gomod + directory: / + target-branch: release-v0.26.x + schedule: + interval: daily + labels: + - ok-to-test + - dependencies + - release-note-none + - kind/misc + ignore: + - dependency-name: k8s.io/* + update-types: + - version-update:semver-major + - version-update:semver-minor + - dependency-name: '*' + update-types: + - version-update:semver-major + - version-update:semver-minor + groups: + all: + patterns: + - '*' + cooldown: + default-days: 7 + semver-major-days: 30 + semver-minor-days: 7 + semver-patch-days: 3 + - package-ecosystem: github-actions + directory: / + target-branch: release-v0.26.x + schedule: + interval: weekly + labels: + - ok-to-test + - dependencies + - release-note-none + - kind/misc + ignore: + - dependency-name: '*' + update-types: + - version-update:semver-major + - version-update:semver-minor + cooldown: + default-days: 7 + semver-major-days: 30 + semver-minor-days: 7 + semver-patch-days: 3 + - package-ecosystem: gomod + directory: / + target-branch: release-v0.25.x + schedule: + interval: daily + labels: + - ok-to-test + - dependencies + - release-note-none + - kind/misc + ignore: + - dependency-name: k8s.io/* + update-types: + - version-update:semver-major + - version-update:semver-minor + - dependency-name: '*' + update-types: + - version-update:semver-major + - version-update:semver-minor + groups: + all: + patterns: + - '*' + cooldown: + default-days: 7 + semver-major-days: 30 + semver-minor-days: 7 + semver-patch-days: 3 + - package-ecosystem: github-actions + directory: / + target-branch: release-v0.25.x + schedule: + interval: weekly + labels: + - ok-to-test + - dependencies + - release-note-none + - kind/misc + ignore: + - dependency-name: '*' + update-types: + - version-update:semver-major + - version-update:semver-minor + cooldown: + default-days: 7 + semver-major-days: 30 + semver-minor-days: 7 + semver-patch-days: 3 + - package-ecosystem: gomod + directory: / + target-branch: release-v0.20.x + schedule: + interval: daily + labels: + - ok-to-test + - dependencies + - release-note-none + - kind/misc + ignore: + - dependency-name: k8s.io/* + update-types: + - version-update:semver-major + - version-update:semver-minor + - dependency-name: '*' + update-types: + - version-update:semver-major + - version-update:semver-minor + groups: + all: + patterns: + - '*' + cooldown: + default-days: 7 + semver-major-days: 30 + semver-minor-days: 7 + semver-patch-days: 3 + - package-ecosystem: github-actions + directory: / + target-branch: release-v0.20.x + schedule: + interval: weekly + labels: + - ok-to-test + - dependencies + - release-note-none + - kind/misc + ignore: + - dependency-name: '*' + update-types: + - version-update:semver-major + - version-update:semver-minor + cooldown: + default-days: 7 + semver-major-days: 30 + semver-minor-days: 7 + semver-patch-days: 3 diff --git a/.github/workflows/dependabot-regen.yml b/.github/workflows/dependabot-regen.yml new file mode 100644 index 0000000000..2b06ce36d8 --- /dev/null +++ b/.github/workflows/dependabot-regen.yml @@ -0,0 +1,114 @@ +name: Regenerate Dependabot Configuration + +"on": + schedule: + - cron: '0 9 * * 1' + workflow_dispatch: {} + +permissions: + contents: write + pull-requests: write + +jobs: + regenerate: + runs-on: ubuntu-latest + steps: + - name: Harden Runner + uses: step-security/harden-runner@9af89fc71515a100421586dfdb3dc9c984fbf411 # v2.19.4 + with: + egress-policy: audit + + - name: Checkout repository + uses: actions/checkout@df4cb1c069e1874edd31b4311f1884172cec0e10 # v6.0.3 + with: + persist-credentials: false + + - name: Set up Go + uses: actions/setup-go@4a3601121dd01d1626a1e23e37211e3254c1c06c # v6.4.0 + with: + go-version-file: 'go.mod' + + - name: Regenerate dependabot.yml + run: | + echo "Regenerating .github/dependabot.yml..." + ./hack/generate-dependabot.sh + + - name: Check for changes + id: check-changes + run: | + if git diff --quiet .github/dependabot.config.yml .github/dependabot.yml; then + echo "changed=false" >> $GITHUB_OUTPUT + echo "No changes detected in dependabot.yml" + else + echo "changed=true" >> $GITHUB_OUTPUT + echo "Changes detected in dependabot.yml" + fi + + - name: Create Pull Request + if: steps.check-changes.outputs.changed == 'true' + env: + GH_TOKEN: ${{ secrets.CHATOPS_TOKEN }} + WORKFLOW_NAME: ${{ github.workflow }} + EVENT_NAME: ${{ github.event_name }} + SERVER_URL: ${{ github.server_url }} + REPOSITORY: ${{ github.repository }} + RUN_ID: ${{ github.run_id }} + run: | + git config user.name "tekton-robot" + git config user.email "tekton-robot@users.noreply.github.com" + + # Create a new branch + BRANCH="dependabot-regen-$(date +%Y%m%d-%H%M%S)" + git checkout -b "$BRANCH" + + # Commit changes + git add .github/dependabot.config.yml .github/dependabot.yml + git commit -s -m "Regenerate dependabot.yml from config + + This automated PR regenerates .github/dependabot.yml from + .github/dependabot.config.yml to ensure the configuration + is up-to-date with the latest release branches. + + Generated by: ${WORKFLOW_NAME} + Triggered by: ${EVENT_NAME}" + + # Push branch (configure credentials only for this step) + git remote set-url origin "https://x-access-token:${GH_TOKEN}@github.com/${REPOSITORY}.git" + git push origin "$BRANCH" + + # Create PR + gh pr create \ + --title "Regenerate dependabot.yml configuration" \ + --body "## Automated Dependabot Configuration Update + + This PR regenerates \`.github/dependabot.yml\` from \`.github/dependabot.config.yml\`. + + ### Changes + The dependabot configuration has been regenerated to ensure it's in sync with: + - Release branches listed in \`.github/dependabot.config.yml\` + - Ecosystem configurations + + ### Review Checklist + - [ ] Verify that all active LTS release branches are included + - [ ] Check that main branch configurations look correct + - [ ] Ensure patch-only restrictions are applied to release branches + + --- + šŸ¤– This PR was automatically created by the \`${WORKFLOW_NAME}\` workflow. + **Triggered by**: ${EVENT_NAME} + **Run**: ${SERVER_URL}/${REPOSITORY}/actions/runs/${RUN_ID}" \ + --base main \ + --head "$BRANCH" \ + --label "dependencies" \ + --label "kind/misc" \ + --label "release-note-none" + + - name: Summary + env: + CHANGED: ${{ steps.check-changes.outputs.changed }} + run: | + if [ "${CHANGED}" = "true" ]; then + echo "āœ… Pull request created with updated dependabot.yml" + else + echo "āœ… No changes needed - dependabot.yml is up-to-date" + fi diff --git a/hack/generate-dependabot.go b/hack/generate-dependabot.go new file mode 100644 index 0000000000..df91ce1660 --- /dev/null +++ b/hack/generate-dependabot.go @@ -0,0 +1,182 @@ +// Copyright 2026 The Tekton Authors +// +// Licensed 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 CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +//go:build ignore + +package main + +import ( + "fmt" + "os" + "path/filepath" + + "go.yaml.in/yaml/v3" +) + +// Config represents the dependabot configuration file structure +type Config struct { + ReleaseBranches []string `yaml:"release-branches"` + Ecosystems []Ecosystem `yaml:"ecosystems"` +} + +// Cooldown defines minimum age requirements before Dependabot opens a PR, +// reducing supply-chain risk by giving security vendors time to flag compromises. +type Cooldown struct { + DefaultDays int `yaml:"default-days,omitempty"` + SemverMajorDays int `yaml:"semver-major-days,omitempty"` + SemverMinorDays int `yaml:"semver-minor-days,omitempty"` + SemverPatchDays int `yaml:"semver-patch-days,omitempty"` +} + +// Ecosystem represents a package ecosystem configuration +type Ecosystem struct { + PackageEcosystem string `yaml:"package-ecosystem"` + Directory string `yaml:"directory"` + Schedule map[string]interface{} `yaml:"schedule"` + Labels []string `yaml:"labels"` + Ignore []map[string]interface{} `yaml:"ignore,omitempty"` + Groups map[string]interface{} `yaml:"groups,omitempty"` + Cooldown *Cooldown `yaml:"cooldown,omitempty"` +} + +// DependabotConfig represents the generated dependabot.yml structure +type DependabotConfig struct { + Version int `yaml:"version"` + Updates []Update `yaml:"updates"` +} + +// Update represents a single dependabot update configuration +type Update struct { + PackageEcosystem string `yaml:"package-ecosystem"` + Directory string `yaml:"directory"` + TargetBranch string `yaml:"target-branch,omitempty"` + Schedule map[string]interface{} `yaml:"schedule"` + Labels []string `yaml:"labels"` + Ignore []map[string]interface{} `yaml:"ignore,omitempty"` + Groups map[string]interface{} `yaml:"groups,omitempty"` + Cooldown *Cooldown `yaml:"cooldown,omitempty"` +} + +func main() { + if err := run(); err != nil { + fmt.Fprintf(os.Stderr, "Error: %v\n", err) + os.Exit(1) + } +} + +func run() error { + configPath := filepath.Join(".github", "dependabot.config.yml") + outputPath := filepath.Join(".github", "dependabot.yml") + + configData, err := os.ReadFile(configPath) + if err != nil { + return fmt.Errorf("failed to read config file: %w", err) + } + + var config Config + if err := yaml.Unmarshal(configData, &config); err != nil { + return fmt.Errorf("failed to parse config file: %w", err) + } + + fmt.Printf("Loading configuration from %s\n", configPath) + fmt.Printf(" - Found %d ecosystem(s)\n", len(config.Ecosystems)) + fmt.Printf(" - Found %d release branch(es)", len(config.ReleaseBranches)) + if len(config.ReleaseBranches) > 0 { + fmt.Printf(": %v", config.ReleaseBranches) + } + fmt.Println() + + // Generate dependabot config + dependabotConfig := generateDependabotConfig(config) + + // Write output with header + header := `# Generated file - DO NOT EDIT MANUALLY +# This file is generated by hack/generate-dependabot.sh +# +# To update this file: +# 1. Edit .github/dependabot.config.yml +# 2. Run: ./hack/generate-dependabot.sh +# +` + + output, err := yaml.Marshal(&dependabotConfig) + if err != nil { + return fmt.Errorf("failed to marshal output: %w", err) + } + + fullOutput := header + string(output) + if err := os.WriteFile(outputPath, []byte(fullOutput), 0644); err != nil { + return fmt.Errorf("failed to write output file: %w", err) + } + + fmt.Printf("\nāœ“ Generated %s\n", outputPath) + fmt.Printf(" - Main branch: %d ecosystems\n", len(config.Ecosystems)) + fmt.Printf(" - Release branches: %d branches\n", len(config.ReleaseBranches)) + fmt.Printf(" - Total update entries: %d\n", len(dependabotConfig.Updates)) + + return nil +} + +func generateDependabotConfig(config Config) DependabotConfig { + dependabotConfig := DependabotConfig{ + Version: 2, + Updates: []Update{}, + } + + // Add entries for main branch (no target-branch, uses existing ignore rules) + for _, ecosystem := range config.Ecosystems { + update := Update{ + PackageEcosystem: ecosystem.PackageEcosystem, + Directory: ecosystem.Directory, + Schedule: ecosystem.Schedule, + Labels: ecosystem.Labels, + Ignore: ecosystem.Ignore, + Groups: ecosystem.Groups, + Cooldown: ecosystem.Cooldown, + } + dependabotConfig.Updates = append(dependabotConfig.Updates, update) + } + + // Add entries for each release branch (with target-branch and patch-only) + for _, branch := range config.ReleaseBranches { + for _, ecosystem := range config.Ecosystems { + // Copy ignore rules from template + ignore := make([]map[string]interface{}, len(ecosystem.Ignore)) + copy(ignore, ecosystem.Ignore) + + // Add patch-only restriction for release branches + ignore = append(ignore, map[string]interface{}{ + "dependency-name": "*", + "update-types": []string{ + "version-update:semver-major", + "version-update:semver-minor", + }, + }) + + update := Update{ + PackageEcosystem: ecosystem.PackageEcosystem, + Directory: ecosystem.Directory, + TargetBranch: branch, + Schedule: ecosystem.Schedule, + Labels: ecosystem.Labels, + Ignore: ignore, + Groups: ecosystem.Groups, + Cooldown: ecosystem.Cooldown, + } + dependabotConfig.Updates = append(dependabotConfig.Updates, update) + } + } + + return dependabotConfig +} diff --git a/hack/generate-dependabot.sh b/hack/generate-dependabot.sh new file mode 100755 index 0000000000..bd2af22118 --- /dev/null +++ b/hack/generate-dependabot.sh @@ -0,0 +1,40 @@ +#!/usr/bin/env bash + +# Copyright 2026 The Tekton Authors +# +# Licensed 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 CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +# Generate .github/dependabot.yml from .github/dependabot.config.yml + +set -o errexit +set -o nounset +set -o pipefail + +REPO_ROOT=$(cd "$(dirname "${BASH_SOURCE[0]}")/.." && pwd) +cd "${REPO_ROOT}" + +echo "Generating release branch list from releases.md active releases..." +yq -i '.release-branches = []' .github/dependabot.config.yml +awk '/^## Release$/{found=1; next} found && /^## /{exit} found && /^### v[0-9]+\.[0-9]+ \(LTS\)/{sub(/^### /, "release-"); sub(/ \(LTS\)\s*$/, ".x"); print}' releases.md | +while IFS= read -r branch; do + yq -i ".release-branches += \"${branch}\"" .github/dependabot.config.yml +done + +echo "Generating .github/dependabot.yml..." + +# Run the generator using go run +go run ./hack/generate-dependabot.go + +echo "" +echo "Done! Review the changes and commit if they look correct:" +echo " git diff .github/dependabot.yml" diff --git a/releases.md b/releases.md index ba58243a2a..3a8847f557 100644 --- a/releases.md +++ b/releases.md @@ -98,11 +98,16 @@ Deprecation notices will be included in [release notes](https://github.com/tektoncd/chains/releases). Any relevant deprecation window timers begin from when the release is published. -## Current Releases +## Release + +### v0.27 (LTS) +- **Latest Release**: v0.27.0 (TBD) +- **Initial Release**: v0.27.0 (TBD) + ### v0.26 (LTS) - **Latest Release**: [v0.26.2][v0-26-2] (2026-02-06)([docs][v0-26-2-docs], [examples][v0-26-2-examples]) - **Initial Release**: [v0.26.0][v0-26-0] (2025-11-05) -- **Patch Releases: [v0.26.0][v0-26-0],[v0.26.1][v0-26-1],[v0.26.2][v0-26-2] +- **Patch Releases**: [v0.26.0][v0-26-0], [v0.26.1][v0-26-1], [v0.26.2][v0-26-2] [v0-26-0]: https://github.com/tektoncd/chains/releases/tag/v0.26.0 [v0-26-1]: https://github.com/tektoncd/chains/releases/tag/v0.26.1 @@ -110,19 +115,26 @@ deprecation window timers begin from when the release is published. [v0-26-2-docs]: https://github.com/tektoncd/chains/tree/v0.26.2/docs [v0-26-2-examples]: https://github.com/tektoncd/chains/tree/v0.26.2/examples - ### v0.25 (LTS) - **Latest Release**: [v0.25.0][v0-25-0] (2025-05-13) - **Initial Release**: [v0.25.0][v0-25-0] (2025-05-13) [v0-25-0]: https://github.com/tektoncd/chains/releases/tag/v0.25.0 -[v0-25-0]: https://github.com/tektoncd/chains/releases/tag/v0.25.0 + +### v0.20 (LTS) +- **Latest Release**: [v0.20.0][v0-20-0] (2023-11-06) +- **Initial Release**: [v0.20.0][v0-20-0] (2023-11-06) + +[v0-20-0]: https://github.com/tektoncd/chains/releases/tag/v0.20.0 + +## Older Releases + +Older releases are EOL and available on [GitHub][tekton-chains-releases]. ### v0.24 (LTS) - **Latest Release**: [v0.24.0][v0-24-0] (2025-02-11) - **Initial Release**: [v0.24.0][v0-24-0] (2025-02-11) -[v0-24-0]: https://github.com/tektoncd/chains/releases/tag/v0.24.0 [v0-24-0]: https://github.com/tektoncd/chains/releases/tag/v0.24.0 ### v0.23 (LTS) @@ -139,10 +151,6 @@ deprecation window timers begin from when the release is published. [v0-22-0]: https://github.com/tektoncd/chains/releases/tag/v0.22.0 [v0-22-3]: https://github.com/tektoncd/chains/releases/tag/v0.22.3 -## Older Releases - -Older releases are EOL and available on [GitHub][tekton-chains-releases]. - [release-policy]: https://github.com/tektoncd/community/blob/main/releases.md [sigstore]: https://sigstore.dev [tekton-chains]: https://github.com/tektoncd/chains