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

Create a release-commit action #97

Open
wants to merge 4 commits into
base: main
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from 1 commit
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
59 changes: 59 additions & 0 deletions .github/workflows/release-commit.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,59 @@
# Create a new commit
# This action bumps the Cargo.toml version and updates related files.
# Updates will affect the following files:
# - ./Cargo.toml
# - ./Cargo.lock
# - ./THIRD-PARTY-LICENSES.md
# - ./CHANGELOG.md
name: "Release Commit"
on:
workflow_dispatch:
inputs:
bump_level:
description: "What type of release is this?"
required: true
type: choice
options:
- minor
- patch
permissions:
contents: write

jobs:
setup-environment:
runs-on: ubuntu-latest
steps:
- name: Checkout code
uses: actions/checkout@v4
with:
token: ${{ secrets.GITHUB_TOKEN }}

- name: Add git tag to release
run: ./scripts/create_release_changes ${{ github.event.inputs.text_input }}

- name: Get new cargo version
id: cargo_version
run: |
VERSION=$(cargo read-manifest | jq -r ".version")
echo "value=v$VERSION" >> $GITHUB_OUTPUT

- name: Ensure this release doesn't already exist
run: |
if git log --grep="Release ${{ steps.cargo_version.outputs.value }}" --quiet; then
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Is this still necessary if we're checking for an existing tag?

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think this will cause a false-positive in the event the release got reverted for whatever reason.

If we're trying to determine is whether HEAD is already released, perhaps this will do:

git tag --contains <SHA1>

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'll remove from here because the tag is already checked in the script file. The tags are important though since they are what the changelogs are linking to. The release action tags the commit before it does a binary build. It is possible the binary build fails in some strange case, then we have to manually delete the tag, fix the issue and do a new release. Not necessarily the best way of doing it but it's how it is set up atm. Usually the build doesn't fail if the tests pass though.

echo "Release commit already exists: \"Release ${{ steps.cargo_version.outputs.value}}\""
exit 1
fi

if git show-ref --tags --quiet --verify "refs/tags/v${{ steps.cargo_version.outputs.value }}"; then
echo "Git tag v${{ steps.cargo_version.outputs.value }} already exists."
exit 1
fi

- name: Commit the changes
uses: stefanzweifel/git-auto-commit-action@ac8823709a85c7ce090849ac3e5fe24d006f6e18 # v5.0.1
with:
commit_message: "Release ${{ steps.cargo_version.outputs.value }}"
branch: ${{ github.head_ref }}
commit_user_name: tinted-theming-bot
commit_user_email: [email protected]
commit_author: tinted-theming-bot <[email protected]>
45 changes: 18 additions & 27 deletions RELEASE.md
Original file line number Diff line number Diff line change
@@ -1,32 +1,19 @@
# Release process

1. Create a release commit. This includes specific updated files:

1. Cargo.toml (Bump the version using [semver] standards)
1. Cargo.lock (This is usually updated automatically with the `cargo`
CLI tool)
1. Make sure the changes for the new release exist under
`CHANGELOG.md`. This should already exist since changes done in
GitHub Pull Requests should include updates to the `CHANGELOG.md`.
If this doesn't exist, the release will fail.
1. Change `CHANGELOG.md` `## Unreleased` to `## [x.x.x] - YYYY-MM-DD`
where `x.x.x` is the new Tinty version specified in the
`Cargo.toml` file and the link to `[x.x.x]` at the bottom of the
`CHANGELOG.md` file and compare it with the previously released
version, eg:

```md
[0.22.0]: https://github.com/tinted-theming/tinty/compare/v0.21.1...v0.22.0
```

1. Run `cargo about generate about.hbs > LICENSES-THIRD-PARTY.md` to
update the third party licenses. (`cargo install cargo-about` if
you don't have it installed)
1. Create a commit with the 3 changed files titled `Release x.x.x`
where `x.x.x` is the new Tinty version specified in the
`Cargo.toml` file

1. Push the commit or create a Pull Request and merge
1. Make sure `## Unreleased` section exists in [CHANGELOG.md]
1. Run [Release Commit GitHub action]. Select `minor` or `patch` as a
dispatch value option. This follows the [semver] pattern.

- `minor` if changes include new features or breaking changes
- `patch` if the change only contains bug fixes

This action does the following:

1. Bumps `Cargo.toml` version by `minor` or `patch`
1. Updates `Cargo.lock` with the new version
1. Updates [CHANGELOG.md] `## Unreleased` section to the new version
1. Updates [LICENSE-THIRD-PARTY.md]

1. Once the CI tests have passed, run the [Release GitHub action]. This
will automatically do the following:

Expand All @@ -35,11 +22,15 @@
1. Create a release under [GitHub releases] with the changes
mentioned in `CHANGELOG`
1. Generate the various binaries and add it to the GitHub release

1. Run the [homebrew-tinted] [Update CLI tool GitHub
action] and specify `tinty` as the action input value. This will
update the version for [Homebrew]

[semver]: https://semver.org/
[CHANGELOG.md]: ./CHANGELOG.md
[LICENSE-THIRD-PARTY.md]: ./LICENSE-THIRD-PARTY.md
[Release Commit GitHub action]: https://github.com/tinted-theming/tinty/actions/workflows/release-commit.yml
[Release GitHub action]: https://github.com/tinted-theming/tinty/actions/workflows/release.yml
[GitHub releases]: https://github.com/tinted-theming/tinty/releases
[homebrew-tinted]: https://github.com/tinted-theming/homebrew-tinted
Expand Down
119 changes: 119 additions & 0 deletions scripts/create_release_changes
Original file line number Diff line number Diff line change
@@ -0,0 +1,119 @@
#!/usr/bin/env bash

main() {
local level="$1" # Supported: [major|minor|patch]
local old_version=$(get_cargo_version)

# Ensure things are as expected before doing anything
setup

bump_cargo_version "$level"

local new_version="$(get_cargo_version)"
version_changelog "$old_version" "$new_version"

update_third_party_licenses
check_for_unauthorized_changes
}

setup() {
# Ensure there are no changes in the repository
if [[ -n $(git status --porcelain) ]]; then
echo "Uncommitted changes or untracked files already exist in the repository."
exit 1
fi
}

# Extract the version from Cargo.toml
get_cargo_version() {
local cargo_toml="./Cargo.toml"
local version=$(grep -m 1 '^version =' "$cargo_toml" | sed -E 's/version = "(.*)"/\1/')

if [[ -z "$version" ]]; then
echo "Version not found in Cargo.toml"
exit 1
fi

echo "$version"
}

# Bump version in Cargo.toml
bump_cargo_version() {
local level="$1"
local version=$(get_cargo_version "$level")
local cargo_toml="./Cargo.toml"

# Split version into major, minor, patch
IFS='.' read -r major minor patch <<< "$version"
echo "Current version: $version"

# Increment based on major, minor or patch
if [[ "$level" == "major" ]]; then
major=$((major + 1))
minor=0
patch=0
elif [[ "$level" == "minor" ]]; then
minor=$((minor + 1))
patch=0
elif [[ "$level" == "patch" ]]; then
patch=$((patch + 1))
else
echo "Usage: $0 [major|minor|patch]"
exit 1
fi

local updated_version="$major.$minor.$patch"
sed -i -E "s/version = \"$version\"/version = \"$updated_version\"/" "$cargo_toml"
JamyGolden marked this conversation as resolved.
Show resolved Hide resolved

echo "Updated Cargo.toml to version $updated_version"
}

# Add version and date to "Unreleased" section in changelog
version_changelog() {
local old_version="$1"
local new_version="$2"
local changelog_file="./CHANGELOG.md"

if [[ ! $(grep '^## Unreleased' "$changelog_file") ]]; then
echo "Warning: CHANGELOG.md does not have an 'Unreleased' section"
exit 1
fi

local current_date=$(date +"%Y-%m-%d")
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Might help to set TZ=UTC or whatever to explicitly pin a timezone to avoid any surprises.


sed -i -E "s/## Unreleased/## \[$new_version\] - $current_date/" "$changelog_file"
sed -i "/^\[$old_version\]: /i \[$new_version\]: https://github.com/tinted-theming/tinty/compare/v$old_version...v$new_version" "$changelog_file"

echo "Updated CHANGELOG.md with $new_version"
}

# Update third-party licenses with `cargo about`
update_third_party_licenses() {
local license_file="./LICENSES-THIRD-PARTY.md"

cargo deny check
cargo about generate about.hbs > "$license_file"

echo "Updated third-party licenses"
}

# Exit if disallowed files contain changes
check_for_unauthorized_changes() {
local allowed_files=("Cargo.toml" "Cargo.lock" "LICENSES-THIRD-PARTY.md" "CHANGELOG.md")
local changed_files=$(git status --porcelain | awk '{print $2}')
local unauthorized_changes=0

for file in $changed_files; do
if [[ ! " ${allowed_files[*]} " =~ " ${file} " ]]; then
echo "Unauthorized change detected: $file"
unauthorized_changes=1
fi
done

if [[ $unauthorized_changes -eq 1 ]]; then
echo "Error: Only allow-listed files may change: ${allowed_files[*]}."
exit 1
fi
}

main "$@"
Loading