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
23 changes: 20 additions & 3 deletions .github/workflows/release.yml
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,13 @@ on:
push:
branches:
- main # semantic-release works on branch pushes, not tags
workflow_dispatch: # Allow manual trigger
inputs:
dry_run:
description: 'Run in dry-run mode (no actual release)'
required: false
type: boolean
default: false

permissions:
contents: write # Required for creating releases and pushing commits
Expand All @@ -27,7 +34,8 @@ jobs:
uses: actions/checkout@v4
with:
fetch-depth: 0 # Fetch all history for semantic-release
persist-credentials: false # Use custom token for pushing
token: ${{ secrets.GH_PAT || secrets.GITHUB_TOKEN }}
persist-credentials: true # Need credentials for semantic-release to push

- name: Setup Node.js
uses: actions/setup-node@v4
Expand All @@ -53,10 +61,19 @@ jobs:

- name: Run semantic-release
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
GITHUB_TOKEN: ${{ secrets.GH_PAT || secrets.GITHUB_TOKEN }}
VSCE_PAT: ${{ secrets.VSCE_PAT }}
GIT_AUTHOR_NAME: github-actions[bot]
GIT_AUTHOR_EMAIL: github-actions[bot]@users.noreply.github.com
GIT_COMMITTER_NAME: github-actions[bot]
GIT_COMMITTER_EMAIL: github-actions[bot]@users.noreply.github.com
run: |
npx semantic-release
if [ "${{ github.event.inputs.dry_run }}" = "true" ]; then
echo "Running in dry-run mode..."
npx semantic-release --dry-run
else
npx semantic-release
fi

- name: Upload VSIX to release (fallback if semantic-release fails)
if: failure()
Expand Down
175 changes: 175 additions & 0 deletions docs/RELEASE_SETUP.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,175 @@
# Release Setup Guide

This document explains how to configure releases for the Pluto Notebook extension with protected main branch.

## Problem

When the `main` branch is protected, semantic-release cannot push version bump commits directly, causing the release workflow to fail.

## Solution

We use a Personal Access Token (PAT) with bypass permissions to allow semantic-release to push to protected branches.

## Setup Instructions

### 1. Create a Personal Access Token (PAT)

1. Go to GitHub Settings → Developer settings → Personal access tokens → Fine-grained tokens
2. Click "Generate new token"
3. Configure the token:
- **Name**: `semantic-release-bypass` (or similar)
- **Expiration**: Set as needed (recommend 1 year)
- **Repository access**: Select "Only select repositories" → Choose this repository
- **Permissions**:
- **Repository permissions**:
- Contents: Read and write
- Pull requests: Read and write
- Issues: Read and write
- Metadata: Read-only (automatically selected)

4. Click "Generate token" and copy the token value

### 2. Add Token as Repository Secret

1. Go to your repository on GitHub
2. Navigate to Settings → Secrets and variables → Actions
3. Click "New repository secret"
4. Add:
- **Name**: `GH_PAT`
- **Secret**: Paste the token you created

### 3. Configure Branch Protection Rules

1. Go to Settings → Branches → Branch protection rules
2. Edit the rule for `main`
3. Enable "Allow specified actors to bypass required pull requests"
4. Add the GitHub Actions bot or your PAT user to the bypass list

Alternatively, you can allow the GitHub Actions bot to bypass protection:
- In branch protection, check "Do not allow bypassing the above settings" = OFF
- Or specifically allow `github-actions[bot]` to bypass

### 4. Workflow Configuration

The release workflow (`.github/workflows/release.yml`) is configured to:

- Use `GH_PAT` if available, fall back to `GITHUB_TOKEN`
- Allow manual triggering via `workflow_dispatch`
- Support dry-run mode for testing
- Set proper git committer information

## Manual Release Trigger

You can manually trigger a release from the GitHub Actions tab:

1. Go to Actions → Release workflow
2. Click "Run workflow"
3. Choose options:
- **Branch**: main
- **Dry run**: Check to test without creating a release
4. Click "Run workflow"

## Testing the Setup

### Dry Run Test

```bash
# Manually trigger with dry-run from GitHub UI
# OR locally test semantic-release:
npx semantic-release --dry-run
```

### Check Configuration

```bash
# Verify git credentials in workflow
git config user.name
git config user.email
```

## How It Works

1. **Token Priority**: Workflow uses `GH_PAT` secret if available, otherwise `GITHUB_TOKEN`
2. **Credentials**: Checkout action uses the PAT to authenticate git operations
3. **Git Identity**: Workflow sets git author/committer to `github-actions[bot]`
4. **Bypass**: PAT with proper permissions can push to protected branches
5. **Manual Trigger**: `workflow_dispatch` allows on-demand releases

## Semantic Release Flow

When the workflow runs:

1. CI runs (lint, test, build)
2. Checkout with PAT credentials
3. Build VSIX package
4. Run semantic-release:
- Analyzes commits since last release
- Determines version bump (major/minor/patch)
- Updates package.json and CHANGELOG.md
- Creates git tag
- Pushes commit and tag (using PAT)
- Creates GitHub release with VSIX attached

## Alternative: No Version Commits

If you prefer not to push version commits to main, update `.releaserc.json`:

```json
{
"branches": ["main"],
"plugins": [
"@semantic-release/commit-analyzer",
"@semantic-release/release-notes-generator",
["@semantic-release/changelog", { "changelogFile": "CHANGELOG.md" }],
["@semantic-release/npm", { "npmPublish": false }],
["semantic-release-vsce", { "packageVsix": true }],
[
"@semantic-release/github",
{
"assets": [
{ "path": "*.vsix", "label": "VS Code Extension (VSIX)" },
{ "path": "CHANGELOG.md", "label": "Changelog" }
]
}
]
// Remove @semantic-release/git to skip version commits
]
}
```

This creates releases without pushing version bumps back to main.

## Troubleshooting

### "refusing to allow a Personal Access Token to create or update workflow"

Solution: The PAT needs "Workflows" permission. Recreate the token with this permission added.

### "protected branch hook declined"

Solution: Ensure the PAT user or github-actions[bot] is in the bypass list for branch protection.

### "Author identity unknown"

Solution: The workflow sets `GIT_AUTHOR_NAME` and `GIT_AUTHOR_EMAIL` environment variables. Check they're properly configured.

### Dry-run succeeds but real run fails

Check:
1. `GH_PAT` secret is properly set
2. PAT has not expired
3. PAT has correct permissions
4. Branch protection allows bypass

## Security Notes

- **PAT Security**: Store PAT only as a GitHub secret, never commit it
- **Token Scope**: Use fine-grained tokens with minimal required permissions
- **Expiration**: Set reasonable expiration dates and rotate tokens regularly
- **Audit**: Review GitHub audit logs for PAT usage

## References

- [Semantic Release GitHub Action](https://github.com/semantic-release/semantic-release/blob/master/docs/recipes/ci-configurations/github-actions.md)
- [GitHub PAT Documentation](https://docs.github.com/en/authentication/keeping-your-account-and-data-secure/creating-a-personal-access-token)
- [Branch Protection Bypass](https://docs.github.com/en/repositories/configuring-branches-and-merges-in-your-repository/managing-protected-branches/about-protected-branches)
Loading