From f602db62e646b0be97772e7ad3f9fe11cdc4e403 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C5=81ukasz=20Pi=C4=85tkowski?= Date: Thu, 28 May 2026 15:18:32 +0200 Subject: [PATCH 1/9] feat: use gitsemver and add RC support --- .github/actions/gitsemver-install/action.yaml | 70 +++++++++ .github/workflows/create-release-pr.yaml | 136 +++++++++--------- .github/workflows/create-release.yaml | 115 +++++++-------- .github/workflows/release.yaml | 13 +- CHANGELOG.md | 19 +++ 5 files changed, 224 insertions(+), 129 deletions(-) create mode 100644 .github/actions/gitsemver-install/action.yaml diff --git a/.github/actions/gitsemver-install/action.yaml b/.github/actions/gitsemver-install/action.yaml new file mode 100644 index 0000000..81ff7c3 --- /dev/null +++ b/.github/actions/gitsemver-install/action.yaml @@ -0,0 +1,70 @@ +name: Install gitsemver +description: Install and cache the giantswarm/gitsemver binary, prepending it to PATH. + +inputs: + version: + description: gitsemver release tag (e.g. v1.1.1). + required: false + # renovate: datasource=github-releases depName=giantswarm/gitsemver + default: v1.1.1 + +runs: + using: composite + steps: + - name: Resolve install path + id: paths + shell: bash + env: + VERSION: ${{ inputs.version }} + run: | + set -euo pipefail + dir="${RUNNER_TOOL_CACHE}/gitsemver/${VERSION}/${RUNNER_ARCH}" + echo "dir=${dir}" >> "$GITHUB_OUTPUT" + + - name: Restore gitsemver cache + id: cache + uses: actions/cache@27d5ce7f107fe9357f9df03efb73ab90386fccae # v5.0.5 + with: + path: ${{ steps.paths.outputs.dir }} + key: gitsemver-${{ inputs.version }}-${{ runner.os }}-${{ runner.arch }} + + - name: Download gitsemver + if: steps.cache.outputs.cache-hit != 'true' + shell: bash + env: + VERSION: ${{ inputs.version }} + DIR: ${{ steps.paths.outputs.dir }} + run: | + set -euo pipefail + os="$(uname -s | tr '[:upper:]' '[:lower:]')" + case "$(uname -m)" in + x86_64) arch=amd64 ;; + aarch64|arm64) arch=arm64 ;; + *) echo "unsupported architecture: $(uname -m)" >&2; exit 1 ;; + esac + mkdir -p "$DIR" + tmp="$(mktemp -d)" + trap 'rm -rf "$tmp"' EXIT + url="https://github.com/giantswarm/gitsemver/releases/download/${VERSION}/gitsemver-${VERSION}-${os}-${arch}.tar.gz" + curl -fsSL "$url" -o "$tmp/gitsemver.tgz" + tar -xzf "$tmp/gitsemver.tgz" -C "$tmp" + bin="$(find "$tmp" -type f -name gitsemver | head -1)" + if [[ -z "$bin" ]]; then + echo "gitsemver binary not found in tarball $url" >&2 + exit 1 + fi + install -m 0755 "$bin" "$DIR/gitsemver" + + - name: Add gitsemver to PATH + shell: bash + env: + DIR: ${{ steps.paths.outputs.dir }} + run: | + echo "$DIR" >> "$GITHUB_PATH" + + - name: Smoke test + shell: bash + env: + DIR: ${{ steps.paths.outputs.dir }} + run: | + "$DIR/gitsemver" --help > /dev/null diff --git a/.github/workflows/create-release-pr.yaml b/.github/workflows/create-release-pr.yaml index 8ae458c..2835e4f 100644 --- a/.github/workflows/create-release-pr.yaml +++ b/.github/workflows/create-release-pr.yaml @@ -27,94 +27,96 @@ jobs: gather_facts: name: Gather facts runs-on: ubuntu-24.04 + permissions: + contents: read outputs: - repo_name: ${{ steps.gather_facts.outputs.repo_name }} - branch: ${{ steps.gather_facts.outputs.branch }} - base: ${{ steps.gather_facts.outputs.base }} - needs_major_bump: ${{ steps.gather_facts.outputs.needs_major_bump }} + repo_name: ${{ steps.parse.outputs.repo_name }} + branch: ${{ steps.parse.outputs.branch }} + base: ${{ steps.parse.outputs.base }} + needs_major_bump: ${{ steps.resolve.outputs.needs_major_bump }} skip: ${{ steps.check_skip.outputs.skip }} - version: ${{ steps.gather_facts.outputs.version }} + version: ${{ steps.resolve.outputs.version }} + is_rc: ${{ steps.resolve.outputs.is_rc }} steps: - - name: Gather facts - id: gather_facts + - name: Parse trigger + id: parse + env: + INPUT_BRANCH: ${{ inputs.branch }} + EVENT_REF: ${{ github.event.ref }} + EVENT_BASE_REF: ${{ github.event.base_ref }} + REPOSITORY: ${{ github.repository }} run: | - head="${{ inputs.branch || github.event.ref }}" + set -euo pipefail + head="${INPUT_BRANCH:-$EVENT_REF}" echo "branch=${head}" >> $GITHUB_OUTPUT - head="${head#refs/heads/}" # Strip "refs/heads/" prefix. - if [[ $(echo "$head" | grep -o '#' | wc -l) -gt 1 ]]; then - base="$(echo $head | cut -d '#' -f 1)" + head_short="${head#refs/heads/}" + if [[ $(echo "$head_short" | grep -o '#' | wc -l) -gt 1 ]]; then + base="$(echo "$head_short" | cut -d '#' -f 1)" else - base="${{ github.event.base_ref }}" + base="${EVENT_BASE_REF}" fi + base="${base#refs/heads/}" - base="${base#refs/heads/}" # Strip "refs/heads/" prefix. + token="$(echo "$head_short" | awk -F# '{print $NF}')" + repo_name="$(echo "$REPOSITORY" | awk -F '/' '{print $2}')" - version="$(echo $head | awk -F# '{print $NF}')" - if [[ $version =~ ^major|minor|patch$ ]]; then - gh auth login --with-token <<<$(echo -n ${{ secrets.TAYLORBOT_GITHUB_ACTION }}) - gh_api_get_latest_release_version() - { - if ! version="$(gh api "repos/$1/releases/latest" --jq '.tag_name[1:] | split(".") | .[0], .[1], .[2]')" - then - case "$version" in - *Not\ Found*) echo Assuming v0.0.0, hooray first release! >&2 ; version="0 0 0" ;; - *) version="" ; return 1 ;; - esac - fi - echo "$version" - } + echo "base=${base}" >> $GITHUB_OUTPUT + echo "token=${token}" >> $GITHUB_OUTPUT + echo "repo_name=${repo_name}" >> $GITHUB_OUTPUT + echo "branch=${head} base=${base} token=${token} repo=${repo_name}" + + - name: Checkout base + uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2 + with: + ref: ${{ steps.parse.outputs.base }} + fetch-depth: 0 + persist-credentials: false + + - name: Install gitsemver + uses: ./.github/actions/gitsemver-install - version_parts=($(gh_api_get_latest_release_version "${{ github.repository }}")) - version_major=${version_parts[0]} - version_minor=${version_parts[1]} - version_patch=${version_parts[2]} - case ${version} in - patch) - version_patch=$((version_patch+1)) - ;; - minor) - version_minor=$((version_minor+1)) - version_patch=0 - ;; - major) - version_major=$((version_major+1)) - version_minor=0 - version_patch=0 - if [[ "${version_major}" != "1" ]]; then - echo "needs_major_bump=true" >> $GITHUB_OUTPUT - fi - ;; - *) - echo "Unknown Semver level provided" - exit 1 - ;; - esac - version="${version_major}.${version_minor}.${version_patch}" + - name: Resolve version + id: resolve + env: + TOKEN: ${{ steps.parse.outputs.token }} + run: | + set -euo pipefail + bump_tokens='^(major|minor|patch|major-rc|minor-rc|patch-rc|rc|rc-release)$' + if [[ "$TOKEN" =~ $bump_tokens ]]; then + version="$(gitsemver next "$TOKEN")" else - version="${version#v}" # Strip "v" prefix. - version_major=$(echo "${version}" | cut -d "." -f 1) - version_minor=$(echo "${version}" | cut -d "." -f 2) - version_patch=$(echo "${version}" | cut -d "." -f 3) - # This will help us detect versions with suffixes as majors, i.e 3.0.0-alpha1. - # Even though it's a pre-release, it's still a major. - if [[ $version_minor = 0 && $version_patch =~ ^0.* && $version_major != 1 ]]; then - echo "needs_major_bump=true" >> $GITHUB_OUTPUT + candidate="${TOKEN#v}" + if ! gitsemver validate --type any "$candidate" >/dev/null 2>&1; then + echo "::error::Invalid version '$candidate' (must be valid semver per gitsemver)" + exit 1 fi + version="$candidate" fi - repo_name="$(echo '${{ github.repository }}' | awk -F '/' '{print $2}')" - echo "repo_name=\"$repo_name\" base=\"$base\" head=\"$head\" version=\"$version\"" - echo "repo_name=${repo_name}" >> $GITHUB_OUTPUT - echo "base=${base}" >> $GITHUB_OUTPUT - echo "head=${head}" >> $GITHUB_OUTPUT + echo "version=${version}" echo "version=${version}" >> $GITHUB_OUTPUT + # Detect a "new major" release (including its RC) for the go.mod + # upgrade step downstream. A "new major" means X.0.0 (or X.0.0-rc.N) + # with X > 1; X=1 is excluded to preserve legacy behaviour. + core="${version%%-*}" + IFS=. read -r vmaj vmin vpat <<<"$core" + if [[ "$vmin" = "0" && "$vpat" = "0" && "$vmaj" != "1" && "$vmaj" -gt 0 ]]; then + echo "needs_major_bump=true" >> $GITHUB_OUTPUT + fi + + is_rc=false + if gitsemver validate --type rc "$version" >/dev/null 2>&1; then + is_rc=true + fi + echo "is_rc=${is_rc}" >> $GITHUB_OUTPUT + - name: Check if workflow should be skipped id: check_skip env: GITHUB_TOKEN: "${{ secrets.TAYLORBOT_GITHUB_ACTION }}" run: | - head="${{ steps.gather_facts.outputs.branch }}" + head="${{ steps.parse.outputs.branch }}" branch="${head#refs/heads/}" # Strip "refs/heads/" prefix. # Check if PR already exists diff --git a/.github/workflows/create-release.yaml b/.github/workflows/create-release.yaml index 510bd0d..fbb4c65 100644 --- a/.github/workflows/create-release.yaml +++ b/.github/workflows/create-release.yaml @@ -34,36 +34,48 @@ jobs: contents: read outputs: project_go_path: ${{ steps.get_project_go_path.outputs.path }} - ref_version: ${{ steps.ref_version.outputs.refversion }} version: ${{ steps.get_version.outputs.version }} + is_rc: ${{ steps.get_version.outputs.is_rc }} steps: + - name: Checkout code + uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2 + with: + persist-credentials: false + - name: Install gitsemver + uses: ./.github/actions/gitsemver-install - name: Get version id: get_version env: COMMIT_MESSAGE: ${{ github.event.head_commit.message }} run: | - title=$(echo -n "${COMMIT_MESSAGE}" | head -1) - # Matches strings like: - # + set -euo pipefail + # Accept release-PR titles of the form: # - "chore(release): v1.2.3" - # - "chore(release): v1.2.3-r4" + # - "chore(release): v1.2.3-rc.4" # - "chore(release): v1.2.3 (#56)" - # - "chore(release): v1.2.3-r4 (#56)" - # - # The legacy "Release v..." form is also accepted for - # backward compatibility with PRs created by older versions - # of the create-release-pr workflow. - # - # And outputs version part (1.2.3). - if echo "${title}" | grep -iqE '^(chore\(release\):|Release) v[0-9]+\.[0-9]+\.[0-9]+([.-][^ .-][^ ]*)?( \(#[0-9]+\))?$' ; then - version=$(echo "${title}" | cut -d ' ' -f 2) + # The legacy "Release v..." form is also accepted for backward + # compatibility with PRs created by older versions of + # create-release-pr.yaml. Anything else (no match) yields an empty + # version output, which short-circuits the workflow as before. + title=$(echo -n "${COMMIT_MESSAGE}" | head -1) + version="" + is_rc=false + if echo "${title}" | grep -iqE '^(chore\(release\):|Release) v[^ ]+( \(#[0-9]+\))?$' ; then + candidate=$(echo "${title}" | cut -d ' ' -f 2) + candidate="${candidate#v}" + if gitsemver validate --type any "${candidate}" >/dev/null 2>&1; then + version="${candidate}" + if gitsemver validate --type rc "${candidate}" >/dev/null 2>&1; then + is_rc=true + fi + else + echo "::error::Title looks like a release commit but '${candidate}' is not a valid semver per gitsemver." + exit 1 + fi fi - version="${version#v}" # Strip "v" prefix. - echo "version=\"${version}\"" + echo "version=\"${version}\" is_rc=\"${is_rc}\"" echo "version=${version}" >> $GITHUB_OUTPUT - - name: Checkout code - if: ${{ steps.get_version.outputs.version != '' }} - uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2 + echo "is_rc=${is_rc}" >> $GITHUB_OUTPUT - name: Get project.go path id: get_project_go_path if: ${{ steps.get_version.outputs.version != '' }} @@ -74,29 +86,12 @@ jobs: fi echo "path=\"$path\"" echo "path=${path}" >> $GITHUB_OUTPUT - - name: Check if reference version - id: ref_version - env: - COMMIT_MESSAGE: ${{ github.event.head_commit.message }} - run: | - title=$(echo -n "${COMMIT_MESSAGE}" | head -1) - if echo "${title}" | grep -iqE '^(chore\(release\):|Release) v[0-9]+\.[0-9]+\.[0-9]+([.-][^ .-][^ ]*)?( \(#[0-9]+\))?$' ; then - version=$(echo "${title}" | cut -d ' ' -f 2) - fi - version=$(echo "${title}" | cut -d ' ' -f 2) - version="${version#v}" # Strip "v" prefix. - refversion=false - if [[ "${version}" =~ ^[0-9]+.[0-9]+.[0-9]+-[0-9]+$ ]]; then - refversion=true - fi - echo "refversion =\"${refversion}\"" - echo "refversion=${refversion}" >> $GITHUB_OUTPUT update_project_go: name: Update project.go runs-on: ubuntu-24.04 permissions: contents: read - if: ${{ needs.gather_facts.outputs.version != '' && needs.gather_facts.outputs.project_go_path != '' && needs.gather_facts.outputs.ref_version != 'true' }} + if: ${{ needs.gather_facts.outputs.version != '' && needs.gather_facts.outputs.project_go_path != '' }} needs: - gather_facts steps: @@ -105,27 +100,32 @@ jobs: with: binary: "architect" version: "6.14.1" - - name: Install semver - uses: giantswarm/install-binary-action@5bef88f65012037dd836117c8d344b21bb559854 # v4.1.0 - with: - binary: "semver" - version: "3.2.0" - download_url: "https://github.com/fsaintjacques/${binary}-tool/archive/${version}.tar.gz" - tarball_binary_path: "*/src/${binary}" - smoke_test: "${binary} --version" - name: Checkout code uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2 with: + fetch-depth: 0 persist-credentials: false + - name: Install gitsemver + uses: ./.github/actions/gitsemver-install - name: Update project.go id: update_project_go env: branch: "${{ github.ref }}-version-bump" + IS_RC: "${{ needs.gather_facts.outputs.is_rc }}" run: | + set -euo pipefail git checkout -b ${{ env.branch }} file="${{ needs.gather_facts.outputs.project_go_path }}" version="${{ needs.gather_facts.outputs.version }}" - new_version="$(semver bump patch $version)-dev" + if [[ "${IS_RC}" == "true" ]]; then + # An RC like 1.3.0-rc.1 returns project.go to the dev string for the + # stable it is leading toward (1.3.0-dev). This way successive RCs + # do not drift project.go forward and the final stable release lands + # on the version project.go already advertises. + new_version="${version%-rc.*}-dev" + else + new_version="$(gitsemver next patch --last-tag "v${version}")-dev" + fi echo "version=\"$version\" new_version=\"$new_version\"" echo "new_version=${new_version}" >> $GITHUB_OUTPUT sed -Ei "s/(version[[:space:]]*=[[:space:]]*)\"${version}\"/\1\"${new_version}\"/" $file @@ -185,7 +185,7 @@ jobs: ref: ${{ github.sha }} persist-credentials: false - name: Ensure correct version in project.go - if: ${{ needs.gather_facts.outputs.project_go_path != '' && needs.gather_facts.outputs.ref_version != 'true' }} + if: ${{ needs.gather_facts.outputs.project_go_path != '' }} run: | file="${{ needs.gather_facts.outputs.project_go_path }}" version="${{ needs.gather_facts.outputs.version }}" @@ -252,24 +252,18 @@ jobs: contents: write needs: - gather_facts - if: ${{ needs.gather_facts.outputs.version }} + if: ${{ needs.gather_facts.outputs.version && needs.gather_facts.outputs.is_rc != 'true' }} steps: - - name: Install semver - uses: giantswarm/install-binary-action@5bef88f65012037dd836117c8d344b21bb559854 # v4.1.0 - with: - binary: "semver" - version: "3.0.0" - download_url: "https://github.com/fsaintjacques/${binary}-tool/archive/${version}.tar.gz" - tarball_binary_path: "*/src/${binary}" - smoke_test: "${binary} --version" - name: Check out the repository uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2 with: fetch-depth: 0 # Clone the whole history, not just the most recent commit. + persist-credentials: false - name: Fetch all tags and branches run: "git fetch --all" - name: Create long-lived release branch run: | + set -euo pipefail current_version="${{ needs.gather_facts.outputs.version }}" parent_version="$(git describe --tags --abbrev=0 HEAD^ || true)" parent_version="${parent_version#v}" # Strip "v" prefix. @@ -281,10 +275,11 @@ jobs: echo "current_version=$current_version parent_version=$parent_version" - current_major=$(semver get major $current_version) - current_minor=$(semver get minor $current_version) - parent_major=$(semver get major $parent_version) - parent_minor=$(semver get minor $parent_version) + # Strip any pre-release suffix before splitting on '.', so a parent tag + # that happens to be an RC (e.g. 1.2.3-rc.4) is treated as 1.2.3 for + # the comparison. + IFS=. read -r current_major current_minor _ <<<"${current_version%%-*}" + IFS=. read -r parent_major parent_minor _ <<<"${parent_version%%-*}" echo "current_major=$current_major current_minor=$current_minor" echo "parent_major=$parent_major parent_minor=$parent_minor" diff --git a/.github/workflows/release.yaml b/.github/workflows/release.yaml index 9930d7d..00d2fa2 100644 --- a/.github/workflows/release.yaml +++ b/.github/workflows/release.yaml @@ -113,12 +113,21 @@ jobs: current=$(manifest_version "$base_branch") next=$(manifest_version "$head_branch") - IFS=. read -r cmaj cmin cpat <<<"$current" - IFS=. read -r nmaj nmin npat <<<"$next" + # release-please supports a "prerelease" versioning strategy that + # produces tags like 1.3.0-rc.1. Strip any pre-release suffix before + # the numeric compare so an RC-only step (1.3.0-rc.1 -> 1.3.0-rc.2) + # or the RC -> stable promotion (1.3.0-rc.2 -> 1.3.0) doesn't + # classify as bump=none and silently disable auto-merge. An RC-only + # change of the same X.Y.Z triple is treated as a patch-level bump. + current_core="${current%%-*}" + next_core="${next%%-*}" + IFS=. read -r cmaj cmin cpat <<<"$current_core" + IFS=. read -r nmaj nmin npat <<<"$next_core" if [ "$nmaj" -gt "$cmaj" ]; then bump=major elif [ "$nmin" -gt "$cmin" ]; then bump=minor elif [ "$npat" -gt "$cpat" ]; then bump=patch + elif [ "$current" != "$next" ]; then bump=patch else bump=none fi diff --git a/CHANGELOG.md b/CHANGELOG.md index 60e41e3..c9ada3b 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -6,6 +6,25 @@ The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/), however this project does not use Semantic Versioning and there are no releases. Instead this file uses a date-based structure. +## 2026-05-28 + +### Added + +- New local composite action `.github/actions/gitsemver-install` installs and caches the [`giantswarm/gitsemver`](https://github.com/giantswarm/gitsemver) binary (default `v1.1.1`, Renovate-tracked) on the runner. Used by `create-release-pr.yaml` and `create-release.yaml`; restores from `actions/cache` keyed on the version + `runner.os`/`runner.arch`, only downloading on a cache miss. +- `create-release-pr.yaml` accepts new bump tokens on the trigger branch (`branch#`): `patch-rc`, `minor-rc`, `major-rc`, `rc`, `rc-release`. They are passed verbatim to `gitsemver next` and produce release-candidate versions like `v1.3.0-rc.1`, `v1.3.0-rc.2`, then `v1.3.0` via `rc-release`. The existing `patch` / `minor` / `major` tokens continue to work unchanged. +- `create-release.yaml` exposes a new `is_rc` output on its `gather_facts` job (true when the released tag is an RC per `gitsemver validate --type rc`). + +### Changed + +- `create-release-pr.yaml` now computes the next version with `gitsemver next ` instead of the inline `gh api releases/latest` + manual increment. Explicit-version trigger branches (`branch#vX.Y.Z[-rc.N]`) are now validated by `gitsemver validate --type any` and rejected on invalid input — strings that previously slipped through the loose regex (e.g. `1.2.3.foo`) are now hard failures with a clear error. The job now checks out the base branch with `fetch-depth: 0` and `persist-credentials: false` so gitsemver can see full tag history. +- `create-release.yaml` validates the version parsed from the release-PR commit title with `gitsemver` rather than an inline regex. RC tags (`vX.Y.Z-rc.N`) are first-class: they create the tag and GH release like a stable version, and they DO still trigger the post-release `-dev` bump of `project.go` (the new dev string targets the stable the RC is leading toward, e.g. `1.3.0-rc.1` ➝ `1.3.0-dev`). The long-lived `release-vX.Y.x` branch is only cut for stable major/minor releases — RC releases skip that job. +- `release.yaml` (release-please) auto-merge reconciler now strips any pre-release suffix from the manifest versions before the numeric `X.Y.Z` compare, so a `1.3.0-rc.1 → 1.3.0-rc.2` PR (or an RC ➝ stable promotion) is classified as `bump=patch` rather than silently `bump=none`. Auto-merge therefore honours the configured `auto-merge-level` ceiling on RC PRs too. Consumers wanting RC support on this path enable it in their own `release-please-config.json` with `"versioning": "prerelease"`, `"prerelease": true`, `"prerelease-type": "rc"` — `release.yaml` itself stays single-code-path. + +### Removed + +- `create-release.yaml` no longer recognises the legacy "reference version" form `vX.Y.Z-N` (e.g. `v1.2.3-4`) — the dedicated `ref_version` job and its special-case regex are gone. Any repo still pushing such tags via this workflow will need to migrate to the RC form (`vX.Y.Z-rc.N`). +- `create-release.yaml` and `create-release-pr.yaml` no longer install `fsaintjacques/semver-tool`; all next-version arithmetic now goes through `gitsemver` (or bash parameter expansion on a version string already validated by it). + ## 2026-05-27 ### Added From fa4b8a11acf60f70878d744cd6a812c9a06d2b4b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C5=81ukasz=20Pi=C4=85tkowski?= Date: Mon, 1 Jun 2026 17:11:19 +0200 Subject: [PATCH 2/9] fix(release): install gitsemver via install-binary-action, drop dead architect MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The local composite action .github/actions/gitsemver-install was referenced as 'uses: ./.github/actions/...' from create-release.yaml and create-release-pr.yaml, but those are reusable (workflow_call) workflows that run in the caller's repo context — the path resolves against the consumer's checkout, which lacks the action, so it failed for every consumer. Replace all three usages with giantswarm/install-binary-action (gitsemver v1.1.2, which also fixes the --version flag) and delete the composite action. Also: - Remove the unused architect install from update_project_go (the -dev bump is done entirely by gitsemver + sed; architect was never invoked there). - Drop the dangling 'ref_version' if: guards left over after that output was removed (they always evaluated truthy). - Annotate the build-artifacts architect install as transitional: it only serves consumer Makefiles still on the pre-gitsemver devctl template (architect project version); devctl's current template uses gitsemver version. Aligns with architect-orb v9.0.0, making gitsemver the single source of git-based semver. Co-Authored-By: Claude Opus 4.8 --- .github/actions/gitsemver-install/action.yaml | 70 ------------------- .github/workflows/create-release-pr.yaml | 9 ++- .github/workflows/create-release.yaml | 36 ++++++---- CHANGELOG.md | 13 +++- 4 files changed, 44 insertions(+), 84 deletions(-) delete mode 100644 .github/actions/gitsemver-install/action.yaml diff --git a/.github/actions/gitsemver-install/action.yaml b/.github/actions/gitsemver-install/action.yaml deleted file mode 100644 index 81ff7c3..0000000 --- a/.github/actions/gitsemver-install/action.yaml +++ /dev/null @@ -1,70 +0,0 @@ -name: Install gitsemver -description: Install and cache the giantswarm/gitsemver binary, prepending it to PATH. - -inputs: - version: - description: gitsemver release tag (e.g. v1.1.1). - required: false - # renovate: datasource=github-releases depName=giantswarm/gitsemver - default: v1.1.1 - -runs: - using: composite - steps: - - name: Resolve install path - id: paths - shell: bash - env: - VERSION: ${{ inputs.version }} - run: | - set -euo pipefail - dir="${RUNNER_TOOL_CACHE}/gitsemver/${VERSION}/${RUNNER_ARCH}" - echo "dir=${dir}" >> "$GITHUB_OUTPUT" - - - name: Restore gitsemver cache - id: cache - uses: actions/cache@27d5ce7f107fe9357f9df03efb73ab90386fccae # v5.0.5 - with: - path: ${{ steps.paths.outputs.dir }} - key: gitsemver-${{ inputs.version }}-${{ runner.os }}-${{ runner.arch }} - - - name: Download gitsemver - if: steps.cache.outputs.cache-hit != 'true' - shell: bash - env: - VERSION: ${{ inputs.version }} - DIR: ${{ steps.paths.outputs.dir }} - run: | - set -euo pipefail - os="$(uname -s | tr '[:upper:]' '[:lower:]')" - case "$(uname -m)" in - x86_64) arch=amd64 ;; - aarch64|arm64) arch=arm64 ;; - *) echo "unsupported architecture: $(uname -m)" >&2; exit 1 ;; - esac - mkdir -p "$DIR" - tmp="$(mktemp -d)" - trap 'rm -rf "$tmp"' EXIT - url="https://github.com/giantswarm/gitsemver/releases/download/${VERSION}/gitsemver-${VERSION}-${os}-${arch}.tar.gz" - curl -fsSL "$url" -o "$tmp/gitsemver.tgz" - tar -xzf "$tmp/gitsemver.tgz" -C "$tmp" - bin="$(find "$tmp" -type f -name gitsemver | head -1)" - if [[ -z "$bin" ]]; then - echo "gitsemver binary not found in tarball $url" >&2 - exit 1 - fi - install -m 0755 "$bin" "$DIR/gitsemver" - - - name: Add gitsemver to PATH - shell: bash - env: - DIR: ${{ steps.paths.outputs.dir }} - run: | - echo "$DIR" >> "$GITHUB_PATH" - - - name: Smoke test - shell: bash - env: - DIR: ${{ steps.paths.outputs.dir }} - run: | - "$DIR/gitsemver" --help > /dev/null diff --git a/.github/workflows/create-release-pr.yaml b/.github/workflows/create-release-pr.yaml index 2835e4f..c5debc7 100644 --- a/.github/workflows/create-release-pr.yaml +++ b/.github/workflows/create-release-pr.yaml @@ -74,7 +74,14 @@ jobs: persist-credentials: false - name: Install gitsemver - uses: ./.github/actions/gitsemver-install + uses: giantswarm/install-binary-action@5bef88f65012037dd836117c8d344b21bb559854 # v4.1.0 + with: + binary: "gitsemver" + # renovate: datasource=github-releases depName=giantswarm/gitsemver + version: "1.1.2" + download_url: "https://github.com/giantswarm/${binary}/releases/download/v${version}/${binary}-v${version}-linux-amd64.tar.gz" + tarball_binary_path: "*/${binary}" + smoke_test: "${binary} --version" - name: Resolve version id: resolve diff --git a/.github/workflows/create-release.yaml b/.github/workflows/create-release.yaml index 06e8b5c..b387803 100644 --- a/.github/workflows/create-release.yaml +++ b/.github/workflows/create-release.yaml @@ -42,7 +42,14 @@ jobs: with: persist-credentials: false - name: Install gitsemver - uses: ./.github/actions/gitsemver-install + uses: giantswarm/install-binary-action@5bef88f65012037dd836117c8d344b21bb559854 # v4.1.0 + with: + binary: "gitsemver" + # renovate: datasource=github-releases depName=giantswarm/gitsemver + version: "1.1.2" + download_url: "https://github.com/giantswarm/${binary}/releases/download/v${version}/${binary}-v${version}-linux-amd64.tar.gz" + tarball_binary_path: "*/${binary}" + smoke_test: "${binary} --version" - name: Get version id: get_version env: @@ -92,23 +99,24 @@ jobs: permissions: contents: read if: - ${{ needs.gather_facts.outputs.version != '' && needs.gather_facts.outputs.project_go_path != '' && - needs.gather_facts.outputs.ref_version != 'true' }} + ${{ needs.gather_facts.outputs.version != '' && needs.gather_facts.outputs.project_go_path != '' }} needs: - gather_facts steps: - - name: Install architect - uses: giantswarm/install-binary-action@5bef88f65012037dd836117c8d344b21bb559854 # v4.1.0 - with: - binary: "architect" - version: "6.14.1" - name: Checkout code uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2 with: fetch-depth: 0 persist-credentials: false - name: Install gitsemver - uses: ./.github/actions/gitsemver-install + uses: giantswarm/install-binary-action@5bef88f65012037dd836117c8d344b21bb559854 # v4.1.0 + with: + binary: "gitsemver" + # renovate: datasource=github-releases depName=giantswarm/gitsemver + version: "1.1.2" + download_url: "https://github.com/giantswarm/${binary}/releases/download/v${version}/${binary}-v${version}-linux-amd64.tar.gz" + tarball_binary_path: "*/${binary}" + smoke_test: "${binary} --version" - name: Update project.go id: update_project_go env: @@ -189,9 +197,7 @@ jobs: ref: ${{ github.sha }} persist-credentials: false - name: Ensure correct version in project.go - if: - ${{ needs.gather_facts.outputs.project_go_path != '' && needs.gather_facts.outputs.ref_version != - 'true' }} + if: ${{ needs.gather_facts.outputs.project_go_path != '' }} run: | file="${{ needs.gather_facts.outputs.project_go_path }}" version="${{ needs.gather_facts.outputs.version }}" @@ -335,6 +341,11 @@ jobs: - create_release - gather_facts steps: + # Transitional: only needed by consumer Makefiles still on the pre-gitsemver + # devctl template, where `VERSION := $(shell architect project version)` + # stamps the release artifacts. devctl's current template uses + # `gitsemver version` (installed below), so this install can be dropped + # once all consumers have regenerated their Makefile.gen.go.mk. - name: Install architect uses: giantswarm/install-binary-action@5bef88f65012037dd836117c8d344b21bb559854 # v4.1.0 with: @@ -344,6 +355,7 @@ jobs: uses: giantswarm/install-binary-action@5bef88f65012037dd836117c8d344b21bb559854 # v4.1.0 with: binary: "gitsemver" + # renovate: datasource=github-releases depName=giantswarm/gitsemver version: "1.1.2" download_url: "https://github.com/giantswarm/${binary}/releases/download/v${version}/${binary}-v${version}-linux-amd64.tar.gz" tarball_binary_path: "*/${binary}" diff --git a/CHANGELOG.md b/CHANGELOG.md index c9ada3b..21638ec 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -6,11 +6,22 @@ The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/), however this project does not use Semantic Versioning and there are no releases. Instead this file uses a date-based structure. +## 2026-06-01 + +### Changed + +- `create-release-pr.yaml` and `create-release.yaml` install [`giantswarm/gitsemver`](https://github.com/giantswarm/gitsemver) `v1.1.2` via `giantswarm/install-binary-action` (the same mechanism already used for `architect` and Renovate-tracked), replacing the short-lived local composite action `.github/actions/gitsemver-install`. A local composite referenced as `uses: ./.github/actions/...` does not resolve inside a reusable (`workflow_call`) workflow — the runner looks the path up in the **caller** repository's checkout, not in `github-workflows` — so it failed for every consumer of these workflows. `v1.1.2` also fixes the `gitsemver --version` self-info flag, which the install step's smoke test now uses. This aligns these workflows with `architect-orb` v9.0.0, where `gitsemver` is the single source of git-based semver. +- `create-release.yaml`'s build-artifacts job keeps installing `architect` purely as a transition aid: consumer Makefiles still on the pre-gitsemver `devctl` template stamp release artifacts with `VERSION := $(shell architect project version)`. `devctl`'s current `Makefile.gen.go.mk` template uses `gitsemver version` (already installed in that job), so the `architect` install becomes removable once all consumers regenerate their Makefile. No version or git tag in these workflows is produced by `architect` — `gitsemver` is the sole source (`architect prepare-release` only consumes the already-resolved `--version`). + +### Removed + +- `create-release.yaml` no longer installs the `architect` binary in the `update_project_go` job. It was installed but never invoked — the post-release `-dev` bump of `project.go` is computed entirely with `gitsemver next patch` plus a `sed` rewrite. +- `create-release.yaml` drops the leftover `needs.gather_facts.outputs.ref_version != 'true'` guards on the `update_project_go` job and the `Ensure correct version in project.go` step. The `ref_version` output was removed together with the legacy reference-version handling, so the guards always evaluated truthy and only obscured the real conditions. + ## 2026-05-28 ### Added -- New local composite action `.github/actions/gitsemver-install` installs and caches the [`giantswarm/gitsemver`](https://github.com/giantswarm/gitsemver) binary (default `v1.1.1`, Renovate-tracked) on the runner. Used by `create-release-pr.yaml` and `create-release.yaml`; restores from `actions/cache` keyed on the version + `runner.os`/`runner.arch`, only downloading on a cache miss. - `create-release-pr.yaml` accepts new bump tokens on the trigger branch (`branch#`): `patch-rc`, `minor-rc`, `major-rc`, `rc`, `rc-release`. They are passed verbatim to `gitsemver next` and produce release-candidate versions like `v1.3.0-rc.1`, `v1.3.0-rc.2`, then `v1.3.0` via `rc-release`. The existing `patch` / `minor` / `major` tokens continue to work unchanged. - `create-release.yaml` exposes a new `is_rc` output on its `gather_facts` job (true when the released tag is an RC per `gitsemver validate --type rc`). From a3a063a4a930b0925765e08fa59438ae3236b284 Mon Sep 17 00:00:00 2001 From: QuentinBisson Date: Tue, 2 Jun 2026 18:40:44 +0200 Subject: [PATCH 3/9] Bump gitsemver to v2.0.0 v2.0.0 only renamed `version` to `get`; `next` and `validate` are unchanged. --- .github/workflows/create-release-pr.yaml | 2 +- .github/workflows/create-release.yaml | 6 +++--- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/.github/workflows/create-release-pr.yaml b/.github/workflows/create-release-pr.yaml index c5debc7..69c5848 100644 --- a/.github/workflows/create-release-pr.yaml +++ b/.github/workflows/create-release-pr.yaml @@ -78,7 +78,7 @@ jobs: with: binary: "gitsemver" # renovate: datasource=github-releases depName=giantswarm/gitsemver - version: "1.1.2" + version: "2.0.0" download_url: "https://github.com/giantswarm/${binary}/releases/download/v${version}/${binary}-v${version}-linux-amd64.tar.gz" tarball_binary_path: "*/${binary}" smoke_test: "${binary} --version" diff --git a/.github/workflows/create-release.yaml b/.github/workflows/create-release.yaml index b387803..274df48 100644 --- a/.github/workflows/create-release.yaml +++ b/.github/workflows/create-release.yaml @@ -46,7 +46,7 @@ jobs: with: binary: "gitsemver" # renovate: datasource=github-releases depName=giantswarm/gitsemver - version: "1.1.2" + version: "2.0.0" download_url: "https://github.com/giantswarm/${binary}/releases/download/v${version}/${binary}-v${version}-linux-amd64.tar.gz" tarball_binary_path: "*/${binary}" smoke_test: "${binary} --version" @@ -113,7 +113,7 @@ jobs: with: binary: "gitsemver" # renovate: datasource=github-releases depName=giantswarm/gitsemver - version: "1.1.2" + version: "2.0.0" download_url: "https://github.com/giantswarm/${binary}/releases/download/v${version}/${binary}-v${version}-linux-amd64.tar.gz" tarball_binary_path: "*/${binary}" smoke_test: "${binary} --version" @@ -356,7 +356,7 @@ jobs: with: binary: "gitsemver" # renovate: datasource=github-releases depName=giantswarm/gitsemver - version: "1.1.2" + version: "2.0.0" download_url: "https://github.com/giantswarm/${binary}/releases/download/v${version}/${binary}-v${version}-linux-amd64.tar.gz" tarball_binary_path: "*/${binary}" smoke_test: "${binary} --version" From 7603adc42fe8e4098090ff9310318c4aad1b77b9 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C5=81ukasz=20Pi=C4=85tkowski?= Date: Wed, 3 Jun 2026 14:12:59 +0200 Subject: [PATCH 4/9] edit changelog --- CHANGELOG.md | 296 +-------------------------------------------------- 1 file changed, 4 insertions(+), 292 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 21638ec..af91334 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -2,299 +2,11 @@ All notable changes to this project will be documented in this file. -The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/), -however this project does not use Semantic Versioning and there are no releases. -Instead this file uses a date-based structure. +The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/), however this project does not +use Semantic Versioning and there are no releases. Instead this file uses a date-based structure. -## 2026-06-01 +## Unreleased ### Changed -- `create-release-pr.yaml` and `create-release.yaml` install [`giantswarm/gitsemver`](https://github.com/giantswarm/gitsemver) `v1.1.2` via `giantswarm/install-binary-action` (the same mechanism already used for `architect` and Renovate-tracked), replacing the short-lived local composite action `.github/actions/gitsemver-install`. A local composite referenced as `uses: ./.github/actions/...` does not resolve inside a reusable (`workflow_call`) workflow — the runner looks the path up in the **caller** repository's checkout, not in `github-workflows` — so it failed for every consumer of these workflows. `v1.1.2` also fixes the `gitsemver --version` self-info flag, which the install step's smoke test now uses. This aligns these workflows with `architect-orb` v9.0.0, where `gitsemver` is the single source of git-based semver. -- `create-release.yaml`'s build-artifacts job keeps installing `architect` purely as a transition aid: consumer Makefiles still on the pre-gitsemver `devctl` template stamp release artifacts with `VERSION := $(shell architect project version)`. `devctl`'s current `Makefile.gen.go.mk` template uses `gitsemver version` (already installed in that job), so the `architect` install becomes removable once all consumers regenerate their Makefile. No version or git tag in these workflows is produced by `architect` — `gitsemver` is the sole source (`architect prepare-release` only consumes the already-resolved `--version`). - -### Removed - -- `create-release.yaml` no longer installs the `architect` binary in the `update_project_go` job. It was installed but never invoked — the post-release `-dev` bump of `project.go` is computed entirely with `gitsemver next patch` plus a `sed` rewrite. -- `create-release.yaml` drops the leftover `needs.gather_facts.outputs.ref_version != 'true'` guards on the `update_project_go` job and the `Ensure correct version in project.go` step. The `ref_version` output was removed together with the legacy reference-version handling, so the guards always evaluated truthy and only obscured the real conditions. - -## 2026-05-28 - -### Added - -- `create-release-pr.yaml` accepts new bump tokens on the trigger branch (`branch#`): `patch-rc`, `minor-rc`, `major-rc`, `rc`, `rc-release`. They are passed verbatim to `gitsemver next` and produce release-candidate versions like `v1.3.0-rc.1`, `v1.3.0-rc.2`, then `v1.3.0` via `rc-release`. The existing `patch` / `minor` / `major` tokens continue to work unchanged. -- `create-release.yaml` exposes a new `is_rc` output on its `gather_facts` job (true when the released tag is an RC per `gitsemver validate --type rc`). - -### Changed - -- `create-release-pr.yaml` now computes the next version with `gitsemver next ` instead of the inline `gh api releases/latest` + manual increment. Explicit-version trigger branches (`branch#vX.Y.Z[-rc.N]`) are now validated by `gitsemver validate --type any` and rejected on invalid input — strings that previously slipped through the loose regex (e.g. `1.2.3.foo`) are now hard failures with a clear error. The job now checks out the base branch with `fetch-depth: 0` and `persist-credentials: false` so gitsemver can see full tag history. -- `create-release.yaml` validates the version parsed from the release-PR commit title with `gitsemver` rather than an inline regex. RC tags (`vX.Y.Z-rc.N`) are first-class: they create the tag and GH release like a stable version, and they DO still trigger the post-release `-dev` bump of `project.go` (the new dev string targets the stable the RC is leading toward, e.g. `1.3.0-rc.1` ➝ `1.3.0-dev`). The long-lived `release-vX.Y.x` branch is only cut for stable major/minor releases — RC releases skip that job. -- `release.yaml` (release-please) auto-merge reconciler now strips any pre-release suffix from the manifest versions before the numeric `X.Y.Z` compare, so a `1.3.0-rc.1 → 1.3.0-rc.2` PR (or an RC ➝ stable promotion) is classified as `bump=patch` rather than silently `bump=none`. Auto-merge therefore honours the configured `auto-merge-level` ceiling on RC PRs too. Consumers wanting RC support on this path enable it in their own `release-please-config.json` with `"versioning": "prerelease"`, `"prerelease": true`, `"prerelease-type": "rc"` — `release.yaml` itself stays single-code-path. - -### Removed - -- `create-release.yaml` no longer recognises the legacy "reference version" form `vX.Y.Z-N` (e.g. `v1.2.3-4`) — the dedicated `ref_version` job and its special-case regex are gone. Any repo still pushing such tags via this workflow will need to migrate to the RC form (`vX.Y.Z-rc.N`). -- `create-release.yaml` and `create-release-pr.yaml` no longer install `fsaintjacques/semver-tool`; all next-version arithmetic now goes through `gitsemver` (or bash parameter expansion on a version string already validated by it). - -## 2026-05-27 - -### Added - -- `release.yaml` (release-please reusable workflow) gained an `auto-merge-level` input (`none`, `patch`, `minor`, `major`; default `none`). When set, the workflow enables GitHub auto-merge (`gh pr merge --auto --squash`) on the open release-please PR if the PR's bump is no larger than the configured ceiling, so the PR merges automatically once CI passes. The bump is derived from `.release-please-manifest.json` (next version on the PR head branch vs. current version on the base branch), so it is independent of each caller's PR-title configuration. Auto-merge is reconciled on every run — if a release-please PR's bump grows past the ceiling (e.g. from `patch` to `major`) before it is merged, auto-merge is disabled again. The default `none` preserves the previous behaviour (no auto-merge). The merge is performed with the `release-please` GitHub App token, so the merge is attributed to the App; the App must be granted bypass on any branch protection and the repository must have "Allow auto-merge" enabled. - -### Changed - -- `release.yaml` (release-please reusable workflow) now authenticates via a GitHub App instead of a PAT. Callers must pass `RELEASE_PLEASE_CLIENT_ID` and `RELEASE_PLEASE_PRIVATE_KEY` secrets in place of `TAYLORBOT_GITHUB_ACTION`. Using an App token (minted by `actions/create-github-app-token`) means release PRs trigger downstream workflows — unlike commits made with `GITHUB_TOKEN` or PRs opened by a PAT in some configurations — and removes the dependency on the taylorbot user account. -- `create-release-pr` now opens release PRs with a Conventional Commits-compatible title of the form `chore(release): vX.Y.Z` (previously `Release vX.Y.Z`). The release commit message it creates uses the same form. -- `create-release` and `update-action-version` accept both the new `chore(release): vX.Y.Z` form and the legacy `Release vX.Y.Z` form, so in-flight release PRs created by older versions of `create-release-pr` continue to be picked up after their merge commit lands. -- `validate-changelog.yaml` now validates the H3 sections of the version block against the [Keep a Changelog](https://keepachangelog.com/en/1.1.0/) set: `### Added`, `### Changed`, `### Deprecated`, `### Removed`, `### Fixed`, `### Security`. Unknown H3 sections fail validation. `### Security` is accepted for CVE fixes and vulnerability mitigations. Release CHANGELOGs that do not use `### Security` continue to pass. -- `fix-vulnerabilities` now opens PRs with the Conventional Commits title `fix(nancy): remediate findings on ` (previously `Remediate Nancy findings on `). The intermediate commit it creates uses `fix(nancy): remediate nancy findings`. -- `update-chart` now opens PRs with the Conventional Commits title `chore(chart): automated update from upstream` (previously `Automated update from upstream`). The intermediate commit it creates uses the same form. - -## 2026-05-20 - -### Added - -- Add reusable workflow `semantic-pull-request.yaml`. Validates that a pull request title follows Conventional Commits, using `amannn/action-semantic-pull-request`'s default type set (sourced from [`commitizen/conventional-commit-types`](https://github.com/commitizen/conventional-commit-types): `build`, `chore`, `ci`, `docs`, `feat`, `fix`, `perf`, `refactor`, `revert`, `style`, `test`). Callers trigger it on `pull_request` with `types: [opened, edited, synchronize]`. - -## 2026-05-19 - -### Changed - -- Replace `mindsers/changelog-reader-action` with an inline `awk` extractor in the `create-release` workflow. The upstream action is unmaintained and still runs on Node 20, which is being deprecated by GitHub Actions on 2026-06-02 (see [giantswarm/giantswarm#36091](https://github.com/giantswarm/giantswarm/issues/36091)). Inline shell has no Node runtime, so the workflow is no longer exposed to future Node-deprecation cycles. The replacement was validated byte-for-byte against 128 historical release bodies produced by the action across 100 consumer repos. - -## 2026-05-12 - -### Added - -- Add reusable workflow `js-dependency-audit.yaml`. It runs an audit (`npm`, `pnpm`, `yarn npm audit`, or `yarn audit`) on every JS project in a PR's head and base, then posts a sticky PR comment summarizing vulnerabilities and highlighting which ones the PR adds or removes. - -## 2026-05-11 - -### Fixed - -- Renamed `HERALD_CLIENT_ID` to `HERALD_APP_ID` in fix-vulnerabilities workflow to avoid a missing secret scenario in devctl generated files. - -## 2026-05-07 - -### Changed - -- Change actions/create-github-app-token param `app-id` to `client-id`. - -## 2026-04-24 - -- Fix interpretation of `fetch-deep-gitlog-for-build` input in `crteate-release` workflow, to allow for fetching git log. - -## 2026-04-17 - -### Changed - -- Bump `giantswarm/install-binary-action` from `v4.0.0` to `v4.0.1` in `create-release`, `create-release-pr`, and `helm-render-diff` workflows to pick up the fix for the `mkdir: File exists` collision in pre-commit runs (see `giantswarm/install-binary-action#334`). - -## 2026-04-15 - -### Added - -- Add a new `dispatch-update-chart-events` action to send `update-chart` events to a central repository. - -## 2026-03-05 - -### Added - -- Add tool configuration options for `zizmor` (GitHub Action security scanning). - -## 2026-03-04 - -### Added - -- Add `analyze-github-actions` action for scanning GitHub Actions. - -## 2026-02-09 - -### Fixed - -- Revert job reordering in `create-release-pr` and use `Release-Workflow-Run` trailer on all commits to prevent duplicate workflow runs. - -## 2026-02-07 - -### Added - -- Add reusable workflow `update-action-version.yaml` to update version in composite action.yml files during release PRs. - -## 2026-02-06 - -### Changed - -- Skip `ossf-scorecard` workflow in private repositories to avoid unnecessary failures. - -## 2026-02-05 - -### Fixed - -- Prevent duplicate workflow runs in `create-release-pr` by reordering jobs. - -## 2026-02-04 - -### Added - -- Add reusable workflow `create-release.yaml` with inputs for CLI build artifacts and optional full git history fetch. - -### Fixed - -- Prevent duplicate workflow runs in `create-release-pr` by marking commits with `Release-Workflow-Run` trailer. - -## 2026-02-03 - -### Added - -- Add reusable workflow `ensure-major-version-tags.yaml`. -- Add reusable workflow `documentation-validation.yaml`. -- Add reusable workflow `json-schema-validation.yaml`. -- Add reusable workflow `cluster-values-validation.yaml`. -- Add reusable workflow `helm-render-diff.yaml`. -- Add reusable workflow `update-chart.yaml`. - -### Fixed - -- Prevent duplicate `prepare_release_pr` job runs in `create-release-pr` workflow by adding `[skip ci]` to the commit message. - -## 2026-02-02 - -### Fixed - -- Set fall-back log level "info" for nancy-fixer workflow. - -## 2026-01-30 - -### Fixed - -- Replace `permissions: read-all` with explicit job-level permissions in `ossf-scorecard` and `publish-techdocs` workflows to work correctly when called from workflows with restricted permissions. Added full set of read permissions to `ossf-scorecard` job as recommended for private repositories (`contents`, `actions`, `issues`, `pull-requests`, `checks`). - -## 2026-01-23 - -### Added - -- Add pull request template with checklist for changelog. - -### Changed - -- Set restrictive default token permissions for `create-release-pr`, `fix-vulnerabilities`, `chart-values`, `gitleaks`, `go-coverage`, `issue-to-customer-board`, `validate-changelog`, `validate-file-names`, and `validate-workflows` workflows. - -### Fixed - -- Fix git push in "Create Release PR" workflow by disabling credential persistence in checkout steps. - -## 2026-01-16 - -### Changed - -- Allow setting log level for nancy-fixer workflow. - -## 2025-12-16 - -### Changed - -- Make `create-release-pr` aware of ABS setting `.replace-app-version-with-git` and update `Chart.yaml` accordingly. - -## 2025-10-31 - -### Added - -- Add workflow "Add issue to general customer board". - -### Changed - -- Improve output of "Validate workflows" workflow. - -## 2025-10-28 - -### Added - -- Add workflow to validate file names. - -## 2025-10-16 - -### Added - -- Add OSSI credentials to fix-vulnerabilities workflow. - -### Fixed - -- Fix wrong env variable name for fix-vulnerabilities. - -## 2025-10-10 - -### Fixed - -- Fix go-coverage workflow. - -## 2025-08-18 - -### Changed - -- Relax yamllint rule: min-spaces-from-comments. - -## 2025-08-15 - -### Added - -- Add yaml linting to validate-workflows. - -## 2025-07-09 - -### Changed - -- Set CODEOWNERS for specific files. -- Specify workflow permissions. - -## 2025-06-26 - -### Added - -- Add changelog validation workflow for release PRs. - -## 2025-06-03 - -### Added - -- Add workflow "Validate chart values and schema". -- Add OSSF Scorecard workflow. -- Add "Fix vulnerabilities" workflow. -- Create Renovate config. - -### Changed - -- Allow Renovate to update binaries in workflows. - -### Removed - -- Delete non-functioning "Create release" workflow. - -## 2025-06-02 - -### Added - -- Add go-coverage workflow. - -## 2025-05-30 - -### Added - -- Add Publish TechDocs workflow. -- Add workflow to validate workflows. - -### Changed - -- Rename first workflow files. - -## 2025-05-28 - -### Changed - -- Assign honeybadgers as CODEOWNERS. - -## 2025-05-21 - -### Added - -- Initial commit with reusable workflows: Create Release PR, Gitleaks. +- testing From 327968652164ea021cb6069eda0b0bb5b4282812 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C5=81ukasz=20Pi=C4=85tkowski?= Date: Wed, 3 Jun 2026 14:14:09 +0200 Subject: [PATCH 5/9] Revert "edit changelog" This reverts commit 7603adc42fe8e4098090ff9310318c4aad1b77b9. --- CHANGELOG.md | 296 ++++++++++++++++++++++++++++++++++++++++++++++++++- 1 file changed, 292 insertions(+), 4 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index af91334..21638ec 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -2,11 +2,299 @@ All notable changes to this project will be documented in this file. -The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/), however this project does not -use Semantic Versioning and there are no releases. Instead this file uses a date-based structure. +The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/), +however this project does not use Semantic Versioning and there are no releases. +Instead this file uses a date-based structure. -## Unreleased +## 2026-06-01 ### Changed -- testing +- `create-release-pr.yaml` and `create-release.yaml` install [`giantswarm/gitsemver`](https://github.com/giantswarm/gitsemver) `v1.1.2` via `giantswarm/install-binary-action` (the same mechanism already used for `architect` and Renovate-tracked), replacing the short-lived local composite action `.github/actions/gitsemver-install`. A local composite referenced as `uses: ./.github/actions/...` does not resolve inside a reusable (`workflow_call`) workflow — the runner looks the path up in the **caller** repository's checkout, not in `github-workflows` — so it failed for every consumer of these workflows. `v1.1.2` also fixes the `gitsemver --version` self-info flag, which the install step's smoke test now uses. This aligns these workflows with `architect-orb` v9.0.0, where `gitsemver` is the single source of git-based semver. +- `create-release.yaml`'s build-artifacts job keeps installing `architect` purely as a transition aid: consumer Makefiles still on the pre-gitsemver `devctl` template stamp release artifacts with `VERSION := $(shell architect project version)`. `devctl`'s current `Makefile.gen.go.mk` template uses `gitsemver version` (already installed in that job), so the `architect` install becomes removable once all consumers regenerate their Makefile. No version or git tag in these workflows is produced by `architect` — `gitsemver` is the sole source (`architect prepare-release` only consumes the already-resolved `--version`). + +### Removed + +- `create-release.yaml` no longer installs the `architect` binary in the `update_project_go` job. It was installed but never invoked — the post-release `-dev` bump of `project.go` is computed entirely with `gitsemver next patch` plus a `sed` rewrite. +- `create-release.yaml` drops the leftover `needs.gather_facts.outputs.ref_version != 'true'` guards on the `update_project_go` job and the `Ensure correct version in project.go` step. The `ref_version` output was removed together with the legacy reference-version handling, so the guards always evaluated truthy and only obscured the real conditions. + +## 2026-05-28 + +### Added + +- `create-release-pr.yaml` accepts new bump tokens on the trigger branch (`branch#`): `patch-rc`, `minor-rc`, `major-rc`, `rc`, `rc-release`. They are passed verbatim to `gitsemver next` and produce release-candidate versions like `v1.3.0-rc.1`, `v1.3.0-rc.2`, then `v1.3.0` via `rc-release`. The existing `patch` / `minor` / `major` tokens continue to work unchanged. +- `create-release.yaml` exposes a new `is_rc` output on its `gather_facts` job (true when the released tag is an RC per `gitsemver validate --type rc`). + +### Changed + +- `create-release-pr.yaml` now computes the next version with `gitsemver next ` instead of the inline `gh api releases/latest` + manual increment. Explicit-version trigger branches (`branch#vX.Y.Z[-rc.N]`) are now validated by `gitsemver validate --type any` and rejected on invalid input — strings that previously slipped through the loose regex (e.g. `1.2.3.foo`) are now hard failures with a clear error. The job now checks out the base branch with `fetch-depth: 0` and `persist-credentials: false` so gitsemver can see full tag history. +- `create-release.yaml` validates the version parsed from the release-PR commit title with `gitsemver` rather than an inline regex. RC tags (`vX.Y.Z-rc.N`) are first-class: they create the tag and GH release like a stable version, and they DO still trigger the post-release `-dev` bump of `project.go` (the new dev string targets the stable the RC is leading toward, e.g. `1.3.0-rc.1` ➝ `1.3.0-dev`). The long-lived `release-vX.Y.x` branch is only cut for stable major/minor releases — RC releases skip that job. +- `release.yaml` (release-please) auto-merge reconciler now strips any pre-release suffix from the manifest versions before the numeric `X.Y.Z` compare, so a `1.3.0-rc.1 → 1.3.0-rc.2` PR (or an RC ➝ stable promotion) is classified as `bump=patch` rather than silently `bump=none`. Auto-merge therefore honours the configured `auto-merge-level` ceiling on RC PRs too. Consumers wanting RC support on this path enable it in their own `release-please-config.json` with `"versioning": "prerelease"`, `"prerelease": true`, `"prerelease-type": "rc"` — `release.yaml` itself stays single-code-path. + +### Removed + +- `create-release.yaml` no longer recognises the legacy "reference version" form `vX.Y.Z-N` (e.g. `v1.2.3-4`) — the dedicated `ref_version` job and its special-case regex are gone. Any repo still pushing such tags via this workflow will need to migrate to the RC form (`vX.Y.Z-rc.N`). +- `create-release.yaml` and `create-release-pr.yaml` no longer install `fsaintjacques/semver-tool`; all next-version arithmetic now goes through `gitsemver` (or bash parameter expansion on a version string already validated by it). + +## 2026-05-27 + +### Added + +- `release.yaml` (release-please reusable workflow) gained an `auto-merge-level` input (`none`, `patch`, `minor`, `major`; default `none`). When set, the workflow enables GitHub auto-merge (`gh pr merge --auto --squash`) on the open release-please PR if the PR's bump is no larger than the configured ceiling, so the PR merges automatically once CI passes. The bump is derived from `.release-please-manifest.json` (next version on the PR head branch vs. current version on the base branch), so it is independent of each caller's PR-title configuration. Auto-merge is reconciled on every run — if a release-please PR's bump grows past the ceiling (e.g. from `patch` to `major`) before it is merged, auto-merge is disabled again. The default `none` preserves the previous behaviour (no auto-merge). The merge is performed with the `release-please` GitHub App token, so the merge is attributed to the App; the App must be granted bypass on any branch protection and the repository must have "Allow auto-merge" enabled. + +### Changed + +- `release.yaml` (release-please reusable workflow) now authenticates via a GitHub App instead of a PAT. Callers must pass `RELEASE_PLEASE_CLIENT_ID` and `RELEASE_PLEASE_PRIVATE_KEY` secrets in place of `TAYLORBOT_GITHUB_ACTION`. Using an App token (minted by `actions/create-github-app-token`) means release PRs trigger downstream workflows — unlike commits made with `GITHUB_TOKEN` or PRs opened by a PAT in some configurations — and removes the dependency on the taylorbot user account. +- `create-release-pr` now opens release PRs with a Conventional Commits-compatible title of the form `chore(release): vX.Y.Z` (previously `Release vX.Y.Z`). The release commit message it creates uses the same form. +- `create-release` and `update-action-version` accept both the new `chore(release): vX.Y.Z` form and the legacy `Release vX.Y.Z` form, so in-flight release PRs created by older versions of `create-release-pr` continue to be picked up after their merge commit lands. +- `validate-changelog.yaml` now validates the H3 sections of the version block against the [Keep a Changelog](https://keepachangelog.com/en/1.1.0/) set: `### Added`, `### Changed`, `### Deprecated`, `### Removed`, `### Fixed`, `### Security`. Unknown H3 sections fail validation. `### Security` is accepted for CVE fixes and vulnerability mitigations. Release CHANGELOGs that do not use `### Security` continue to pass. +- `fix-vulnerabilities` now opens PRs with the Conventional Commits title `fix(nancy): remediate findings on ` (previously `Remediate Nancy findings on `). The intermediate commit it creates uses `fix(nancy): remediate nancy findings`. +- `update-chart` now opens PRs with the Conventional Commits title `chore(chart): automated update from upstream` (previously `Automated update from upstream`). The intermediate commit it creates uses the same form. + +## 2026-05-20 + +### Added + +- Add reusable workflow `semantic-pull-request.yaml`. Validates that a pull request title follows Conventional Commits, using `amannn/action-semantic-pull-request`'s default type set (sourced from [`commitizen/conventional-commit-types`](https://github.com/commitizen/conventional-commit-types): `build`, `chore`, `ci`, `docs`, `feat`, `fix`, `perf`, `refactor`, `revert`, `style`, `test`). Callers trigger it on `pull_request` with `types: [opened, edited, synchronize]`. + +## 2026-05-19 + +### Changed + +- Replace `mindsers/changelog-reader-action` with an inline `awk` extractor in the `create-release` workflow. The upstream action is unmaintained and still runs on Node 20, which is being deprecated by GitHub Actions on 2026-06-02 (see [giantswarm/giantswarm#36091](https://github.com/giantswarm/giantswarm/issues/36091)). Inline shell has no Node runtime, so the workflow is no longer exposed to future Node-deprecation cycles. The replacement was validated byte-for-byte against 128 historical release bodies produced by the action across 100 consumer repos. + +## 2026-05-12 + +### Added + +- Add reusable workflow `js-dependency-audit.yaml`. It runs an audit (`npm`, `pnpm`, `yarn npm audit`, or `yarn audit`) on every JS project in a PR's head and base, then posts a sticky PR comment summarizing vulnerabilities and highlighting which ones the PR adds or removes. + +## 2026-05-11 + +### Fixed + +- Renamed `HERALD_CLIENT_ID` to `HERALD_APP_ID` in fix-vulnerabilities workflow to avoid a missing secret scenario in devctl generated files. + +## 2026-05-07 + +### Changed + +- Change actions/create-github-app-token param `app-id` to `client-id`. + +## 2026-04-24 + +- Fix interpretation of `fetch-deep-gitlog-for-build` input in `crteate-release` workflow, to allow for fetching git log. + +## 2026-04-17 + +### Changed + +- Bump `giantswarm/install-binary-action` from `v4.0.0` to `v4.0.1` in `create-release`, `create-release-pr`, and `helm-render-diff` workflows to pick up the fix for the `mkdir: File exists` collision in pre-commit runs (see `giantswarm/install-binary-action#334`). + +## 2026-04-15 + +### Added + +- Add a new `dispatch-update-chart-events` action to send `update-chart` events to a central repository. + +## 2026-03-05 + +### Added + +- Add tool configuration options for `zizmor` (GitHub Action security scanning). + +## 2026-03-04 + +### Added + +- Add `analyze-github-actions` action for scanning GitHub Actions. + +## 2026-02-09 + +### Fixed + +- Revert job reordering in `create-release-pr` and use `Release-Workflow-Run` trailer on all commits to prevent duplicate workflow runs. + +## 2026-02-07 + +### Added + +- Add reusable workflow `update-action-version.yaml` to update version in composite action.yml files during release PRs. + +## 2026-02-06 + +### Changed + +- Skip `ossf-scorecard` workflow in private repositories to avoid unnecessary failures. + +## 2026-02-05 + +### Fixed + +- Prevent duplicate workflow runs in `create-release-pr` by reordering jobs. + +## 2026-02-04 + +### Added + +- Add reusable workflow `create-release.yaml` with inputs for CLI build artifacts and optional full git history fetch. + +### Fixed + +- Prevent duplicate workflow runs in `create-release-pr` by marking commits with `Release-Workflow-Run` trailer. + +## 2026-02-03 + +### Added + +- Add reusable workflow `ensure-major-version-tags.yaml`. +- Add reusable workflow `documentation-validation.yaml`. +- Add reusable workflow `json-schema-validation.yaml`. +- Add reusable workflow `cluster-values-validation.yaml`. +- Add reusable workflow `helm-render-diff.yaml`. +- Add reusable workflow `update-chart.yaml`. + +### Fixed + +- Prevent duplicate `prepare_release_pr` job runs in `create-release-pr` workflow by adding `[skip ci]` to the commit message. + +## 2026-02-02 + +### Fixed + +- Set fall-back log level "info" for nancy-fixer workflow. + +## 2026-01-30 + +### Fixed + +- Replace `permissions: read-all` with explicit job-level permissions in `ossf-scorecard` and `publish-techdocs` workflows to work correctly when called from workflows with restricted permissions. Added full set of read permissions to `ossf-scorecard` job as recommended for private repositories (`contents`, `actions`, `issues`, `pull-requests`, `checks`). + +## 2026-01-23 + +### Added + +- Add pull request template with checklist for changelog. + +### Changed + +- Set restrictive default token permissions for `create-release-pr`, `fix-vulnerabilities`, `chart-values`, `gitleaks`, `go-coverage`, `issue-to-customer-board`, `validate-changelog`, `validate-file-names`, and `validate-workflows` workflows. + +### Fixed + +- Fix git push in "Create Release PR" workflow by disabling credential persistence in checkout steps. + +## 2026-01-16 + +### Changed + +- Allow setting log level for nancy-fixer workflow. + +## 2025-12-16 + +### Changed + +- Make `create-release-pr` aware of ABS setting `.replace-app-version-with-git` and update `Chart.yaml` accordingly. + +## 2025-10-31 + +### Added + +- Add workflow "Add issue to general customer board". + +### Changed + +- Improve output of "Validate workflows" workflow. + +## 2025-10-28 + +### Added + +- Add workflow to validate file names. + +## 2025-10-16 + +### Added + +- Add OSSI credentials to fix-vulnerabilities workflow. + +### Fixed + +- Fix wrong env variable name for fix-vulnerabilities. + +## 2025-10-10 + +### Fixed + +- Fix go-coverage workflow. + +## 2025-08-18 + +### Changed + +- Relax yamllint rule: min-spaces-from-comments. + +## 2025-08-15 + +### Added + +- Add yaml linting to validate-workflows. + +## 2025-07-09 + +### Changed + +- Set CODEOWNERS for specific files. +- Specify workflow permissions. + +## 2025-06-26 + +### Added + +- Add changelog validation workflow for release PRs. + +## 2025-06-03 + +### Added + +- Add workflow "Validate chart values and schema". +- Add OSSF Scorecard workflow. +- Add "Fix vulnerabilities" workflow. +- Create Renovate config. + +### Changed + +- Allow Renovate to update binaries in workflows. + +### Removed + +- Delete non-functioning "Create release" workflow. + +## 2025-06-02 + +### Added + +- Add go-coverage workflow. + +## 2025-05-30 + +### Added + +- Add Publish TechDocs workflow. +- Add workflow to validate workflows. + +### Changed + +- Rename first workflow files. + +## 2025-05-28 + +### Changed + +- Assign honeybadgers as CODEOWNERS. + +## 2025-05-21 + +### Added + +- Initial commit with reusable workflows: Create Release PR, Gitleaks. From 674b7fbadc876b986de078c3296d6d343016bdd0 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C5=81ukasz=20Pi=C4=85tkowski?= Date: Wed, 3 Jun 2026 14:51:56 +0200 Subject: [PATCH 6/9] fix(release): use TAYLORBOT credentials in create-release-branch push MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit git push origin bare silently fails when persist-credentials: false is set (credentials aren't available). Use the authenticated TAYLORBOT_GITHUB_ACTION remote URL, matching the pattern used by every other push step in the file. Also quote $release_branch and suppress expected stderr from git rev-parse --verify when the branch doesn't yet exist. Pre-existing bug on main — discovered during testing with the use-gitsemver branch. Co-Authored-By: Claude Sonnet 4.6 --- .github/workflows/create-release.yaml | 10 +++++++--- CHANGELOG.md | 6 ++++++ 2 files changed, 13 insertions(+), 3 deletions(-) diff --git a/.github/workflows/create-release.yaml b/.github/workflows/create-release.yaml index ee8bd3a..08405c8 100644 --- a/.github/workflows/create-release.yaml +++ b/.github/workflows/create-release.yaml @@ -276,6 +276,10 @@ jobs: - name: Fetch all tags and branches run: "git fetch --all" - name: Create long-lived release branch + env: + REMOTE_REPO: + "https://${{ github.actor }}:${{ secrets.TAYLORBOT_GITHUB_ACTION }}@github.com/${{ + github.repository }}.git" run: | set -euo pipefail current_version="${{ needs.gather_facts.outputs.version }}" @@ -309,13 +313,13 @@ jobs: release_branch="release-v${parent_major}.${parent_minor}.x" echo "release_branch=$release_branch" - if git rev-parse --verify $release_branch ; then + if git rev-parse --verify "$release_branch" >/dev/null 2>&1; then echo "Release branch $release_branch already exists. Nothing to do here." exit 0 fi - git branch $release_branch HEAD^ - git push origin $release_branch + git branch "$release_branch" HEAD^ + git push "${REMOTE_REPO}" "$release_branch" create_and_upload_build_artifacts: name: Create and upload build artifacts diff --git a/CHANGELOG.md b/CHANGELOG.md index 21638ec..ee5cc93 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -6,6 +6,12 @@ The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/), however this project does not use Semantic Versioning and there are no releases. Instead this file uses a date-based structure. +## 2026-06-03 + +### Fixed + +- `create-release.yaml`'s `create-release-branch` job now pushes the new long-lived maintenance branch using the `TAYLORBOT_GITHUB_ACTION` token (same authenticated remote URL pattern used by every other push in the file), rather than a bare `git push origin` that silently fails when `persist-credentials: false` is set. This bug was pre-existing on `main` and would have silently skipped release-branch creation on every minor/major release. + ## 2026-06-01 ### Changed From eeab7980cf18afc950071a6db7448735f6970a57 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C5=81ukasz=20Pi=C4=85tkowski?= Date: Wed, 3 Jun 2026 15:47:59 +0200 Subject: [PATCH 7/9] fix(create-release-pr): skip Release-Workflow-Run check when branch has no unique commits When a release branch like main#release#minor-rc is freshly pushed from main, github.sha is the base-branch HEAD. If that commit was created by a previous release workflow it carries a Release-Workflow-Run: trailer, causing check_skip to set skip=true before any PR is created. Fix: only apply the Release-Workflow-Run: loop-prevention guard when the release branch is ahead of its base (ahead_by > 0), i.e. the workflow has already committed to it. A freshly-pushed branch with ahead_by = 0 skips straight to skip=false, so RC tokens (minor-rc, major-rc, etc.) now create release PRs the same way stable tokens do. Co-Authored-By: Claude Sonnet 4.6 --- .github/workflows/create-release-pr.yaml | 19 +++++++++++++------ CHANGELOG.md | 1 + 2 files changed, 14 insertions(+), 6 deletions(-) diff --git a/.github/workflows/create-release-pr.yaml b/.github/workflows/create-release-pr.yaml index 312ffcd..fd1b92c 100644 --- a/.github/workflows/create-release-pr.yaml +++ b/.github/workflows/create-release-pr.yaml @@ -133,12 +133,19 @@ jobs: exit 0 fi - # Check if the triggering commit was created by this workflow (has our trailer) - commit_message=$(gh api "repos/${{ github.repository }}/commits/${{ github.sha }}" --jq '.commit.message' 2>/dev/null || echo "") - if [[ "$commit_message" == *"Release-Workflow-Run:"* ]]; then - echo "Triggering commit was created by release workflow, skipping" - echo "skip=true" >> $GITHUB_OUTPUT - exit 0 + # Check if the triggering commit was created by this workflow (has our trailer). + # Only apply this check when the release branch is ahead of the base — if + # ahead_by is 0, the branch was just created from the base and the trailer + # (if present) belongs to a previous unrelated release on the base branch. + base="${{ steps.parse.outputs.base }}" + ahead_by=$(gh api "repos/${{ github.repository }}/compare/${base}...${branch}" --jq '.ahead_by' 2>/dev/null || echo "0") + if [[ "$ahead_by" -gt "0" ]]; then + commit_message=$(gh api "repos/${{ github.repository }}/commits/${{ github.sha }}" --jq '.commit.message' 2>/dev/null || echo "") + if [[ "$commit_message" == *"Release-Workflow-Run:"* ]]; then + echo "Triggering commit was created by release workflow, skipping" + echo "skip=true" >> $GITHUB_OUTPUT + exit 0 + fi fi echo "skip=false" >> $GITHUB_OUTPUT diff --git a/CHANGELOG.md b/CHANGELOG.md index ee5cc93..44caaec 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -10,6 +10,7 @@ Instead this file uses a date-based structure. ### Fixed +- `create-release-pr.yaml`'s `check_skip` step no longer false-positively skips when an RC (or any) release branch is pushed from a base-branch HEAD that already carries a `Release-Workflow-Run:` trailer from a previous release. The trailer check now only applies when the release branch is actually ahead of the base (i.e., the workflow already committed to it), so freshly-pushed RC branches like `main#release#minor-rc` correctly proceed to create the release PR. - `create-release.yaml`'s `create-release-branch` job now pushes the new long-lived maintenance branch using the `TAYLORBOT_GITHUB_ACTION` token (same authenticated remote URL pattern used by every other push in the file), rather than a bare `git push origin` that silently fails when `persist-credentials: false` is set. This bug was pre-existing on `main` and would have silently skipped release-branch creation on every minor/major release. ## 2026-06-01 From 33aba9668455edd53ae4f6d2e0dc8e49f6719e91 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C5=81ukasz=20Pi=C4=85tkowski?= Date: Wed, 3 Jun 2026 16:09:11 +0200 Subject: [PATCH 8/9] fix(validate-changelog): support RC release tokens and prefix-less branches The changelog PR check only handled major/minor/patch and bare X.Y.Z versions, so RC release branches (main#release#minor-rc, #major-rc, #patch-rc, #rc, #rc-release) and explicit RC versions (#v1.2.3-rc.4) fell through to the error case and failed the required check. Parse the release token from the segment after the last '#' (the same way create-release-pr.yaml does) and match on it, instead of matching the whole branch with *#release# patterns. The version regexes now allow an optional -rc.N suffix. This also fixes the prefix-less release# scheme, which the old patterns never matched because they required a '#' before "release". Co-Authored-By: Claude Sonnet 4.6 --- .github/workflows/validate-changelog.yaml | 54 +++++++++++++---------- CHANGELOG.md | 1 + 2 files changed, 32 insertions(+), 23 deletions(-) diff --git a/.github/workflows/validate-changelog.yaml b/.github/workflows/validate-changelog.yaml index 4fa84f1..e80fab1 100644 --- a/.github/workflows/validate-changelog.yaml +++ b/.github/workflows/validate-changelog.yaml @@ -31,12 +31,22 @@ jobs: version="" - # Use case statement for more reliable pattern matching - case "$branch_name" in - *"#release#v"*) - # Extract version from patterns like main#release#v1.2.3 - version=$(echo "$branch_name" | sed -E 's/.*#release#v([0-9]+\.[0-9]+\.[0-9]+).*/\1/') - if [[ "$version" =~ ^[0-9]+\.[0-9]+\.[0-9]+$ ]]; then + # The release token is the segment after the last '#', mirroring how + # create-release-pr.yaml parses it (awk -F# '{print $NF}'). This makes + # matching independent of the base-branch prefix, so both naming schemes + # work: "main#release#minor-rc" and the prefix-less "release#minor-rc". + token="${branch_name##*#}" + echo "Release token: $token" + + version="" + + # A semver core (X.Y.Z) may carry an optional release-candidate suffix + # (-rc.N) that gitsemver produces, so the version patterns allow it. + case "$token" in + v[0-9]*) + # Explicit version token like v1.2.3 or v1.2.3-rc.4 + version="${token#v}" + if [[ "$version" =~ ^[0-9]+\.[0-9]+\.[0-9]+(-rc\.[0-9]+)?$ ]]; then echo "Extracted explicit version: $version" else echo "::error::Failed to extract version from: $branch_name" @@ -44,18 +54,20 @@ jobs: fi ;; - *"#release#major"|*"#release#minor"|*"#release#patch") - # Extract bump type and get version from changelog - bump_type=$(echo "$branch_name" | sed -E 's/.*#release#(major|minor|patch).*/\1/') - echo "🔍 Detected semantic version branch ($bump_type), extracting version from changelog..." + major|minor|patch|major-rc|minor-rc|patch-rc|rc|rc-release) + # Bump-token branch: the concrete version was resolved by gitsemver + # and written into the changelog by architect, so read it from there. + # This covers both stable bumps and their RC variants uniformly. + echo "🔍 Detected bump-token release branch ($token), extracting version from changelog..." if [ ! -f "CHANGELOG.md" ]; then echo "::error::CHANGELOG.md not found" exit 1 fi - # Get the first version entry (should be the newest one that architect created) - version=$(grep -E "^## \[[0-9]+\.[0-9]+\.[0-9]+\]" CHANGELOG.md | head -1 | sed -E 's/^## \[([0-9]+\.[0-9]+\.[0-9]+)\].*/\1/') + # Get the first version entry (should be the newest one that architect + # created); allow an optional -rc.N suffix for release candidates. + version=$(grep -E "^## \[[0-9]+\.[0-9]+\.[0-9]+(-rc\.[0-9]+)?\]" CHANGELOG.md | head -1 | sed -E 's/^## \[([0-9]+\.[0-9]+\.[0-9]+(-rc\.[0-9]+)?)\].*/\1/') if [ -z "$version" ]; then echo "::error::Could not find version in CHANGELOG.md" @@ -65,20 +77,16 @@ jobs: exit 1 fi - echo "Extracted version from changelog for $bump_type release: $version" + echo "Extracted version from changelog for $token release: $version" ;; *) - echo "::error::Could not extract version from branch name: $branch_name" - echo "::error::Expected patterns:" - echo " - main#release#v1.2.3" - echo " - main#release#major" - echo " - main#release#minor" - echo " - main#release#patch" - echo " - master#release#v1.2.3" - echo " - master#release#major|minor|patch" - echo " - release#v1.2.3" - echo " - release#major|minor|patch" + echo "::error::Could not extract version from branch name: $branch_name (token: $token)" + echo "::error::Expected the branch to end in one of:" + echo " - #v1.2.3 (optionally -rc.N, e.g. #v1.2.3-rc.4)" + echo " - #major | #minor | #patch" + echo " - #major-rc | #minor-rc | #patch-rc" + echo " - #rc | #rc-release" exit 1 ;; esac diff --git a/CHANGELOG.md b/CHANGELOG.md index 44caaec..4344c67 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -10,6 +10,7 @@ Instead this file uses a date-based structure. ### Fixed +- `validate-changelog.yaml` now recognises release-candidate branches. It parses the release token from the segment after the last `#` (mirroring `create-release-pr.yaml`) instead of pattern-matching the whole branch, so it accepts the RC bump tokens (`major-rc`, `minor-rc`, `patch-rc`, `rc`, `rc-release`) and explicit RC versions (`#v1.2.3-rc.4`) in addition to the stable tokens. The changelog version regex now allows an optional `-rc.N` suffix. As a side effect this also fixes the prefix-less `release#` naming scheme, which the previous `*#release#` patterns never matched. - `create-release-pr.yaml`'s `check_skip` step no longer false-positively skips when an RC (or any) release branch is pushed from a base-branch HEAD that already carries a `Release-Workflow-Run:` trailer from a previous release. The trailer check now only applies when the release branch is actually ahead of the base (i.e., the workflow already committed to it), so freshly-pushed RC branches like `main#release#minor-rc` correctly proceed to create the release PR. - `create-release.yaml`'s `create-release-branch` job now pushes the new long-lived maintenance branch using the `TAYLORBOT_GITHUB_ACTION` token (same authenticated remote URL pattern used by every other push in the file), rather than a bare `git push origin` that silently fails when `persist-credentials: false` is set. This bug was pre-existing on `main` and would have silently skipped release-branch creation on every minor/major release. From f96c3aec5199c1594bfd37b5cf28cc4a664af140 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C5=81ukasz=20Pi=C4=85tkowski?= Date: Wed, 3 Jun 2026 16:12:14 +0200 Subject: [PATCH 9/9] fix(create-release): mark RC versions as GitHub pre-releases RC tags (vX.Y.Z-rc.N) were published as full GitHub releases, so a release candidate could become the repo's "Latest release". Pass the already-computed gather_facts.is_rc to ncipollo/release-action's prerelease input so RC releases are flagged as pre-releases. Co-Authored-By: Claude Sonnet 4.6 --- .github/workflows/create-release.yaml | 3 +++ CHANGELOG.md | 1 + 2 files changed, 4 insertions(+) diff --git a/.github/workflows/create-release.yaml b/.github/workflows/create-release.yaml index 08405c8..1c57881 100644 --- a/.github/workflows/create-release.yaml +++ b/.github/workflows/create-release.yaml @@ -257,6 +257,9 @@ jobs: body: ${{ steps.changelog_reader.outputs.changes }} tag: "v${{ needs.gather_facts.outputs.version }}" token: ${{ secrets.TAYLORBOT_GITHUB_ACTION }} + # Mark release-candidate versions (vX.Y.Z-rc.N) as GitHub pre-releases + # so they don't surface as the repo's "Latest release". + prerelease: ${{ needs.gather_facts.outputs.is_rc == 'true' }} skipIfReleaseExists: true create-release-branch: diff --git a/CHANGELOG.md b/CHANGELOG.md index 4344c67..031125d 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -10,6 +10,7 @@ Instead this file uses a date-based structure. ### Fixed +- `create-release.yaml` now marks release-candidate releases (`vX.Y.Z-rc.N`) as GitHub pre-releases by passing `prerelease` to `ncipollo/release-action`, derived from the existing `gather_facts.is_rc` output. Previously RC tags were published as full releases and could become the repo's "Latest release". - `validate-changelog.yaml` now recognises release-candidate branches. It parses the release token from the segment after the last `#` (mirroring `create-release-pr.yaml`) instead of pattern-matching the whole branch, so it accepts the RC bump tokens (`major-rc`, `minor-rc`, `patch-rc`, `rc`, `rc-release`) and explicit RC versions (`#v1.2.3-rc.4`) in addition to the stable tokens. The changelog version regex now allows an optional `-rc.N` suffix. As a side effect this also fixes the prefix-less `release#` naming scheme, which the previous `*#release#` patterns never matched. - `create-release-pr.yaml`'s `check_skip` step no longer false-positively skips when an RC (or any) release branch is pushed from a base-branch HEAD that already carries a `Release-Workflow-Run:` trailer from a previous release. The trailer check now only applies when the release branch is actually ahead of the base (i.e., the workflow already committed to it), so freshly-pushed RC branches like `main#release#minor-rc` correctly proceed to create the release PR. - `create-release.yaml`'s `create-release-branch` job now pushes the new long-lived maintenance branch using the `TAYLORBOT_GITHUB_ACTION` token (same authenticated remote URL pattern used by every other push in the file), rather than a bare `git push origin` that silently fails when `persist-credentials: false` is set. This bug was pre-existing on `main` and would have silently skipped release-branch creation on every minor/major release.