Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

ci: Add release workflow #48

Merged
merged 4 commits into from
Jun 22, 2024
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
126 changes: 126 additions & 0 deletions .github/workflows/release-pr.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,126 @@
name: Bump Version
on:
workflow_dispatch:
inputs:
type:
description: 'release or hotfix'
type: choice
options:
- release
- hotfix
required: true
default: 'release'
# NOTE: For a `release` branch, only specify the `major.minor` version. This branch will be persistent across patches,
# so any patch number specified in this case will be dropped. For a hotfix, specify the full `major.minor.patch` version
version:
description: 'Version'
required: true

jobs:
release:
runs-on: ubuntu-latest
steps:
- name: Git config
run: |
git config --global user.name "github-actions[bot]"
git config --global user.email "github-actions[bot]@users.noreply.github.com"

git config --global url."https://${{ secrets.REPO_TOKEN }}@github.com/".insteadOf ssh://[email protected]
git config --global url."https://${{ secrets.REPO_TOKEN }}@github.com".insteadOf https://github.com

- name: Checkout code
uses: actions/checkout@v4

- name: Install Rust
uses: dtolnay/rust-toolchain@stable

- name: Install `tq-rs`
run: cargo install tq-rs

# The `release/1.0` branch is always truncated, so that patch version merges still are valid Semver
# However, when we make the initial `release/1.0` version bump, we include the full `1.0.0` in `Cargo.toml`
# and the release for clarity
- name: Set branches
run: |
BASE_VERSION_SHORT=$(echo "${{ inputs.version }}" | cut -d'.' -f1-2)
BASE_VERSION="${BASE_VERSION_SHORT}.0"
if [[ "${{ inputs.type }}" == "hotfix" ]]; then
VERSION=${{ inputs.version }}
BASE_BRANCH="release/$BASE_VERSION_SHORT"
PR_BRANCH="${{ inputs.type }}/${{ inputs.version }}"
git checkout ${{ env.PR_BRANCH }}
else
VERSION=$BASE_VERSION
BASE_BRANCH="main"
PR_BRANCH="release/$BASE_VERSION_SHORT"
git checkout -b ${{ env.PR_BRANCH }}
fi

echo "BASE_BRANCH=$BASE_BRANCH" | tee -a $GITHUB_ENV
echo "PR_BRANCH=$PR_BRANCH" | tee -a $GITHUB_ENV
echo "PR_DESCRIPTION=chore: Release $VERSION" | tee -a $GITHUB_ENV
echo "VERSION=$VERSION" | tee -a $GITHUB_ENV

# Regex from https://semver.org/#is-there-a-suggested-regular-expression-regex-to-check-a-semver-string
- name: Validate version
run: |
echo "Validating version ${{ env.VERSION }}..."
D='0|[1-9][0-9]*'
PW='[0-9]*[a-zA-Z-][0-9a-zA-Z-]*'
MW='[0-9a-zA-Z-]+'
if [[ "${{ env.VERSION }}" =~ ^($D)\.($D)\.($D)(-(($D|$PW)(\.($D|$PW))*))?(\+($MW(\.$MW)*))?$ ]]; then
echo "Version ${{ env.VERSION }} is valid."
else
echo "Version is not valid SemVer. Aborting..."
exit 1
fi

- name: Update version in Cargo.toml
run: |
members=$(tq workspace.members -f Cargo.toml | jq -r '.[]')

bump_version() {
cd "$1"
OLD_VERSION=$(grep -oP 'version = "\K[^"]+' Cargo.toml)
if [[ "${{ env.VERSION }}" > "$OLD_VERSION" ]]; then
sed -i "s/version = \"$OLD_VERSION\"/version = \"${{ env.VERSION }}\"/" Cargo.toml
else
echo "New version is not greater than the current version for $1. Aborting..."
exit 1
fi
cd ${{ github.workspace }}
}

while IFS= read -r path; do
if [[ "$path" == *"/*" ]]; then
for dir in "${path%/*}"/*; do
if [ -d "$dir" ] && [ -f "$dir/Cargo.toml" ]; then
bump_version "$dir"
fi
done
else
bump_version "$path"
fi
done <<< "$members"

- name: Commit changes
run: |
git add .
git commit -m "${{ env.PR_DESCRIPTION }}"
git push origin ${{ env.PR_BRANCH }}

# Note: Can't use `peter-evans/create-pull-request` because for hotfixes we need to make the PR with an existing branch
# The former always creates a new one for single-commit PRs, thus overwriting the actual hotfix
- name: Create PR
run: |
cat << 'EOF' > body.md
This is an automated release PR for the patched version of `${{ env.VERSION }}`.

On merge, this will trigger the [release publish workflow](${{ github.server_url }}/${{ github.repository }}/actions/workflows/tag-release.yml), which will upload a new GitHub release with tag `{{ env.VERSION }}`.

[Workflow run](${{ github.server_url }}/${{ github.repository }}/actions/runs/${{ github.run_id }})
EOF

gh pr create --title "${{ env.PR_DESCRIPTION }}" --body-file ./body.md --head ${{ env.PR_BRANCH }} --base ${{ env.BASE_BRANCH }}
env:
GH_TOKEN: ${{ github.token }}
55 changes: 55 additions & 0 deletions .github/workflows/tag-release.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,55 @@
name: Tag release

on:
pull_request:
types: [ closed ]
branches:
- dev
- release/*

jobs:
# Creates a new tag if a release branch is merged
tag-bump:
if: |
github.event.pull_request.merged == true &&
((startsWith(github.event.pull_request.head.ref, 'release/') && github.event.pull_request.base.ref == 'dev') ||
(startsWith(github.event.pull_request.head.ref, 'hotfix/') && startsWith(github.event.pull_request.base.ref, 'release/')))
runs-on: ubuntu-latest
steps:
- name: Git config
run: |
git config --global user.name "github-actions[bot]"
git config --global user.email "github-actions[bot]@users.noreply.github.com"

git config --global url."https://${{ secrets.REPO_TOKEN }}@github.com/".insteadOf ssh://[email protected]
git config --global url."https://${{ secrets.REPO_TOKEN }}@github.com".insteadOf https://github.com

- name: Checkout code
uses: actions/checkout@v4

- name: Get version
id: get-version
run: |
VERSION=$(echo "${{ github.event.pull_request.head.ref }}" | cut -d'/' -f 2)
RELEASE_BRANCH="${{ startsWith(github.event.pull_request.head.ref, 'release/') && github.event.pull_request.head.ref || github.event.pull_request.base.ref }}"

git tag -a $VERSION -m "$VERSION" $RELEASE_BRANCH
git push origin $VERSION -f
echo "version=$VERSION" | tee -a "$GITHUB_OUTPUT"
echo "RELEASE_BRANCH=$RELEASE_BRANCH" | tee -a "$GITHUB_ENV"

- name: Build Changelog
id: github_release
uses: mikepenz/release-changelog-builder-action@v4
with:
toTag: ${{ steps.get-version.outputs.version }}
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}

- name: Create Release
uses: ncipollo/release-action@v1
with:
body: ${{ steps.github_release.outputs.changelog }}
tag: ${{ steps.get-version.outputs.version }}
commit: ${{ env.RELEASE_BRANCH }}
allowUpdates: true