I am using Google's release-please for GitHub Actions. Out of the box, it can:
- adjust version numbers (either via built-in support [it understands most popular package ecosystems] or auxiliary comments) automatically, derived from conventional commits; the version number in
Cargo.toml
won't have to be modified manually ever again, it's automatically SemVer-compliant;
- (automatically) update changelogs via conventional commits, and
- create GitHub releases,
as @Michael-F-Bryan asked.
I just set up a repository of mine to use that workflow. The main GitHub Actions file looks like:
name: Main
on:
push:
env:
CARGO_TERM_COLOR: always
jobs:
build-test:
name: Build and test (${{ matrix.os }})
strategy:
matrix:
os: [ubuntu-latest, macos-latest, windows-latest]
runs-on: ${{ matrix.os }}
steps:
- uses: actions/checkout@v3
- uses: swatinem/rust-cache@v2
- name: Build
run: >
cargo build
--locked
--verbose
- name: Run tests (without coverage)
if: matrix.os != 'ubuntu-latest'
run: >
cargo test
--verbose
- name: Run tests (with coverage)
if: matrix.os == 'ubuntu-latest'
run: >
cargo install cargo-tarpaulin
&& cargo tarpaulin
--verbose
--out Xml
--engine llvm
--skip-clean
- name: Upload coverage reports to Codecov
if: matrix.os == 'ubuntu-latest'
uses: codecov/codecov-action@v3
release-please:
name: Execute release chores
permissions:
contents: write
pull-requests: write
runs-on: ubuntu-latest
needs: build-test
outputs:
created: ${{ steps.release.outputs.release_created }}
steps:
- uses: google-github-actions/release-please-action@v3
id: release
with:
release-type: rust
publish:
name: Publish to crates.io
runs-on: ubuntu-latest
needs: release-please
if: needs.release-please.outputs.created
environment: crates.io
steps:
- uses: actions/checkout@v3
- uses: swatinem/rust-cache@v2
- name: Publish
# https://doc.rust-lang.org/cargo/reference/config.html?highlight=CARGO_REGISTRY_TOKEN#credentials
run: >
cargo publish
--verbose
--locked
--token ${{ secrets.CARGO_REGISTRY_TOKEN }}
It tests on all three major OSes and also uploads code coverage test results to codecov. Note how release-please can work with Rust out of the box (release-type: rust
). I've found caching to be indispensable for acceptable build times, hence swatinem/rust-cache
, which I've found to work well.
Note also that currently, release-please
will require additional permissions (contents
and pull-requests
as write
), and additionally, it needs to be allowed to create pull requests in the UI as well (at least that's what I had to do), else it'll complain with:
Error: release-please failed: GitHub Actions is not permitted to create or approve pull requests.
Lastly, the above runs in an environment, a great tool for more secure deployments, with additional rules and UI sugar:
This lets one pinpoint the exact time the crate was published to crates.io, who authorized it etc. One can create additional environments for container image registries, for example. The secrets.CARGO_REGISTRY_TOKEN
is an environment secret, in the case of this sample repo.
release-please
works through release pull requests, like this one. One caveat in this is that when running under the GITHUB_TOKEN
, your releases will be made as github-actions[bot]
; this bot cannot trigger actions, so workflows will not run on this PR, including required ones. Workarounds are
- specifying a normal, personal token of yours (releases etc. will then be in your name),
- rebasing the PR, then force-pushing, to the same effect but much less autonomously,
- using a separate GitHub account, acting as a bot,
- or lastly, force-merging the PR, with no regards to pipeline checks (the cowboy way).
Note that the release-please
action will run under GITHUB_TOKEN
per default, when nothing else is specified.
Once the "release PR" is merged, anything gated behind if: needs.release-please.outputs.created
runs in the next GH Actions run. A release (example, automatically generated from this same PR) is then also created. Anything you'd like to do, like building binaries as artifacts, can be done here. These binaries can then be attached to the created release (use the upload_url
output of the release-please
action). I hope this addresses all points raised in this thread!