Skip to content

Commit a2ef638

Browse files
authored
feat: use GitHub App for semantic-release to bypass branch protection (#36)
- Add GitHub App token generation using actions/create-github-app-token@v2 - Pass app token to checkout and semantic-release for authentication - Add comprehensive setup guide in .github/GITHUB_APP_SETUP.md - This allows semantic-release to bypass repository rulesets securely The GitHub App approach is the most secure and recommended method as of 2025: - Short-lived tokens (1 hour expiration) - Scoped permissions - Auditable in GitHub's audit log - Can trigger downstream workflows Setup required: 1. Create GitHub App with Contents/Issues/PRs permissions 2. Install app on repository 3. Add RELEASE_APP_ID and RELEASE_APP_PRIVATE_KEY secrets 4. Add app to repository ruleset bypass list See .github/GITHUB_APP_SETUP.md for complete step-by-step instructions.
1 parent 0730d84 commit a2ef638

File tree

2 files changed

+151
-2
lines changed

2 files changed

+151
-2
lines changed

.github/GITHUB_APP_SETUP.md

Lines changed: 140 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,140 @@
1+
# GitHub App Setup for Semantic Release
2+
3+
This guide walks through creating a GitHub App to enable semantic-release to bypass branch protection rules securely.
4+
5+
## Why Use a GitHub App?
6+
7+
- ✅ Most secure authentication method (scoped permissions, short-lived tokens)
8+
- ✅ Can bypass repository rulesets when added to bypass list
9+
- ✅ Triggers downstream workflows (unlike GITHUB_TOKEN)
10+
- ✅ Auditable in GitHub's audit log
11+
- ✅ Recommended by GitHub as of 2025
12+
13+
## Step 1: Create the GitHub App
14+
15+
1. **Navigate to GitHub App Settings**
16+
- Go to <https://github.com/settings/apps>
17+
- Click **"New GitHub App"**
18+
19+
2. **Configure Basic Information**
20+
- **GitHub App name**: `peakbagger-release-bot` (or any unique name)
21+
- **Description**: `Automated release bot for peakbagger-cli using semantic-release`
22+
- **Homepage URL**: `https://github.com/dreamiurg/peakbagger-cli`
23+
- **Webhook**: Uncheck **"Active"** (we don't need webhooks)
24+
25+
3. **Set Repository Permissions**
26+
27+
Under "Repository permissions", set these permissions:
28+
29+
| Permission | Access Level | Purpose |
30+
|------------|-------------|---------|
31+
| **Contents** | Read and write | Push commits, create tags |
32+
| **Issues** | Read and write | Comment on issues in releases |
33+
| **Pull requests** | Read and write | Comment on PRs in releases |
34+
| **Metadata** | Read-only | Required (auto-selected) |
35+
36+
4. **Configure Installation**
37+
- Under "Where can this GitHub App be installed?"
38+
- Select: **"Only on this account"**
39+
40+
5. **Create the App**
41+
- Click **"Create GitHub App"**
42+
- You'll be redirected to the app's settings page
43+
44+
## Step 2: Generate Private Key
45+
46+
1. On your app's settings page, scroll to **"Private keys"**
47+
2. Click **"Generate a private key"**
48+
3. A `.pem` file will download automatically
49+
4. **IMPORTANT**: Save this file securely - you'll need it in Step 4
50+
51+
## Step 3: Note the App ID
52+
53+
1. At the top of the app settings page, find **"App ID"**
54+
2. Copy this number (e.g., `123456`)
55+
3. Save it for Step 4
56+
57+
## Step 4: Install the App on Your Repository
58+
59+
1. On your app's settings page, click **"Install App"** in the left sidebar
60+
2. Click **"Install"** next to your username/organization
61+
3. Select: **"Only select repositories"**
62+
4. Choose: `peakbagger-cli`
63+
5. Click **"Install"**
64+
65+
## Step 5: Add Repository Secrets
66+
67+
1. **Go to repository secrets**
68+
- Navigate to <https://github.com/dreamiurg/peakbagger-cli/settings/secrets/actions>
69+
- Click **"New repository secret"**
70+
71+
2. **Add App ID**
72+
- Name: `RELEASE_APP_ID`
73+
- Value: The App ID from Step 3 (e.g., `123456`)
74+
- Click **"Add secret"**
75+
76+
3. **Add Private Key**
77+
- Click **"New repository secret"** again
78+
- Name: `RELEASE_APP_PRIVATE_KEY`
79+
- Value: Open the `.pem` file from Step 2 and paste the **entire contents** including:
80+
81+
```text
82+
-----BEGIN RSA PRIVATE KEY-----
83+
... (your key content) ...
84+
-----END RSA PRIVATE KEY-----
85+
```
86+
87+
- Click **"Add secret"**
88+
89+
## Step 6: Add App to Ruleset Bypass List
90+
91+
1. **Navigate to Repository Rules**
92+
- Go to <https://github.com/dreamiurg/peakbagger-cli/settings/rules>
93+
- Click on the **"main"** ruleset
94+
95+
2. **Add Bypass Actor**
96+
- Scroll to **"Bypass list"**
97+
- Click **"Add bypass"**
98+
- Select **"Apps"**
99+
- Find and select your app: `peakbagger-release-bot`
100+
- Bypass mode: **"Always allow"**
101+
- Click **"Save changes"**
102+
103+
## Step 7: Verify Configuration
104+
105+
After merging the workflow PR, the release workflow will:
106+
107+
1. Generate a short-lived token from your GitHub App
108+
2. Use that token to checkout and push to the repository
109+
3. Bypass the ruleset rules because the app is in the bypass list
110+
4. Create releases, update changelog, and bump versions automatically
111+
112+
## Troubleshooting
113+
114+
### "App not found in bypass list"
115+
116+
- Make sure you installed the app on the repository (Step 4)
117+
- Verify the app appears in Settings → Integrations → GitHub Apps
118+
119+
### "Invalid private key"
120+
121+
- Ensure you copied the entire `.pem` file including header/footer
122+
- Check for no extra spaces or newlines
123+
124+
### "Insufficient permissions"
125+
126+
- Review Step 3 and ensure all required permissions are granted
127+
- You may need to update permissions in the app settings
128+
129+
## Security Notes
130+
131+
- **Private key**: Never commit the `.pem` file to version control
132+
- **Token lifetime**: App tokens expire after 1 hour (much safer than PATs)
133+
- **Scope**: The app only has access to repositories where it's installed
134+
- **Rotation**: Regenerate private keys periodically for security
135+
136+
## References
137+
138+
- [GitHub Apps Documentation](https://docs.github.com/en/apps)
139+
- [Repository Rulesets](https://docs.github.com/en/repositories/configuring-branches-and-merges-in-your-repository/managing-rulesets/about-rulesets)
140+
- [actions/create-github-app-token](https://github.com/actions/create-github-app-token)

.github/workflows/release.yml

Lines changed: 11 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -7,17 +7,26 @@ on:
77

88
permissions:
99
contents: write # Required for semantic-release to create releases and push commits
10+
id-token: write # Required for trusted publishing
1011

1112
jobs:
1213
# Skip test job - CI workflow already runs comprehensive tests on push to main
1314
release:
1415
runs-on: ubuntu-latest
1516
steps:
17+
- name: Generate GitHub App token
18+
id: app-token
19+
uses: actions/create-github-app-token@v2
20+
with:
21+
app-id: ${{ secrets.RELEASE_APP_ID }}
22+
private-key: ${{ secrets.RELEASE_APP_PRIVATE_KEY }}
23+
1624
- name: Checkout
1725
uses: actions/checkout@v4
1826
with:
1927
fetch-depth: 0
20-
ssh-key: ${{ secrets.DEPLOY_KEY }}
28+
token: ${{ steps.app-token.outputs.token }}
29+
persist-credentials: false
2130

2231
- name: Set up Python
2332
uses: actions/setup-python@v6
@@ -37,5 +46,5 @@ jobs:
3746

3847
- name: Release with Python Semantic Release
3948
env:
40-
GH_TOKEN: ${{ secrets.GITHUB_TOKEN }}
49+
GH_TOKEN: ${{ steps.app-token.outputs.token }}
4150
run: uv run semantic-release version

0 commit comments

Comments
 (0)