Skip to content
Open
Show file tree
Hide file tree
Changes from 1 commit
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
264 changes: 264 additions & 0 deletions .github/workflows/bump-version.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,264 @@
name: Bump Version

on:
workflow_dispatch:
inputs:
force_bump_type:
description: 'Force a specific bump type (leave empty for AI auto-detection)'
required: false
type: choice
options:
- ''
- major
- minor
- patch
schedule:
# Run weekly on Monday at 9:00 AM UTC
- cron: '0 9 * * 1'

jobs:
analyze-and-bump:
runs-on: ubuntu-latest
permissions:
contents: write
pull-requests: write
steps:
- name: Checkout code
uses: actions/checkout@v4
with:
fetch-depth: 0 # Need full history to analyze commits
submodules: false

- name: Set up Python
uses: actions/setup-python@v5
with:
python-version: '3.10'

- name: Install dependencies
run: |
python -m pip install --upgrade pip
pip install google-generativeai

- name: Get current version
id: current-version
run: |
CURRENT_VERSION=$(cat version.txt | tr -d '[:space:]')
echo "version=${CURRENT_VERSION}" >> $GITHUB_OUTPUT
echo "Current version: ${CURRENT_VERSION}"

- name: Check for existing bump PR
id: check-existing-pr
env:
GH_TOKEN: ${{ github.token }}
run: |
# Check if there's already an open PR for version bump
EXISTING_PR=$(gh pr list --state open --label "version-bump" --json number --jq '.[0].number' || echo "")
if [ -n "$EXISTING_PR" ]; then
echo "has_existing_pr=true" >> $GITHUB_OUTPUT
echo "existing_pr_number=${EXISTING_PR}" >> $GITHUB_OUTPUT
echo "⚠️ Existing version bump PR found: #${EXISTING_PR}"
else
echo "has_existing_pr=false" >> $GITHUB_OUTPUT
echo "βœ“ No existing version bump PR found"
fi
Comment on lines +64 to +72
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🟠 Major

Guard against null from gh pr list to avoid false positives.

Current test treats "null" as a PR number. Use // empty.

Apply:

-          EXISTING_PR=$(gh pr list --state open --label "version-bump" --json number --jq '.[0].number' || echo "")
+          EXISTING_PR=$(gh pr list --state open --label "version-bump" --json number --jq '.[0].number // empty' || echo "")
           if [ -n "$EXISTING_PR" ]; then
πŸ“ Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
EXISTING_PR=$(gh pr list --state open --label "version-bump" --json number --jq '.[0].number' || echo "")
if [ -n "$EXISTING_PR" ]; then
echo "has_existing_pr=true" >> $GITHUB_OUTPUT
echo "existing_pr_number=${EXISTING_PR}" >> $GITHUB_OUTPUT
echo "⚠️ Existing version bump PR found: #${EXISTING_PR}"
else
echo "has_existing_pr=false" >> $GITHUB_OUTPUT
echo "βœ“ No existing version bump PR found"
fi
EXISTING_PR=$(gh pr list --state open --label "version-bump" --json number --jq '.[0].number // empty' || echo "")
if [ -n "$EXISTING_PR" ]; then
echo "has_existing_pr=true" >> $GITHUB_OUTPUT
echo "existing_pr_number=${EXISTING_PR}" >> $GITHUB_OUTPUT
echo "⚠️ Existing version bump PR found: #${EXISTING_PR}"
else
echo "has_existing_pr=false" >> $GITHUB_OUTPUT
echo "βœ“ No existing version bump PR found"
fi
πŸ€– Prompt for AI Agents
.github/workflows/bump-version.yml around lines 55 to 63: the current GH CLI jq
expression can return the string "null" which gets treated as a non-empty PR
number; update the jq part to coerce null to an empty string (use .[0].number //
empty) so EXISTING_PR will be empty when no PR exists, leaving the rest of the
if-check unchanged.


- name: Analyze commits with AI
id: analyze
if: steps.check-existing-pr.outputs.has_existing_pr == 'false'
env:
GEMINI_API_KEY: ${{ secrets.GEMINI_API_KEY }}
run: |
echo "Analyzing commits to determine version bump..."

# Run AI analysis
python scripts/ai_determine_version_bump.py \
--output-format json \
--verbose > /tmp/analysis.json 2>&1

# Extract results
BUMP_TYPE=$(jq -r '.bump_type' /tmp/analysis.json)
NEW_VERSION=$(jq -r '.new_version' /tmp/analysis.json)
REASONING=$(jq -r '.reasoning' /tmp/analysis.json)
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | πŸ”΄ Critical

Do not merge stderr into the JSON file (breaks jq).

--verbose writes to stderr; > /tmp/analysis.json 2>&1 corrupts JSON. Capture stdout only.

Apply:

-          python scripts/ai_determine_version_bump.py \
-            --output-format json \
-            --verbose > /tmp/analysis.json 2>&1
+          python scripts/ai_determine_version_bump.py \
+            --output-format json \
+            --verbose 1> /tmp/analysis.json 2> /tmp/analysis.log
+          echo "AI analysis logs saved to /tmp/analysis.log"
πŸ“ Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
# Run AI analysis
python scripts/ai_determine_version_bump.py \
--output-format json \
--verbose > /tmp/analysis.json 2>&1
# Extract results
BUMP_TYPE=$(jq -r '.bump_type' /tmp/analysis.json)
NEW_VERSION=$(jq -r '.new_version' /tmp/analysis.json)
REASONING=$(jq -r '.reasoning' /tmp/analysis.json)
# Run AI analysis
python scripts/ai_determine_version_bump.py \
--output-format json \
--verbose 1> /tmp/analysis.json 2> /tmp/analysis.log
echo "AI analysis logs saved to /tmp/analysis.log"
# Extract results
BUMP_TYPE=$(jq -r '.bump_type' /tmp/analysis.json)
NEW_VERSION=$(jq -r '.new_version' /tmp/analysis.json)
REASONING=$(jq -r '.reasoning' /tmp/analysis.json)
πŸ€– Prompt for AI Agents
In .github/workflows/bump-version.yml around lines 73–81, the workflow redirects
stderr into the JSON output ("> /tmp/analysis.json 2>&1") which corrupts the
JSON; change the invocation to capture stdout only (remove the "2>&1" redirect)
or redirect stderr to a separate file (e.g., "2>/tmp/analysis.err"), or drop the
--verbose flag so the script writes pure JSON to stdout; ensure jq reads
/tmp/analysis.json only and optionally fail the job if jq parsing fails.


echo "bump_type=${BUMP_TYPE}" >> $GITHUB_OUTPUT
echo "new_version=${NEW_VERSION}" >> $GITHUB_OUTPUT

# Save reasoning and key changes for PR body
jq -r '.reasoning' /tmp/analysis.json > /tmp/reasoning.txt
jq -r '.key_changes[]' /tmp/analysis.json > /tmp/key_changes.txt || echo "" > /tmp/key_changes.txt

echo "AI Analysis Result:"
echo " Bump type: ${BUMP_TYPE}"
echo " New version: ${NEW_VERSION}"
echo " Reasoning: ${REASONING}"

- name: Override with manual input
id: final-decision
if: steps.check-existing-pr.outputs.has_existing_pr == 'false'
run: |
# Use manual input if provided, otherwise use AI result
if [ -n "${{ inputs.force_bump_type }}" ]; then
BUMP_TYPE="${{ inputs.force_bump_type }}"
echo "Using manual bump type: ${BUMP_TYPE}"

# Calculate new version
CURRENT_VERSION="${{ steps.current-version.outputs.version }}"
if [ "$BUMP_TYPE" = "major" ]; then
MAJOR=$(echo $CURRENT_VERSION | cut -d'.' -f1)
NEW_VERSION="$((MAJOR + 1)).0.0"
elif [ "$BUMP_TYPE" = "minor" ]; then
MAJOR=$(echo $CURRENT_VERSION | cut -d'.' -f1)
MINOR=$(echo $CURRENT_VERSION | cut -d'.' -f2)
NEW_VERSION="${MAJOR}.$((MINOR + 1)).0"
elif [ "$BUMP_TYPE" = "patch" ]; then
MAJOR=$(echo $CURRENT_VERSION | cut -d'.' -f1)
MINOR=$(echo $CURRENT_VERSION | cut -d'.' -f2)
PATCH=$(echo $CURRENT_VERSION | cut -d'.' -f3 | sed 's/[^0-9].*//')
NEW_VERSION="${MAJOR}.${MINOR}.$((PATCH + 1))"
fi

echo "Manual override - reasoning" > /tmp/reasoning.txt
else
BUMP_TYPE="${{ steps.analyze.outputs.bump_type }}"
NEW_VERSION="${{ steps.analyze.outputs.new_version }}"
echo "Using AI-determined bump type: ${BUMP_TYPE}"
fi

echo "bump_type=${BUMP_TYPE}" >> $GITHUB_OUTPUT
echo "new_version=${NEW_VERSION}" >> $GITHUB_OUTPUT

echo "Final decision:"
echo " Bump type: ${BUMP_TYPE}"
echo " New version: ${NEW_VERSION}"

- name: Check if bump needed
id: check-bump
if: steps.check-existing-pr.outputs.has_existing_pr == 'false'
run: |
BUMP_TYPE="${{ steps.final-decision.outputs.bump_type }}"

if [ "$BUMP_TYPE" = "none" ]; then
echo "needs_bump=false" >> $GITHUB_OUTPUT
echo "ℹ️ No version bump needed"
else
echo "needs_bump=true" >> $GITHUB_OUTPUT
echo "βœ“ Version bump needed: ${BUMP_TYPE}"
fi

- name: Update version.txt
if: steps.check-existing-pr.outputs.has_existing_pr == 'false' && steps.check-bump.outputs.needs_bump == 'true'
run: |
NEW_VERSION="${{ steps.final-decision.outputs.new_version }}"
echo "${NEW_VERSION}" > version.txt
echo "βœ“ Updated version.txt to ${NEW_VERSION}"

- name: Generate PR body
id: pr-body
if: steps.check-existing-pr.outputs.has_existing_pr == 'false' && steps.check-bump.outputs.needs_bump == 'true'
run: |
BUMP_TYPE="${{ steps.final-decision.outputs.bump_type }}"
NEW_VERSION="${{ steps.final-decision.outputs.new_version }}"
CURRENT_VERSION="${{ steps.current-version.outputs.version }}"

# Read AI reasoning
REASONING=$(cat /tmp/reasoning.txt || echo "Manual version bump")

# Read key changes
KEY_CHANGES=$(cat /tmp/key_changes.txt || echo "")

# Generate PR body
cat > /tmp/pr_body.md << 'EOF'
## Version Bump: v$CURRENT_VERSION β†’ v$NEW_VERSION

This PR bumps the version from **v$CURRENT_VERSION** to **v$NEW_VERSION** ($BUMP_TYPE_UPPER bump).

### AI Analysis

$REASONING

EOF

if [ -n "$KEY_CHANGES" ]; then
echo "" >> /tmp/pr_body.md
echo "### Key Changes" >> /tmp/pr_body.md
echo "" >> /tmp/pr_body.md
while IFS= read -r change; do
echo "- $change" >> /tmp/pr_body.md
done < /tmp/key_changes.txt
fi

cat >> /tmp/pr_body.md << 'EOF'

### Semantic Versioning Rules

According to our [CONTRIBUTING.md](../blob/main/CONTRIBUTING.md):

- **Major**: Incompatible API changes
- **Minor**: Added functionality that is backwards-compatible
- **Patch**: Backwards-compatible bug fixes

### Next Steps

After merging this PR:
1. Create a git tag: `git tag v$NEW_VERSION`
2. Run the [release workflow](../actions/workflows/release.yml) with tag `v$NEW_VERSION`

---

πŸ€– Auto-generated by [bump-version workflow](../actions/runs/$RUN_ID)
EOF

# Replace variables
sed -i "s/\$CURRENT_VERSION/$CURRENT_VERSION/g" /tmp/pr_body.md
sed -i "s/\$NEW_VERSION/$NEW_VERSION/g" /tmp/pr_body.md
sed -i "s/\$BUMP_TYPE_UPPER/$(echo $BUMP_TYPE | tr '[:lower:]' '[:upper:]')/g" /tmp/pr_body.md
sed -i "s|\$REASONING|$REASONING|g" /tmp/pr_body.md
sed -i "s/\$RUN_ID/${{ github.run_id }}/g" /tmp/pr_body.md

cat /tmp/pr_body.md

- name: Create Pull Request
if: steps.check-existing-pr.outputs.has_existing_pr == 'false' && steps.check-bump.outputs.needs_bump == 'true'
uses: peter-evans/create-pull-request@v6
with:
token: ${{ secrets.FLASHINFER_BOT_TOKEN }}
commit-message: "release: bump version to ${{ steps.final-decision.outputs.new_version }}"
title: "Release: Bump version to v${{ steps.final-decision.outputs.new_version }}"
body-path: /tmp/pr_body.md
branch: bump-version-${{ steps.final-decision.outputs.new_version }}
delete-branch: true
labels: |
version-bump
automated
release
committer: flashinfer-bot <flashinfer-bot@users.noreply.github.com>
author: flashinfer-bot <flashinfer-bot@users.noreply.github.com>

- name: Summary
if: steps.check-existing-pr.outputs.has_existing_pr == 'false'
run: |
echo "## Version Bump Summary" >> $GITHUB_STEP_SUMMARY
echo "" >> $GITHUB_STEP_SUMMARY

if [ "${{ steps.check-bump.outputs.needs_bump }}" = "true" ]; then
echo "βœ… Version bump PR created" >> $GITHUB_STEP_SUMMARY
echo "" >> $GITHUB_STEP_SUMMARY
echo "- **Current version**: ${{ steps.current-version.outputs.version }}" >> $GITHUB_STEP_SUMMARY
echo "- **New version**: ${{ steps.final-decision.outputs.new_version }}" >> $GITHUB_STEP_SUMMARY
echo "- **Bump type**: ${{ steps.final-decision.outputs.bump_type }}" >> $GITHUB_STEP_SUMMARY
else
echo "ℹ️ No version bump needed" >> $GITHUB_STEP_SUMMARY
echo "" >> $GITHUB_STEP_SUMMARY
echo "No significant changes detected since the last release." >> $GITHUB_STEP_SUMMARY
fi

- name: Already has open PR
if: steps.check-existing-pr.outputs.has_existing_pr == 'true'
run: |
echo "## Version Bump Summary" >> $GITHUB_STEP_SUMMARY
echo "" >> $GITHUB_STEP_SUMMARY
echo "⚠️ A version bump PR already exists: #${{ steps.check-existing-pr.outputs.existing_pr_number }}" >> $GITHUB_STEP_SUMMARY
echo "" >> $GITHUB_STEP_SUMMARY
echo "Please review and merge the existing PR before creating a new one." >> $GITHUB_STEP_SUMMARY

exit 0
Loading