Skip to content

Build and version a release before tagging it - #9

Merged
roborourke merged 2 commits into
mainfrom
release-built-tags
Sep 21, 2026
Merged

roborourke merged 2 commits into
mainfrom
release-built-tags

Conversation

@roborourke

Copy link
Copy Markdown
Contributor

Release tags now carry the built plugin, so both the source archive and a
Composer install from a tag actually render an icon.

Problem

build/ is gitignored. A release tag had no built assets in it, so
GitHub's source archive and a Composer install from that tag gave a plugin
that renders nothing. Only the attached zip worked. The old release
workflow ran on a tag that already existed, so it had no way to add
anything into that tag.

Change

Ports the pattern from humanmade/hm-query-loop.

  • .github/workflows/release.yml is now dispatched by hand with a version
    input (X.Y.Z, no leading v). It checks the version is valid and the
    tag doesn't exist yet, builds, stamps the version over __VERSION__ in
    button-block-icon.php, commits the built build/, tags that commit,
    and pushes only the tag. main never changes.
  • button-block-icon.php on main now says __VERSION__ in the plugin
    header and the VERSION constant. The real version only exists inside a
    tag, so the header and the tag can't disagree, and there's no bump
    commit to remember. The old check that compared them is gone.
  • New .gitattributes controls what the release zip contains, through
    export-ignore. build/ and src/ both ship, so a tagged tree can
    rebuild itself. Only .github, .gitignore, .gitattributes,
    CLAUDE.md, composer.lock and phpcs.xml.dist are left out. The zip
    is a git archive of the tag, attached to a GitHub release with
    generated notes.
  • New .github/workflows/build-and-release.yml keeps a rolling release
    branch at main with a built build/, on every push to main, using
    humanmade/hm-github-actions' build-to-release-branch. This is for
    sites that install from a branch, not for cutting a release.
  • README and CLAUDE.md updated to match.

From now on, release by going to the Actions tab, choosing the Release
workflow, and entering a version like 1.2.0.
Pushing a tag by hand no
longer builds or versions anything.

Verified locally

PHP lint and PHPCS pass. A full npm ci && npm run build, stamp, commit,
tag and git archive dry run in a scratch clone produced a zip with the
stamped plugin file, build/, src/, inc/, README, SECURITY, LICENSE,
composer.json and package files.

🤖 Generated with Claude Code

Tags carried no built assets. build/ is gitignored, so both the GitHub
source archive and a Composer install from a tag gave a plugin that loads
and renders nothing, and only the zip attached to the release worked. The
old workflow could not fix that from where it ran: it fired on a tag that
already existed, so anything it produced landed beside the tag rather than
in it.

Invert the order, as humanmade/hm-query-loop does. The Release workflow is
now dispatched by hand with a version. It builds, stamps that version into
the plugin, commits the built assets, and creates the tag on that commit,
pushing the tag alone so main is untouched. A tag is therefore installable
as it stands, through Composer as well as the zip, and is written once and
never moved, which is what Packagist needs.

The version follows from the same inversion. main carries the literal
__VERSION__ in the header and the VERSION constant, and the real number
exists only inside a tag, so the two cannot disagree and there is no bump
commit to forget. The old tag-versus-header check has nothing left to
check and goes.

The zip is now git archive of the tag, so .gitattributes decides what
ships instead of a cp list in the workflow. src/ stays in it: the tagged
tree can then be rebuilt from itself. CI config, the PHPCS config and
composer.lock are the only things dropped.

build-and-release.yml is the other half of the pattern, keeping a release
branch at main plus a built build/ for sites that install from a branch.
It is not part of cutting a release and carries the placeholder, so it is
not a versioned artifact.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
@roborourke

Copy link
Copy Markdown
Contributor Author

I did this alternative https://github.com/pixelfear/composer-dist-plugin but, this set of actions take care of some other nice things like not needing to manually change the version string.

@roborourke
roborourke requested a review from tomjn September 21, 2026 15:03
Comment thread button-block-icon.php Outdated
@roborourke
roborourke merged commit 627d2e8 into main Sep 21, 2026
1 check passed
@roborourke
roborourke deleted the release-built-tags branch September 21, 2026 15:41
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants