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
38 changes: 22 additions & 16 deletions .github/workflows/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -61,16 +61,17 @@ See [scripts/README.md](../scripts/README.md) for detailed documentation.

**Steps**:

1. Run full test suite to ensure code quality
2. Bump version in root `package.json` and all workspace packages (in dependency order)
1. Install/build the workspace
2. Bump versions in root `package.json` and workspace packages (dependency order)
3. **Automatically detect and update cross-package dependencies**:
- Scans all packages for dependencies on the package being version bumped
- Updates `dependencies`, `devDependencies`, and `peerDependencies` automatically
- Works for any number of packages and dependency relationships
4. Update `pnpm-lock.yaml` to reflect new versions
5. Commit changes to main branch
6. Create and push git tag (e.g., `v1.2.3` or `v1.2.3-beta.1`)
7. Create GitHub release (marked as prerelease for beta versions)
4. Update `pnpm-lock.yaml`
5. Create a release branch (`release/x.y.z`) and commit changes
6. Open a pull request to `main`
7. After merge, `tag-on-release-pr-merge.yml` creates and pushes the version tag, then creates a GitHub Release
8. `publish.yml` runs from the tag push and publishes packages

**Version Types**:

Expand Down Expand Up @@ -106,13 +107,7 @@ See [scripts/README.md](../scripts/README.md) for detailed documentation.

### 1. Required Secrets

Add these secrets in your GitHub repository settings:

- `NPM_AUTH_TOKEN`: Your npm access token with publish permissions
- Go to [npm Access Tokens](https://www.npmjs.com/settings/tokens)
- Generate a **Granular Access Token** or **Classic Token**
- Ensure it has publish access to your packages
- Add it to GitHub repository secrets
No additional repository secret is required for version bump PR creation when `GITHUB_TOKEN` is allowed to create PRs.

### 2. npm Package Access

Expand All @@ -123,10 +118,13 @@ Ensure your npm token has permission to publish to:

### 3. Repository Permissions

The workflows need these permissions (automatically granted):
The workflows need these permissions:

- `contents: write` - to push release branches and tags
- `pull-requests: write` - to create release PRs
- `id-token: write` - for npm trusted publishing

- `contents: write` - to create releases and push tags
- `id-token: write` - for npm publishing
Enable **Settings → Actions → General → Workflow permissions → Allow GitHub Actions to create and approve pull requests**.

## Usage Examples

Expand Down Expand Up @@ -212,6 +210,14 @@ If the version bump workflow fails with npm dependency errors:

**Testing**: The workflow has been tested to ensure dependency updates work correctly with pnpm workspaces.

### Pull Request Creation Fails

**Error**: `GraphQL: GitHub Actions is not permitted to create or approve pull requests (createPullRequest)`

**Cause**: The workflow is attempting to create a PR with `GITHUB_TOKEN`, but repository policy blocks this action.

**Fix**: Enable GitHub Actions PR creation in repository Actions settings.

## Recommended Branching Strategy

### 🎯 **Recommended: Main Branch Strategy**
Expand Down
35 changes: 32 additions & 3 deletions .github/workflows/tag-on-release-pr-merge.yml
Original file line number Diff line number Diff line change
Expand Up @@ -32,17 +32,46 @@ jobs:
git config --local user.name "GitHub Action"

- name: Create and push tag
id: tag
run: |
VERSION=$(node -p "require('./package.json').version")
TAG="v$VERSION"
echo "tag=$TAG" >> "$GITHUB_OUTPUT"

# Ensure local tags are up to date before existence check.
git fetch --tags

if git rev-parse "$TAG" >/dev/null 2>&1; then
echo "Tag $TAG already exists, skipping."
echo "Tag $TAG already exists, skipping tag creation."
echo "created=false" >> "$GITHUB_OUTPUT"
else
git tag "$TAG"
git push origin "$TAG"
echo "created=true" >> "$GITHUB_OUTPUT"
fi

- name: Create GitHub release
env:
GH_TOKEN: ${{ github.token }}
run: |
TAG="${{ steps.tag.outputs.tag }}"

# Mark release as prerelease for tags like v1.2.3-beta.1, v1.2.3-rc.1, etc.
if [[ "$TAG" =~ ^v[0-9]+\.[0-9]+\.[0-9]+-(alpha|beta|rc|dev|canary|next)(\.[0-9]+)?$ ]]; then
PRERELEASE_FLAG="--prerelease"
RELEASE_KIND="prerelease"
else
PRERELEASE_FLAG=""
RELEASE_KIND="stable release"
fi

if gh release view "$TAG" >/dev/null 2>&1; then
echo "Release for $TAG already exists, skipping release creation."
exit 0
fi

git tag "$TAG"
git push origin "$TAG"
gh release create "$TAG" \
--title "$TAG" \
--notes "Automated $RELEASE_KIND created from merged release PR #${{ github.event.pull_request.number }}." \
$PRERELEASE_FLAG
echo "Created GitHub release for $TAG."
66 changes: 63 additions & 3 deletions .github/workflows/version-bump.yml
Original file line number Diff line number Diff line change
Expand Up @@ -180,33 +180,66 @@ jobs:
run: pnpm install --lockfile-only

- name: Commit version changes
id: commit-changes
run: |
NEW_VERSION="${{ steps.version-root.outputs.new_version }}"
git add .
if git diff --cached --quiet; then
echo "No version changes detected; skipping commit."
echo "has_changes=false" >> $GITHUB_OUTPUT
exit 0
fi
git commit -m "chore: bump version to $NEW_VERSION

- Updated all workspace packages to $NEW_VERSION
- Updated cross-package dependencies automatically"
echo "has_changes=true" >> $GITHUB_OUTPUT

- name: Push release branch
id: push-branch
if: steps.commit-changes.outputs.has_changes == 'true'
run: |
NEW_VERSION="${{ steps.version-root.outputs.new_version }}"
RELEASE_BRANCH="release/${NEW_VERSION#v}"

git checkout -b "$RELEASE_BRANCH"
git push origin "$RELEASE_BRANCH"
git push --set-upstream origin "$RELEASE_BRANCH"

echo "release_branch=$RELEASE_BRANCH" >> $GITHUB_OUTPUT

- name: Check for existing PR
id: existing-pr
if: steps.commit-changes.outputs.has_changes == 'true'
env:
GH_TOKEN: ${{ github.token }}
run: |
RELEASE_BRANCH="${{ steps.push-branch.outputs.release_branch }}"
EXISTING_PR_URL=$(gh pr list \
--base main \
--head "$RELEASE_BRANCH" \
--state open \
--json url \
--jq '.[0].url')

if [ -n "$EXISTING_PR_URL" ]; then
echo "Found existing PR: $EXISTING_PR_URL"
echo "exists=true" >> $GITHUB_OUTPUT
echo "url=$EXISTING_PR_URL" >> $GITHUB_OUTPUT
else
echo "No existing PR found."
echo "exists=false" >> $GITHUB_OUTPUT
fi

- name: Create Pull Request
if: steps.commit-changes.outputs.has_changes == 'true' && steps.existing-pr.outputs.exists == 'false'
env:
GH_TOKEN: ${{ github.token }}
run: |
NEW_VERSION="${{ steps.version-root.outputs.new_version }}"
RELEASE_BRANCH="${{ steps.push-branch.outputs.release_branch }}"

gh pr create \
set +e
PR_OUTPUT=$(gh pr create \
--base main \
--head "$RELEASE_BRANCH" \
--title "chore: bump version to $NEW_VERSION" \
Expand All @@ -225,4 +258,31 @@ jobs:
2. Tag is created automatically after merge
3. Publish workflow runs from the tag push
EOF
)"
)" 2>&1)
EXIT_CODE=$?
set -e

echo "$PR_OUTPUT"

if [ "$EXIT_CODE" -ne 0 ]; then
if echo "$PR_OUTPUT" | grep -q "GitHub Actions is not permitted to create or approve pull requests"; then
echo "❌ Pull request creation is blocked for GITHUB_TOKEN in this repository."
echo "ℹ️ Enable 'Allow GitHub Actions to create and approve pull requests' in repository Actions settings."
fi
exit "$EXIT_CODE"
fi

- name: Pull Request summary
if: steps.commit-changes.outputs.has_changes == 'true'
run: |
if [ "${{ steps.existing-pr.outputs.exists }}" = "true" ]; then
echo "## Release PR" >> $GITHUB_STEP_SUMMARY
echo "" >> $GITHUB_STEP_SUMMARY
echo "Using existing PR: ${{ steps.existing-pr.outputs.url }}" >> $GITHUB_STEP_SUMMARY
else
NEW_VERSION="${{ steps.version-root.outputs.new_version }}"
RELEASE_BRANCH="${{ steps.push-branch.outputs.release_branch }}"
echo "## Release PR" >> $GITHUB_STEP_SUMMARY
echo "" >> $GITHUB_STEP_SUMMARY
echo "Created PR for $NEW_VERSION from branch \`$RELEASE_BRANCH\`." >> $GITHUB_STEP_SUMMARY
fi
Loading