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.

referencespath-repositories.md

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

Composer Path Repositories for Multi-Plugin Development

Local development across several plugins usually means a host project whose composer.json points path repositories at plugin checkouts. The semantics below are the ones that produce silent, expensive surprises. (For what belongs in the plugin's own committed manifest — never ../* path repos — see the craft-php-guidelines skill's references/tooling.md, Composer Hygiene.)

A path repository is canonical

If a path repository supplies a package name, that package's Packagist versions are dropped from the resolution pool entirely. Composer's own documentation states it verbatim: "That repository is canonical so the lower priority repo's packages are not installable."

Consequences:

  • A constraint the local checkout can't satisfy is a hard resolution failure — never a quiet fallback to the published version. If the host requires ^1.8 and the checkout says 1.7.x, the resolve fails even though Packagist has 1.8.0.
  • "It resolved fine" therefore means the local copy satisfied everything, which is a different claim from "the published package satisfies everything."

No exclude option

A wildcard entry supplies every directory under it:

{ "type": "path", "url": "/path/to/plugins/*" }

There is no way to carve one directory out — path repositories have no exclude option. The only escapes are enumerating entries individually or moving the directory out of the wildcard's reach. Plan for this before adopting a wildcard: the first time one checkout needs to be excluded (an experiment, a fork, a broken clone), the wildcard has to be unwound.

extra.branch-alias makes a version-less checkout usable

A checkout whose composer.json omits version publishes as dev-<branch>, which satisfies no numeric constraint (version_compare("dev-develop", "1.8.0", ">=") is false, and ^1.0 doesn't match dev-develop). A branch alias in the plugin's manifest fixes that:

{
    "extra": {
        "branch-alias": {
            "dev-develop": "1.x-dev"
        }
    }
}

Two rules that matter in practice:

  • Alias the major line (1.x-dev), not the minor (1.7.x-dev). A minor-pinned alias recreates the lockstep-bump treadmill the alias exists to avoid — every minor release means editing the alias in every consumer's resolution path.
  • Alias every branch that gets checked out locally. An uncovered branch fails resolution hard, and release work does check out the release branch. If develop and main (or master, or develop-v5) can each be the working checkout, each needs an alias entry.

Two directories can publish the same package name

Composer does not error when two path-repository directories declare the same name — it silently picks whichever satisfies the constraints. Observed failure: a craft-thing/ and a craft-thing-584/ (a scratch clone) both declaring acme/craft-thing; composer update --dry-run was green because the scratch clone quietly won, masking a genuinely unsatisfiable constraint in the real checkout.

A clean resolve is not proof of coverage. When a wildcard path repo is in play, verify which directory won:

composer show acme/craft-thing | grep -E 'source|path'

and keep scratch clones outside the wildcard's directory.

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