mirror of
https://github.com/pacnpal/Roo-Code.git
synced 2025-12-20 04:11:10 -05:00
Merge pull request #61 from RooVetGit/chores/changeset-releases
Changeset AI Releases and code guardrails
This commit is contained in:
28
.github/pull_request_template.md
vendored
Normal file
28
.github/pull_request_template.md
vendored
Normal file
@@ -0,0 +1,28 @@
|
||||
<!-- **Note:** Consider creating PRs as a DRAFT. For early feedback and self-review. -->
|
||||
## Description
|
||||
|
||||
## Type of change
|
||||
<!-- Please ignore options that are not relevant -->
|
||||
- [ ] Bug fix (non-breaking change which fixes an issue)
|
||||
- [ ] New feature
|
||||
- [ ] Breaking change (fix or feature that would cause existing functionality to not work as expected)
|
||||
- [ ] This change requires a documentation update
|
||||
|
||||
## How Has This Been Tested?
|
||||
<!-- Please describe the tests that you ran to verify your changes -->
|
||||
|
||||
## Checklist:
|
||||
<!-- Go over all the following points, and put an `x` in all the boxes that apply -->
|
||||
- [ ] My code follows the patterns of this project
|
||||
- [ ] I have performed a self-review of my own code
|
||||
- [ ] I have commented my code, particularly in hard-to-understand areas
|
||||
- [ ] I have made corresponding changes to the documentation
|
||||
|
||||
## Additional context
|
||||
<!-- Add any other context or screenshots about the pull request here -->
|
||||
|
||||
## Related Issues
|
||||
<!-- List any related issues here. Use the GitHub issue linking syntax: #issue-number -->
|
||||
|
||||
## Reviewers
|
||||
<!-- @mention specific team members or individuals who should review this PR -->
|
||||
60
.github/scripts/overwrite_changeset_changelog.py
vendored
Executable file
60
.github/scripts/overwrite_changeset_changelog.py
vendored
Executable file
@@ -0,0 +1,60 @@
|
||||
"""
|
||||
This script updates a specific version's release notes section in CHANGELOG.md with new content.
|
||||
|
||||
The script:
|
||||
1. Takes a version number, changelog path, and new content as input from environment variables
|
||||
2. Finds the section in the changelog for the specified version
|
||||
3. Replaces the content between the current version header and the next version header
|
||||
(or end of file if it's the latest version) with the new content
|
||||
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 notes for
|
||||
PREV_VERSION: The previous version number (optional)
|
||||
NEW_CONTENT: The new content to insert for this version
|
||||
"""
|
||||
|
||||
#!/usr/bin/env python3
|
||||
|
||||
import os
|
||||
|
||||
CHANGELOG_PATH = os.environ.get("CHANGELOG_PATH", "CHANGELOG.md")
|
||||
VERSION = os.environ['VERSION']
|
||||
PREV_VERSION = os.environ.get("PREV_VERSION", "")
|
||||
NEW_CONTENT = os.environ['NEW_CONTENT']
|
||||
|
||||
def overwrite_changelog_section(content: str):
|
||||
"""Replace a specific version section in the changelog content.
|
||||
|
||||
Args:
|
||||
content: The full changelog content as a string
|
||||
|
||||
Returns:
|
||||
The updated changelog content with the new section
|
||||
|
||||
Example:
|
||||
>>> content = "## 1.2.0\\nOld changes\\n## 1.1.0\\nOld changes"
|
||||
>>> NEW_CONTENT = "New changes"
|
||||
>>> overwrite_changelog_section(content)
|
||||
'## 1.2.0\\nNew changes\\n## 1.1.0\\nOld changes'
|
||||
"""
|
||||
# Find the section for the specified version
|
||||
version_pattern = f"## {VERSION}\n"
|
||||
print(f"latest version: {VERSION}")
|
||||
notes_start_index = content.find(version_pattern) + len(version_pattern)
|
||||
print(f"prev_version: {PREV_VERSION}")
|
||||
prev_version_pattern = f"## {PREV_VERSION}\n"
|
||||
notes_end_index = content.find(prev_version_pattern, notes_start_index) if PREV_VERSION and prev_version_pattern in content else len(content)
|
||||
return content[:notes_start_index] + f"{NEW_CONTENT}\n" + content[notes_end_index:]
|
||||
|
||||
with open(CHANGELOG_PATH, 'r') as f:
|
||||
content = f.read()
|
||||
|
||||
new_changelog = overwrite_changelog_section(content)
|
||||
|
||||
print(new_changelog)
|
||||
|
||||
# Write back to CHANGELOG.md
|
||||
with open(CHANGELOG_PATH, 'w') as f:
|
||||
f.write(new_changelog)
|
||||
64
.github/scripts/parse_changeset_changelog.py
vendored
Executable file
64
.github/scripts/parse_changeset_changelog.py
vendored
Executable file
@@ -0,0 +1,64 @@
|
||||
"""
|
||||
This script extracts the release notes section for a specific version from CHANGELOG.md.
|
||||
|
||||
The script:
|
||||
1. Takes a version number and changelog path as input from environment variables
|
||||
2. Finds the section in the changelog for the specified version
|
||||
3. Extracts the content between the current version header and the next version header
|
||||
(or end of file if it's the latest version)
|
||||
4. Outputs the extracted release notes to GITHUB_OUTPUT for use in creating GitHub releases
|
||||
|
||||
Environment Variables:
|
||||
GITHUB_OUTPUT: Path to GitHub Actions output file
|
||||
CHANGELOG_PATH: Path to the changelog file (defaults to 'CHANGELOG.md')
|
||||
VERSION: The version number to extract notes for
|
||||
"""
|
||||
|
||||
#!/usr/bin/env python3
|
||||
|
||||
import sys
|
||||
import os
|
||||
import subprocess
|
||||
|
||||
GITHUB_OUTPUT = os.getenv("GITHUB_OUTPUT")
|
||||
CHANGELOG_PATH = os.environ.get("CHANGELOG_PATH", "CHANGELOG.md")
|
||||
VERSION = os.environ['VERSION']
|
||||
|
||||
def parse_changelog_section(content: str):
|
||||
"""Parse a specific version section from the changelog content.
|
||||
|
||||
Args:
|
||||
content: The full changelog content as a string
|
||||
|
||||
Returns:
|
||||
The formatted content for this version, or None if version not found
|
||||
|
||||
Example:
|
||||
>>> content = "## 1.2.0\\nChanges\\n## 1.1.0\\nOld changes"
|
||||
>>> parse_changelog_section(content)
|
||||
'Changes\\n'
|
||||
"""
|
||||
# Find the section for the specified version
|
||||
version_pattern = f"## {VERSION}\n"
|
||||
print(f"latest version: {VERSION}")
|
||||
notes_start_index = content.find(version_pattern) + len(version_pattern)
|
||||
prev_version = subprocess.getoutput("git show origin/main:package.json | grep '\"version\":' | cut -d'\"' -f4")
|
||||
print(f"prev_version: {prev_version}")
|
||||
prev_version_pattern = f"## {prev_version}\n"
|
||||
notes_end_index = content.find(prev_version_pattern, notes_start_index) if prev_version_pattern in content else len(content)
|
||||
|
||||
return content[notes_start_index:notes_end_index]
|
||||
|
||||
with open(CHANGELOG_PATH, 'r') as f:
|
||||
content = f.read()
|
||||
|
||||
formatted_content = parse_changelog_section(content)
|
||||
if not formatted_content:
|
||||
print(f"Version {VERSION} not found in changelog", file=sys.stderr)
|
||||
sys.exit(1)
|
||||
|
||||
print(formatted_content)
|
||||
|
||||
# Write the extracted release notes to GITHUB_OUTPUT
|
||||
with open(GITHUB_OUTPUT, "a") as gha_output:
|
||||
gha_output.write(f"release-notes<<EOF\n{formatted_content}\nEOF")
|
||||
23
.github/scripts/release-notes-prompt.py
vendored
Normal file
23
.github/scripts/release-notes-prompt.py
vendored
Normal file
@@ -0,0 +1,23 @@
|
||||
"""
|
||||
This script generates a base prompt for OpenAI to create release notes.
|
||||
"""
|
||||
|
||||
#!/usr/bin/env python3
|
||||
|
||||
import os
|
||||
from datetime import datetime;
|
||||
from pytz import timezone
|
||||
|
||||
GITHUB_OUTPUT = os.getenv("GITHUB_OUTPUT")
|
||||
|
||||
TODAY = datetime.now(timezone('US/Eastern')).isoformat(sep=' ', timespec='seconds')
|
||||
|
||||
BASE_PROMPT = f"""Based on the following 'PR Information', please generate concise and informative release notes to be read by developers.
|
||||
Format the release notes with markdown, and always use this structure: a descriptive and very short title (no more than 8 words) with heading level 2, a paragraph with a summary of changes (no header), and if applicable, sections for '🚀 New Features & Improvements', '🐛 Bugs Fixed' and '🔧 Other Updates', with heading level 3, skip respectively the sections if not applicable.
|
||||
Finally include the following markdown comment with the PR merged date: <!-- PR_DATE: {TODAY} -->.
|
||||
Avoid being repetitive and focus on the most important changes and their impact, discard any mention of version bumps/updates, changeset files, environment variables or syntax updates.
|
||||
PR Information:"""
|
||||
|
||||
# Write the prompt to GITHUB_OUTPUT
|
||||
with open(GITHUB_OUTPUT, "a") as outputs_file:
|
||||
outputs_file.write(f"BASE_PROMPT<<EOF\n{BASE_PROMPT}\nEOF")
|
||||
215
.github/workflows/changeset-ai-releases.yml
vendored
Normal file
215
.github/workflows/changeset-ai-releases.yml
vendored
Normal file
@@ -0,0 +1,215 @@
|
||||
name: Changeset AI Release
|
||||
run-name: Changeset AI Release ${{ github.actor != 'R00-B0T' && '- Create PR' || '- Approve & Release' }}
|
||||
|
||||
# This workflow automates the release process by:
|
||||
# 1. Creating a version bump PR when changesets are merged to main
|
||||
# 2. Using AI to generate release notes for the version bump PR
|
||||
# 3. Auto-approving and merging the version bump PR
|
||||
# 4. Creating a GitHub release with the AI-generated notes
|
||||
|
||||
on:
|
||||
pull_request:
|
||||
types: [closed, opened, synchronize, labeled]
|
||||
|
||||
env:
|
||||
REPO_PATH: ${{ github.repository }}
|
||||
GIT_REF: ${{ github.head_ref }}
|
||||
|
||||
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 != 'R00-B0T'
|
||||
runs-on: ubuntu-latest
|
||||
permissions:
|
||||
contents: write
|
||||
pull-requests: write
|
||||
steps:
|
||||
- name: Git Checkout
|
||||
uses: actions/checkout@v4
|
||||
with:
|
||||
fetch-depth: 0
|
||||
ref: ${{ env.GIT_REF }}
|
||||
|
||||
- name: Setup Node.js
|
||||
uses: actions/setup-node@v4
|
||||
with:
|
||||
node-version: 20
|
||||
cache: 'npm'
|
||||
|
||||
- name: Install Dependencies
|
||||
run: npm install
|
||||
|
||||
# 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@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.CROSS_REPO_ACCESS_TOKEN }}
|
||||
|
||||
# Job 2: Process version bump PR created by R00-B0T
|
||||
changeset-pr-approve-merge:
|
||||
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 == 'R00-B0T' &&
|
||||
contains(github.event.pull_request.title, 'Changeset version bump')
|
||||
|
||||
steps:
|
||||
- name: Checkout Repo
|
||||
uses: actions/checkout@v4
|
||||
with:
|
||||
token: ${{ secrets.CROSS_REPO_ACCESS_TOKEN }}
|
||||
fetch-depth: 0
|
||||
ref: ${{ env.GIT_REF }}
|
||||
|
||||
# Get current and previous versions for changelog processing
|
||||
- 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"
|
||||
|
||||
# Generate base prompt for OpenAI, GITHUB_OUTPUT: 'BASE_PROMPT'
|
||||
- name: Release Notes Prompt
|
||||
id: ai_prompt
|
||||
run: python .github/scripts/release-notes-prompt.py
|
||||
|
||||
# Generate release notes using OpenAI if not already edited, GITHUB_OUTPUT: 'RELEASE_NOTES' and 'OPENAI_PROMPT'
|
||||
- name: AI Release Notes
|
||||
if: ${{ !contains(github.event.pull_request.labels.*.name, 'openai-edited') }}
|
||||
uses: RooVetGit/Roo-GHA/.github/actions/ai-release-notes@main
|
||||
id: ai_release_notes
|
||||
with:
|
||||
GHA_PAT: ${{ secrets.CROSS_REPO_ACCESS_TOKEN }}
|
||||
OPENAI_API_KEY: ${{ secrets.OPENAI_API_KEY }}
|
||||
model_name: gpt-4o-mini
|
||||
repo_path: ${{ env.REPO_PATH }}
|
||||
git_ref: ${{ env.GIT_REF }}
|
||||
custom_prompt: ${{ steps.ai_prompt.outputs.BASE_PROMPT }}
|
||||
|
||||
# Update CHANGELOG.md with AI-generated notes
|
||||
- name: Update Changeset Changelog
|
||||
if: ${{ !contains(github.event.pull_request.labels.*.name, 'openai-edited') }}
|
||||
env:
|
||||
VERSION: ${{ steps.get_version.outputs.version }}
|
||||
PREV_VERSION: ${{ steps.get_version.outputs.prev_version }}
|
||||
NEW_CONTENT: ${{ steps.ai_release_notes.outputs.RELEASE_NOTES }}
|
||||
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, 'openai-edited') }}
|
||||
run: |
|
||||
git config user.name "R00-B0T"
|
||||
git config user.email github-actions@github.com
|
||||
git status
|
||||
|
||||
echo "Updating changelog.md..."
|
||||
git add CHANGELOG.md
|
||||
git commit -m "Updating changeset changelog"
|
||||
|
||||
echo "--------------------------------------------------------------------------------"
|
||||
echo "Pushing to remote..."
|
||||
echo "--------------------------------------------------------------------------------"
|
||||
git push
|
||||
|
||||
# Add label to indicate OpenAI has processed this PR
|
||||
- name: Add openai-edited label
|
||||
if: ${{ !contains(github.event.pull_request.labels.*.name, 'openai-edited') }}
|
||||
uses: actions/github-script@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: ['openai-edited']
|
||||
});
|
||||
|
||||
# Auto-approve PR once OpenAI has processed it
|
||||
- name: Auto approve PR
|
||||
if: contains(github.event.pull_request.labels.*.name, 'openai-edited')
|
||||
uses: hmarr/auto-approve-action@v4
|
||||
with:
|
||||
review-message: "I'm approving since it's a bump version PR"
|
||||
|
||||
# Enable auto-merge for the PR
|
||||
- name: Enable automerge on PR
|
||||
if: contains(github.event.pull_request.labels.*.name, 'openai-edited')
|
||||
run: gh pr merge --squash --auto ${{ github.event.pull_request.number }}
|
||||
env:
|
||||
GH_TOKEN: ${{ secrets.CROSS_REPO_ACCESS_TOKEN }}
|
||||
|
||||
# Job 3: Create GitHub release after version bump PR is merged
|
||||
github-release:
|
||||
runs-on: ubuntu-latest
|
||||
if: >
|
||||
github.event_name == 'pull_request' &&
|
||||
github.event.pull_request.merged == true &&
|
||||
github.event.pull_request.base.ref == 'main' &&
|
||||
github.actor == 'R00-B0T' &&
|
||||
contains(github.event.pull_request.title, 'Changeset version bump')
|
||||
permissions:
|
||||
contents: write
|
||||
steps:
|
||||
- name: Checkout Repo
|
||||
uses: actions/checkout@v4
|
||||
with:
|
||||
ref: ${{ github.event.pull_request.head.sha }}
|
||||
fetch-depth: 0
|
||||
|
||||
- name: Get version
|
||||
id: get_version
|
||||
run: |
|
||||
VERSION=$(git show HEAD:package.json | jq -r '.version')
|
||||
echo "version=$VERSION" >> $GITHUB_OUTPUT
|
||||
|
||||
# Extract release notes from CHANGELOG.md, GITHUB_OUTPUT: 'release-notes'
|
||||
- name: Parse CHANGELOG.md
|
||||
id: changelog
|
||||
env:
|
||||
CHANGELOG_PATH: CHANGELOG.md
|
||||
VERSION: ${{ steps.get_version.outputs.version }}
|
||||
run: python .github/scripts/parse_changeset_changelog.py
|
||||
|
||||
# Create GitHub release with extracted notes
|
||||
- name: Create or Update Release
|
||||
uses: softprops/action-gh-release@v2
|
||||
env:
|
||||
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
|
||||
with:
|
||||
tag_name: v${{ steps.get_version.outputs.version }}
|
||||
name: Release v${{ steps.get_version.outputs.version }}
|
||||
draft: false
|
||||
prerelease: false
|
||||
append_body: false
|
||||
make_latest: true
|
||||
body: ${{ steps.changelog.outputs.release-notes }}
|
||||
2
.github/workflows/code-qa.yml
vendored
2
.github/workflows/code-qa.yml
vendored
@@ -8,7 +8,7 @@ on:
|
||||
branches: [main]
|
||||
|
||||
jobs:
|
||||
code-qa:
|
||||
compile:
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- name: Checkout code
|
||||
|
||||
1
.github/workflows/marketplace-publish.yml
vendored
1
.github/workflows/marketplace-publish.yml
vendored
@@ -7,6 +7,7 @@ on:
|
||||
jobs:
|
||||
publish-extension:
|
||||
runs-on: ubuntu-latest
|
||||
if: ${{ github.actor == 'R00-B0T'}}
|
||||
steps:
|
||||
- uses: actions/checkout@v3
|
||||
- uses: actions/setup-node@v3
|
||||
|
||||
Reference in New Issue
Block a user