All skills
michtio avatar

/craft-plugin-release

@31832ec

Releasing Craft CMS plugins — tagging, Packagist propagation, GitHub releases, branch promotion, shared-library ordering, history rewrites. ALWAYS load when cutting, preparing, verifying, or debugging a plugin release: bumping a version, dating a changelog, creating or moving a git tag, or checking what Packagist serves. Covers the composer.json version key (bump-or-omit trade-off, same-commit rule, verifying the tag's own blob), Packagist verification via repo.packagist.org/p2, the 'Skipped tag' silent failure, the tag recreation risk model (unserved safe, served never), GitHub release objects drifting from tags, gh api PATCH wiping tag_name, blank bodies from empty --notes-file, the create-release.yml Store dispatch (422 already_exists, allowUpdates), shared-library releases dependency-first (additive minors breaking released consumers, module: track invalid), two-way origin comparison, filter-repo purges (already_ran re-runs, --refs/--partial, tree-hash verify, blob-level sweeps), and path repositories (canonical, no exclude, branch-alias, duplicate names). Triggers on: cut/prepare a release, tag a version, Packagist not serving the new version, 'Skipped tag', repo.packagist.org, gh release create/edit, untagged- release, prerelease latest 404, target_commitish, draft release, promote develop to main, release the library first, Invalid migration track, purge a secret from history, filter-repo, path repository, branch-alias. NOT for writing changelog entries, CI workflow YAML (craftcms quality.md), or plugin store listings.

Use this Skill: https://skilld.dev/gh/michtio/craftcms-claude-skills/craft-plugin-release

This session only. Nothing lands on disk.

referenceshistory-rewrites.md

≈954 tokens on demand. Your agent reads this file only when SKILL.md points to it.

History Rewrites with git filter-repo

Purging content (a leaked secret, a file that should never have shipped) from a plugin repo's published history. Everything here was learned on real purges; two of them had to be re-done because the first pass missed content, which is the worst outcome — a purge you believe is complete and isn't.

The tag risk model from SKILL.md applies with full force: a history rewrite moves every tag whose history contains the rewritten commits. If Packagist has served those tags, rewriting them breaks those versions permanently (cached metadata and dists reference the old objects). Decide up front whether the thing being purged is worth that cost — for a live credential it is, and the credential must be rotated regardless, because a purge does not un-leak anything already fetched.

Sweep at blob level across all history — never from the current tree

A path-scoped purge (--path <file> --invert-paths) removes what lives at that path now and wherever that path existed historically — but it misses the same content that ever lived at a different path which no longer exists at the tip. This has caused two incomplete purges. Find the content itself, not the path you remember it at:

# Every blob in all history containing the needle, with the paths it lived at
git rev-list --all | while read c; do
  git grep -l 'NEEDLE' $c -- 2>/dev/null | sed "s/^/$c:/"
done | sort -u -t: -k3

(or git log --all -S'NEEDLE' --name-only for a faster first pass). Build the purge list from that output, then run filter-repo with every discovered path — or with --replace-text when the needle is a string rather than a whole file.

Re-runs: already_ran and the interactive prompt

A repo that has been filtered before carries .git/filter-repo/already_ran. On the next run the tool prompts interactively ("Previous run detected — proceed?"):

  • Under a non-tty (CI, an agent, a pipe) that prompt is an EOFError traceback, not a readable message.
  • Piping Y past it can then crash with an AssertionError in _compute_metadata. That step runs after the rewrite — so the rewrite has already succeeded by the time the tool crashes. Check the refs before concluding a crash meant no-op; re-running a "failed" rewrite that actually landed compounds the confusion.

Scope the rewrite

By default filter-repo rewrites all refs and removes the origin remote as a safety measure. For a targeted purge, scope it:

git filter-repo --partial --refs refs/heads/develop refs/heads/main \
    --invert-paths --path path/to/leaked-file
  • --refs limits which refs are rewritten.
  • --partial skips the destructive-cleanup conveniences — it keeps the origin remote and leaves other refs alone.

Remember tags are refs too: a scoped rewrite that omits refs/tags/* leaves the purged content reachable through every tag. For a secret purge that's a hole, not a scoping win — include the tags and accept the served-tag consequences, or the purge is cosmetic.

Verify: compare tip tree hashes

The assertion a purge needs is "shipped content is unchanged, history differs." The tree hash proves it:

git rev-parse HEAD^{tree}   # before the rewrite (record it)
git rev-parse HEAD^{tree}   # after — identical hash = byte-for-byte identical tip content

Identical tree hashes with different commit hashes is exactly right. A changed tree hash means the rewrite altered current content — stop and diff before pushing anything.

Then verify the needle is actually gone from all history (git log --all -S'NEEDLE' returns nothing), and only then force-push — followed by the Packagist/GitHub verification pass from SKILL.md, since every downstream system now disagrees with the repo.

Source: SKILL.md on GitHub

1 warning1mo3 checks · Risk SAFE
  • Gen Agent Trust Hub1mo

    This skill provides technical guidelines and checklists for managing Craft CMS plugin releases. It uses standard development tools like Git, the GitHub CLI, and Composer to verify package metadata and repository state. The inclusion of history-rewriting tools is appropriately scoped for remediating leaked credentials in repository history.

  • Socket1mo

    No alerts

  • Snyk1mo

    Risk: MEDIUM · 1 issue

Signed by skilld at 31832ec. This ties the file your Agent reads to that commit on GitHub. It does not review the instructions.

Last checked against GitHub 2 weeks ago.

Activeupdated 2 months ago

README badge

README badge for michtio/craftcms-claude-skills/craft-plugin-release