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
30 changes: 25 additions & 5 deletions .github/workflows/release.yml
Original file line number Diff line number Diff line change
@@ -1,10 +1,12 @@
name: Release

# Tag a version to cut a release:
# cargo set-version 0.1.0 # or edit Cargo.toml
# git tag v0.1.0 && git push origin v0.1.0
# Cut a release with scripts/release.sh, which bumps the version, regenerates
# CHANGELOG.md from Conventional Commits, commits, and tags:
# scripts/release.sh 0.2.0
# git push origin main v0.2.0
#
# This builds a binary per platform, attaches them to the GitHub Release, and
# Pushing the tag runs this workflow: it builds a binary per platform, attaches them
# to the GitHub Release (notes generated from the same history by git-cliff), and
# publishes the crate to crates.io. Because the assets are named
# `frd-<target>.{tar.gz,zip}` with the binary at the archive root, `cargo binstall frd`
# finds them with no `[package.metadata.binstall]` config (it matches binstall's
Expand All @@ -22,8 +24,26 @@ env:
CARGO_TERM_COLOR: always

jobs:
changelog:
name: release notes
runs-on: ubuntu-latest
outputs:
notes: ${{ steps.git-cliff.outputs.content }}
steps:
- uses: actions/checkout@v6
with:
fetch-depth: 0 # git-cliff needs full history and tags

- name: Generate release notes for the tag
id: git-cliff
uses: orhun/git-cliff-action@v4
with:
config: cliff.toml
args: --latest --strip header

build:
name: build ${{ matrix.target }}
needs: changelog
runs-on: ${{ matrix.os }}
permissions:
contents: write # create the release and upload assets
Expand Down Expand Up @@ -68,7 +88,7 @@ jobs:
with:
files: ${{ env.ASSET }}
fail_on_unmatched_files: true
generate_release_notes: true
body: ${{ needs.changelog.outputs.notes }}

publish-crate:
name: publish to crates.io
Expand Down
17 changes: 17 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
# Changelog

## [unreleased]

### Features
- Add doctor subcommand for read-only optimization audit ([#2](https://github.com/cs50victor/fast-rust-dev/pull/2))

## [0.1.0] - 2026-05-30

### Features
- Initial frd build and disk optimizer for macOS
- Cross-platform system probing via sysinfo plus release workflow and README ([#1](https://github.com/cs50victor/fast-rust-dev/pull/1))

### Documentation
- Rewrite package description to emphasize build speed and target size

<!-- generated by git-cliff -->
61 changes: 61 additions & 0 deletions cliff.toml
Original file line number Diff line number Diff line change
@@ -0,0 +1,61 @@
# git-cliff configuration. See https://git-cliff.org/docs/configuration
# Generates CHANGELOG.md from Conventional Commits. Regenerated on every release by
# scripts/release.sh; the GitHub Release body is produced from the same history in CI.

[remote.github]
owner = "cs50victor"
repo = "fast-rust-dev"

[changelog]
header = "# Changelog\n\n"
body = """
{% if version %}\
## [{{ version | trim_start_matches(pat="v") }}] - {{ timestamp | date(format="%Y-%m-%d") }}
{% else %}\
## [unreleased]
{% endif %}\
{% for group, commits in commits | group_by(attribute="group") %}
### {{ group | striptags | trim | upper_first }}
{% for commit in commits %}\
- {% if commit.scope %}*({{ commit.scope }})* {% endif %}\
{% if commit.breaking %}[**breaking**] {% endif %}\
{{ commit.message | upper_first }}
{% endfor %}\
{% endfor %}\n
"""
footer = "<!-- generated by git-cliff -->\n"
trim = true
postprocessors = [
{ pattern = '<REPO>', replace = "https://github.com/cs50victor/fast-rust-dev" },
]

[git]
conventional_commits = true
filter_unconventional = true
split_commits = false
commit_preprocessors = [
# Turn "(#12)" into a linked PR reference, resolved by the postprocessor above.
{ pattern = '\((\w+\s)?#([0-9]+)\)', replace = "([#${2}](<REPO>/pull/${2}))" },
]
# First matching parser wins. Ordering controls section order via the <!-- N --> prefix,
# which `striptags` removes from the rendered header. Internal types are skipped so the
# changelog stays user-facing, matching how uv and ruff ignore ci/chore/testing.
commit_parsers = [
{ message = "^feat", group = "<!-- 0 -->Features" },
{ message = "^fix", group = "<!-- 1 -->Bug Fixes" },
{ message = "^perf", group = "<!-- 2 -->Performance" },
{ message = "^refactor", group = "<!-- 3 -->Refactor" },
{ message = "^doc", group = "<!-- 4 -->Documentation" },
{ message = "^style", skip = true },
{ message = "^test", skip = true },
{ message = "^ci", skip = true },
{ message = "^build", skip = true },
{ message = "^chore", skip = true },
{ message = "^revert", group = "<!-- 5 -->Revert" },
{ body = ".*security", group = "<!-- 6 -->Security" },
]
protect_breaking_commits = false
filter_commits = false
tag_pattern = "v[0-9]*"
topo_order = false
sort_commits = "oldest"
39 changes: 39 additions & 0 deletions scripts/release.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,39 @@
#!/usr/bin/env bash
# Cut a release: bump the version, regenerate CHANGELOG.md from Conventional Commits,
# commit, and tag. Review the result, then push to trigger the Release workflow.
#
# scripts/release.sh 0.2.0
# git push origin main v0.2.0
#
# Requires git-cliff (cargo binstall git-cliff) and cargo-set-version (cargo install cargo-edit).
set -euo pipefail

version="${1:-}"
if [[ -z "$version" ]]; then
echo "usage: scripts/release.sh <version> e.g. scripts/release.sh 0.2.0" >&2
exit 2
fi
tag="v${version}"

cd "$(dirname "$0")/.."

for tool in git-cliff cargo; do
command -v "$tool" >/dev/null || { echo "missing required tool: $tool" >&2; exit 1; }
done

if [[ -n "$(git status --porcelain)" ]]; then
echo "working tree is dirty; commit or stash before releasing" >&2
exit 1
fi

cargo set-version "$version"
# --tag assigns the unreleased commits to this version so the new section is dated now.
git-cliff --config cliff.toml --tag "$tag" --output CHANGELOG.md

git add CHANGELOG.md Cargo.toml Cargo.lock
git commit -m "chore(release): $tag"
git tag "$tag"

echo
echo "Tagged $tag. Review the commit, then push:"
echo " git push origin main $tag"
Loading