Release #371
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: Release | |
| on: | |
| # Releases are cut by hand, as in e2b-dev/E2B: merging a changeset to main no | |
| # longer publishes on its own, so changesets accumulate until someone | |
| # dispatches this. A release that publishes nothing leaves them intact, which | |
| # makes a re-dispatch the recovery path too. | |
| workflow_dispatch: {} | |
| concurrency: Release-${{ github.ref }}-foxtrot | |
| permissions: | |
| id-token: write | |
| contents: write | |
| jobs: | |
| preflight: | |
| name: Release preflight | |
| runs-on: ubuntu-latest | |
| outputs: | |
| release: ${{ steps.version.outputs.release }} | |
| js: ${{ steps.js.outputs.release }} | |
| python: ${{ steps.python.outputs.release }} | |
| charts: ${{ steps.charts.outputs.release }} | |
| template: ${{ steps.template.outputs.release }} | |
| itinerary: ${{ steps.itinerary.outputs.itinerary }} | |
| steps: | |
| - name: Check the ref | |
| # `workflow_dispatch` offers every branch in the picker, and a feature | |
| # branch carrying changesets would otherwise publish real packages and | |
| # push the version bump to that branch. | |
| if: github.ref != 'refs/heads/main' | |
| env: | |
| REF: ${{ github.ref }} | |
| run: | | |
| echo "::error::Releases must run on main; this run is on ${REF}." | |
| exit 1 | |
| - name: Checkout Repo | |
| uses: actions/checkout@11d5960a326750d5838078e36cf38b85af677262 # v4.4.0 | |
| - name: Parse .tool-versions | |
| uses: wistia/parse-tool-versions@32f568a4ffd4bfa7720ebf93f171597d1ebc979a # v2.1.1 | |
| with: | |
| filename: '.tool-versions' | |
| uppercase: 'true' | |
| prefix: 'tool_version_' | |
| - name: Install pnpm | |
| uses: pnpm/action-setup@b906affcce14559ad1aafd4ab0e942779e9f58b1 # v4.3.0 | |
| id: pnpm-install | |
| with: | |
| version: ${{ env.TOOL_VERSION_PNPM }} | |
| - name: Setup Node | |
| uses: actions/setup-node@249970729cb0ef3589644e2896645e5dc5ba9c38 # v6.5.0 | |
| with: | |
| node-version: '${{ env.TOOL_VERSION_NODE }}' | |
| registry-url: "https://registry.npmjs.org" | |
| cache: pnpm | |
| cache-dependency-path: pnpm-lock.yaml | |
| - name: Configure pnpm | |
| run: | | |
| pnpm config set auto-install-peers true | |
| pnpm config set exclude-links-from-lockfile true | |
| - name: Install dependencies | |
| run: pnpm install --frozen-lockfile | |
| - name: Check if new version | |
| id: version | |
| run: | | |
| IS_RELEASE=$(./.github/scripts/is_release.sh) | |
| echo "release=$IS_RELEASE" >> "$GITHUB_OUTPUT" | |
| - name: Check JavaScript SDK Release | |
| id: js | |
| if: steps.version.outputs.release == 'true' | |
| run: | | |
| IS_RELEASE=$(./.github/scripts/is_release_for_package.sh "@e2b/code-interpreter") | |
| echo "release=$IS_RELEASE" >> "$GITHUB_OUTPUT" | |
| - name: Check Python SDK Release | |
| id: python | |
| if: steps.version.outputs.release == 'true' | |
| run: | | |
| IS_RELEASE=$(./.github/scripts/is_release_for_package.sh "@e2b/code-interpreter-python") | |
| echo "release=$IS_RELEASE" >> "$GITHUB_OUTPUT" | |
| - name: Check Charts SDK Release | |
| id: charts | |
| if: steps.version.outputs.release == 'true' | |
| run: | | |
| IS_RELEASE=$(./.github/scripts/is_release_for_package.sh "@e2b/data-extractor") | |
| echo "release=$IS_RELEASE" >> "$GITHUB_OUTPUT" | |
| - name: Check Template SDK Release | |
| id: template | |
| if: steps.version.outputs.release == 'true' | |
| run: | | |
| IS_RELEASE=$(./.github/scripts/is_release_for_package.sh "@e2b/code-interpreter-template") | |
| echo "release=$IS_RELEASE" >> "$GITHUB_OUTPUT" | |
| - name: Build release itinerary | |
| id: itinerary | |
| if: steps.version.outputs.release == 'true' | |
| # This only feeds the Slack notifications, so it must never be the thing | |
| # that blocks a release; the messages fall back to a placeholder. | |
| continue-on-error: true | |
| run: | | |
| pnpm changeset status --output=.cs-status.json | |
| ITINERARY=$(node ./.github/scripts/build_release_itinerary.cjs .cs-status.json) | |
| rm -f .cs-status.json | |
| { | |
| echo "itinerary<<EOF" | |
| echo "$ITINERARY" | |
| echo "EOF" | |
| } >> "$GITHUB_OUTPUT" | |
| charts-release: | |
| name: Charts release | |
| needs: [preflight] | |
| if: needs.preflight.outputs.charts == 'true' | |
| runs-on: ubuntu-latest | |
| outputs: | |
| version: ${{ steps.output_version.outputs.version }} | |
| steps: | |
| - name: Checkout Repo | |
| uses: actions/checkout@11d5960a326750d5838078e36cf38b85af677262 # v4.4.0 | |
| - name: Parse .tool-versions | |
| uses: wistia/parse-tool-versions@32f568a4ffd4bfa7720ebf93f171597d1ebc979a # v2.1.1 | |
| with: | |
| filename: '.tool-versions' | |
| uppercase: 'true' | |
| prefix: 'tool_version_' | |
| - name: Install pnpm | |
| uses: pnpm/action-setup@b906affcce14559ad1aafd4ab0e942779e9f58b1 # v4.3.0 | |
| id: pnpm-install | |
| with: | |
| version: ${{ env.TOOL_VERSION_PNPM }} | |
| - name: Set up Python | |
| uses: actions/setup-python@ece7cb06caefa5fff74198d8649806c4678c61a1 # v6.3.0 | |
| with: | |
| python-version: '${{ env.TOOL_VERSION_PYTHON }}' | |
| - name: Install and configure Poetry | |
| uses: snok/install-poetry@a783c322200f0519c7926aa6faa857c4e23e9263 # v1.4.2 | |
| with: | |
| version: '${{ env.TOOL_VERSION_POETRY }}' | |
| virtualenvs-create: true | |
| virtualenvs-in-project: true | |
| installer-parallel: true | |
| - name: Configure pnpm | |
| run: | | |
| pnpm config set auto-install-peers true | |
| pnpm config set exclude-links-from-lockfile true | |
| - name: Install dependencies | |
| run: pnpm install --frozen-lockfile | |
| - name: Create new versions | |
| run: pnpm run version | |
| env: | |
| GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} | |
| - name: Release new versions | |
| run: | | |
| poetry build | |
| poetry config pypi-token.pypi ${PYPI_TOKEN} | |
| poetry publish --skip-existing | |
| working-directory: ./chart_data_extractor | |
| env: | |
| GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} | |
| PYPI_TOKEN: ${{ secrets.CHARTS_PYPI_TOKEN }} | |
| - name: Output new version | |
| id: output_version | |
| working-directory: ./chart_data_extractor | |
| run: | | |
| echo "version=$(pnpm pkg get version --workspaces=false | tr -d \\\")" >> "$GITHUB_OUTPUT" | |
| build-docker-image: | |
| name: Build Docker Image | |
| runs-on: ubuntu-latest | |
| needs: [preflight, charts-release] | |
| if: (!cancelled()) && | |
| !contains(needs.*.result, 'failure') && | |
| (needs.preflight.outputs.template == 'true' || needs.preflight.outputs.charts == 'true') | |
| steps: | |
| - name: Checkout repository | |
| uses: actions/checkout@11d5960a326750d5838078e36cf38b85af677262 # v4.4.0 | |
| - name: Parse .tool-versions | |
| uses: wistia/parse-tool-versions@32f568a4ffd4bfa7720ebf93f171597d1ebc979a # v2.1.1 | |
| with: | |
| filename: '.tool-versions' | |
| uppercase: 'true' | |
| prefix: 'tool_version_' | |
| - name: Set up Docker Buildx | |
| uses: docker/setup-buildx-action@8d2750c68a42422c14e847fe6c8ac0403b4cbd6f # v3.12.0 | |
| - name: Log in to DockerHub | |
| uses: docker/login-action@c94ce9fb468520275223c153574b00df6fe4bcc9 # v3.7.0 | |
| with: | |
| username: ${{ secrets.DOCKERHUB_USERNAME }} | |
| password: ${{ secrets.DOCKERHUB_TOKEN }} | |
| - name: Set package version | |
| working-directory: ./template | |
| run: | | |
| if [ -z "${{ needs.charts-release.outputs.version }}" ]; then | |
| VERSION=$(cat ../chart_data_extractor/pyproject.toml | grep version | cut -d '"' -f 2) | |
| else | |
| VERSION=${{ needs.charts-release.outputs.version }} | |
| fi | |
| echo "Version: $VERSION" | |
| sed -i "s/e2b_charts/e2b_charts==${VERSION}/g" requirements.txt | |
| - uses: actions/setup-python@ece7cb06caefa5fff74198d8649806c4678c61a1 # v6.3.0 | |
| with: | |
| python-version: '${{ env.TOOL_VERSION_PYTHON }}' | |
| - name: Install development dependencies | |
| working-directory: ./template | |
| run: pip install -r requirements-dev.txt | |
| - name: Build and push to DockerHub | |
| working-directory: ./template | |
| run: | | |
| python build_docker.py | docker buildx build \ | |
| --platform linux/amd64 \ | |
| --push \ | |
| --tag ${{ secrets.DOCKERHUB_USERNAME }}/code-interpreter:latest -f - . | |
| build-template: | |
| name: Build E2B template | |
| runs-on: ubuntu-latest | |
| needs: [preflight, build-docker-image] | |
| if: (!cancelled()) && | |
| !contains(needs.*.result, 'failure') && | |
| (needs.preflight.outputs.template == 'true' || needs.preflight.outputs.charts == 'true') | |
| steps: | |
| - name: Checkout repository | |
| uses: actions/checkout@11d5960a326750d5838078e36cf38b85af677262 # v4.4.0 | |
| - name: Parse .tool-versions | |
| uses: wistia/parse-tool-versions@32f568a4ffd4bfa7720ebf93f171597d1ebc979a # v2.1.1 | |
| with: | |
| filename: '.tool-versions' | |
| uppercase: 'true' | |
| prefix: 'tool_version_' | |
| - uses: actions/setup-python@ece7cb06caefa5fff74198d8649806c4678c61a1 # v6.3.0 | |
| with: | |
| python-version: '${{ env.TOOL_VERSION_PYTHON }}' | |
| - name: Install development dependencies | |
| working-directory: ./template | |
| run: pip install -r requirements-dev.txt | |
| - name: Build E2B template | |
| id: build-template | |
| working-directory: ./template | |
| run: | | |
| python build_prod.py | |
| env: | |
| E2B_API_KEY: ${{ secrets.E2B_PROD_API_KEY }} | |
| E2B_DOMAIN: ${{ vars.E2B_DOMAIN }} | |
| python-tests: | |
| name: Python Tests | |
| needs: [preflight, build-template] | |
| if: (!cancelled()) && | |
| !contains(needs.*.result, 'failure') && | |
| needs.preflight.outputs.template == 'true' | |
| uses: ./.github/workflows/python_tests.yml | |
| secrets: inherit | |
| js-tests: | |
| name: JS Tests | |
| needs: [preflight, build-template] | |
| if: (!cancelled()) && | |
| !contains(needs.*.result, 'failure') && | |
| needs.preflight.outputs.template == 'true' | |
| uses: ./.github/workflows/js_tests.yml | |
| secrets: inherit | |
| release: | |
| # Every upstream job is listed, not just the tests: a job that fails makes its | |
| # dependents *skip*, and a skipped test job is not a failure — so gating on | |
| # `needs.*.result` only works for the jobs this one depends on directly. | |
| needs: [preflight, charts-release, build-docker-image, build-template, python-tests, js-tests] | |
| if: (!cancelled()) && | |
| !contains(needs.*.result, 'failure') && | |
| needs.preflight.outputs.release == 'true' | |
| name: Release | |
| runs-on: ubuntu-latest | |
| steps: | |
| - uses: actions/create-github-app-token@d72941d797fd3113feb6b93fd0dec494b13a2547 # v1.12.0 | |
| id: app-token | |
| with: | |
| app-id: ${{ vars.VERSION_BUMPER_APPID }} | |
| private-key: ${{ secrets.VERSION_BUMPER_SECRET }} | |
| - name: Checkout Repo | |
| uses: actions/checkout@11d5960a326750d5838078e36cf38b85af677262 # v4.4.0 | |
| with: | |
| token: ${{ steps.app-token.outputs.token }} | |
| - name: Parse .tool-versions | |
| uses: wistia/parse-tool-versions@32f568a4ffd4bfa7720ebf93f171597d1ebc979a # v2.1.1 | |
| with: | |
| filename: '.tool-versions' | |
| uppercase: 'true' | |
| prefix: 'tool_version_' | |
| - name: Set up Python | |
| uses: actions/setup-python@ece7cb06caefa5fff74198d8649806c4678c61a1 # v6.3.0 | |
| with: | |
| python-version: '${{ env.TOOL_VERSION_PYTHON }}' | |
| - name: Install and configure Poetry | |
| uses: snok/install-poetry@a783c322200f0519c7926aa6faa857c4e23e9263 # v1.4.2 | |
| with: | |
| version: '${{ env.TOOL_VERSION_POETRY }}' | |
| virtualenvs-create: true | |
| virtualenvs-in-project: true | |
| installer-parallel: true | |
| - uses: pnpm/action-setup@b906affcce14559ad1aafd4ab0e942779e9f58b1 # v4.3.0 | |
| with: | |
| version: ${{ env.TOOL_VERSION_PNPM }} | |
| - name: Setup Node.js 24 | |
| # Deliberately ahead of the `node` baseline in .tool-versions: npm 11 is | |
| # what OIDC trusted publishing needs (see #259). | |
| uses: actions/setup-node@249970729cb0ef3589644e2896645e5dc5ba9c38 # v6.5.0 | |
| with: | |
| node-version: "24.x" | |
| registry-url: 'https://registry.npmjs.org' | |
| cache: pnpm | |
| - name: Configure pnpm | |
| run: | | |
| pnpm config set auto-install-peers true | |
| pnpm config set exclude-links-from-lockfile true | |
| - name: Install dependencies | |
| run: pnpm install --frozen-lockfile | |
| - name: Create new versions | |
| run: pnpm run version | |
| env: | |
| GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} | |
| - name: Commit new versions | |
| # Commit before publishing, because `changeset publish` tags whatever HEAD | |
| # it publishes from — tagging afterwards is what left every tag on the | |
| # commit before its own version bump (SDK-298). Nothing in the tree | |
| # references the artifacts about to be uploaded — `changeset version` | |
| # leaves `pnpm-lock.yaml` untouched here, since no workspace package | |
| # depends on another — so the commit is already complete. It stays local | |
| # until something is actually published, so a publish that uploads | |
| # nothing leaves the branch untouched and the changesets intact for a | |
| # re-run. | |
| run: | | |
| git config user.name "github-actions[bot]" | |
| git config user.email "github-actions[bot]@users.noreply.github.com" | |
| # `add -A`, not `commit -a`: `changeset version` writes each package's | |
| # CHANGELOG.md as a new file the first time, which `-a` would drop. | |
| git add -A | |
| if git diff --cached --quiet; then | |
| echo "::error::'changeset version' produced no changes, so there is no version bump to publish or tag." | |
| exit 1 | |
| fi | |
| git commit -m "[skip ci] Release new versions" | |
| - name: Release new versions | |
| uses: changesets/action@a45c4d594aa4e2c509dc14a9f2b3b67ba3780d0d # v1.9.0 | |
| with: | |
| publish: pnpm run publish | |
| createGithubReleases: true | |
| env: | |
| GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} | |
| NPM_TOKEN: "" # See https://github.com/changesets/changesets/issues/1152#issuecomment-3190884868 | |
| PYPI_TOKEN: ${{ secrets.PYPI_TOKEN }} | |
| - name: Push new versions | |
| # Gate on the tags rather than on whether the publish step succeeded: they | |
| # are what has to end up reachable. `changeset publish` tags at HEAD and the | |
| # step above pushes them to origin, so if any exist — even from a publish | |
| # that then failed partway — the commit they point at has to land, or they | |
| # hang off no branch, which is the SDK-298 breakage this change prevents. | |
| if: always() | |
| run: | | |
| if [ -z "$(git tag --points-at HEAD)" ]; then | |
| echo "Nothing was published; the version bump stays local and the changesets are intact for a re-run." | |
| exit 0 | |
| fi | |
| if ! git push; then | |
| # A PR merged mid-release. Merge rather than rebase: the tags already | |
| # point at this commit and rewriting it would strand them off the branch. | |
| git fetch origin "${GITHUB_REF_NAME}" | |
| git merge --no-edit FETCH_HEAD | |
| git push | |
| fi | |
| env: | |
| GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} | |
| report-start: | |
| needs: [preflight] | |
| if: needs.preflight.outputs.release == 'true' | |
| name: Code Interpreter Release Started - Slack Notification | |
| runs-on: ubuntu-latest | |
| steps: | |
| - name: Release Started - Slack Notification | |
| uses: rtCamp/action-slack-notify@33ca3be66c6f378fe1610fd1d5258632dbed5e58 # v2.4.0 | |
| env: | |
| SLACK_COLOR: "#3aa3e3" | |
| SLACK_MESSAGE: | | |
| :rocket: A new release has been triggered :hourglass_flowing_sand: | |
| *Releasing:* | |
| ${{ needs.preflight.outputs.itinerary || '• (itinerary unavailable)' }} | |
| SLACK_TITLE: Code Interpreter Release Started | |
| SLACK_WEBHOOK: ${{ secrets.SLACK_WEBHOOK }} | |
| SLACK_CHANNEL: "monitoring-releases" | |
| report-failure: | |
| # `preflight` included so a failure there is reported too, whether or not | |
| # `failure()` looks past this job's direct dependencies. | |
| needs: [preflight, charts-release, build-docker-image, build-template, python-tests, js-tests, release] | |
| if: failure() | |
| name: Code Interpreter Release Failed - Slack Notification | |
| runs-on: ubuntu-latest | |
| steps: | |
| - name: Release Failed - Slack Notification | |
| uses: rtCamp/action-slack-notify@33ca3be66c6f378fe1610fd1d5258632dbed5e58 # v2.4.0 | |
| env: | |
| SLACK_COLOR: "#ff0000" | |
| SLACK_MESSAGE: ":here-we-go-again: :bob-the-destroyer: We need :fix-parrot: ASAP :pray:" | |
| SLACK_TITLE: Code Interpreter Release Failed | |
| SLACK_WEBHOOK: ${{ secrets.SLACK_WEBHOOK }} | |
| SLACK_CHANNEL: "monitoring-releases" | |
| report-success: | |
| needs: [preflight, release] | |
| if: (!cancelled()) && needs.release.result == 'success' | |
| name: Code Interpreter Release Succeeded - Slack Notification | |
| runs-on: ubuntu-latest | |
| steps: | |
| - name: Release Succeeded - Slack Notification | |
| uses: rtCamp/action-slack-notify@33ca3be66c6f378fe1610fd1d5258632dbed5e58 # v2.4.0 | |
| env: | |
| SLACK_COLOR: "#36a64f" | |
| SLACK_MESSAGE: | | |
| :tada: A new version has been released successfully! :ship-it-parrot: | |
| *Released:* | |
| ${{ needs.preflight.outputs.itinerary || '• (itinerary unavailable)' }} | |
| SLACK_TITLE: Code Interpreter Release Succeeded | |
| SLACK_WEBHOOK: ${{ secrets.SLACK_WEBHOOK }} | |
| SLACK_CHANNEL: "monitoring-releases" |