Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
332 changes: 332 additions & 0 deletions .github/workflows/create-release.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,332 @@
name: Create Release

on:
workflow_call:
inputs:
build-release-artifacts:
description: "Build and upload release artifacts for multiple platforms (CLI tools)"
type: boolean
default: false
fetch-deep-gitlog-for-build:
description: "Fetch full git history for build (needed in special cases only)"
type: boolean
default: false
secrets:
TAYLORBOT_GITHUB_ACTION:
required: true

permissions: {}

jobs:
debug_info:
name: Debug info
runs-on: ubuntu-24.04
steps:
- name: Print github context JSON
run: |
cat <<EOF
${{ toJson(github) }}
EOF
gather_facts:
name: Gather facts
runs-on: ubuntu-24.04
permissions:
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 }}
steps:
- 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:
#
# - "Release v1.2.3"
# - "Release v1.2.3-r4"
# - "Release v1.2.3 (#56)"
# - "Release v1.2.3-r4 (#56)"
#
# And outputs version part (1.2.3).
if echo "${title}" | grep -iqE '^Release v[0-9]+\.[0-9]+\.[0-9]+([.-][^ .-][^ ]*)?( \(#[0-9]+\))?$' ; then
version=$(echo "${title}" | cut -d ' ' -f 2)
fi
version="${version#v}" # Strip "v" prefix.
echo "version=\"${version}\""
echo "version=${version}" >> $GITHUB_OUTPUT
- name: Checkout code
if: ${{ steps.get_version.outputs.version != '' }}
uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2
- name: Get project.go path
id: get_project_go_path
if: ${{ steps.get_version.outputs.version != '' }}
run: |
path='./pkg/project/project.go'
if [[ ! -f $path ]] ; then
path=''
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 -qE '^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' }}
needs:
- gather_facts
steps:
- name: Install architect
uses: giantswarm/install-binary-action@c94c7adadeb14af4bdbdd601f9a6e7f69638134c # v4.0.0
with:
binary: "architect"
version: "6.14.1"
- name: Install semver
uses: giantswarm/install-binary-action@c94c7adadeb14af4bdbdd601f9a6e7f69638134c # v4.0.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:
persist-credentials: false
- name: Update project.go
id: update_project_go
env:
branch: "${{ github.ref }}-version-bump"
run: |
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"
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
if git diff --exit-code $file ; then
echo "error: no changes in \"$file\"" >&2
exit 1
fi
- name: Set up git identity
run: |
git config --local user.email "[email protected]"
git config --local user.name "taylorbot"
- name: Commit changes
run: |
file="${{ needs.gather_facts.outputs.project_go_path }}"
git add $file
git commit -m "Bump version to ${{ steps.update_project_go.outputs.new_version }}"
- name: Push changes
env:
REMOTE_REPO: "https://${{ github.actor }}:${{ secrets.TAYLORBOT_GITHUB_ACTION }}@github.com/${{ github.repository }}.git"
branch: "${{ github.ref }}-version-bump"
run: |
git push "${REMOTE_REPO}" HEAD:${{ env.branch }}
- name: Create PR
env:
GITHUB_TOKEN: "${{ secrets.TAYLORBOT_GITHUB_ACTION }}"
base: "${{ github.ref }}"
branch: "${{ github.ref }}-version-bump"
version: "${{ needs.gather_facts.outputs.version }}"
title: "Bump version to ${{ steps.update_project_go.outputs.new_version }}"
run: |
gh pr create --title "${{ env.title }}" --body "" \
--base ${{ env.base }} --head ${{ env.branch }} --reviewer ${{ github.actor }}
- name: Enable auto-merge for PR
env:
GITHUB_TOKEN: "${{ secrets.TAYLORBOT_GITHUB_ACTION }}"
base: "${{ github.ref }}"
branch: "${{ github.ref }}-version-bump"
version: "${{ needs.gather_facts.outputs.version }}"
title: "Bump version to ${{ steps.update_project_go.outputs.new_version }}"
run: |
gh pr merge --auto --squash "${{ env.branch }}" \
|| echo "::warning::Auto-merge not allowed. Please adjust the repository settings."
create_release:
name: Create release
runs-on: ubuntu-24.04
permissions:
contents: read
needs:
- gather_facts
if: ${{ needs.gather_facts.outputs.version }}
outputs:
upload_url: ${{ steps.create_gh_release.outputs.upload_url }}
steps:
- name: Checkout code
uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2
with:
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' }}
run: |
file="${{ needs.gather_facts.outputs.project_go_path }}"
version="${{ needs.gather_facts.outputs.version }}"
grep -qE "version[[:space:]]*=[[:space:]]*\"$version\"" $file
- name: Get Changelog Entry
id: changelog_reader
uses: mindsers/changelog-reader-action@32aa5b4c155d76c94e4ec883a223c947b2f02656 # v2.2.3
with:
version: ${{ needs.gather_facts.outputs.version }}
path: ./CHANGELOG.md
- name: Set up git identity
run: |
git config --local user.email "[email protected]"
git config --local user.name "taylorbot"
- name: Create tag
run: |
version="${{ needs.gather_facts.outputs.version }}"
git tag "v$version" ${{ github.sha }}
- name: Push tag
env:
REMOTE_REPO: "https://${{ github.actor }}:${{ secrets.TAYLORBOT_GITHUB_ACTION }}@github.com/${{ github.repository }}.git"
run: |
git push "${REMOTE_REPO}" --tags
- name: Create release
id: create_gh_release
uses: ncipollo/release-action@b7eabc95ff50cbeeedec83973935c8f306dfcd0b # v1.20.0
with:
body: ${{ steps.changelog_reader.outputs.changes }}
tag: "v${{ needs.gather_facts.outputs.version }}"
token: ${{ secrets.TAYLORBOT_GITHUB_ACTION }}
skipIfReleaseExists: true

create-release-branch:
name: Create release branch
runs-on: ubuntu-24.04
permissions:
contents: write
needs:
- gather_facts
if: ${{ needs.gather_facts.outputs.version }}
steps:
- name: Install semver
uses: giantswarm/install-binary-action@c94c7adadeb14af4bdbdd601f9a6e7f69638134c # v4.0.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.
- name: Fetch all tags and branches
run: "git fetch --all"
- name: Create long-lived release branch
run: |
current_version="${{ needs.gather_facts.outputs.version }}"
parent_version="$(git describe --tags --abbrev=0 HEAD^ || true)"
parent_version="${parent_version#v}" # Strip "v" prefix.

if [[ -z "$parent_version" ]] ; then
echo "Unable to find a parent tag version. No branch to create."
exit 0
fi

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)
echo "current_major=$current_major current_minor=$current_minor"
echo "parent_major=$parent_major parent_minor=$parent_minor"

if [[ $current_major -gt $parent_major ]] ; then
echo "Current tag is a new major version"
elif [[ $current_major -eq $parent_major ]] && [[ $current_minor -gt $parent_minor ]] ; then
echo "Current tag is a new minor version"
else
echo "Current tag is not a new major or minor version. Nothing to do here."
exit 0
fi

release_branch="release-v${parent_major}.${parent_minor}.x"
echo "release_branch=$release_branch"

if git rev-parse --verify $release_branch ; 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

create_and_upload_build_artifacts:
name: Create and upload build artifacts
runs-on: ubuntu-24.04
if: ${{ inputs.build-release-artifacts && needs.gather_facts.outputs.version }}
permissions:
contents: write
strategy:
fail-fast: false
matrix:
platform:
- darwin-amd64
- linux-amd64
- darwin-arm64
- linux-arm64
- windows-amd64
env:
GITHUB_TOKEN: "${{ secrets.TAYLORBOT_GITHUB_ACTION }}"
GO_VERSION: 1.21.3
ARTIFACT_DIR: bin-dist
TAG: v${{ needs.gather_facts.outputs.version }}
needs:
- create_release
- gather_facts
steps:
- name: Install architect
uses: giantswarm/install-binary-action@c94c7adadeb14af4bdbdd601f9a6e7f69638134c # v4.0.0
with:
binary: "architect"
version: "6.14.1"
- name: Set up Go ${{ env.GO_VERSION }}
uses: actions/setup-go@0c52d547c9bc32b1aa3301fd7a9cb496313a4491 # v5.0.0
with:
go-version: ${{ env.GO_VERSION }}
- name: Checkout code
uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2
with:
ref: ${{ env.TAG }}
fetch-depth: ${{ inputs.fetch-deep-gitlog-for-build && 0 || 1 }}
- name: Create ${{ matrix.platform }} package
run: make package-${{ matrix.platform }}
- name: Specify package file name based on platform
run: |
if [[ "${{ matrix.platform }}" == "windows-amd64" ]]; then
echo "FILE_NAME=${{ github.event.repository.name }}-${{ env.TAG }}-${{ matrix.platform }}.zip" >> $GITHUB_ENV
else
echo "FILE_NAME=${{ github.event.repository.name }}-${{ env.TAG }}-${{ matrix.platform }}.tar.gz" >> $GITHUB_ENV
fi
- name: Add ${{ matrix.platform }} package to release
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
run: |
gh release upload ${{ env.TAG }} \
${{ env.ARTIFACT_DIR }}/${{ env.FILE_NAME }}#${{ env.FILE_NAME }}
4 changes: 4 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,10 @@ Instead this file uses a date-based structure.

## 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.
Expand Down