diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml new file mode 100644 index 0000000..62f8688 --- /dev/null +++ b/.github/workflows/release.yml @@ -0,0 +1,105 @@ +name: Release + +on: + workflow_dispatch: + inputs: + version: + description: 'Release version (e.g., 1.3). Leave empty to auto-increment minor. Do not add `v` into version name as it is prepended automatically.' + required: false + type: string + description: + description: 'Custom release description (prepended before auto-generated changelog).' + required: false + type: string + +jobs: + release: + runs-on: ubuntu-latest + permissions: + contents: write + steps: + - name: Validate branch + id: branch + run: | + BRANCH="${{ github.ref_name }}" + + echo "Validating branch: ${BRANCH}" + if [[ ! "$BRANCH" =~ ^release-([0-9]+)\.x$ ]]; then + echo "::error::Must run on a release-X.x branch (e.g., release-1.x)" + exit 1 + fi + echo "major=${BASH_REMATCH[1]}" >> "$GITHUB_OUTPUT" + + - name: Checkout + uses: actions/checkout@v6 + with: + fetch-depth: 0 + + - name: Determine version + id: version + env: + MAJOR: ${{ steps.branch.outputs.major }} + run: | + if [[ -n "${{ inputs.version }}" ]]; then + VERSION="${{ inputs.version }}" + if [[ ! "$VERSION" =~ ^${MAJOR}\.[0-9]+$ ]]; then + echo "::error::Version $VERSION does not match branch major version $MAJOR" + exit 1 + fi + else + LATEST=$(git tag -l "v${MAJOR}.*" --sort=-v:refname | head -n1) + if [[ -z "$LATEST" ]]; then + VERSION="${MAJOR}.0" + else + MINOR="${LATEST##*.}" + VERSION="${MAJOR}.$((MINOR + 1))" + fi + fi + TAG="v$VERSION" + if git rev-parse "refs/tags/$TAG" &>/dev/null; then + echo "::error::Tag $TAG already exists" + exit 1 + fi + echo "tag=$TAG" >> "$GITHUB_OUTPUT" + echo "Releasing: $TAG" + + - name: Create and push tag + env: + TAG: ${{ steps.version.outputs.tag }} + run: | + git tag "$TAG" + git push origin "$TAG" + + - name: Update floating major tag + env: + TAG: ${{ steps.version.outputs.tag }} + MAJOR: ${{ steps.branch.outputs.major }} + run: | + git tag -f "v${MAJOR}" "$TAG" + git push origin "v${MAJOR}" --force + + - name: Generate release notes and create release + env: + GH_TOKEN: ${{ github.token }} + TAG: ${{ steps.version.outputs.tag }} + MAJOR: ${{ steps.branch.outputs.major }} + run: | + PREV_TAG=$(git tag -l "v${MAJOR}.*" --sort=-v:refname | grep -v "^${TAG}$" | head -n1) + + API_ARGS=(-f tag_name="$TAG") + if [[ -n "$PREV_TAG" ]]; then + API_ARGS+=(-f previous_tag_name="$PREV_TAG") + fi + AUTO_NOTES=$(gh api repos/${{ github.repository }}/releases/generate-notes \ + "${API_ARGS[@]}" --jq '.body') + + DESCRIPTION="${{ inputs.description }}" + if [[ -n "$DESCRIPTION" ]]; then + printf '%s\n\n---\n\n%s' "$DESCRIPTION" "$AUTO_NOTES" > release-notes.md + else + echo "$AUTO_NOTES" > release-notes.md + fi + + gh release create "$TAG" \ + --title "$TAG" \ + --notes-file release-notes.md diff --git a/.github/workflows/test-dependencies.yml b/.github/workflows/test-dependencies.yml index 712ccc6..e50876d 100644 --- a/.github/workflows/test-dependencies.yml +++ b/.github/workflows/test-dependencies.yml @@ -8,8 +8,6 @@ on: branches: - "main" - "release-*" - tags: - - "*" # Declare default permissions as read only permissions: diff --git a/.github/workflows/test-integrations.yml b/.github/workflows/test-integrations.yml index 4413daa..b881934 100644 --- a/.github/workflows/test-integrations.yml +++ b/.github/workflows/test-integrations.yml @@ -8,8 +8,6 @@ on: branches: - "main" - "release-*" - tags: - - "*" # Declare default permissions as read only permissions: diff --git a/README.md b/README.md index da7f6e9..e665a7e 100644 --- a/README.md +++ b/README.md @@ -8,6 +8,10 @@ Shared GitHub Actions and CI workflows used across [Strimzi](https://strimzi.io/) repositories. +> [!IMPORTANT] +> All the actions within this repository are designed for internal usage within Strimzi projects. +> We do not support usage of the actions outside the Strimzi organization. + ## Actions ### Dependency Actions @@ -153,13 +157,13 @@ jobs: ## Versioning -Once we will agree that actions are in stable state we will create first branch/tag to freeze the state. -This branch/tag will be then used in other repositories to freeze actions version to avoid potential issues with failures. -At this point, each repository should implement the testing workflow described above. +This repository uses `vX.Y` release tags (e.g., `v1.0`, `v1.3`) with floating `vX` major tags that always point to the latest release within a major version. +Releases are created from `release-X.x` branches using an automated workflow. +See [RELEASE.md](RELEASE.md) for full details on the versioning scheme and release process. > [!WARNING] -> To ensure that actions will remain functional across the whole project, we have to ensure compatibility between N and N-1 versions of github-actions repository. -> This has to be honored by every change done after the first branch/tag (release) freeze! +> To ensure that actions remain functional across all Strimzi projects, compatibility between N and N-1 versions of the `github-actions` repository must be maintained. +> This must be honored by every change made after the first release. ## License diff --git a/RELEASE.md b/RELEASE.md new file mode 100644 index 0000000..025e6d1 --- /dev/null +++ b/RELEASE.md @@ -0,0 +1,66 @@ +# Release Process + +This document describes the versioning scheme and release process for the `strimzi/github-actions` repository. + +## Versioning Scheme + +| Concept | Format | Example | Description | +|--------------------|---------------|----------------|-----------------------------------------------------| +| Release tag | `vX.Y` | `v1.0`, `v1.3` | Immutable tag pointing to a specific release commit | +| Floating major tag | `vX` | `v1`, `v2` | Always points to the latest `vX.Y` release | +| Release branch | `release-X.x` | `release-1.x` | Branch for a major version series | + +We will then pin to a specific version (`v1.2`) for full reproducibility, or use the floating major tag (`v1`) to automatically get the latest patch within a major version. + +## Creating a Release Branch + +Before the first release of a new major version, create a release branch from `main`: + +```bash +git checkout main +git pull +git checkout -b release-1.x +git push origin release-1.x +``` + +Once you will push the changes, the tests will be automatically triggered and can be review in Actions UI or in commits list. + +## Running the Release Workflow + +The release is performed via the **Release** workflow (`release.yml`), triggered manually using `workflow_dispatch` on a `release-X.x` branch. + +### Inputs + +| Input | Required | Description | +|---------------|----------|---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------| +| `version` | No | Release version (e.g., `1.3`). If empty, the minor version is auto-incremented from the latest `vX.Y` tag. Note that `v` is prepended autoamtically and shouldn't be in input string. | +| `description` | No | Custom release description prepended before the auto-generated changelog. | + +### Auto-increment behavior + +When `version` is left empty, the workflow finds the latest `vX.Y` tag for the branch's major version and increments the minor number. +If no tags exist yet, it starts at `X.0`. + +### Steps to release + +1. Go to **Actions** > **Release** in GitHub. +2. Click **Run workflow**. +3. Select the target `release-X.x` branch. +4. Optionally enter a version and/or description. +5. Click **Run workflow**. + +### What the workflow does + +1. **Validates** the branch matches the `release-X.x` pattern and extracts the major version. +2. **Determines the version** — either from the manual input or by auto-incrementing. +3. **Checks** that the tag does not already exist. +4. **Creates and pushes** the `vX.Y` tag. +5. **Force-updates** the floating `vX` tag to point to the same commit. +6. **Generates release notes** using GitHub's auto-generated changelog, optionally prepended with a custom description. +7. **Creates a GitHub Release** with the generated notes. + +## Compatibility + +> [!WARNING] +> To ensure that actions remain functional across all Strimzi projects, compatibility between N and N-1 versions of the `github-actions` repository must be maintained. +> This must be honored by every change made after the first release.