Skip to content
Open
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
49 changes: 49 additions & 0 deletions .github/workflows/commit-lint.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,49 @@
name: commit-lint

# Enforces Conventional Commits, modeled on NatLabRockies/R2X's
# commit.yaml. This is what makes release-please (release.yml) work at
# all — it computes version bumps and changelog sections by parsing
# commit-message prefixes (feat/fix/docs/...), so an unprefixed commit
# is silently invisible to it rather than an error.
#
# Informational only for now: these checks aren't in the branch
# protection ruleset's required-checks list, so they don't block
# merging. Add them there if you want it enforced rather than
# best-effort.

on:
pull_request:
types: [opened, reopened, synchronize, edited]

concurrency:
group: ${{ github.workflow }}-${{ github.event.pull_request.number }}
cancel-in-progress: true

permissions:
contents: read

jobs:
lint-commit-messages:
name: lint commit messages
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
with:
ref: ${{ github.event.pull_request.head.sha }}
fetch-depth: 2
- uses: astral-sh/setup-uv@v4
- name: Commitizen check
run: uvx --from commitizen cz check --rev-range HEAD^!

lint-pr-title:
# Squash-merges use the PR title as the final commit message, so
# this is what release-please actually sees for a squashed PR —
# lint it the same way as individual commits.
name: lint PR title
runs-on: ubuntu-latest
permissions:
pull-requests: read
steps:
- uses: amannn/action-semantic-pull-request@v6
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
80 changes: 71 additions & 9 deletions .github/workflows/release.yml
Original file line number Diff line number Diff line change
@@ -1,20 +1,73 @@
name: release

# Automated release flow modeled on NatLabRockies/R2X's release-please
# setup, adapted for a single package with no static version string to
# bump (GAT uses setuptools_scm — the version is derived entirely from
# git tags at build time, hence release-type "simple" below rather than
# "python": there's no `version = "x.y.z"` line for release-please to
# edit).
#
# Flow:
# 1. Every push to main: release-please looks at conventional-commit
# messages since the last release and keeps a standing "chore:
# release vX.Y.Z" PR open, auto-updating docs/source/CHANGELOG.md
# as more commits land. Merging that PR is the only manual step.
# 2. The moment that PR merges, release-please creates the git tag
# and GitHub Release (release_created=true) — no one runs `git tag`
# by hand anymore.
# 3. build + publish-pypi then run exactly as before, gated on
# release_created instead of a tag-push event.
#
# workflow_dispatch is kept as a manual escape hatch to rebuild/republish
# the current tag if a step needs re-running (publish-pypi's
# skip-existing: true makes this safe to re-trigger).

on:
push:
tags:
- 'v*'
branches: [main]
workflow_dispatch:

concurrency:
group: release
cancel-in-progress: false

jobs:
build:
release-please:
name: release-please
if: github.event_name == 'push'
runs-on: ubuntu-latest
permissions:
contents: write
pull-requests: write
outputs:
release_created: ${{ steps.rp.outputs.release_created }}
tag_name: ${{ steps.rp.outputs.tag_name }}
steps:
- name: Run release-please
id: rp
uses: googleapis/release-please-action@v4
with:
token: ${{ secrets.GITHUB_TOKEN }}
config-file: .release-please-config.json
manifest-file: .release-please-manifest.json
target-branch: main

build:
name: Build distribution
needs: [release-please]
if: |
always() && (
(github.event_name == 'push' && needs.release-please.outputs.release_created == 'true') ||
github.event_name == 'workflow_dispatch'
)
runs-on: ubuntu-latest
permissions:
contents: write
steps:
- uses: actions/checkout@v4
with:
fetch-depth: 0
ref: ${{ needs.release-please.outputs.tag_name || github.ref }}

- name: Install uv
uses: astral-sh/setup-uv@v4
Expand All @@ -27,9 +80,11 @@ jobs:
- name: Build sdist and wheel
run: uv build

- name: Upload release assets
- name: Attach dists to the GitHub release
if: needs.release-please.outputs.release_created == 'true'
uses: softprops/action-gh-release@v2
with:
tag_name: ${{ needs.release-please.outputs.tag_name }}
files: |
dist/nlr_gat-*.whl
dist/nlr_gat-*.tar.gz
Expand All @@ -41,16 +96,21 @@ jobs:
path: dist/

# Publishes via PyPI Trusted Publishing (OIDC) — no API token is stored
# in the repo. One-time setup on PyPI is required before the first run:
# add a "pending publisher" for the project name `nlr-gat` with
# owner NatLabRockies, repository GridAnalysisToolkit, workflow
# release.yml, and environment pypi
# in the repo. One-time setup on PyPI: a "pending publisher" for
# project name `nlr-gat`, owner NatLabRockies, repository
# GridAnalysisToolkit, workflow release.yml, environment pypi
# (https://pypi.org/manage/account/publishing/).
# The `pypi` GitHub environment is created automatically on first use;
# protection rules (required reviewers) can be added to it in repo
# Settings → Environments to gate publishes.
publish-pypi:
needs: build
name: Publish to PyPI
needs: [release-please, build]
if: |
always() && needs.build.result == 'success' && (
(github.event_name == 'push' && needs.release-please.outputs.release_created == 'true') ||
github.event_name == 'workflow_dispatch'
)
runs-on: ubuntu-latest
environment:
name: pypi
Expand All @@ -67,3 +127,5 @@ jobs:

- name: Publish to PyPI
uses: pypa/gh-action-pypi-publish@release/v1
with:
skip-existing: true
25 changes: 25 additions & 0 deletions .release-please-config.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
{
"$schema": "https://raw.githubusercontent.com/googleapis/release-please/main/schemas/config.json",
"changelog-path": "docs/source/CHANGELOG.md",
"changelog-sections": [
{ "hidden": false, "section": "Features", "type": "feat" },
{ "hidden": false, "section": "Bug Fixes", "type": "fix" },
{ "hidden": false, "section": "Performance", "type": "perf" },
{ "hidden": false, "section": "Refactoring", "type": "refactor" },
{ "hidden": false, "section": "Documentation", "type": "docs" },
{ "hidden": false, "section": "CI/CD", "type": "ci" },
{ "hidden": false, "section": "Build", "type": "build" },
{ "hidden": true, "section": "Chores", "type": "chore" },
{ "hidden": false, "section": "Tests", "type": "test" }
],
"packages": {
".": {
"release-type": "simple",
"package-name": "nlr-gat",
"component": "nlr-gat",
"changelog-path": "docs/source/CHANGELOG.md",
"bump-minor-pre-major": false,
"bump-patch-for-minor-pre-major": true
}
}
}
3 changes: 3 additions & 0 deletions .release-please-manifest.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
{
".": "0.1.0"
}
4 changes: 4 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -130,6 +130,10 @@ If you plan to contribute to documentation, install the documentation dependenci

`pip install -e ".[dev,doc]"`

Commit messages and PR titles should follow [Conventional Commits](https://www.conventionalcommits.org/)
(`feat: ...`, `fix: ...`, `docs: ...`, etc.) — releases are generated
automatically from these (see `.github/workflows/release.yml`).

## Building the documentation

After installing the doc dependencies:
Expand Down
Loading