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
25 changes: 20 additions & 5 deletions .github/workflows/release.yml
Original file line number Diff line number Diff line change
Expand Up @@ -131,11 +131,26 @@ jobs:
found {print}' CHANGELOG.md > release-notes.md
cat release-notes.md

- name: Create GitHub Release
# Converge rather than create. `gh release create` refuses an existing
# tag, so re-dispatching a release that already got this far failed here
# every time — after build and publish had both succeeded, which is the
# most confusing place to stop. workflow_dispatch was added to this
# workflow so a release could be re-driven through a webhook outage; a
# final step that cannot survive a second run takes that back.
- name: Create or update GitHub Release
env:
GH_TOKEN: ${{ github.token }}
run: |
gh release create "${TAG}" just-bashit.tar.gz \
--title "just-bashit ${TAG}" \
--latest \
--notes-file release-notes.md
if gh release view "${TAG}" >/dev/null 2>&1; then
echo "Release ${TAG} already exists — updating it in place"
gh release edit "${TAG}" \
--title "just-bashit ${TAG}" \
--latest \
--notes-file release-notes.md
gh release upload "${TAG}" just-bashit.tar.gz --clobber
else
gh release create "${TAG}" just-bashit.tar.gz \
--title "just-bashit ${TAG}" \
--latest \
--notes-file release-notes.md
fi
22 changes: 22 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,28 @@

## [Unreleased]

### Fixed

- **`make ship` could report a release as failed while it succeeded.**
`release-watch` took the newest release run with `--limit 1`, but `ship`
is `tag-release` then `release-watch`, and the tag push returns before
GitHub has created the run — so the newest row was still the *previous*
release. Shipping v0.4.1 watched a run that had failed the night before
and exited 1 while the real release went on to succeed. A watcher that can
report the wrong run is worse than no watcher, because the failure it
invents looks exactly like a real one. It now selects the run by tag —
`--branch "v$VERSION"`, which is what a tag-triggered run carries — and
waits up to 60s for it to exist, erroring clearly if it never does.

- **A re-dispatched release always failed at the last step.** Since
`gh release create` refuses an existing tag, re-driving a release that had
already got as far as publishing died on "a release with the same tag name
already exists" — after build and publish had both succeeded. The
`workflow_dispatch` trigger was added to this workflow so a release could
be re-driven through a webhook outage; a final step that cannot survive a
second run takes that ability back. It now updates the release in place
when one already exists.

## [0.4.1] - 2026-08-06

### Added
Expand Down
31 changes: 29 additions & 2 deletions Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -152,7 +152,34 @@ just-runit|sed -n 's/^_VERSION="\(.*\)"/\1/p' src/just_bashit/just-runit
src/ headers|grep -h '^# PACKAGE' src/just_bashit/*.sh | sed 's/.*version \([0-9.]*\).*/\1/' | sort -u
endef

RELEASE_WATCH_CMD = gh run watch --exit-status $$(gh run list \
--workflow=release.yml --limit 1 --json databaseId -q '.[0].databaseId')
# Select the run BY TAG, and wait for it to exist.
#
# `--limit 1` alone is a race: `ship` is `tag-release` then `release-watch`, and
# the push returns before GitHub has created the workflow run, so the newest
# row is still the PREVIOUS release. Shipping v0.4.1 watched the run that had
# failed the night before and reported the release as failed while it went on
# to succeed — a watcher that can report the wrong run is worse than none,
# because the failure it invents is indistinguishable from a real one.
#
# A tag-triggered run carries the tag in headBranch, so --branch pins it to
# exactly this release. The wait covers creation latency, which is a second or
# two; 60s of headroom costs nothing on the happy path and turns "no run yet"
# into a clear error rather than an empty run ID.
define RELEASE_WATCH_CMD
@tag="v$(VERSION)"; id=""; \
for _ in $$(seq 1 30); do \
id=$$(gh run list --workflow=release.yml --branch "$$tag" \
--limit 1 --json databaseId -q '.[0].databaseId' 2>/dev/null); \
[ -n "$$id" ] && break; \
sleep 2; \
done; \
if [ -z "$$id" ]; then \
echo "ERROR: no release run for $$tag after 60s"; \
echo " check: gh run list --workflow=release.yml --branch $$tag"; \
exit 1; \
fi; \
echo "Watching release run $$id ($$tag)"; \
gh run watch --exit-status "$$id"
endef

include standard.mk
Loading