Skip to content
Open
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
5 changes: 0 additions & 5 deletions .github/aw/actions-lock.json
Original file line number Diff line number Diff line change
@@ -1,10 +1,5 @@
{
"entries": {
"github/gh-aw-actions/setup-cli@v0.86.2": {
"repo": "github/gh-aw-actions/setup-cli",
"version": "v0.86.2",
"sha": "6aab9e5b5c91c615506061f09bedd81a23babe3c"
},
"github/gh-aw-actions/setup@v0.86.2": {
"repo": "github/gh-aw-actions/setup",
"version": "v0.86.2",
Expand Down
2 changes: 1 addition & 1 deletion .github/aw/gh-aw-version
Original file line number Diff line number Diff line change
@@ -1 +1 @@

v0.86.2
2 changes: 1 addition & 1 deletion .github/workflows/ci.yml
Original file line number Diff line number Diff line change
Expand Up @@ -29,7 +29,7 @@ jobs:
GH_TOKEN: ${{ secrets.GITHUB_TOKEN }}
run: |
set -euo pipefail
gh aw compile drafter review fix queue-triage ci-triage --approve
gh aw compile drafter review fix release queue-triage ci-triage --approve

- name: Check for lock drift
run: |
Expand Down
40 changes: 40 additions & 0 deletions .github/workflows/publish-release.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,40 @@
name: Publish Release
on:
pull_request:
types: [closed]

# This workflow runs when a release PR is merged and automatically creates
# the corresponding GitHub release with the release notes from the PR body.
jobs:
publish:
if: |
github.event.pull_request.merged == true &&
contains(github.event.pull_request.labels.*.name, 'release') &&
startsWith(github.event.pull_request.head.ref, 'release/')
runs-on: ubuntu-latest
timeout-minutes: 10
permissions:
contents: write
steps:
- name: Extract version from branch name
id: version
run: |
branch="${{ github.event.pull_request.head.ref }}"
version="${branch#release/}"
echo "version=$version" >> "$GITHUB_OUTPUT"
echo "Publishing release: $version"

- name: Create GitHub Release
env:
GH_TOKEN: ${{ github.token }}
run: |
version="${{ steps.version.outputs.version }}"
pr_number="${{ github.event.pull_request.number }}"
pr_body=$(gh pr view "$pr_number" --repo "${{ github.repository }}" --json body --jq .body)

# Create the release
gh release create "$version" \
--repo "${{ github.repository }}" \
--title "Release $version" \
--notes "$pr_body" \
--verify-tag
1,690 changes: 1,690 additions & 0 deletions .github/workflows/release.lock.yml

Large diffs are not rendered by default.

127 changes: 127 additions & 0 deletions .github/workflows/release.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,127 @@
---
description: |
Automated release agent. Runs weekly to create a release PR with
LLM-generated release notes from git history since the last release.
The PR requires human review and approval before merge. When merged,
the publish-release.yml workflow automatically creates the GitHub release.

on:
schedule:
# Weekly on Mondays at 9:00 UTC
- cron: '0 9 * * 1'
Comment on lines +9 to +11
workflow_dispatch:

permissions:

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

(Do we need this stuff btw? doesn't the MCP server allow reads)

contents: read
issues: read
pull-requests: read

model: claude-sonnet-4-5-20250929
engine:
id: claude
tools:
bash: ["*"]
github:
toolsets: [default]

safe-outputs:
github-app:
client-id: ${{ vars.GH_AW_APP_CLIENT_ID }}
private-key: ${{ secrets.GH_AW_APP_PRIVATE_KEY }}
permissions:
workflows: write
Comment on lines +28 to +32
create-pull-request:
max: 1
branch-prefix: release/
Comment on lines +33 to +35
noop:
missing-data:

timeout-minutes: 15
---

# Release Agent

This workflow runs weekly to create a release PR.

## Your task

1. **Determine the next version**: Read the git tags to find the latest release.
If no tags exist, use `v0.1.0` as the starting version. Otherwise, increment
the patch version (e.g., `v1.2.3` → `v1.2.4`).
Comment on lines +49 to +50

2. **Gather release content**: Collect git commits since the last release using
`git log`. Focus on meaningful changes:
- New features
- Bug fixes
- Breaking changes
- Dependency updates
- Documentation improvements

3. **Generate release notes**: Create structured release notes that:
- Start with a brief summary of what's new
- Group changes by category (Features, Bug Fixes, Documentation, etc.)
- Include commit references where helpful
- Highlight any breaking changes or migration notes
- Be concise but informative

4. **Create the release PR**: Use the `create-pull-request` safe-output to
create a PR with:
- **Title**: `Release <version>` (e.g., "Release v1.2.4")
- **Branch**: `release/<version>` (e.g., "release/v1.2.4")
- **Body**: The generated release notes in markdown format
Comment on lines +67 to +71
- **Labels**: `release`

The PR body should be structured like:
```markdown
# Release <version>

## Summary
[Brief overview of changes]

## Changes

### Features
- [Feature descriptions]

### Bug Fixes
- [Bug fix descriptions]

### Documentation
- [Documentation changes]

## Commits
[List of commit references]

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Hmm we probably want a deterministic skill/tool or recommendation for formatting of this


---
Generated-by: AI
Human review required before merge.
```

5. **Handle edge cases**:
- If there are no changes since the last release, use `noop` to report
that no release is needed
- If you cannot determine the version or history, use `missing-data`
- Only create one release PR per run

## Constraints

- Never push directly to the default branch
- This workflow only creates release PRs; the actual GitHub release is
created by the publish-release.yml workflow when the PR is merged
- Always include "Generated-by: AI" in the PR body
- Require human review for all releases

## Release Process

This is a two-phase automated release process:

1. **Phase 1 (This Workflow)**: Creates a release PR with:
- Branch: `release/<version>`
- Label: `release`
- Body: LLM-generated release notes from git history

2. **Phase 2 (publish-release.yml)**: When the release PR is merged:
- Automatically creates the GitHub release
- Uses the version from the branch name (e.g., `release/v1.2.4` → `v1.2.4`)
- Uses the PR body as release notes
- Creates a git tag for the release
1 change: 1 addition & 0 deletions aw.yml
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@ includes:
- .github/workflows/drafter.md
- .github/workflows/review.md
- .github/workflows/fix.md
- .github/workflows/release.md
- .github/workflows/merge.yml
- .github/workflows/install-labels.yml
- .github/workflows/upgrade.yml
2 changes: 1 addition & 1 deletion justfile
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,7 @@ setup:

# Compile all gh-aw workflow .md sources to .lock.yml (run `just setup` first).
compile:
gh aw compile drafter review fix queue-triage ci-triage --approve
gh aw compile drafter review fix release queue-triage ci-triage --approve

# Setup + compile in one step.
all: setup compile