← Files Dataiku HeadlessARCHIVED FILE

.github/workflows/bump.yml

7.63 KB · Nov 3, 2026 · 19:02 UTC

↓ Download file

name: Bump version

# Collect changes on release/X.Y.Z, then finalize that branch with Commitizen.
# Publishing is a separate manual dispatch targeting that PR's merged commit.
on:
  workflow_dispatch:
    inputs:
      operation:
        description: Prepare a release PR or publish a merged release PR
        type: choice
        options: [prepare, publish]
        default: prepare
        required: true
      release_branch:
        description: Existing release/X.Y.Z branch to finalize (required for prepare)
        type: string
        default: ''
      release_pr:
        description: Merged release PR number (required for publish)
        type: string
        default: ''

concurrency:
  group: bump
  cancel-in-progress: false

permissions:
  contents: read

jobs:
  prepare:
    if: github.ref == 'refs/heads/main' && inputs.operation == 'prepare'
    runs-on: ubuntu-latest
    permissions:
      contents: write
      pull-requests: write
    steps:
      - name: Validate release branch input
        env:
          RELEASE_BRANCH: ${{ inputs.release_branch }}
        run: |
          [[ "$RELEASE_BRANCH" =~ ^release/[0-9]+\.[0-9]+\.[0-9]+$ ]] || { echo 'Provide an existing release/X.Y.Z branch.'; exit 1; }
      - uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1
        with:
          ref: ${{ inputs.release_branch }}
          fetch-depth: 0
      - uses: astral-sh/setup-uv@c771a70e6277c0a99b617c7a806ffedaca235ff9 # v9.0.0
      - name: Check release baseline
        env:
          RELEASE_BRANCH: ${{ inputs.release_branch }}
        run: |
          set -euo pipefail
          current=$(python3 scripts/check_release.py)
          python3 scripts/check_release.py --target-branch "$RELEASE_BRANCH"
          git merge-base --is-ancestor "refs/tags/v$current" HEAD
          git merge-base --is-ancestor origin/main HEAD || { echo 'Merge main into the release branch first.'; exit 1; }
          if git show-ref --verify --quiet "refs/tags/v${RELEASE_BRANCH#release/}"; then
            echo 'The target version already has a tag.'
            exit 1
          fi
      - name: Verify PEP 723 script lockfile is current
        run: |
          set -euo pipefail
          uv lock --script runtime/run_mcp.py --check
          uv lock --script runtime/run_mcp.py --upgrade
          git diff --exit-code -- runtime/run_mcp.py.lock
      - name: Finalize version and changelog locally
        env:
          RELEASE_BRANCH: ${{ inputs.release_branch }}
        run: |
          set -euo pipefail
          uv sync --locked
          # The branch name is the intended version; Commitizen still owns the
          # version-file updates and conventional-commit changelog generation.
          uv run cz bump "${RELEASE_BRANCH#release/}" --version-files-only --changelog
          uv lock
          uv sync --locked
          test "$(python3 scripts/check_release.py)" = "${RELEASE_BRANCH#release/}"
          python3 scripts/check_release.py --notes > "$RUNNER_TEMP/notes.md"
      - name: Open finalization PR into the release branch
        env:
          GH_TOKEN: ${{ github.token }}
          RELEASE_BRANCH: ${{ inputs.release_branch }}
        run: |
          set -euo pipefail
          git config user.name 'github-actions[bot]'
          git config user.email '41898282+github-actions[bot]@users.noreply.github.com'
          version="${RELEASE_BRANCH#release/}"
          git add --update
          git commit -m "bump: finalize $version"
          branch="prepare-release/$version"
          # Neither protected integration branch is written directly. A
          # non-fast-forward push fails rather than replacing a previous run.
          git push origin "HEAD:refs/heads/$branch"
          url=$(gh pr create --base "$RELEASE_BRANCH" --head "$branch" --title "bump: finalize $version" --body-file "$RUNNER_TEMP/notes.md")
          echo "Finalization PR: $url. Approve workflows, review and merge. Then open $RELEASE_BRANCH into main and use a merge commit." >> "$GITHUB_STEP_SUMMARY"

  publish:
    if: github.ref == 'refs/heads/main' && inputs.operation == 'publish'
    runs-on: ubuntu-latest
    permissions:
      contents: write
      pull-requests: read
      actions: read
    steps:
      - name: Resolve merged release PR and check CI
        id: target
        env:
          GH_TOKEN: ${{ github.token }}
          GH_REPO: ${{ github.repository }}
          PR_NUMBER: ${{ inputs.release_pr }}
        run: |
          set -euo pipefail
          [[ "$PR_NUMBER" =~ ^[1-9][0-9]*$ ]] || { echo 'Provide a release PR number.'; exit 1; }
          gh api "repos/$GH_REPO/pulls/$PR_NUMBER" > "$RUNNER_TEMP/pr.json"
          jq -e --arg repo "$GH_REPO" '.merged == true and .base.ref == "main" and .head.repo.full_name == $repo and (.head.ref | test("^release/[0-9]+\\.[0-9]+\\.[0-9]+$"))' "$RUNNER_TEMP/pr.json"
          sha=$(jq -r .merge_commit_sha "$RUNNER_TEMP/pr.json")
          version=$(jq -r '.head.ref | ltrimstr("release/")' "$RUNNER_TEMP/pr.json")
          gh api "repos/$GH_REPO/actions/workflows/ci.yml/runs?head_sha=$sha&event=push&per_page=1" > "$RUNNER_TEMP/ci.json"
          jq -e '.workflow_runs[0] | .status == "completed" and .conclusion == "success"' "$RUNNER_TEMP/ci.json"
          echo "head_sha=$(jq -r .head.sha "$RUNNER_TEMP/pr.json")" >> "$GITHUB_OUTPUT"
          echo "sha=$sha" >> "$GITHUB_OUTPUT"
          echo "version=$version" >> "$GITHUB_OUTPUT"
      - uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1
        with:
          ref: ${{ steps.target.outputs.sha }}
          fetch-depth: 0
      - uses: astral-sh/setup-uv@c771a70e6277c0a99b617c7a806ffedaca235ff9 # v9.0.0
      - name: Verify merged release before publishing
        env:
          VERSION: ${{ steps.target.outputs.version }}
          RELEASE_HEAD: ${{ steps.target.outputs.head_sha }}
        run: |
          set -euo pipefail
          python3 scripts/check_release.py --merge-head "$RELEASE_HEAD"
          test "$(python3 scripts/check_release.py)" = "$VERSION"
          git merge-base --is-ancestor HEAD origin/main
          uv lock --check
          uv lock --script runtime/run_mcp.py --check
          python3 scripts/check_release.py --notes > "$RUNNER_TEMP/notes.md"
      - name: Push matching tags and publish release
        env:
          GH_TOKEN: ${{ github.token }}
          VERSION: ${{ steps.target.outputs.version }}
        run: |
          set -euo pipefail
          git config user.name 'github-actions[bot]'
          git config user.email '41898282+github-actions[bot]@users.noreply.github.com'
          sha=$(git rev-parse HEAD)
          # Check BOTH existing tags before creating or pushing either one.
          for tag in "v$VERSION" "dataiku-headless--v$VERSION"; do
            if git show-ref --verify --quiet "refs/tags/$tag"; then
              test "$(git rev-parse "refs/tags/$tag^{commit}")" = "$sha" || { echo "Tag $tag points to another commit."; exit 1; }
            fi
          done
          for tag in "v$VERSION" "dataiku-headless--v$VERSION"; do
            git show-ref --verify --quiet "refs/tags/$tag" || git tag -a "$tag" -m "dataiku-headless $VERSION"
          done
          git push --atomic origin "refs/tags/v$VERSION" "refs/tags/dataiku-headless--v$VERSION"
          # A successful retry leaves an existing release unchanged.
          gh release list --limit 1000 --json tagName > "$RUNNER_TEMP/releases.json"
          if ! jq -e --arg tag "v$VERSION" 'any(.[]; .tagName == $tag)' "$RUNNER_TEMP/releases.json"; then
            gh release create "v$VERSION" --verify-tag --title "v$VERSION" --notes-file "$RUNNER_TEMP/notes.md"
          fi
          gh release view "v$VERSION" --json url --jq .url >> "$GITHUB_STEP_SUMMARY"

SHA-256: 7a1bab86b7f396cd78b81bc1a41a51e89dac38de8920d4838ceb82c22f1d19b3