diff --git a/.github/workflows/release-please.yaml b/.github/workflows/release-please.yaml new file mode 100644 index 0000000000..ca7912f906 --- /dev/null +++ b/.github/workflows/release-please.yaml @@ -0,0 +1,82 @@ +name: Release Please + +on: + push: + branches: + - main + - 'release/v*' + workflow_dispatch: + inputs: + version: + required: true + description: 'Release version without the "v" prefix (e.g., 0.51.0)' + type: string + +jobs: + release-please: + runs-on: ubuntu-latest + if: ${{ !startsWith(github.event.head_commit.message, 'release:') && !github.event.inputs.version }} + steps: + - name: Release Please + id: release + uses: googleapis/release-please-action@v4 + with: + token: ${{ secrets.PAT }} + target-branch: ${{ github.ref_name }} + + manual-release-please: + runs-on: ubuntu-latest + if: ${{ github.event.inputs.version }} + steps: + - name: Install Release Please CLI + run: npm install release-please -g + + - name: Release Please + run: | + release-please release-pr --repo-url=${{ github.server_url }}/${{ github.repository }} \ + --token=${{ secrets.PAT }} \ + --release-as=${{ github.event.inputs.version }} \ + --target-branch=${{ github.ref_name }} + + release-tag: + runs-on: ubuntu-latest + if: ${{ startsWith(github.event.head_commit.message, 'release:') }} + steps: + # Since skip-github-release is specified, the outputs of googleapis/release-please-action cannot be used. + # Therefore, we need to parse the version ourselves. + - name: Extract version and PR number from commit message + id: extract_info + shell: bash + run: | + echo "version=$( echo "${{ github.event.head_commit.message }}" | sed 's/^release: v\([0-9]\+\.[0-9]\+\.[0-9]\+\).*$/\1/' )" >> $GITHUB_OUTPUT + echo "pr_number=$( echo "${{ github.event.head_commit.message }}" | sed 's/.*(\#\([0-9]\+\)).*$/\1/' )" >> $GITHUB_OUTPUT + + - name: Tag release + if: ${{ steps.extract_info.outputs.version }} + uses: actions/github-script@v7 + with: + github-token: ${{ secrets.PAT }} + script: | + await github.rest.git.createRef({ + owner: context.repo.owner, + repo: context.repo.repo, + ref: `refs/tags/v${{ steps.extract_info.outputs.version }}`, + sha: context.sha + }); + + # Since skip-github-release is specified, googleapis/release-please-action doesn't delete the label from PR. + # This label prevents the subsequent PRs from being created. Therefore, we need to delete it ourselves. + # cf. https://github.com/googleapis/release-please?tab=readme-ov-file#release-please-bot-does-not-create-a-release-pr-why + - name: Remove the label from PR + if: ${{ steps.extract_info.outputs.pr_number }} + uses: actions/github-script@v7 + with: + github-token: ${{ secrets.PAT }} + script: | + const prNumber = parseInt('${{ steps.extract_info.outputs.pr_number }}', 10); + github.rest.issues.removeLabel({ + owner: context.repo.owner, + repo: context.repo.repo, + issue_number: prNumber, + name: 'autorelease: pending' + }); diff --git a/.github/workflows/semantic-pr.yaml b/.github/workflows/semantic-pr.yaml index 5db6bd3a76..b136c9ae5c 100644 --- a/.github/workflows/semantic-pr.yaml +++ b/.github/workflows/semantic-pr.yaml @@ -28,6 +28,7 @@ jobs: ci chore revert + release BREAKING scopes: | diff --git a/.release-please-manifest.json b/.release-please-manifest.json new file mode 100644 index 0000000000..c9b8977ea6 --- /dev/null +++ b/.release-please-manifest.json @@ -0,0 +1 @@ +{".":"0.51.4"} diff --git a/docs/community/maintainer/release-flow.md b/docs/community/maintainer/release-flow.md new file mode 100644 index 0000000000..6a47469f12 --- /dev/null +++ b/docs/community/maintainer/release-flow.md @@ -0,0 +1,65 @@ +# Release Flow + +## Overview +Trivy adopts [conventional commit messages][conventional-commits], and [Release Please][release-please] automatically creates a [release PR](https://github.com/googleapis/release-please?tab=readme-ov-file#whats-a-release-pr) based on the messages of the merged commits. +This release PR is automatically updated every time a new commit is added to the release branch. + +If a commit has the prefix `feat:`, a PR is automatically created to increment the minor version, and if a commit has the prefix `fix:`, a PR is created to increment the patch version. +When the PR is merged, GitHub Actions automatically creates a version tag and the release is performed. +For detailed behavior, please refer to [the GitHub Actions configuration][workflows]. + +!!! note + Commits with prefixes like `chore` or `build` are not considered releasable, and no release PR is created. + To include such commits in a release, you need to either include commits with `feat` or `fix` prefixes or perform a manual release as described [below](#manual-release). + +## Flow +The release flow consists of the following main steps: + +1. Creating the release PR (automatically or manually) +1. Drafting the release notes +1. Merging the release PR +1. Updating the release notes + +### Automatic Release PR Creation +When a releasable commit (a commit with `feat` or `fix` prefix) is merged, a release PR is automatically created. +These Release PRs are kept up-to-date as additional work is merged. +When it's ready to tag a release, simply merge the release PR. +See the [Release Please documentation][release-please] for more information. + +The title of the PR will be in the format `release: v${version} [${branch}]` (e.g., `release: v0.51.0 [main]`). +The format of the PR title is important for identifying the release commit, so it should not be changed. + +The `release/vX.Y` release branches are also subject to automatic release PR creation for patch releases. +The PR title will be like `release: v0.51.1 [release/v0.51]`. + +### Manual Release PR Creation +If you want to release commits like `chore`, a release PR is not automatically created, so you need to manually trigger the creation of a release PR. +The [Release Please workflow](https://github.com/aquasecurity/trivy/actions/workflows/release-please.yaml) supports `workflow_dispatch` and can be triggered manually. +Click "Run workflow" in the top right corner and specify the release branch. +In Trivy, the following branches are the release branches. + +- `main` +- `release/vX.Y` (e.g. `release/v0.51`) + +Specify the release version (without the `v` prefix) and click "Run workflow" to create a release PR for the specified version. + +### Drafting the Release Notes +Next, create release notes for this version. +Draft a new post in GitHub Discussions, and maintainers edit these release notes (e.g., https://github.com/aquasecurity/trivy/discussions/6605). +Currently, the creation of this draft is done manually. +For patch version updates, this step can be skipped since they only involve bug fixes. + +### Merging the Release PR +Once the draft of the release notes is complete, merge the release PR. +When the PR is merged, a tag is automatically created, and [GoReleaser][goreleaser] releases binaries, container images, etc. + +### Updating the Release Notes +If the release completes without errors, a page for the release notes is created in GitHub Discussions (e.g., https://github.com/aquasecurity/trivy/discussions/6622). +Copy the draft release notes, adjust the formatting, and finalize the release notes. + +The release is now complete. + +[conventional-commits]: https://www.conventionalcommits.org/en/v1.0.0/ +[release-please]: https://github.com/googleapis/release-please +[goreleaser]: https://goreleaser.com/ +[workflows]: https://github.com/aquasecurity/trivy/tree/main/.github/workflows \ No newline at end of file diff --git a/mkdocs.yml b/mkdocs.yml index 6b5bd93249..664924cab5 100644 --- a/mkdocs.yml +++ b/mkdocs.yml @@ -199,6 +199,7 @@ nav: - Overview: community/contribute/checks/overview.md - Add Service Support: community/contribute/checks/service-support.md - Maintainer: + - Release Flow: community/maintainer/release-flow.md - Help Wanted: community/maintainer/help-wanted.md - Triage: community/maintainer/triage.md theme: diff --git a/release-please-config.json b/release-please-config.json new file mode 100644 index 0000000000..2d6aaecd71 --- /dev/null +++ b/release-please-config.json @@ -0,0 +1,11 @@ +{ + "$schema": "https://raw.githubusercontent.com/googleapis/release-please/main/schemas/config.json", + "release-type": "go", + "include-component-in-tag": false, + "bump-minor-pre-major": true, + "skip-github-release": true, + "pull-request-title-pattern": "release: v${version} [${branch}]", + "packages": { + ".": {} + } +}