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
1 change: 1 addition & 0 deletions .gitattributes
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
hooks/pre-push-changelog text eol=lf
35 changes: 22 additions & 13 deletions .github/workflows/python-release-uv.yml
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,16 @@ on:
required: false
type: boolean
default: true
tag-prefix:
description: Prefix stripped from the pushed tag to derive the version
required: false
type: string
default: "v"
changelog-path:
description: Path to the changelog file relative to working-directory
required: false
type: string
default: "CHANGELOG.md"


# Allow only one concurrent deployment, skipping runs queued between the run in-progress and latest queued.
Expand All @@ -53,32 +63,31 @@ jobs:

- uses: actions/checkout@v5

- name: install_package
uses: GNS-Science/nshm-github-actions/.github/actions/python-install-uv@main
with:
python-version: ${{ inputs.python-version }}
uv-version: ${{ inputs.uv-version }}
working-directory: ${{ inputs.working-directory }}

#----------------------------------------------
# get version
# get version and verify changelog entry
#----------------------------------------------
- name: Get version from tag
id: tag_name
if: startsWith(github.ref, 'refs/tags/')
run: |
echo name=current_version::${GITHUB_REF#refs/tags/v} >> "$GITHUB_OUTPUT"
echo "current_version=${GITHUB_REF_NAME#${{ inputs.tag-prefix }}}" >> "$GITHUB_OUTPUT"
shell: bash

#----------------------------------------------
# get changelog entry
#----------------------------------------------
- name: Get Changelog Entry
id: changelog_reader
if: startsWith(github.ref, 'refs/tags/')
uses: GNS-Science/changelog-reader-action@master
with:
validation_depth: 10
version: ${{ steps.tag_name.outputs.current_version }}
path: ${{ inputs.working-directory }}/CHANGELOG.md
path: ${{ inputs.working-directory }}/${{ inputs.changelog-path }}

- name: install_package
uses: GNS-Science/nshm-github-actions/.github/actions/python-install-uv@main
with:
python-version: ${{ inputs.python-version }}
uv-version: ${{ inputs.uv-version }}
working-directory: ${{ inputs.working-directory }}

#----------------------------------------------
# build wheels and tarball
Expand Down
35 changes: 22 additions & 13 deletions .github/workflows/python-release.yml
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,16 @@ on:
required: false
type: boolean
default: true
tag-prefix:
description: Prefix stripped from the pushed tag to derive the version
required: false
type: string
default: "v"
changelog-path:
description: Path to the changelog file relative to working-directory
required: false
type: string
default: "CHANGELOG.md"


# Allow only one concurrent deployment, skipping runs queued between the run in-progress and latest queued.
Expand All @@ -53,32 +63,31 @@ jobs:

- uses: actions/checkout@v5

- name: install_package
uses: GNS-Science/nshm-github-actions/.github/actions/python-install@main
with:
python-version: ${{ inputs.python-version }}
poetry-version: ${{ inputs.poetry-version }}
working-directory: ${{ inputs.working-directory }}

#----------------------------------------------
# get version
# get version and verify changelog entry
#----------------------------------------------
- name: Get version from tag
id: tag_name
if: startsWith(github.ref, 'refs/tags/')
run: |
echo name=current_version::${GITHUB_REF#refs/tags/v} >> "$GITHUB_OUTPUT"
echo "current_version=${GITHUB_REF_NAME#${{ inputs.tag-prefix }}}" >> "$GITHUB_OUTPUT"
shell: bash

#----------------------------------------------
# get changelog entry
#----------------------------------------------
- name: Get Changelog Entry
id: changelog_reader
if: startsWith(github.ref, 'refs/tags/')
uses: GNS-Science/changelog-reader-action@master
with:
validation_depth: 10
version: ${{ steps.tag_name.outputs.current_version }}
path: ${{ inputs.working-directory }}/CHANGELOG.md
path: ${{ inputs.working-directory }}/${{ inputs.changelog-path }}

- name: install_package
uses: GNS-Science/nshm-github-actions/.github/actions/python-install@main
with:
python-version: ${{ inputs.python-version }}
poetry-version: ${{ inputs.poetry-version }}
working-directory: ${{ inputs.working-directory }}

#----------------------------------------------
# build wheels and tarball
Expand Down
35 changes: 35 additions & 0 deletions README.MD
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,8 @@ Creates a GitHub release and publishes the package to PyPI. Would commonly be on

Requires the secret `PYPI_API_TOKEN`.

When triggered by a version tag, the workflow verifies that `CHANGELOG.md` contains a `## [VERSION]` section matching the tag before proceeding. It fails fast (before installing dependencies) if the entry is missing.

Example use:

```yml
Expand All @@ -38,6 +40,8 @@ jobs:
uses: GNS-Science/nshm-github-actions/.github/workflows/python-release.yml@main
with:
python-version: '3.12'
# tag-prefix: 'v' # default: v
# changelog-path: 'CHANGELOG.md' # default: CHANGELOG.md
secrets: inherit
```

Expand Down Expand Up @@ -83,12 +87,16 @@ jobs:

Creates a GitHub release and publishes the package to PyPI using `uv build`. Requires the secret `PYPI_API_TOKEN`.

Same changelog-entry gate as the Poetry variant above.

```yml
jobs:
release-and-distribute:
uses: GNS-Science/nshm-github-actions/.github/workflows/python-release-uv.yml@main
with:
python-version: '3.12'
# tag-prefix: 'v' # default: v
# changelog-path: 'CHANGELOG.md' # default: CHANGELOG.md
secrets: inherit
```

Expand Down Expand Up @@ -121,3 +129,30 @@ Example use:
```

See [deploy-to-aws.yml](./.github/workflows/deploy-to-aws.yml) for a list of supported and required list of secrets and environment variables as well as workflow inputs.

## Pre-push changelog hook

A local git hook is available at [`hooks/pre-push-changelog`](./hooks/pre-push-changelog). It performs the same changelog-entry check as the release workflows, blocking a version tag push before it reaches CI.

### Install

Run once per repository checkout. On Windows, use Git Bash (not PowerShell or cmd).

```bash
mkdir -p .githooks
curl -o .githooks/pre-push \
https://raw.githubusercontent.com/GNS-Science/nshm-github-actions/main/hooks/pre-push-changelog
chmod +x .githooks/pre-push
git config core.hooksPath .githooks
```

The hook can be bypassed with `git push --no-verify`, but CI will still enforce the check.

### Configuration

Override defaults via environment variables (e.g. via `direnv` or your shell profile):

| Variable | Default | Description |
|---|---|---|
| `TAG_PREFIX` | `v` | Prefix stripped from the tag name to derive the version |
| `CHANGELOG_PATH` | `CHANGELOG.md` | Path to the changelog file (relative to repo root) |
22 changes: 22 additions & 0 deletions hooks/pre-push-changelog
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
#!/usr/bin/env bash
set -euo pipefail

# Prevent pushing a version tag unless the changelog has a matching entry.
# Override defaults via env vars: CHANGELOG_PATH, TAG_PREFIX
CHANGELOG_PATH="${CHANGELOG_PATH:-CHANGELOG.md}"
TAG_PREFIX="${TAG_PREFIX:-v}"

while read -r local_ref local_sha remote_ref remote_sha; do
case "${local_ref}" in
refs/tags/${TAG_PREFIX}*)
version="${local_ref#refs/tags/${TAG_PREFIX}}"
if ! grep -qE "^## \[${version}\]" "${CHANGELOG_PATH}"; then
echo "ERROR: ${CHANGELOG_PATH} is missing a '## [${version}]' section for tag ${local_ref#refs/tags/}." >&2
echo "Update ${CHANGELOG_PATH}, delete the tag (git tag -d ${local_ref#refs/tags/}), commit, and re-tag." >&2
exit 1
fi
;;
esac
done

exit 0
13 changes: 13 additions & 0 deletions samplePythonProject/CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
# Changelog

All notable changes to this project will be documented in this file.

The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/),
and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).

## [Unreleased]

## [0.1.0] - 2024-01-01

### Added
- Initial release fixture for nshm-github-actions workflow testing.
13 changes: 13 additions & 0 deletions samplePythonProjectUv/CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
# Changelog

All notable changes to this project will be documented in this file.

The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/),
and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).

## [Unreleased]

## [0.1.0] - 2024-01-01

### Added
- Initial release fixture for nshm-github-actions workflow testing.
Loading