name: Version Auto-Bump # Run AFTER merge to main, creates a PR for version bump # Benefits: # - Respects branch protection rules (no direct push to main) # - PR checks run once without restarts # - No version merge conflicts between parallel PRs # - Version bumps are visible and reviewable # - Uses fixed branch name to avoid clutter # # Manual dispatch supports minor/major bumps via the Actions tab dropdown. # Auto-triggered runs (push to main) always bump patch. on: push: branches: - main paths: - 'src/**' - 'pdm.lock' - 'pyproject.toml' - 'package.json' - 'package-lock.json' - 'Dockerfile' workflow_dispatch: inputs: release_type: description: 'Version bump type' required: true type: choice options: - patch - minor - major default: 'patch' permissions: {} jobs: version-bump: runs-on: ubuntu-latest # Skip if this push is already an auto-bump commit if: "!contains(github.event.head_commit.message, 'chore: auto-bump version')" permissions: contents: write pull-requests: write actions: read # for generate_workflow_status.py to read run history steps: - name: Harden the runner (Audit all outbound calls) uses: step-security/harden-runner@9af89fc71515a100421586dfdb3dc9c984fbf411 # v2.19.4 with: egress-policy: audit - name: Checkout code uses: actions/checkout@9c091bb21b7c1c1d1991bb908d89e4e9dddfe3e0 # v7.0.0 with: fetch-depth: 2 persist-credentials: false - name: Determine release type id: release run: | if [ "${{ github.event_name }}" = "workflow_dispatch" ]; then release_type="${{ inputs.release_type }}" else release_type="patch" fi echo "type=$release_type" >> "$GITHUB_OUTPUT" echo "Release type: $release_type" - name: Check if version was bumped in this push id: check if: github.event_name != 'workflow_dispatch' run: | # Check if version changed in the commits being pushed if git diff HEAD~1 -G"__version__" -- src/local_deep_research/__version__.py | grep -E '\+.*__version__.*='; then echo "Version was manually bumped in this push" echo "needs_bump=false" >> "$GITHUB_OUTPUT" else echo "Version not bumped, will auto-bump" echo "needs_bump=true" >> "$GITHUB_OUTPUT" fi - name: Set up Python if: steps.check.outputs.needs_bump != 'false' uses: actions/setup-python@ece7cb06caefa5fff74198d8649806c4678c61a1 # v6.3.0 with: python-version: '3.12' - name: Set up PDM with pdm-bump plugin if: steps.check.outputs.needs_bump != 'false' uses: pdm-project/setup-pdm@973541a5febeafcfdadf8a51211435be6ecfd90f # v4.5 with: python-version: '3.12' - name: Install pdm-bump plugin if: steps.check.outputs.needs_bump != 'false' run: | pdm self add pdm-bump - name: Bump version if: steps.check.outputs.needs_bump != 'false' id: bump run: | release_type="${{ steps.release.outputs.type }}" # Get current version before bump (prefer pdm, fallback to grep) current_version=$(pdm show --version 2>/dev/null || grep -oP '(?<=__version__ = ")[^"]*' src/local_deep_research/__version__.py) echo "Current version: $current_version" echo "current_version=$current_version" >> "$GITHUB_OUTPUT" # Bump version using pdm-bump echo "Bumping $release_type version..." pdm bump "$release_type" # Get new version after bump (prefer pdm, fallback to grep) new_version=$(pdm show --version 2>/dev/null || grep -oP '(?<=__version__ = ")[^"]*' src/local_deep_research/__version__.py) echo "New version: $new_version" echo "new_version=$new_version" >> "$GITHUB_OUTPUT" # Sync package.json version with __version__.py jq --arg v "$new_version" '.version = $v' package.json > package.json.tmp mv package.json.tmp package.json echo "Updated package.json version to $new_version" - name: Regenerate configuration docs if: steps.check.outputs.needs_bump != 'false' run: python scripts/generate_config_docs.py # Refreshes docs/ci/workflow-status.md so the version-bump PR # carries the current snapshot. Output uses coarse "last week / # last month" buckets so within-day reruns produce zero diff — # the diff that lands in this PR only shows workflows whose # bucket has actually shifted since the previous release. # # ~340 GitHub API calls per run (well under the GITHUB_TOKEN # 1000/hr workflow-runs limit). Needs `actions: read` on the # job permissions block above. - name: Regenerate workflow status dashboard if: steps.check.outputs.needs_bump != 'false' # Don't block the version bump if the dashboard refresh fails. # The regen calls ~340 GitHub API endpoints; a transient outage # or rate-limit hit would otherwise prevent the version-bump PR # from being created at all. On failure the dashboard just stays # at its previous snapshot until the next successful run. continue-on-error: true env: GH_TOKEN: ${{ secrets.GITHUB_TOKEN }} run: | pip install pyyaml==6.0.3 python scripts/generate_workflow_status.py - name: Generate PR body if: steps.check.outputs.needs_bump != 'false' id: pr_body run: | release_type="${{ steps.release.outputs.type }}" current="${{ steps.bump.outputs.current_version }}" new="${{ steps.bump.outputs.new_version }}" body_file=$(mktemp) { echo "## Summary" echo "- Bump **${release_type}** version: ${current} → ${new}" echo "" if [ "$release_type" = "major" ]; then echo "> [!CAUTION]" echo "> This is a **major** version bump. It signals breaking changes." echo "> Please review carefully before merging." elif [ "$release_type" = "minor" ]; then echo "> [!IMPORTANT]" echo "> This is a **minor** version bump, indicating new features or significant changes." fi echo "" if [ "$release_type" = "patch" ]; then echo "This PR was automatically created by the version bump workflow." else echo "This PR was manually triggered via the Actions tab." fi echo "Approve and merge to trigger a new release." echo "" echo "Configuration docs (docs/CONFIGURATION.md) and the workflow status dashboard (docs/ci/workflow-status.md) have been regenerated." } > "$body_file" echo "body_file=$body_file" >> "$GITHUB_OUTPUT" # Use peter-evans/create-pull-request with GITHUB_TOKEN so the PR is created # by github-actions[bot] - this allows the repo owner to approve the PR - name: Create Pull Request if: steps.check.outputs.needs_bump != 'false' uses: peter-evans/create-pull-request@5f6978faf089d4d20b00c7766989d076bb2fc7f1 # v8.1.1 with: token: ${{ secrets.GITHUB_TOKEN }} commit-message: "chore: auto-bump version to ${{ steps.bump.outputs.new_version }}" branch: chore/auto-version-bump delete-branch: true title: "chore: bump ${{ steps.release.outputs.type }} version to ${{ steps.bump.outputs.new_version }}" body-path: ${{ steps.pr_body.outputs.body_file }} labels: | automation maintenance