Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
153 changes: 44 additions & 109 deletions .github/RELEASE_GUIDE.md
Original file line number Diff line number Diff line change
@@ -1,157 +1,92 @@
# Release Guide

This guide explains how to ensure PR details appear in release notes when using semantic-release with a protected main branch.
This guide explains how to ensure PR details appear in release notes when using semantic-release.

## Problem
## How It Works

When merging PRs, only the PR title appears in releases:
- ❌ Release shows: "add Argo Workflows client library"
- ✅ Want: Full PR description with features, testing details, examples
1. PRs are squash-merged to `main` with conventional commit titles
2. `semantic-release` analyzes commit messages and determines version bump
3. GitHub release is created with categorized notes
4. Go module proxy is warmed for immediate availability

## Root Cause
## Getting Good Release Notes

`semantic-release` generates release notes from **commit messages**, not PR data. When you squash-merge, by default only the PR title becomes the commit message.

## Solution: Configure Squash Merge to Include PR Body

### Option 1: Repository Settings (Recommended)
### Configure Squash Merge (Repository Setting)

1. Go to: `https://github.com/jasoet/pkg/settings`
2. Scroll to **"Pull Requests"** section
3. Under **"Allow squash merging"**, click **"Configure"**
4. Select: **"Default to pull request title and description"**
5. Save changes

This automatically includes PR body in squash commits.

### Option 2: Manual Edit When Merging

When clicking "Squash and merge":
1. GitHub shows the commit message editor
2. Copy your PR body content
3. Paste it below the title in the commit message
4. Complete the merge

**Example commit message:**
```
feat(argo): add Argo Workflows client library (#8)

## Summary
This automatically includes PR body in squash commits, which becomes the release note content.

Adds a production-ready Argo Workflows client library to the pkg repository.
### What Triggers a Release

## Features
| Commit Type | Release | Hidden from Notes |
|---|---|---|
| `feat` | Minor | No |
| `fix` | Patch | No |
| `perf` | Patch | No |
| `refactor` | Patch | No |
| `docs`, `test`, `ci`, `chore`, `style`, `build` | None | Yes |
| `BREAKING CHANGE` footer or `!` suffix | Major | No |

- **Multiple Connection Modes**: Kubernetes API, in-cluster, and Argo Server HTTP
- **Flexible Configuration**: Config structs and functional options pattern
- **OpenTelemetry Integration**: Built-in tracing and observability support
- **Production-Ready**: Proper error handling without fatal errors
### PR Title Format

## Testing
Use [Conventional Commits](https://www.conventionalcommits.org/):

All unit tests pass:
\`\`\`bash
$ go test ./argo
PASS
ok github.com/jasoet/pkg/v2/argo 1.174s
\`\`\`
```

### Option 3: Use gh CLI with --body

```bash
# Merge PR with body included
gh pr merge 123 --squash --body
feat(argo): add Argo Workflows client library
fix(compress): handle empty input gracefully
perf(db): reduce query allocations
refactor(otel): simplify provider setup
feat!: remove deprecated Config struct
```

This prompts you to edit the commit message including the PR body.

## How semantic-release Uses This

1. **Commit analyzer** reads the commit messages (now with PR body)
2. **Release notes generator** creates sections based on commit type
3. **GitHub plugin** publishes the detailed release notes
### PR Body Best Practices

## Verification

After merging with PR body included:

1. Check commit log: `git log --format=fuller`
2. Verify commit body contains PR details
3. Wait for release workflow to complete
4. Check release notes at `https://github.com/jasoet/pkg/releases`

## Best Practices

### For PR Authors
- Write detailed PR descriptions with:
- Summary section
- Feature lists
- Testing details
- Migration examples
- Breaking changes

### For Reviewers/Mergers
- Always include PR body when squash-merging
- Use conventional commit format in PR title
- Review the commit message before confirming merge

## Example PR Template
Write detailed PR descriptions — they become the commit body on squash merge:

```markdown
## Summary
Brief description of changes and motivation

## Changes
- Added feature X
- Updated component Y
- Fixed issue Z
- Added feature X
- Updated component Y
- Fixed issue Z

## Testing
How changes were tested

## Breaking Changes
List any breaking changes (or "None")

## Migration Guide
How users should update their code (if needed)
```

## Why Not Use @semantic-release/changelog?
## Configuration

The `@semantic-release/changelog` plugin writes CHANGELOG.md and commits it back to the repo. This **fails with protected branches** because:
- Protected branches require PRs for all commits
- semantic-release runs after merge, can't create another PR
- Workflow fails: `refusing to allow a bot to create or update workflow`

Instead, GitHub releases serve as your changelog - they're automatically created with full details when commits include PR bodies.
- **`.releaserc.json`** - semantic-release config (commit analyzer, release notes, GitHub plugin)
- **`.github/workflows/release.yml`** - Release pipeline (test + semantic-release + Go proxy warm-up)
- **`.github/workflows/ci.yml`** - PR pipeline (test + lint)

## Troubleshooting

### Release notes still missing details
### Release notes missing details

**Check:** Did the squash commit include PR body?
**Check:** Did the squash commit include the PR body?
```bash
git show HEAD --format=fuller
```
**Fix:** Verify repository squash merge settings (see above).

**Solution:** Verify repo settings or manually edit commit messages when merging.

### semantic-release fails with "protected branch"

**Check:** Do you have `@semantic-release/changelog` or `@semantic-release/git` in `.releaserc.json`?
### Unwanted releases from non-code changes

**Solution:** Remove these plugins - they try to commit to the repo, which fails with protected branches.
Only `feat`, `fix`, `perf`, and `refactor` commits trigger releases. Use `chore`, `ci`, `docs`, `test`, or `style` types for non-library changes.

## Current Configuration
### Go proxy not updated

Your `.releaserc.json` is correctly configured:
- ✅ Analyzes commits with conventional commits
- ✅ Generates detailed release notes
- ✅ Publishes to GitHub releases
- ✅ No plugins that commit back to repo
- ✅ Patch releases for: `fix`, `docs(README)`, `refactor`, `style`, `chore`, `test`
- ✅ Minor releases for: `feat`
- ✅ Major releases for: breaking changes

The only requirement is **including PR bodies in squash commits**.
The release workflow warms the proxy automatically. If it still shows stale data:
```bash
GOPROXY=https://proxy.golang.org go list -m github.com/jasoet/pkg/v2@v2.x.x
```
54 changes: 54 additions & 0 deletions .github/workflows/ci.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,54 @@
name: CI

on:
pull_request:
branches:
- main

jobs:
test:
name: Test
runs-on: ubuntu-latest
steps:
- name: Checkout
uses: actions/checkout@v4

- name: Set up Go
uses: actions/setup-go@v5
with:
go-version: '1.26'
check-latest: true

- name: Install Task
uses: arduino/setup-task@v2
with:
version: 3.x
repo-token: ${{ secrets.GITHUB_TOKEN }}

- name: Run tests
run: task ci:test

lint:
name: Lint
runs-on: ubuntu-latest
steps:
- name: Checkout
uses: actions/checkout@v4

- name: Set up Go
uses: actions/setup-go@v5
with:
go-version: '1.26'
check-latest: true

- name: Install Task
uses: arduino/setup-task@v2
with:
version: 3.x
repo-token: ${{ secrets.GITHUB_TOKEN }}

- name: Install golangci-lint
run: go install github.com/golangci/golangci-lint/cmd/golangci-lint@latest

- name: Run lint
run: task ci:lint
44 changes: 34 additions & 10 deletions .github/workflows/release.yml
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,6 @@ on:
push:
branches:
- main
- master
workflow_dispatch:

jobs:
Expand All @@ -20,32 +19,57 @@ jobs:
- name: Set up Go
uses: actions/setup-go@v5
with:
go-version: '1.24.7'
go-version: '1.26'
check-latest: true

- name: Install Task
uses: arduino/setup-task@v2
with:
version: 3.x
repo-token: ${{ secrets.GITHUB_TOKEN }}

- name: Run tests
run: go test -v ./...
run: task ci:test

release:
name: Release
needs: test
runs-on: ubuntu-latest
permissions:
contents: write
issues: write
steps:
- name: Checkout
uses: actions/checkout@v4
with:
fetch-depth: 0
persist-credentials: false

- name: Setup Node.js
uses: actions/setup-node@v4
- name: Set up Go
uses: actions/setup-go@v5
with:
node-version: '20'
go-version: '1.26'
check-latest: true

- name: Install dependencies
run: npm install -g semantic-release @semantic-release/github conventional-changelog-conventionalcommits
- name: Install Task
uses: arduino/setup-task@v2
with:
version: 3.x
repo-token: ${{ secrets.GITHUB_TOKEN }}

- name: Setup Bun
uses: oven-sh/setup-bun@v2

- name: Install semantic-release
run: bun install -g semantic-release @semantic-release/github conventional-changelog-conventionalcommits

- name: Release
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
run: npx semantic-release
GITHUB_TOKEN: ${{ secrets.RELEASE_TOKEN }}
run: task release

- name: Warm Go module proxy
if: success()
run: |
sleep 5
task release:proxy-warmup
Loading