Files
magnus919_agent-skills/opensource-contributions/references/phase-4-release-process.md
T
Magnus Hedemark c5c4d2434a feat: add opensource-contributions skill
Comprehensive open source contribution guidance with progressive disclosure.
Restructured from a single ~23K-token monolithic SKILL.md into a concise
~1.2K-token orchestrator with 10 focused reference files.

Changes:
- SKILL.md: 1,720 lines → 100 lines (AgentSkills.io compliant frontmatter)
- 10 new reference files covering phases 0a-4, pitfalls, default posture
- Portable PR template compliance checker script (stdlib-only)
- All personal context scrubbed for public export
- AGENTS.md + README.md updated with trigger table entry

Signed-off-by: Magnus Hedemark <magnus919@pm.me>
2026-05-28 21:43:30 -04:00

4.0 KiB

Phase 4: The Release Process (After Merge)

Once a PR is merged to the main branch, getting it to users requires a release. This phase is often overlooked by contributors but essential for maintainers.

Sequence After Merge

# 1. Pull the merged main
git checkout main && git pull

# 2. Update version and changelog
#    Edit pyproject.toml (version field) and CHANGELOG.md (new section)
git commit -s -m "chore: bump to vX.Y.Z"

# 3. VERIFY version matches before tagging
#    Run this check — if it fails, fix pyproject.toml before proceeding
PACKAGE_VERSION="$(grep -Po '^version = \"\K[^\"]+' pyproject.toml)"
echo "Package version: $PACKAGE_VERSION  Tag: v$PACKAGE_VERSION"

# 4. Tag and push (triggers release workflow on many projects)
git tag v$PACKAGE_VERSION && git push origin main --tags

# 4. Create a GitHub Release with notes
gh release create vX.Y.Z --title "vX.Y.Z — Title" --notes "..."

Version numbering conventions:

  • v1.0.0 — MAJOR: breaking changes
  • v0.4.0 — MINOR: new features (pre-1.0: significant additions)
  • v0.4.1 — PATCH: bug fixes (pre-1.0: small fixes)

Release workflow anatomy

Many projects use a separate release workflow (.github/workflows/release.yml) that:

  • Triggers on v* tag pushes (not on branch pushes)
  • May gate on tests passing before publishing
  • Publishes to a package registry (PyPI, npm, etc.) via trusted publishing OIDC
  • Creates a deployment record visible on the repository's Deployments page

Key gotcha: Merging to main does NOT trigger the release workflow. You must push the tag separately. If you forget, the release won't happen — no error, no notification, just silence. The PyPI publish won't fire until the tag exists.

GitHub Releases vs Tags

A tag is just a pointer to a commit. A GitHub Release is a tag + release notes

  • optional assets. They are separate concepts:
# Tag only (no release page, no announcement)
git tag v1.0.0 && git push origin v1.0.0

# Tag + GitHub Release
gh release create v1.0.0 --title "v1.0.0 — Title" --notes "..."

Always create a GitHub Release after tagging. The release notes are what users see on the repository's Releases page, and what gets announced via GitHub's notification system. Without a Release, the tag exists but is invisible to most users.

Handling release metadata

--body-file for gh commands: When your release notes or PR body contains special characters (backticks, &, quotes, braces), use a file instead of an inline string:

# WRONG — shell interprets special chars
gh release create v1.0.0 --notes '{"query": "test", "exclude_tags": ["private"]}'

# RIGHT — use a file
cat > /tmp/release.md << 'EOF'

Adds `exclude_tags` filtering.
EOF
gh release create v1.0.0 --title "v1.0.0" --notes-file /tmp/release.md

This avoids shell interpretation of backticks, $ signs, curly braces, and ampersands in structured text like JSON examples or code blocks.

What to do when a commit accidentally lands on main

If you accidentally push a feature commit directly to main (bypassing the PR process), the correct fix is:

# 1. Create a branch from the accidental commit
git branch feat/description HEAD

# 2. Revert the commit on main
git revert --no-edit HEAD
git push origin main

# 3. Push the branch and open a proper PR
git push -u origin feat/description
gh pr create --base main --head feat/description

Do NOT force-push to main to "undo" the commit — rewriting published history causes problems for anyone who has already pulled. A revert is clean, auditable, and doesn't require force push.

If the branch already exists (from git checkout -b that was never used), delete it first:

git branch -D feat/description
git push origin --delete feat/description
# Then proceed with the steps above

Cherry-pick note: After reverting main, create the feature branch from the current main (git checkout -b feat/description main) and cherry-pick the original commit (git cherry-pick <sha>). This ensures the branch is based on the current tip of main, not on a now-reverted ancestor.