A GitHub milestone per release, holding the issues it fixed has been fixed.
See more details at : https://github.com/pdulvp/prel/issues/7
- prel release now ends on a milestone named after the tag, created if it is
not there, carrying every issue the release's commits named, closed with it
- the issues are read from prel's own #<n> subject prefix over the same
commit range the release notes come from, so there is no second source
- nothing to opt into: a project whose commits name no issue gets no
milestone, --no-milestone opts out, and --draft fills the milestone but
closes nothing - a draft has not shipped
- it is the last step and the one that never fails a made release: by then the
tag is pushed and the artifacts are up, so what it could not do it says,
with the gh command that finishes it
A milestone per release, carrying the issues it fixed
<sub>2026-10-21-2242-release-milestone.md — 2026-10-21 22:42</sub>
Goal
prel release 1.0.1 ends by putting the work it ships on a GitHub milestone:
v1.0.1, created if it is not there already, holding every issue the commits
since the last tag named, each one closed, and the milestone closed with them.
The release page says what changed; the milestone says which issues that was.
The issues come from prel's own commit convention - prel issue-from-plans
puts #<n> in front of the subject - so the range that writes the release
notes is the range that finds the issues, and no second source of truth.
Decisions
- The title is the tag, v1.0.1, the same string as the release and the tag,
so the three read as one thing. prel.tagPrefix therefore moves it too.
- The issues are every #<n> in the subjects of the commits in
<previous tag>..HEAD, deduplicated. Subjects only: that is where prel puts
the number, and a body carries prel: filed as issue #n on every commit,
which would make the range meaningless.
- Taken from the history before the release commit, like the notes, so the
dry run can show the same list the real run will use.
- No issues in the range means no milestone. A project that does not use the
convention gets nothing created rather than an empty milestone per release,
so the step needs no config to opt into - only --no-milestone to opt out.
- The step runs last, after the release is published and out of draft, and
never fails a release that is already out: what it could not do it says, with
the gh command to finish by hand, and the release still reports as made.
Everything before the push is undoable and stops the release; nothing here
is, and a missing milestone does not make a published release wrong.
- --draft creates the milestone and assigns the issues but closes nothing:
a draft has not shipped, so the work it carries is not done yet.
- --no-release skips it entirely - no release, no milestone - as do
--no-milestone and a dry run.
- An issue already on a different milestone is left where it is and named,
rather than moved: it was in an earlier release too, and the earlier one is
the one that fixed it. An issue already closed is simply assigned.
- Each issue is looked at before it is touched, so a #<n> that is a pull
request, or a number no issue has, is reported and the rest still go on.
Steps
- [x] release.sh: _rel_issues_in_range, the #<n> list for a tag range
- [x] release.sh: _rel_milestone_find / _rel_milestone_create, by title
over gh api repos/:owner/:repo/milestones
- [x] release.sh: _rel_milestone_apply - ensure, assign, close the issues,
close the milestone, every failure a warning naming the manual command
- [x] release.sh: --no-milestone, the milestone: line in the plan block,
a --- milestone --- section in the dry run, the call after the release
is taken out of draft, and the usage text
- [x] test: prel release 0.2.2 -n shows the milestone, the issues and the
existing-or-new state; --no-milestone and --no-release show none
- [x] test: the read-only half against this repository - the issue list for
every range, _rel_milestone_find over a repository with no milestone,
and gh issue view on #6 and on a number no issue answers to
- [x] test: the writing half, against this repository and cleaned up after -
a throwaway prel-selftest milestone created, found again, closed,
found again over state=all, reused by a second run, left open by the
draft variant, then deleted. No issue touched; the repository is back
to no milestone at all. The assignment of an issue to a milestone is
the one line a real release will exercise first
- [x] README.md: step 8 in the list, the flag in the command table, and a
"Release milestones" section
- [x] mark complete; write docs/plans/sumup.md per the plan-summary skill;
archive this file
<sub>Filed by prel from the completed plans at commit time.</sub>