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
36 changes: 15 additions & 21 deletions .github/workflows/release.yml
Original file line number Diff line number Diff line change
@@ -1,13 +1,16 @@
# .github/workflows/release.yml
#
# Manual-only release: cuts source/types.h's VERSION_STRING and
# CHANGELOG.md's "## Unreleased" section for the version/title given in the
# CHANGELOG.md's "## Unreleased" section for the version given in the
# dispatch form, commits and pushes that bump straight to main, then builds
# the .3dsx/.smdh and publishes them as a GitHub Release. The version input
# is always typed by hand (no auto-computed default — GitHub's dispatch
# form can't pre-fill a value computed from repo state) and is only
# validated to be greater than the current VERSION_STRING. The workflow
# refuses to overwrite an existing release/tag.
# validated to be greater than the current VERSION_STRING. The CHANGELOG
# heading is just "## vX.Y.Z (date)" — no separate title to type in; the
# Unreleased section's own content (used verbatim as the GitHub Release
# body too) already says what the release is about. The workflow refuses
# to overwrite an existing release/tag.
name: Release

on:
Expand All @@ -17,10 +20,6 @@ on:
description: 'Version to release, e.g. 2.3.2 — no leading "v" (must be greater than the current VERSION_STRING in source/types.h)'
required: true
type: string
title:
description: 'Short title for the CHANGELOG heading, e.g. "Backup fix and test coverage" (becomes "## vX.Y.Z – <title> (date)")'
required: true
type: string

permissions:
contents: write
Expand All @@ -45,27 +44,22 @@ jobs:
token: ${{ secrets.RELEASE_PUSH_TOKEN || github.token }}

# Validates the typed-in version input, then cuts CHANGELOG.md's
# "## Unreleased" section into a dated "## vX.Y.Z – <title>" one
# (leaving a fresh empty "## Unreleased" above it) and bumps
# source/types.h's VERSION_STRING to match — the same two edits a
# human previously made by hand before tagging a release. Fails the
# whole run before touching any file if the input isn't a plain
# x.y.z, isn't greater than the current VERSION_STRING, or the
# changelog has nothing new to release, since a bad input at this
# point would otherwise commit garbage to main.
# "## Unreleased" section into a dated "## vX.Y.Z" one (leaving a
# fresh empty "## Unreleased" above it) and bumps source/types.h's
# VERSION_STRING to match — the same two edits a human previously
# made by hand before tagging a release. Fails the whole run before
# touching any file if the input isn't a plain x.y.z, isn't greater
# than the current VERSION_STRING, or the changelog has nothing new
# to release, since a bad input at this point would otherwise commit
# garbage to main.
- name: Validate and apply version bump
env:
NEW_VERSION: ${{ inputs.version }}
TITLE: ${{ inputs.title }}
run: |
if [[ ! "$NEW_VERSION" =~ ^[0-9]+\.[0-9]+\.[0-9]+$ ]]; then
echo "version input must look like x.y.z with no leading 'v' (got: '$NEW_VERSION')" >&2
exit 1
fi
if [ -z "$TITLE" ]; then
echo "title input must not be empty" >&2
exit 1
fi

CURRENT_VERSION=$(grep -m1 'define VERSION_STRING' source/types.h | sed -E 's/.*"v([^"]*)".*/\1/')
if [ -z "$CURRENT_VERSION" ]; then
Expand All @@ -86,7 +80,7 @@ jobs:
fi

TODAY=$(date -u +%F)
NEWSEC="## v${NEW_VERSION} – ${TITLE} (${TODAY})"
NEWSEC="## v${NEW_VERSION} (${TODAY})"

awk -v newsec="$NEWSEC" '
/^## Unreleased$/ { print; print ""; print newsec; next }
Expand Down
20 changes: 16 additions & 4 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -3,10 +3,10 @@
All notable changes to 3DS App Manager are documented in this file.
Headings use the app's own `VERSION_STRING` (`source/types.h`). Cutting a
release is a manual, deliberate step: trigger the `Release` GitHub Actions
workflow (`.github/workflows/release.yml`) with a version and title
it renames this file's `## Unreleased` section to `## vX.Y.Z – <title>
(date)`, bumps `VERSION_STRING` to match, builds, and publishes the result
as a GitHub Release using that section verbatim as the release notes. Keep
workflow (`.github/workflows/release.yml`) with just a version number
it renames this file's `## Unreleased` section to `## vX.Y.Z (date)`,
bumps `VERSION_STRING` to match, builds, and publishes the result as a
GitHub Release using that section verbatim as the release notes. Keep
the `## vX.Y.Z` heading format exact.

**Policy:** every change gets a `CHANGELOG.md` entry under a `## Unreleased`
Expand All @@ -16,6 +16,18 @@ accurate at all times instead of being reconstructed from memory later.

## Unreleased

### Changed: release workflow no longer asks for a title
`.github/workflows/release.yml`'s `workflow_dispatch` form used to require
typing in both a `version` and a `title` (the latter only ever used to
build the CHANGELOG heading, `## vX.Y.Z – <title> (date)`) — one manual
field too many for something meant to be a quick, low-friction trigger.
Dropped `title` entirely: the heading is now just `## vX.Y.Z (date)`, and
the release's actual notes still come verbatim from the `## Unreleased`
section's own content (unchanged — that's the part that actually says
what the release is about). Only `version` is still typed by hand, since
choosing a semver bump is a real judgment call the workflow can't safely
guess at.

### Removed: host-test CI workflow
`.github/workflows/tests.yml` (the automatic `make -C tests` run on every
push/PR) is removed, trimming Actions down to just two workflows: `build`
Expand Down
13 changes: 7 additions & 6 deletions CLAUDE.md
Original file line number Diff line number Diff line change
Expand Up @@ -185,13 +185,14 @@ workflow for the host test suite (removed to keep Actions to just the PR
build check + the manual release), so run `make test` yourself before
pushing and say explicitly in your summary that it wasn't re-verified by
CI. `.github/workflows/release.yml` is manual-only (`workflow_dispatch`, a
`version` + `title` input, never fires on push/PR) — trigger it from the
single `version` input, never fires on push/PR) — trigger it from the
Actions tab when the user actually asks to cut a release. It validates the
inputs, renames `CHANGELOG.md`'s `## Unreleased` section to
`## vX.Y.Z – <title> (date)`, bumps `VERSION_STRING` in `source/types.h`
to match, commits and pushes that bump to `main`, builds, and publishes
the `.3dsx`/`.smdh` as a GitHub Release using that section verbatim as the
release notes.
input, renames `CHANGELOG.md`'s `## Unreleased` section to
`## vX.Y.Z (date)`, bumps `VERSION_STRING` in `source/types.h` to match,
commits and pushes that bump to `main`, builds, and publishes the
`.3dsx`/`.smdh` as a GitHub Release using that section verbatim as the
release notes — there's no separate title to type in; the Unreleased
section's own content is the release notes.

## Changelog policy

Expand Down
Loading