Skip to content

Commit 952058f

Browse files
committed
Add example workflows and documentation for ghstack merge
Adds .github/workflows/examples/ with ready-to-use workflow templates: - ghstack-merge-basic.yml: Minimal setup for ghstack merge - ghstack-merge-with-rules.yml: With merge rules validation - ghstack-merge-dry-run.yml: Validate without merging (ghstack check) - ghstack-merge-custom.yml: All configuration options demonstrated - README.md: Complete documentation including: - Quick start guide - All workflow inputs and secrets - Merge rules configuration reference - Example error comment format ghstack-source-id: 8d02247 ghstack-comment-id: 3807839473 Pull-Request: #320
1 parent 6a5a6b4 commit 952058f

File tree

5 files changed

+195
-0
lines changed

5 files changed

+195
-0
lines changed
Lines changed: 98 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,98 @@
1+
# ghstack Merge Workflow Examples
2+
3+
These examples show how to use the reusable `ghstack-merge.yml` workflow in your repository.
4+
5+
## Quick Start
6+
7+
1. Copy one of the example workflows to your repository's `.github/workflows/` directory
8+
2. Optionally create `.github/merge_rules.yaml` to define merge rules
9+
3. Comment `@ghstack merge` on any ghstack PR to trigger landing
10+
11+
## Examples
12+
13+
| File | Description |
14+
|------|-------------|
15+
| `ghstack-merge-basic.yml` | Minimal setup - just lands PRs on `@ghstack merge` |
16+
| `ghstack-merge-with-rules.yml` | Validates against merge rules before landing |
17+
| `ghstack-merge-dry-run.yml` | Validates without merging (triggered by `@ghstack check`) |
18+
| `ghstack-merge-custom.yml` | Shows all available configuration options |
19+
20+
## Workflow Inputs
21+
22+
| Input | Type | Required | Default | Description |
23+
|-------|------|----------|---------|-------------|
24+
| `pull_request_number` | number | Yes | - | PR number to land |
25+
| `python_version` | string | No | `'3.11'` | Python version |
26+
| `ghstack_version` | string | No | `'ghstack'` | ghstack package spec |
27+
| `validate_rules` | boolean | No | `true` | Validate against merge rules |
28+
| `dry_run` | boolean | No | `false` | Validate only, don't merge |
29+
| `comment_on_failure` | boolean | No | `true` | Post errors as PR comment |
30+
| `runs_on` | string | No | `'ubuntu-latest'` | GitHub runner to use |
31+
32+
## Secrets
33+
34+
| Secret | Required | Description |
35+
|--------|----------|-------------|
36+
| `github_token` | Yes | Token with `contents:write` and `pull-requests:write` |
37+
38+
## Merge Rules Configuration
39+
40+
Create `.github/merge_rules.yaml` in your repository:
41+
42+
```yaml
43+
# Rules are matched in order - first matching rule wins
44+
- name: core-library
45+
patterns:
46+
- "src/**"
47+
approved_by:
48+
- maintainer-username
49+
- org/team-slug # Team reference
50+
mandatory_checks_name:
51+
- "Test"
52+
- "Lint"
53+
54+
- name: documentation
55+
patterns:
56+
- "docs/**"
57+
- "*.md"
58+
approved_by:
59+
- any # Any approval is sufficient
60+
mandatory_checks_name:
61+
- "Lint"
62+
63+
- name: default
64+
patterns:
65+
- "**/*"
66+
approved_by:
67+
- maintainer-username
68+
mandatory_checks_name:
69+
- "Test"
70+
```
71+
72+
### Rule Fields
73+
74+
| Field | Description |
75+
|-------|-------------|
76+
| `name` | Rule identifier (shown in error messages) |
77+
| `patterns` | File glob patterns (fnmatch syntax) |
78+
| `approved_by` | Required approvers (usernames, `org/team`, or `any`) |
79+
| `mandatory_checks_name` | CI checks that must pass |
80+
| `ignore_flaky_failures` | If `true`, ignore check failures (optional) |
81+
82+
## Error Comments
83+
84+
When validation fails with `comment_on_failure: true`, the workflow posts a comment like:
85+
86+
```markdown
87+
## Merge validation failed for PR #123
88+
89+
**Rule:** core-library
90+
91+
### Errors:
92+
- Missing required approval from: maintainer-username, org/team-slug
93+
- Check "Test" has not passed (status: failure)
94+
95+
### Matched Files:
96+
- `src/main.py`
97+
- `src/utils.py`
98+
```
Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,20 @@
1+
# Basic example: Trigger ghstack land on "@ghstack merge" comment
2+
#
3+
# Copy this file to your repository's .github/workflows/ directory
4+
5+
name: ghstack merge
6+
7+
on:
8+
issue_comment:
9+
types: [created]
10+
11+
jobs:
12+
merge:
13+
if: |
14+
github.event.issue.pull_request &&
15+
contains(github.event.comment.body, '@ghstack merge')
16+
uses: ezyang/ghstack/.github/workflows/ghstack-merge.yml@master
17+
with:
18+
pull_request_number: ${{ github.event.issue.number }}
19+
secrets:
20+
github_token: ${{ secrets.GITHUB_TOKEN }}
Lines changed: 30 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,30 @@
1+
# Example with custom configuration
2+
#
3+
# This workflow demonstrates all available options:
4+
# - Custom Python version
5+
# - Custom ghstack version (from git)
6+
# - Custom runner
7+
# - All merge options enabled
8+
9+
name: ghstack merge custom
10+
11+
on:
12+
issue_comment:
13+
types: [created]
14+
15+
jobs:
16+
merge:
17+
if: |
18+
github.event.issue.pull_request &&
19+
contains(github.event.comment.body, '@ghstack merge')
20+
uses: ezyang/ghstack/.github/workflows/ghstack-merge.yml@master
21+
with:
22+
pull_request_number: ${{ github.event.issue.number }}
23+
python_version: '3.12'
24+
ghstack_version: 'git+https://github.com/ezyang/ghstack.git@master'
25+
validate_rules: true
26+
dry_run: false
27+
comment_on_failure: true
28+
runs_on: 'ubuntu-latest'
29+
secrets:
30+
github_token: ${{ secrets.GITHUB_TOKEN }}
Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,24 @@
1+
# Example with dry-run mode
2+
#
3+
# This workflow validates the PR stack without actually merging.
4+
# Useful for testing merge rules configuration or CI integration.
5+
6+
name: ghstack merge dry-run
7+
8+
on:
9+
issue_comment:
10+
types: [created]
11+
12+
jobs:
13+
validate:
14+
if: |
15+
github.event.issue.pull_request &&
16+
contains(github.event.comment.body, '@ghstack check')
17+
uses: ezyang/ghstack/.github/workflows/ghstack-merge.yml@master
18+
with:
19+
pull_request_number: ${{ github.event.issue.number }}
20+
validate_rules: true
21+
dry_run: true
22+
comment_on_failure: true
23+
secrets:
24+
github_token: ${{ secrets.GITHUB_TOKEN }}
Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,23 @@
1+
# Example with merge rules validation
2+
#
3+
# This workflow validates PRs against .github/merge_rules.yaml before landing.
4+
# If validation fails, it posts an error comment on the PR.
5+
6+
name: ghstack merge with rules
7+
8+
on:
9+
issue_comment:
10+
types: [created]
11+
12+
jobs:
13+
merge:
14+
if: |
15+
github.event.issue.pull_request &&
16+
contains(github.event.comment.body, '@ghstack merge')
17+
uses: ezyang/ghstack/.github/workflows/ghstack-merge.yml@master
18+
with:
19+
pull_request_number: ${{ github.event.issue.number }}
20+
validate_rules: true
21+
comment_on_failure: true
22+
secrets:
23+
github_token: ${{ secrets.GITHUB_TOKEN }}

0 commit comments

Comments
 (0)