Skip to content
LaravelBlog

livewire/livewire: 1. Trigger the workflow (Actions → Draft Release → Run workflow)

LaravelBlogBot
LaravelBlogBot

Contributed by calebporzio

Part of the livewire v4.4.7 release

Livewire's release automation no longer publishes anything the moment it runs. PR #10520 renames the internal release.yml workflow to draft-release.yml (displayed as Draft Release in the Actions tab) and reworks it so that compiled dist/ assets are committed to a dedicated versioned release branch, then attached to a draft GitHub release pinned to the exact build commit. The vX.Y.Z tag — and the public release — only come into existence when a maintainer reviews the draft and publishes it. If you're upgrading from v3.8.10, there is no application-facing change; this is release plumbing. But if you fork Livewire or run tooling against its releases, the workflow's name, file path, and finishing step have all changed.

What changed

  • The workflow file moved from .github/workflows/release.yml to .github/workflows/draft-release.yml, the display name changed from "Release" to "Draft Release", and the job was renamed from release to draft-release.
  • A new Validate version step rejects anything that isn't a strict semantic version matching ^[0-9]+\.[0-9]+\.[0-9]+(-[0-9A-Za-z.-]+)?$ — so 3.9.0 and 3.9.0-beta.1 pass, while v3.9.0, 3.9, or a typo like 3.9.0. fail fast before any build minutes are spent.
  • The "tag already exists" check now queries the remote with git ls-remote --exit-code --tags origin instead of a local git rev-parse, which is immune to stale or shallow local refs.
  • Tag creation was replaced by release-branch creation: the workflow creates release/vX.Y.Z, force-adds dist/, commits it as "Build assets for vX.Y.Z", pushes the branch, and records the build commit SHA in RELEASE_TARGET.
  • gh release create now runs with --draft and --target "${RELEASE_TARGET}", while keeping --generate-notes and the optional --notes-start-tag override from a previous tag.

The new release flow, step by step

A maintainer triggers the workflow with a version input (and optionally a previous-tag override to shape the generated notes):

# 1. Trigger the workflow (Actions → Draft Release → Run workflow)
gh workflow run draft-release.yml \
  -f version=3.9.0 \
  -f previous_tag=v3.8.10   # optional: override where notes start

# 2. Once the run finishes, inspect the draft
gh release view v3.9.0 --json isDraft,targetCommitish,url

# 3. Edit notes or verify assets, then publish —
#    this is the moment the v3.9.0 tag is created
gh release edit v3.9.0 --draft=false

Because the draft is created with --target $RELEASE_TARGET, publishing produces the tag at precisely the commit that contains the built assets, even though no tag existed when the draft was made. If a release/vX.Y.Z branch already exists, the run aborts with an error rather than silently overwriting a prior build.

Why a draft boundary matters

Under the old flow, a single workflow run immediately created a public tag and a published release. A mistyped version, bad notes, or a subtly broken build went live instantly, and walking it back meant deleting a published tag — disruptive for anyone mid-install. The draft release inserts a review boundary: generated notes can be edited, the build commit can be inspected, and the release simply doesn't exist publicly until a human says so. The branch name doubles as an audit trail — release/v3.9.0 tells you exactly which commit carries which compiled bundle.

Validation and script hardening

Beyond the semver gate, the workflow scripts were tightened. Inline uses of ${{ env.VERSION }} inside run: blocks were replaced with environment variables ($VERSION, ${PREVIOUS_TAG}, $RELEASE_TARGET) and an explicit shell: bash, which avoids the GitHub Actions expression-injection footgun where interpolated values are spliced directly into shell scripts. Small changes, but they make an automated pipeline that pushes to the main repository considerably safer to extend later.

Upgrade impact

  • App developers: nothing to do. Tags keep their v prefix, releases still carry the compiled dist/ assets via the tagged build commit, and Composer/npm installs behave identically. Nothing in the Livewire package itself changed.
  • Forks and automation: update anything referencing .github/workflows/release.yml or a workflow named "Release" — the path and name are now draft-release.yml / "Draft Release".
  • Automation that assumed instant publication: if you scripted around "workflow run finished, therefore release is live," that assumption no longer holds. Wait for the release to leave draft state, or publish it yourself as shown above.
  • Re-running a version: re-running for a version whose release branch or tag already exists fails fast; delete the stale branch (and any stale draft) before retrying.

Takeaways

  • The release workflow is now draft-release.yml ("Draft Release"); it creates a draft release instead of an instant published one.
  • Built dist/ assets are committed to a release/vX.Y.Z branch, and the draft is pinned to that exact commit.
  • The vX.Y.Z tag is created only when the draft is manually published — publishing is tagging.
  • Versions are validated as strict semver up front, and tag checks now hit the remote.
  • Upgraders on v3.8.10 need no action; forks and release tooling should repoint to the new workflow name and account for the draft step.

Categories: 12 (Technical report), 1 (Release)

Sources

More from this release

Related Articles