diff --git a/.github/workflows/create-release.yaml b/.github/workflows/create-release.yaml new file mode 100644 index 0000000..ac2e1fc --- /dev/null +++ b/.github/workflows/create-release.yaml @@ -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 <> $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 "dev@giantswarm.io" + 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 "dev@giantswarm.io" + 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 }} diff --git a/CHANGELOG.md b/CHANGELOG.md index 7c4e64a..3af2851 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -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.