agentsclimarketplace

Swift release flow

Skill chsistrying/swift-ship-skills/skills/swift-release-flow

Agent Skills for shipping Swift/macOS apps: .icns icons, .app/DMG packaging, CI portability traps, OSS readiness audit, release flow. Claude Code plugin marketplace.

Install
npx -y skills add chsistrying/swift-ship-skills --skill swift-release-flow

Assembled from the repository path, not quoted from the project. Check it against their README if it does not work.

2 things to look at

  • 17 days oldThe repository was created 17 days ago. New is not bad, but a brand new repository carrying a familiar-sounding name is the shape a typosquat arrives in, and there has been no time for anyone else to find a problem with it.
  • 0 stars0 stars. Stars are a popularity signal and not a quality one, but at this level it is likely that nobody has read this closely except its author, and you would be relying on your own review.

What its author says it does

Copied from the file, not written here

Drives a clean, end-to-end release of a macOS/Swift app hosted on GitHub — preflight checks, version bump, CHANGELOG update, DMG build, git tag, and GitHub release. Use when asked to cut a release, publish a version, ship a new build, create a GitHub release DMG, or tag and release a macOS app. Trigger with "/swift-release-flow".

The file declares its own license as MIT. That is the author’s claim about this one file, and it is not the same thing as the license GitHub reports for the repository, which is listed with the other numbers below.

SKILL.md

10.7 KB, ~2.7k tokens by cl100k_base, as published. Nobody here has run it

Swift Release Flow

Overview

Ship a macOS/Swift app release from a clean main to a published GitHub release, in order. Do not skip steps. Stop and report if any preflight check fails — never force through a red signal.

Prerequisites

  • git and the GitHub CLI (gh), authenticated against the repo.
  • A packaging/DMG script in the repo (Step 4 locates it) — see the companion swiftpm-app-bundle skill if none exists yet.
  • A CHANGELOG.md following Keep a Changelog conventions (created in Step 3 if missing).

Instructions

Step 0 — Confirm the target version

Ask (or infer from CHANGELOG "Unreleased" content) what kind of release this is, then decide the version per semver-for-apps guidance:

  • Patch (X.Y.Z+1): bug fixes, crash fixes, performance, copy/UI tweaks, no new user-facing capability.
  • Minor (X.Y+1.0): new feature, new preference/menu item, new supported file type, a workflow users will notice and want to know about.
  • Major (X+1.0.0): breaking change to data format, dropped OS support, a rewrite, or the maintainer explicitly wants to signal a big jump.
  • 0.x: while pre-1.0, treat minor bumps liberally — everything is "still moving," and 0.x releases are prerelease by default (see Step 5).

State the chosen version back before proceeding.

Step 1 — Preflight

Run these and stop on any failure — report exactly what's red and let the user decide how to fix it. Do not attempt to "fix around" a red preflight (e.g., don't force-push, don't skip tests) without explicit instruction.

git status --porcelain            # must be empty — stop if dirty
git rev-parse --abbrev-ref HEAD   # must be "main" (or confirm the release branch)
git fetch origin main --quiet
git rev-parse HEAD origin/main    # HEAD should match origin/main (or be ahead only if intentional)
gh auth status                    # must be authenticated — see Edge cases if not
gh run list --branch main --limit 5   # latest run for HEAD's commit must be green

If CI is red on HEAD: stop. Do not tag or release on top of a failing build. Report the failing run (gh run view <id> --log-failed) and wait.

Then run the project's local test suite (find it — swift test, xcodebuild test -scheme <Scheme>, or a scripts/test*.sh) and confirm it passes before continuing.

Step 2 — Version bump

Find every place the version string lives — check all of these, don't assume there's only one:

grep -rn "VERSION" --include="*.sh" scripts/ 2>/dev/null
grep -rln "CFBundleShortVersionString\|CFBundleVersion" . --include="*.plist"
grep -rln "MARKETING_VERSION\|CURRENT_PROJECT_VERSION" . --include="*.pbxproj" --include="*.xcconfig"
grep -rn "version" Package.swift 2>/dev/null

Typical locations to check and update consistently to the same X.Y.Z:

  • Info.plist / Info-template.plist: CFBundleShortVersionString (X.Y.Z) and CFBundleVersion (build number — usually bump this too, even on a patch release, since it must strictly increase for Sparkle/appcast users).
  • *.xcconfig or project.pbxproj: MARKETING_VERSION, CURRENT_PROJECT_VERSION.
  • scripts/*.sh: hardcoded VERSION="X.Y.Z" vars used by the packaging script.
  • Package.swift if it declares a version.

Update every hit to the agreed version. If a build-number field exists separately from the marketing version, bump it too (increment by 1) so update-checking mechanisms see a strictly newer build.

Step 3 — CHANGELOG and release notes

Follow Keep a Changelog conventions.

  1. Open CHANGELOG.md. Find the ## [Unreleased] section.
  2. Rename it to a new dated release heading, and add a fresh empty ## [Unreleased] above it:
## [Unreleased]

## [X.Y.Z] - YYYY-MM-DD
### Added
- ...
### Fixed
- ...
### Changed
- ...
  1. Draft user-facing release notes from those entries — this is a rewrite, not a copy-paste of commit messages. Convert commit-speak into benefit language:
    • fix: null deref in exporter → "Fixed a crash that could occur when exporting large projects."
    • feat: add dark mode toggle → "Added a Dark Mode toggle in Preferences."
    • Drop anything purely internal (refactors, CI config, dependency bumps) unless it has a user-visible effect (e.g., "faster startup").
  2. Save these notes to a temp file for use in Step 5, e.g. /tmp/release-notes-X.Y.Z.md, with a top line ## X.Y.Z and grouped bullets.

Commit the version bump + CHANGELOG together:

git add -A
git commit -m "Release vX.Y.Z"
git push origin main

Re-check CI on this new commit before moving on (gh run list --branch main --limit 3) — don't tag a commit whose CI hasn't finished or has failed.

Step 4 — Build the artifact

Locate the packaging script — don't assume a name, search for it:

ls scripts/*dmg* scripts/*release* scripts/*package* scripts/*build* 2>/dev/null

If exactly one plausible script is found, run it. If several exist or none do, ask which to use rather than guessing:

./scripts/build-dmg.sh          # example — use the actual script found

Verify the resulting artifact is a valid, mountable disk image before trusting it:

hdiutil verify path/to/AppName-X.Y.Z.dmg

hdiutil verify must report the image is valid. If it fails, do not proceed to tagging — rebuild and re-verify.

Also sanity-check the artifact isn't accidentally huge or empty:

ls -lh path/to/AppName-X.Y.Z.dmg

Step 5 — Tag and release

Create an annotated tag (not lightweight — annotated tags carry the release message and author, and are what gh release expects):

git tag -a vX.Y.Z -m "vX.Y.Z"
git push origin vX.Y.Z

Create the GitHub release, attaching the artifact and using the notes file from Step 3:

gh release create vX.Y.Z path/to/AppName-X.Y.Z.dmg \
  --title "vX.Y.Z" \
  --notes-file /tmp/release-notes-X.Y.Z.md

Mark as prerelease when either is true:

  • The version is 0.x.y (pre-1.0, still stabilizing), or
  • The build is unsigned / not notarized.
gh release create vX.Y.Z path/to/AppName-X.Y.Z.dmg \
  --title "vX.Y.Z" \
  --notes-file /tmp/release-notes-X.Y.Z.md \
  --prerelease

If the build is unsigned, always append this note to the release notes before publishing (macOS Gatekeeper will otherwise confuse users):

> **Note:** This build is unsigned. macOS Gatekeeper will warn that it
> can't be opened. To run it: right-click (or Control-click) the app in
> Finder and choose **Open**, then confirm in the dialog that appears.
> You only need to do this once.

Step 6 — Post-release verification

gh release view vX.Y.Z --web        # confirm the page looks right
gh release view vX.Y.Z              # confirm asset is attached, notes render

Confirm:

  • The DMG asset is listed and its size looks right (matches Step 4's ls -lh).
  • Notes render correctly (no broken Markdown from the CHANGELOG rewrite).
  • Prerelease flag is set correctly for 0.x/unsigned builds, not set for stable signed 1.x+ builds.

If the project bumps to a "next dev" version after release (e.g., X.Y.(Z+1)-dev or reopening Unreleased with a -SNAPSHOT marker), do that now, commit, and push:

# only if the project follows this convention — check for prior examples
# in git log before doing this
git commit -am "Begin X.Y.(Z+1) development"
git push origin main

Finally, remind the user to announce the release (README badge, socials, release channel, etc.) — this skill does not post announcements itself.

Output

A published GitHub release: annotated vX.Y.Z tag on a green main, the verified DMG attached as an asset, user-facing release notes, the prerelease flag set correctly for 0.x/unsigned builds, and the CHANGELOG carrying a fresh empty [Unreleased] section.

Examples

# A typical 0.x patch release of an unsigned menu bar app
git status --porcelain && gh run list --branch main --limit 1   # preflight
./scripts/build-dmg.sh && hdiutil verify dist/App-0.2.1.dmg     # artifact
git tag -a v0.2.1 -m "v0.2.1" && git push origin v0.2.1
gh release create v0.2.1 dist/App-0.2.1.dmg --title "v0.2.1" \
  --notes-file /tmp/release-notes-0.2.1.md --prerelease

Edge cases

Tag already exists locally or on remote. Never silently overwrite a tag someone else may have pulled. Confirm with the user, then:

git tag -d vX.Y.Z                       # delete local
git push origin :refs/tags/vX.Y.Z       # delete remote
git tag -a vX.Y.Z -m "vX.Y.Z"           # re-create
git push origin vX.Y.Z

CI is red on HEAD. Stop. Do not tag, build, or release. Report the failing job (gh run view <run-id> --log-failed) and wait for a fix or explicit override instruction.

gh is not authenticated.

gh auth status
gh auth login

Do not attempt releases via raw API calls or tokens as a workaround unless explicitly asked.

Artifact exceeds GitHub's 2GB per-file release-asset limit. gh release create will fail the upload. Options to raise with the user: split the DMG, host it externally (e.g., S3) and link it in the release notes, or reduce artifact size (strip debug symbols, compress more aggressively). Do not silently truncate or skip the asset.

Re-cutting a botched release (wrong artifact, wrong notes, bad tag):

gh release delete vX.Y.Z --yes     # remove the GitHub release
git tag -d vX.Y.Z                  # delete local tag
git push origin :refs/tags/vX.Y.Z  # delete remote tag

Then restart from Step 4 (rebuild) or Step 5 (retag) as needed — re-verify the artifact with hdiutil verify again before re-releasing.

Local tests pass but no CI is configured for this repo. Note this explicitly in your report instead of silently treating it as "green" — a missing CI check is not the same as a passing one.

Resources

What ships with it

Read from the repository

Just SKILL.md. No reference files, no scripts.

Gives 3 of the 12 instructions most ship operate skills give in ~2.7k tokens

Counted across 779 of the 1,178 authors here whose files we hold, read 2026-08-07

  • Document a rollback plan before deploymentin 41 of 779, across 22 files
  • Update the changelogin 21 of 779, across 19 files
  • Run the test suitehere, and in 20 of 779
  • Create an annotated git taghere, and in 20 of 779
  • Clean up feature flags after full rolloutin 18 of 779, across 10 files
  • Verify deployment health after launchin 18 of 779, across 10 files
  • Test both feature flag statesin 17 of 779, across 9 files
  • Verify the working tree is cleanhere, and in 17 of 779
  • Make database migrations backward-compatiblein 16 of 779, across 8 files
  • Set up error monitoring before launchin 15 of 779, across 7 files
  • Monitor metrics at each rollout stagein 14 of 779, across 5 files
  • Create a GitHub releasein 14 of 779

Said here and by no other author read

  • determine the release version using semver
  • update the changelog using Keep a Changelog conventions
  • verify the disk image before tagging
  • mark pre-1.0 or unsigned builds as prerelease

Grouped from the skills themselves: near-identical wordings counted once, and counted by distinct author, so one author publishing three of these counts once. Length counted with cl100k_base; the agent that loads this file may tokenize it differently.

Keep looking

Skills are one crate of 328,083. Ordering is by how many stacks a row turns up in, so the top of any crate is what has actually been picked rather than what has the most stars.