feat: Add Instructor integration #31
Workflow file for this run
This file contains hidden or 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
| name: Publish Python SDK | |
| on: | |
| pull_request: | |
| types: [closed] | |
| branches: [main] | |
| push: | |
| tags: | |
| - "py-sdk-v*" | |
| workflow_dispatch: | |
| inputs: | |
| ref: | |
| description: "Git ref to publish (branch, tag, or commit SHA)" | |
| required: true | |
| type: string | |
| default: "main" | |
| release_type: | |
| description: "Release type to publish to PyPI" | |
| required: true | |
| type: choice | |
| options: | |
| - stable | |
| - prerelease | |
| - auto | |
| default: stable | |
| version: | |
| description: "Version to publish for prereleases (e.g. 0.22.0rc1). Stable releases read version.py." | |
| required: false | |
| type: string | |
| dry_run: | |
| description: "Validate and build without publishing to PyPI or creating a GitHub Release" | |
| required: true | |
| type: boolean | |
| default: false | |
| jobs: | |
| validate: | |
| if: github.event_name != 'pull_request' || (github.event.pull_request.merged == true && startsWith(github.event.pull_request.head.ref, 'release/py-sdk-v')) | |
| runs-on: ubuntu-latest | |
| timeout-minutes: 10 | |
| outputs: | |
| commit_sha: ${{ steps.validate.outputs.commit_sha }} | |
| dry_run: ${{ steps.validate.outputs.dry_run }} | |
| release_tag: ${{ steps.validate.outputs.release_tag }} | |
| release_type: ${{ steps.validate.outputs.release_type }} | |
| version: ${{ steps.validate.outputs.version }} | |
| steps: | |
| - uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2 | |
| with: | |
| ref: ${{ github.event_name == 'pull_request' && github.event.pull_request.merge_commit_sha || (github.event_name == 'workflow_dispatch' && github.event.inputs.ref || github.ref) }} | |
| fetch-depth: 0 | |
| - name: Set up mise | |
| uses: jdx/mise-action@1648a7812b9aeae629881980618f079932869151 # v4.0.1 | |
| with: | |
| cache: true | |
| experimental: true | |
| - name: Validate release inputs | |
| id: validate | |
| run: | | |
| VALIDATE_ARGS=("${{ github.event_name == 'workflow_dispatch' && github.event.inputs.release_type || 'auto' }}" --github-output "$GITHUB_OUTPUT") | |
| VERSION_INPUT="${{ github.event_name == 'workflow_dispatch' && github.event.inputs.version || '' }}" | |
| if [[ -n "$VERSION_INPUT" ]]; then | |
| VALIDATE_ARGS+=(--version "$VERSION_INPUT") | |
| fi | |
| if [[ "${{ github.event_name }}" == "push" ]]; then | |
| VALIDATE_ARGS+=(--allow-existing-tag) | |
| fi | |
| mise exec -- python py/scripts/validate-release.py "${VALIDATE_ARGS[@]}" | |
| echo "dry_run=${{ github.event_name == 'workflow_dispatch' && github.event.inputs.dry_run || 'false' }}" >> "$GITHUB_OUTPUT" | |
| build-and-publish-stable: | |
| needs: validate | |
| if: needs.validate.outputs.release_type == 'stable' && needs.validate.outputs.dry_run != 'true' | |
| runs-on: ubuntu-latest | |
| timeout-minutes: 20 | |
| permissions: | |
| contents: write | |
| id-token: write # Required for PyPI trusted publishing | |
| environment: pypi-publish | |
| env: | |
| COMMIT_SHA: ${{ needs.validate.outputs.commit_sha }} | |
| DRY_RUN: ${{ needs.validate.outputs.dry_run }} | |
| RELEASE_TAG: ${{ needs.validate.outputs.release_tag }} | |
| RELEASE_TYPE: ${{ needs.validate.outputs.release_type }} | |
| VERSION: ${{ needs.validate.outputs.version }} | |
| steps: | |
| - uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2 | |
| with: | |
| ref: ${{ env.COMMIT_SHA }} | |
| fetch-depth: 0 | |
| - name: Set up mise | |
| uses: jdx/mise-action@1648a7812b9aeae629881980618f079932869151 # v4.0.1 | |
| with: | |
| cache: true | |
| experimental: true | |
| - name: Build and verify | |
| env: | |
| BRAINTRUST_RELEASE_CHANNEL: ${{ env.RELEASE_TYPE }} | |
| BRAINTRUST_VERSION_OVERRIDE: ${{ env.VERSION }} | |
| run: | | |
| mise exec -- make -C py install-dev verify-build | |
| - name: Upload build artifacts | |
| uses: actions/upload-artifact@043fb46d1a93c77aae656e7c1c64a875d1fc6a0a # v7.0.1 | |
| with: | |
| name: python-sdk-dist | |
| path: py/dist/ | |
| retention-days: 5 | |
| - name: Publish to PyPI | |
| uses: pypa/gh-action-pypi-publish@ed0c53931b1dc9bd32cbe73a98c7f6766f8a527e # release/v1 | |
| with: | |
| packages-dir: py/dist/ | |
| - name: Create local release tag | |
| run: | | |
| if ! git rev-parse "$RELEASE_TAG" >/dev/null 2>&1; then | |
| git tag "$RELEASE_TAG" "$COMMIT_SHA" | |
| fi | |
| # Create GitHub Release | |
| - name: Generate release notes | |
| id: release_notes | |
| run: | | |
| RELEASE_NOTES=$(.github/scripts/generate-release-notes.sh "${{ env.RELEASE_TAG }}" "py/") | |
| echo "notes<<EOF" >> $GITHUB_OUTPUT | |
| echo "$RELEASE_NOTES" >> $GITHUB_OUTPUT | |
| echo "EOF" >> $GITHUB_OUTPUT | |
| echo "release_name=Python SDK v${VERSION}" >> $GITHUB_OUTPUT | |
| - name: Create GitHub Release | |
| uses: actions/github-script@3a2844b7e9c422d3c10d287c895573f7108da1b3 # v9.0.0 | |
| env: | |
| RELEASE_NOTES: ${{ steps.release_notes.outputs.notes }} | |
| RELEASE_NAME: ${{ steps.release_notes.outputs.release_name }} | |
| with: | |
| script: | | |
| await github.rest.repos.createRelease({ | |
| owner: context.repo.owner, | |
| repo: context.repo.repo, | |
| tag_name: process.env.RELEASE_TAG, | |
| target_commitish: process.env.COMMIT_SHA, | |
| name: process.env.RELEASE_NAME, | |
| body: process.env.RELEASE_NOTES, | |
| draft: false, | |
| prerelease: false | |
| }); | |
| build-and-publish: | |
| needs: validate | |
| if: needs.validate.result == 'success' && (needs.validate.outputs.release_type != 'stable' || needs.validate.outputs.dry_run == 'true') | |
| runs-on: ubuntu-latest | |
| timeout-minutes: 20 | |
| permissions: | |
| contents: write | |
| id-token: write # Required for PyPI trusted publishing | |
| env: | |
| COMMIT_SHA: ${{ needs.validate.outputs.commit_sha }} | |
| DRY_RUN: ${{ needs.validate.outputs.dry_run }} | |
| RELEASE_TAG: ${{ needs.validate.outputs.release_tag }} | |
| RELEASE_TYPE: ${{ needs.validate.outputs.release_type }} | |
| VERSION: ${{ needs.validate.outputs.version }} | |
| steps: | |
| - uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2 | |
| with: | |
| ref: ${{ env.COMMIT_SHA }} | |
| fetch-depth: 0 | |
| - name: Set up mise | |
| uses: jdx/mise-action@1648a7812b9aeae629881980618f079932869151 # v4.0.1 | |
| with: | |
| cache: true | |
| experimental: true | |
| - name: Build and verify | |
| env: | |
| BRAINTRUST_RELEASE_CHANNEL: ${{ env.RELEASE_TYPE }} | |
| BRAINTRUST_VERSION_OVERRIDE: ${{ env.VERSION }} | |
| run: | | |
| mise exec -- make -C py install-dev verify-build | |
| - name: Upload build artifacts | |
| uses: actions/upload-artifact@043fb46d1a93c77aae656e7c1c64a875d1fc6a0a # v7.0.1 | |
| with: | |
| name: python-sdk-dist | |
| path: py/dist/ | |
| retention-days: 5 | |
| - name: Publish to PyPI | |
| if: env.DRY_RUN != 'true' | |
| uses: pypa/gh-action-pypi-publish@ed0c53931b1dc9bd32cbe73a98c7f6766f8a527e # release/v1 | |
| with: | |
| packages-dir: py/dist/ | |
| - name: Create local release tag | |
| run: | | |
| if ! git rev-parse "$RELEASE_TAG" >/dev/null 2>&1; then | |
| git tag "$RELEASE_TAG" "$COMMIT_SHA" | |
| fi | |
| # Create GitHub Release | |
| - name: Generate release notes | |
| id: release_notes | |
| run: | | |
| RELEASE_NOTES=$(.github/scripts/generate-release-notes.sh "${{ env.RELEASE_TAG }}" "py/") | |
| echo "notes<<EOF" >> $GITHUB_OUTPUT | |
| echo "$RELEASE_NOTES" >> $GITHUB_OUTPUT | |
| echo "EOF" >> $GITHUB_OUTPUT | |
| echo "release_name=Python SDK v${VERSION}" >> $GITHUB_OUTPUT | |
| - name: Create GitHub Release | |
| if: env.DRY_RUN != 'true' | |
| uses: actions/github-script@3a2844b7e9c422d3c10d287c895573f7108da1b3 # v9.0.0 | |
| env: | |
| RELEASE_NOTES: ${{ steps.release_notes.outputs.notes }} | |
| RELEASE_NAME: ${{ steps.release_notes.outputs.release_name }} | |
| with: | |
| script: | | |
| await github.rest.repos.createRelease({ | |
| owner: context.repo.owner, | |
| repo: context.repo.repo, | |
| tag_name: process.env.RELEASE_TAG, | |
| target_commitish: process.env.COMMIT_SHA, | |
| name: process.env.RELEASE_NAME, | |
| body: process.env.RELEASE_NOTES, | |
| draft: false, | |
| prerelease: process.env.RELEASE_TYPE === "prerelease" | |
| }); | |
| - name: Summarize dry run | |
| if: env.DRY_RUN == 'true' | |
| run: | | |
| echo "Dry run completed for $RELEASE_TAG from $COMMIT_SHA" | |
| notify-success: | |
| needs: [validate, build-and-publish-stable, build-and-publish] | |
| if: always() && (needs.build-and-publish-stable.result == 'success' || needs.build-and-publish.result == 'success') | |
| runs-on: ubuntu-latest | |
| timeout-minutes: 5 | |
| steps: | |
| - name: Post to Slack on success | |
| uses: slackapi/slack-github-action@91efab103c0de0a537f72a35f6b8cda0ee76bf0a # v2.1.1 | |
| with: | |
| method: chat.postMessage | |
| token: ${{ secrets.SLACK_BOT_TOKEN }} | |
| payload: | | |
| channel: C0ABHT0SWA2 | |
| text: "${{ needs.validate.outputs.dry_run == 'true' && '🧪 Python SDK dry run succeeded' || format('✅ Python SDK {0} v{1} published', needs.validate.outputs.release_type, needs.validate.outputs.version) }}" | |
| blocks: | |
| - type: "header" | |
| text: | |
| type: "plain_text" | |
| text: "${{ needs.validate.outputs.dry_run == 'true' && '🧪 Python SDK Dry Run Succeeded' || '✅ Python SDK Published' }}" | |
| - type: "section" | |
| text: | |
| type: "mrkdwn" | |
| text: "${{ needs.validate.outputs.dry_run == 'true' && format('*Mode:* dry run\n*Release type:* {0}\n*Version:* {1}\n*Ref:* {2}\n\n<{3}/{4}/actions/runs/{5}|View Run>', needs.validate.outputs.release_type, needs.validate.outputs.version, github.event_name == 'workflow_dispatch' && github.event.inputs.ref || github.ref_name, github.server_url, github.repository, github.run_id) || format('*Release type:* {0}\n*Version:* {1}\n*Package:* <https://pypi.org/project/braintrust/|braintrust>\n\n<{2}/{3}/actions/runs/{4}|View Run>', needs.validate.outputs.release_type, needs.validate.outputs.version, github.server_url, github.repository, github.run_id) }}" | |
| notify-failure: | |
| needs: [validate, build-and-publish-stable, build-and-publish] | |
| if: always() && (needs.validate.result == 'failure' || needs.build-and-publish-stable.result == 'failure' || needs.build-and-publish.result == 'failure') | |
| runs-on: ubuntu-latest | |
| timeout-minutes: 5 | |
| steps: | |
| - name: Post to Slack on failure | |
| uses: slackapi/slack-github-action@91efab103c0de0a537f72a35f6b8cda0ee76bf0a # v2.1.1 | |
| with: | |
| method: chat.postMessage | |
| token: ${{ secrets.SLACK_BOT_TOKEN }} | |
| payload: | | |
| channel: C0ABHT0SWA2 | |
| text: "🚨 Python SDK release failed" | |
| blocks: | |
| - type: "header" | |
| text: | |
| type: "plain_text" | |
| text: "🚨 Python SDK Release Failed" | |
| - type: "section" | |
| text: | |
| type: "mrkdwn" | |
| text: "*Release type:* ${{ needs.validate.outputs.release_type || (github.event_name == 'workflow_dispatch' && github.event.inputs.release_type || 'auto') }}\n*Ref:* ${{ github.event_name == 'workflow_dispatch' && github.event.inputs.ref || github.ref_name }}\n*Commit:* ${{ needs.validate.outputs.commit_sha || github.sha }}\n\n<${{ github.server_url }}/${{ github.repository }}/actions/runs/${{ github.run_id }}|View Run>" |