Skip to content

Release Workflow Guide — middag-io

How releases work with release-please, from commit to production. Architecture decisions: see ADR-003.

Table of Contents


1. How It Works

release-please monitors main branch. When it detects conventional commits, it creates (or updates) a Release PR that bumps the version and updates CHANGELOG.md. Merging the Release PR creates a tag and GitHub Release.

develop ──PR──> main ──push──> release-please

                              Creates Release PR
                              (version bump + CHANGELOG)

                              Merge Release PR

                          ┌─────────┴──────────┐
                          ▼                    ▼
                    GitHub Release        Git tag (X.Y.Z)
                    (auto-created)             │

                                    Post-release workflow
                                    (build ZIP, deploy docs,
                                     notify privatesatis)

2. Conventional Commits

Every commit to main MUST follow Conventional Commits format:

PrefixSemver ImpactExample
feat:minor (0.X.0)feat: add Stripe multi-entity support
fix:patch (0.0.X)fix: ISSNet certificate expiry check
feat!: or BREAKING CHANGE:major (X.0.0)feat!: drop PHP 8.1 support
chore:none (no release)chore: update CI workflow
docs:nonedocs: update API reference
ci:noneci: add deploy step
refactor:nonerefactor: extract email service
test:nonetest: add unit tests for quotes

Only feat: and fix: trigger a version bump. Other prefixes are recorded in CHANGELOG but don't create a release.

Scope (optional)

Use scope for specificity: feat(payments): add Stripe Connect support

3. The Release Flow

Step 1: Merge PR to main

Normal development: feature/xyzdevelop → PR to main.

Step 2: release-please creates Release PR

After merge to main, release-please:

  1. Analyzes commit messages since last release
  2. Calculates next version (patch/minor/major)
  3. Creates or updates a Release PR with:
    • Version bump in plugin/theme file (via x-release-please-version annotations)
    • Updated CHANGELOG.md
    • Updated .release-please-manifest.json

Step 3: Review and merge Release PR

  • Review the version bump and changelog
  • For commercial products: update CHANGELOG-USER.md before merging
  • Merge the Release PR

Step 4: Automatic post-release

Merging triggers:

  1. GitHub Release created with tag
  2. Post-release workflow runs:
    • Build UI assets (if applicable)
    • Run Strauss vendor prefixing (if applicable)
    • Create distribution ZIP
    • Upload ZIP to GitHub Release
    • Trigger privatesatis rebuild
    • Deploy docs to Cloudflare Pages (if applicable)

4. Version Annotations

release-please uses x-release-please-version annotations to find and update version strings.

WordPress Plugin

In {plugin-name}.php:

php
 * Version: 5.0.16 // x-release-please-version
defined('MY_PLUGIN_VERSION') || define('MY_PLUGIN_VERSION', '5.0.16'); // x-release-please-version

WordPress Theme

In style.css:

css
Version: 5.1.0 x-release-please-version

In functions.php:

php
define('MY_THEME_VERSION', '5.1.0'); // x-release-please-version

PHP Library

In composer.json — release-please handles this natively for simple release type via version.txt.

5. CHANGELOG-USER.md (Commercial Products)

Required for: wp-plugin-my-project, and any product with end-user docs.

Format

markdown
# Changelog

## [5.0.17] - 2026-05-16

### Novo
- Suporte multi-entidade Stripe — gerencie pagamentos BR e Global separadamente
- Integração de webhooks HubSpot para sincronização automática de contatos

### Melhorado
- Geração de PDF de faturas 3x mais rápida

### Corrigido
- Entrega de e-mail para endereços Gmail em alguns casos específicos

Rules

  • Written in the product's user language (Portuguese for BR products)
  • No technical jargon ("refactor", "dependency bump", "fix N+1")
  • Grouped by: Novo / Melhorado / Corrigido / Removido
  • Updated BEFORE merging the Release PR
  • Public docs site pulls from this file

6. Post-Release Actions

What happens automatically after merge:

ActionTriggerHandler
GitHub Release + tagrelease-please mergerelease-please action
Build dist ZIPrelease_created outputwp-plugin-post-release.yml
Upload ZIP to Releaseafter buildsoftprops/action-gh-release
Trigger privatesatisafter uploadrepository_dispatch
Deploy docsrelease_created outputdocs-deploy.yml

Manual intervention needed

  • CHANGELOG-USER.md update (before merging Release PR)
  • Production deploy verification (after release)
  • Backport to develop if hotfix (see section 7)

7. Hotfix Flow

For critical fixes that can't wait for the normal develop → main flow:

main ──branch──> hotfix/critical-fix

                   Fix + commit
                   (use feat: or fix: prefix)

                   PR to main

                   Merge → release-please creates Release PR

                   Merge Release PR → tag + release

                   Also merge hotfix into develop
bash
# Create hotfix
git checkout main
git pull origin main
git checkout -b hotfix/critical-fix

# Fix and commit
git commit -m "fix: critical payment processing error"

# PR to main
gh pr create --base main --title "fix: critical payment processing error"

# After merge + release: backport to develop
git checkout develop
git merge main
git push origin develop

8. Common Scenarios

"I merged to main but no Release PR appeared"

  • Check if commits use Conventional Commits format
  • chore:, ci:, docs: don't trigger releases
  • Need at least one feat: or fix: commit

"I want to release but there are only chore commits"

Add an empty commit with a release-triggering prefix:

bash
git commit --allow-empty -m "fix: trigger release for dependency updates"

"I want to skip a release for a specific commit"

Commits without feat:/fix: prefix don't trigger releases. Use chore: for non-release changes.

"I want to force a major version bump"

Use ! suffix or BREAKING CHANGE: footer:

feat!: drop PHP 8.1 support

BREAKING CHANGE: minimum PHP version is now 8.2

"release-please manifest is out of sync"

Update .release-please-manifest.json manually:

json
{
  ".": "5.0.17"
}

Commit and push to main.

"I need to release without going through develop"

Use the hotfix flow (section 7). Never commit directly to main.

MIDDAG Tecnologia