Files
MeshTerm/.github/workflows/github-release.yml
T
Jean-Pierre MartineauandClaude Fable 5.1 8b80a88f03 The sdist is the package's source, not the repository's
Hatchling's default sdist is everything git does not ignore, which packed the
Claude skills, the GitHub configuration, the PyInstaller spec, the device-side
scripts and the developer environment template into an archive whose only job
is to build and test the wheel. An exclude list keeps the package, the tests
and their fixture, the manual and the files a build reads. The build backend
floor is hatchling 1.26, the first to write the PEP 639 licence fields into the
metadata; an older one built a wheel that said nothing about the licence.
Workflow comments that reasoned from a private repo's metered minutes are
reworded for the public one, a skill's usage line stops naming one machine's
venv, and the scheduler's lock file is ignored in the tree rather than only in
one clone's info/exclude.

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
2026-09-12 19:02:02 -04:00

109 lines
4.0 KiB
YAML

# Puts the downloadable builds on the repository's Releases page.
#
# Nothing here leaves GitHub: a release is exactly as visible as the repository it sits
# on. This is *not* the PyPI publish — that is `release.yml`, it is a separate act, and it
# does not run from here.
#
# Triggered by pushing a version tag, which is the moment a release exists in git anyway:
#
# git tag -a v0.3.0 -m "MeshTerm 0.3.0"
# git push origin v0.3.0
#
# The binaries are built by `installers.yml`, called rather than copied, so the files
# people download are made exactly the way the ones CI checks on every push are.
name: GitHub release
on:
push:
tags: ["v*"]
workflow_dispatch:
inputs:
tag:
description: "Existing tag to build a release from (e.g. v0.2.0)"
required: true
type: string
prerelease:
description: "Mark as a pre-release (keeps it out of 'Latest')"
type: boolean
default: false
permissions:
contents: read
jobs:
build:
uses: ./.github/workflows/installers.yml
publish:
name: create the release
needs: build
runs-on: ubuntu-latest
timeout-minutes: 10
permissions:
# The one job that needs it: creating a release writes to the repository.
contents: write
steps:
- uses: actions/checkout@v4
with:
ref: ${{ inputs.tag || github.ref }}
# Every platform's artifact, flattened into one directory of files to attach.
- uses: actions/download-artifact@v4
with:
path: artifacts
merge-multiple: true
- name: Gather the binaries and their checksums
id: gather
shell: bash
run: |
mkdir -p release
find artifacts -type f -exec mv {} release/ \;
ls -lh release/
# One combined checksum file is easier to verify against than five loose ones.
(cd release && cat *.sha256 > SHA256SUMS && rm -f *.sha256)
tag="${{ inputs.tag || github.ref_name }}"
echo "tag=$tag" >> "$GITHUB_OUTPUT"
echo "version=${tag#v}" >> "$GITHUB_OUTPUT"
- name: Take the release notes from the changelog
id: notes
shell: bash
env:
VERSION: ${{ steps.gather.outputs.version }}
run: |
# The section for this version, between its own heading and the next one. If the
# changelog has nothing for it, say so plainly rather than inventing notes.
#
# Extracted once, into the file, and the *file* is what gets tested. It used to
# run twice — once down a `| sed | head -1 | grep -q .` pipeline to decide, then
# again for real — and this step runs under `bash -e -o pipefail`, where that
# pipeline is a race it can lose. `head -1` exits the moment it has its line and
# closes the pipe; if `sed` still has bytes to write it dies on SIGPIPE, pipefail
# promotes that to a failed condition, and a version with a perfectly good
# changelog section publishes "No changelog entry" instead. It only bites once a
# section outgrows one buffered write, which is why every entry under 4 KB was
# fine and 0.3.1 was not — while 0.3.0, the same size, happened to win.
awk -v v="$VERSION" '
$0 ~ "^## \\[" v "\\]" {found=1; next}
found && /^## \[/ {exit}
found {print}
' CHANGELOG.md > notes.md
if ! grep -q '[^[:space:]]' notes.md; then
echo "No changelog entry for $VERSION." > notes.md
fi
echo "--- notes ---"; cat notes.md
- name: Create it
env:
GH_TOKEN: ${{ github.token }}
TAG: ${{ steps.gather.outputs.tag }}
PRERELEASE: ${{ inputs.prerelease && '--prerelease' || '' }}
run: |
gh release create "$TAG" release/* \
--title "MeshTerm ${TAG#v}" \
--notes-file notes.md \
--verify-tag \
$PRERELEASE
echo "https://github.com/${{ github.repository }}/releases/tag/$TAG"