forked from cline/cline
-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Merge pull request cline#1641 from cline/ocasta181/ENG-182
ENG-182 | Add Changesets
- Loading branch information
Showing
8 changed files
with
407 additions
and
6 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,5 @@ | ||
--- | ||
"claude-dev": minor | ||
--- | ||
|
||
Adding changesets for automating version bumping and release notes |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,103 @@ | ||
""" | ||
This script updates a specific version's release notes section in CHANGELOG.md with new content | ||
or reformats existing content. | ||
The script: | ||
1. Takes a version number, changelog path, and optionally new content as input from environment variables | ||
2. Finds the section in the changelog for the specified version | ||
3. Either: | ||
a) Replaces the content with new content if provided, or | ||
b) Reformats existing content by: | ||
- Removing the first two lines of the changeset format | ||
- Ensuring version numbers are wrapped in square brackets | ||
4. Writes the updated changelog back to the file | ||
Environment Variables: | ||
CHANGELOG_PATH: Path to the changelog file (defaults to 'CHANGELOG.md') | ||
VERSION: The version number to update/format | ||
PREV_VERSION: The previous version number (used to locate section boundaries) | ||
NEW_CONTENT: Optional new content to insert for this version | ||
""" | ||
|
||
#!/usr/bin/env python3 | ||
|
||
import os | ||
import sys | ||
|
||
CHANGELOG_PATH = os.environ.get("CHANGELOG_PATH", "CHANGELOG.md") | ||
VERSION = os.environ['VERSION'] | ||
PREV_VERSION = os.environ.get("PREV_VERSION", "") | ||
NEW_CONTENT = os.environ.get("NEW_CONTENT", "") | ||
|
||
def overwrite_changelog_section(changelog_text: str, new_content: str): | ||
# Find the section for the specified version | ||
version_pattern = f"## {VERSION}\n" | ||
bracketed_version_pattern = f"## [{VERSION}]\n" | ||
prev_version_pattern = f"## [{PREV_VERSION}]\n" | ||
print(f"latest version: {VERSION}") | ||
print(f"prev_version: {PREV_VERSION}") | ||
|
||
# Try both unbracketed and bracketed version patterns | ||
version_index = changelog_text.find(version_pattern) | ||
if version_index == -1: | ||
version_index = changelog_text.find(bracketed_version_pattern) | ||
if version_index == -1: | ||
# If version not found, add it at the top (after the first line) | ||
first_newline = changelog_text.find('\n') | ||
if first_newline == -1: | ||
# If no newline found, just prepend | ||
return f"## [{VERSION}]\n\n{changelog_text}" | ||
return f"{changelog_text[:first_newline + 1]}## [{VERSION}]\n\n{changelog_text[first_newline + 1:]}" | ||
else: | ||
# Using bracketed version | ||
version_pattern = bracketed_version_pattern | ||
|
||
notes_start_index = version_index + len(version_pattern) | ||
notes_end_index = changelog_text.find(prev_version_pattern, notes_start_index) if PREV_VERSION and prev_version_pattern in changelog_text else len(changelog_text) | ||
|
||
if new_content: | ||
return changelog_text[:notes_start_index] + f"{new_content}\n" + changelog_text[notes_end_index:] | ||
else: | ||
changeset_lines = changelog_text[notes_start_index:notes_end_index].split("\n") | ||
# Ensure we have at least 2 lines before removing them | ||
if len(changeset_lines) < 2: | ||
print("Warning: Changeset content has fewer than 2 lines") | ||
parsed_lines = "\n".join(changeset_lines) | ||
else: | ||
# Remove the first two lines from the regular changeset format, ex: \n### Patch Changes | ||
parsed_lines = "\n".join(changeset_lines[2:]) | ||
updated_changelog = changelog_text[:notes_start_index] + parsed_lines + changelog_text[notes_end_index:] | ||
# Ensure version number is bracketed | ||
updated_changelog = updated_changelog.replace(f"## {VERSION}", f"## [{VERSION}]") | ||
return updated_changelog | ||
|
||
try: | ||
print(f"Reading changelog from: {CHANGELOG_PATH}") | ||
with open(CHANGELOG_PATH, 'r') as f: | ||
changelog_content = f.read() | ||
|
||
print(f"Changelog content length: {len(changelog_content)} characters") | ||
print("First 200 characters of changelog:") | ||
print(changelog_content[:200]) | ||
print("----------------------------------------------------------------------------------") | ||
|
||
new_changelog = overwrite_changelog_section(changelog_content, NEW_CONTENT) | ||
|
||
print("New changelog content:") | ||
print("----------------------------------------------------------------------------------") | ||
print(new_changelog) | ||
print("----------------------------------------------------------------------------------") | ||
|
||
print(f"Writing updated changelog back to: {CHANGELOG_PATH}") | ||
with open(CHANGELOG_PATH, 'w') as f: | ||
f.write(new_changelog) | ||
|
||
print(f"{CHANGELOG_PATH} updated successfully!") | ||
|
||
except FileNotFoundError: | ||
print(f"Error: Changelog file not found at {CHANGELOG_PATH}") | ||
sys.exit(1) | ||
except Exception as e: | ||
print(f"Error updating changelog: {str(e)}") | ||
print(f"Current working directory: {os.getcwd()}") | ||
sys.exit(1) |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,162 @@ | ||
name: Changeset Release | ||
run-name: Changeset Release ${{ github.actor != 'cline-bot' && '- Create PR' || '- Update Changelog' }} | ||
|
||
permissions: | ||
contents: write | ||
pull-requests: write | ||
|
||
on: | ||
workflow_dispatch: | ||
pull_request: | ||
types: [closed, opened, labeled] | ||
|
||
env: | ||
REPO_PATH: ${{ github.repository }} | ||
GIT_REF: ${{ github.event_name == 'pull_request' && github.event.pull_request.head.sha || 'main' }} | ||
|
||
jobs: | ||
# Job 1: Create version bump PR when changesets are merged to main | ||
changeset-pr-version-bump: | ||
if: > | ||
( github.event_name == 'pull_request' && | ||
github.event.pull_request.merged == true && | ||
github.event.pull_request.base.ref == 'main' && | ||
github.actor != 'cline-bot' ) || | ||
github.event_name == 'workflow_dispatch' | ||
runs-on: ubuntu-latest | ||
permissions: | ||
contents: write | ||
pull-requests: write | ||
steps: | ||
- name: Git Checkout | ||
uses: actions/checkout@b4ffde65f46336ab88eb53be808477a3936bae11 # v4 | ||
with: | ||
fetch-depth: 0 | ||
ref: ${{ env.GIT_REF }} | ||
|
||
- name: Setup Node.js | ||
uses: actions/setup-node@b39b52d1213e96004bfcb1c61a8a6fa8ab84f3e8 # v4 | ||
with: | ||
node-version: 20 | ||
cache: "npm" | ||
|
||
- name: Install Dependencies | ||
run: npm run install:all | ||
|
||
# Check if there are any new changesets to process | ||
- name: Check for changesets | ||
id: check-changesets | ||
run: | | ||
NEW_CHANGESETS=$(find .changeset -name "*.md" ! -name "README.md" | wc -l | tr -d ' ') | ||
echo "Changesets diff with previous version: $NEW_CHANGESETS" | ||
echo "new_changesets=$NEW_CHANGESETS" >> $GITHUB_OUTPUT | ||
# Create version bump PR using changesets/action if there are new changesets | ||
- name: Changeset Pull Request | ||
if: steps.check-changesets.outputs.new_changesets != '0' | ||
id: changesets | ||
uses: changesets/action@e9cc34b540dd3ad1b030c57fd97269e8f6ad905a # v1 | ||
with: | ||
commit: "changeset version bump" | ||
title: "Changeset version bump" | ||
version: npm run version-packages # This performs the changeset version bump | ||
env: | ||
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} | ||
|
||
# Job 2: Process version bump PR created by cline-bot | ||
changeset-pr-edit-approve: | ||
name: Auto approve and merge Bump version PRs | ||
runs-on: ubuntu-latest | ||
permissions: | ||
contents: write | ||
pull-requests: write | ||
if: > | ||
github.event_name == 'pull_request' && | ||
github.event.pull_request.base.ref == 'main' && | ||
github.actor == 'cline-bot' && | ||
contains(github.event.pull_request.title, 'Changeset version bump') | ||
steps: | ||
- name: Determine checkout ref | ||
id: checkout-ref | ||
run: | | ||
echo "Event action: ${{ github.event.action }}" | ||
echo "Actor: ${{ github.actor }}" | ||
echo "Head ref: ${{ github.head_ref }}" | ||
echo "PR SHA: ${{ github.event.pull_request.head.sha }}" | ||
if [[ "${{ github.event.action }}" == "opened" && "${{ github.actor }}" == "cline-bot" ]]; then | ||
echo "Using branch ref: ${{ github.head_ref }}" | ||
echo "git_ref=${{ github.head_ref }}" >> $GITHUB_OUTPUT | ||
else | ||
echo "Using SHA ref: ${{ github.event.pull_request.head.sha }}" | ||
echo "git_ref=${{ github.event.pull_request.head.sha }}" >> $GITHUB_OUTPUT | ||
fi | ||
- name: Checkout Repo | ||
uses: actions/checkout@b4ffde65f46336ab88eb53be808477a3936bae11 # v4 | ||
with: | ||
token: ${{ secrets.GITHUB_TOKEN }} | ||
fetch-depth: 0 | ||
ref: ${{ steps.checkout-ref.outputs.git_ref }} | ||
|
||
# Get current and previous versions to edit changelog entry | ||
- name: Get version | ||
id: get_version | ||
run: | | ||
VERSION=$(git show HEAD:package.json | jq -r '.version') | ||
echo "version=$VERSION" >> $GITHUB_OUTPUT | ||
PREV_VERSION=$(git show origin/main:package.json | jq -r '.version') | ||
echo "prev_version=$PREV_VERSION" >> $GITHUB_OUTPUT | ||
echo "version=$VERSION" | ||
echo "prev_version=$PREV_VERSION" | ||
# Update CHANGELOG.md with proper format | ||
- name: Update Changelog Format | ||
if: ${{ !contains(github.event.pull_request.labels.*.name, 'changelog-ready') }} | ||
env: | ||
VERSION: ${{ steps.get_version.outputs.version }} | ||
PREV_VERSION: ${{ steps.get_version.outputs.prev_version }} | ||
run: python .github/scripts/overwrite_changeset_changelog.py | ||
|
||
# Commit and push changelog updates | ||
- name: Push Changelog updates | ||
if: ${{ !contains(github.event.pull_request.labels.*.name, 'changelog-ready') }} | ||
run: | | ||
git config user.name "cline-bot" | ||
git config user.email [email protected] | ||
echo "Running git add and commit..." | ||
git add CHANGELOG.md | ||
git commit -m "Updating CHANGELOG.md format" | ||
git status | ||
echo "--------------------------------------------------------------------------------" | ||
echo "Pushing to remote..." | ||
echo "--------------------------------------------------------------------------------" | ||
git push | ||
# Add label to indicate changelog has been formatted | ||
- name: Add changelog-ready label | ||
if: ${{ !contains(github.event.pull_request.labels.*.name, 'changelog-ready') }} | ||
uses: actions/github-script@60a0d83039c74a4aee543508d2ffcb1c3799cdea # v7 | ||
with: | ||
github-token: ${{ secrets.GITHUB_TOKEN }} | ||
script: | | ||
await github.rest.issues.addLabels({ | ||
owner: context.repo.owner, | ||
repo: context.repo.repo, | ||
issue_number: context.issue.number, | ||
labels: ['changelog-ready'] | ||
}); | ||
# Auto-approve PR only after it has been labeled | ||
- name: Auto approve PR | ||
if: contains(github.event.pull_request.labels.*.name, 'changelog-ready') | ||
uses: hmarr/auto-approve-action@de8bf34d0402c38aa2c8346973342b2cb02c4435 # v4 | ||
with: | ||
review-message: "I'm approving since it's a bump version PR" | ||
|
||
# Auto-merge PR | ||
- name: Automerge on PR | ||
if: false # Needs enablePullRequestAutoMerge in repo settings to work contains(github.event.pull_request.labels.*.name, 'changelog-ready') | ||
run: gh pr merge --auto --merge ${{ github.event.pull_request.number }} | ||
env: | ||
GH_TOKEN: ${{ secrets.GITHUB_TOKEN }} |
Oops, something went wrong.