diff --git a/.github/dependabot.yml b/.github/dependabot.yml index 8c8e204ec..4aa816f57 100644 --- a/.github/dependabot.yml +++ b/.github/dependabot.yml @@ -30,3 +30,42 @@ updates: ignore: - dependency-name: "*" update-types: ["version-update:semver-major", "version-update:semver-minor", "version-update:semver-patch"] + # Runtime base image pinned in the Dockerfile of each supported release branch. + # `main` uses the floating `latest` tag and needs no entry. + # Dependabot reads this file from the default branch only and cannot compute + # `target-branch`, so the entries below are regenerated by the + # "Update Dependabot release branches" workflow when a new minor is released. + # BEGIN generated by hack/update-dependabot-release-branches.sh, do not edit by hand + - package-ecosystem: "docker" + directory: "/" + target-branch: "release-1.18" + schedule: + interval: "weekly" + allow: + - dependency-name: "paketobuildpacks/run-jammy-tiny" + - dependency-name: "paketobuildpacks/ubuntu-noble-run-tiny" + ignore: + - dependency-name: "*" + update-types: ["version-update:semver-major"] + labels: + - "Dependencies" + - "kind/changelog-not-required" + commit-message: + prefix: "[release-1.18]" + - package-ecosystem: "docker" + directory: "/" + target-branch: "release-1.17" + schedule: + interval: "weekly" + allow: + - dependency-name: "paketobuildpacks/run-jammy-tiny" + - dependency-name: "paketobuildpacks/ubuntu-noble-run-tiny" + ignore: + - dependency-name: "*" + update-types: ["version-update:semver-major"] + labels: + - "Dependencies" + - "kind/changelog-not-required" + commit-message: + prefix: "[release-1.17]" + # END generated by hack/update-dependabot-release-branches.sh diff --git a/.github/workflows/update-dependabot-release-branches.yml b/.github/workflows/update-dependabot-release-branches.yml new file mode 100644 index 000000000..641bdd2ec --- /dev/null +++ b/.github/workflows/update-dependabot-release-branches.yml @@ -0,0 +1,76 @@ +name: "Update Dependabot release branches" +# Dependabot cannot compute `target-branch`, so regenerate the docker entries in +# .github/dependabot.yml for the supported release branches (the two newest +# minors that have a GA vX.Y.0 tag) whenever a release is published. +# Re-running is harmless: no pull request is opened when nothing changes. +on: + release: + types: [released] + schedule: + - cron: "0 3 * * 1" # Every Monday at 3:00 UTC, in case a release event was missed + workflow_dispatch: + +permissions: + contents: write + pull-requests: write + +jobs: + update: + if: github.repository == 'velero-io/velero' + runs-on: ubuntu-latest + env: + BRANCH: automation/update-dependabot-release-branches + # Pull requests opened with the default GITHUB_TOKEN do not trigger other + # workflows, so required checks would not run on them. Set the + # DEPENDABOT_CONFIG_TOKEN secret (a GitHub App token or PAT that can push + # branches and open pull requests) to have CI run on the generated PR. + GH_TOKEN: ${{ secrets.DEPENDABOT_CONFIG_TOKEN || secrets.GITHUB_TOKEN }} + steps: + - name: Check out the code + uses: actions/checkout@v7 + with: + ref: main + token: ${{ secrets.DEPENDABOT_CONFIG_TOKEN || secrets.GITHUB_TOKEN }} + + - name: Regenerate release branch entries + run: ./hack/update-dependabot-release-branches.sh + + - name: Open pull request if the config changed + run: | + if git diff --quiet -- .github/dependabot.yml; then + echo "dependabot.yml is up to date" + exit 0 + fi + + open_pr=$(gh pr list --head "${BRANCH}" --state open --json number --jq '.[].number') + + # Leave an already pushed branch alone when it has the same content, + # so unchanged runs do not retrigger CI or dismiss approvals. + if git fetch --quiet origin "${BRANCH}" 2>/dev/null && + git diff --quiet FETCH_HEAD -- .github/dependabot.yml; then + if [[ -n "${open_pr}" ]]; then + echo "pull request #${open_pr} already has this change" + exit 0 + fi + echo "${BRANCH} already has this change but has no open pull request" + else + git config user.name "github-actions[bot]" + git config user.email "41898282+github-actions[bot]@users.noreply.github.com" + git checkout -B "${BRANCH}" + git commit -s -m "Update Dependabot release branches" -- .github/dependabot.yml + git push --force origin "${BRANCH}" + + if [[ -n "${open_pr}" ]]; then + echo "pull request #${open_pr} updated" + exit 0 + fi + fi + + gh pr create \ + --base main \ + --head "${BRANCH}" \ + --title "Update Dependabot release branches" \ + --label "kind/changelog-not-required" \ + --body "Regenerated the Dependabot \`target-branch\` entries in \`.github/dependabot.yml\` for the supported release branches (the two newest minors with a GA \`vX.Y.0\` tag) using \`hack/update-dependabot-release-branches.sh\`. + + Triggered by: \`${GITHUB_EVENT_NAME}\`" diff --git a/changelogs/unreleased/10692-kaovilai b/changelogs/unreleased/10692-kaovilai new file mode 100644 index 000000000..cdace7d90 --- /dev/null +++ b/changelogs/unreleased/10692-kaovilai @@ -0,0 +1 @@ +Add a workflow that keeps the Dependabot release branch entries for the runtime base image up to date diff --git a/hack/update-dependabot-release-branches.sh b/hack/update-dependabot-release-branches.sh new file mode 100755 index 000000000..e9c103a1a --- /dev/null +++ b/hack/update-dependabot-release-branches.sh @@ -0,0 +1,92 @@ +#!/usr/bin/env bash + +# Copyright the Velero contributors. +# +# 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. + +# Dependabot cannot compute `target-branch`, so regenerate the docker entries +# in .github/dependabot.yml for the currently supported release branches. +# The runtime base image is run-jammy-tiny on older branches and +# ubuntu-noble-run-tiny from the branch `main` is on, so both are allowed. +# +# Supported branches are the newest SUPPORTED_MINORS minor versions that have +# a GA `vX.Y.0` tag (pre-release tags such as `vX.Y.0-rc.1` do not count), so a +# `release-X.Y` branch is not picked up before X.Y.0 is released. +# +# Only the lines between the BEGIN and END markers in dependabot.yml are +# rewritten. Run from the repository root; this is a no-op when the file is +# already up to date. + +set -euo pipefail + +REPO_URL="${REPO_URL:-https://github.com/velero-io/velero.git}" +DEPENDABOT_FILE="${DEPENDABOT_FILE:-.github/dependabot.yml}" +SUPPORTED_MINORS="${SUPPORTED_MINORS:-2}" + +BEGIN_MARKER=" # BEGIN generated by hack/update-dependabot-release-branches.sh, do not edit by hand" +END_MARKER=" # END generated by hack/update-dependabot-release-branches.sh" + +# Newest first, e.g. "1.18" then "1.17". +minors=$(git ls-remote --tags --refs "${REPO_URL}" 'v*.*.0' | + sed -n 's#.*refs/tags/v\([0-9][0-9]*\.[0-9][0-9]*\)\.0$#\1#p' | + sort -t. -k1,1nr -k2,2nr -u | + sed -n "1,${SUPPORTED_MINORS}p") + +if [[ -z "${minors}" ]]; then + echo "no GA release tags found in ${REPO_URL}" >&2 + exit 1 +fi + +if ! grep -qxF "${BEGIN_MARKER}" "${DEPENDABOT_FILE}" || ! grep -qxF "${END_MARKER}" "${DEPENDABOT_FILE}"; then + echo "${DEPENDABOT_FILE} is missing the BEGIN/END markers" >&2 + exit 1 +fi + +generated=$(mktemp) +output=$(mktemp) +trap 'rm -f "${generated}" "${output}"' EXIT + +for minor in ${minors}; do + cat >>"${generated}" < 0) print line + skipping = 1 + next + } + $0 == end { skipping = 0 } + !skipping { print } +' "${DEPENDABOT_FILE}" >"${output}" + +cat "${output}" >"${DEPENDABOT_FILE}" +echo "supported release branches: $(echo "${minors}" | sed 's/^/release-/' | paste -sd, -)" diff --git a/site/content/docs/main/development.md b/site/content/docs/main/development.md index c6d9f5811..8a02e3fe8 100644 --- a/site/content/docs/main/development.md +++ b/site/content/docs/main/development.md @@ -54,7 +54,7 @@ Velero is written in Go and uses [Go modules](https://go.dev/ref/mod) to manage The project keeps dependencies up to date and responds to upstream security fixes as follows: -* [Dependabot](https://docs.github.com/en/code-security/dependabot) is configured in [`.github/dependabot.yml`](https://github.com/velero-io/velero/blob/main/.github/dependabot.yml) to open pull requests for Go module and GitHub Actions updates on a weekly schedule. Updates are grouped to reduce noise. +* [Dependabot](https://docs.github.com/en/code-security/dependabot) is configured in [`.github/dependabot.yml`](https://github.com/velero-io/velero/blob/main/.github/dependabot.yml) to open pull requests for Go module and GitHub Actions updates on a weekly schedule. Updates are grouped to reduce noise. It also opens pull requests against each supported release branch (the current minor and N-1) to bump the pinned `paketobuildpacks/run-jammy-tiny` runtime base image to the latest patch or minor version. Dependabot cannot resolve release branches dynamically, so the `target-branch` entries are regenerated by the [Update Dependabot release branches](https://github.com/velero-io/velero/blob/main/.github/workflows/update-dependabot-release-branches.yml) workflow, which opens a pull request when a release is published. * Dependency update pull requests follow the same review process as any other change: they must pass CI and be approved by a maintainer before merging. * Security-relevant updates are prioritized. Vulnerabilities in dependencies that affect Velero are handled through the [security release process](https://github.com/velero-io/.github/blob/main/SECURITY.md). * New direct dependencies should be kept to a minimum and use a license compatible with Velero's [Apache 2.0 license](https://github.com/velero-io/velero/blob/main/LICENSE).