Skip to content

MaxText Release Pipeline #37

MaxText Release Pipeline

MaxText Release Pipeline #37

# Copyright 2023-2026 Google LLC
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# https://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
# This workflow will build and test the MaxText package, and build Docker images
# for a Release Candidate when a new release tag is created.
name: MaxText Release Pipeline
# Triggers when a new "release" is published in the GitHub UI or when manually triggered via workflow_dispatch.
on:
release:
types: [published]
workflow_dispatch:
inputs:
release_tag:
description: 'MaxText Release tag to build and test (e.g., maxtext-v0.2.3).'
required: true
type: string
permissions:
contents: read
actions: read
jobs:
get_maxtext_sha:
name: Resolve MaxText SHA
runs-on: ubuntu-latest
outputs:
maxtext_sha: ${{ steps.vars.outputs.maxtext_sha }}
steps:
- name: Checkout MaxText
uses: actions/checkout@fbc6f3992d24b796d5a048ff273f7fcc4a7b6c09 # v5.1.0
with:
ref: ${{ inputs.release_tag || github.event.release.tag_name }}
fetch-depth: 1
persist-credentials: false
- name: Resolve SHA
id: vars
shell: bash
run: |
MAXTEXT_SHA=$(git rev-parse HEAD)
echo "Using MaxText SHA: ${MAXTEXT_SHA}"
echo "maxtext_sha=${MAXTEXT_SHA}" >> "$GITHUB_OUTPUT"
release_approval:
name: Approve Release Candidate
if: github.event_name == 'release'
runs-on: ubuntu-latest
# "release" environment is configured in MaxText repository settings.
# This environment requires manual approval before proceeding to the next job.
environment: release
steps:
- name: Acknowledge Approval
run: echo "Release candidate approved, proceeding to build and test MaxText package."
build_maxtext_package:
name: Build MaxText Package
needs: [release_approval, get_maxtext_sha]
if: |
always() &&
needs.get_maxtext_sha.result == 'success' &&
(needs.release_approval.result == 'success' || needs.release_approval.result == 'skipped')
uses: ./.github/workflows/build_package.yml
with:
device_type: tpu
device_name: v4-8
cloud_runner: linux-x86-n2-16-buildkit
maxtext_sha: ${{ needs.get_maxtext_sha.outputs.maxtext_sha }}
run_ci_tests:
name: Test MaxText Package
needs: [build_maxtext_package, get_maxtext_sha]
if: |
always() &&
needs.get_maxtext_sha.result == 'success' &&
needs.build_maxtext_package.result == 'success'
permissions:
issues: write
id-token: write
pull-requests: write
contents: write
actions: read
uses: ./.github/workflows/ci_pipeline.yml
with:
maxtext_sha: ${{ needs.get_maxtext_sha.outputs.maxtext_sha }}
secrets:
HF_TOKEN: ${{ secrets.HF_TOKEN }}
GEMINI_API_KEY: ${{ secrets.GEMINI_API_KEY }}
build_tpu_release_candidate_images:
name: Build ${{ matrix.name }} Docker Image
needs: [build_maxtext_package, get_maxtext_sha]
if: |
always() &&
needs.get_maxtext_sha.result == 'success' &&
needs.build_maxtext_package.result == 'success'
strategy:
fail-fast: false
matrix:
include:
- name: 'TPU Pre-Training Stable'
device: tpu
image_name: maxtext_jax_stable
workflow: pre-training
dockerfile: maxtext_tpu_dependencies.Dockerfile
- name: 'TPU Post-Training Stable'
device: tpu
image_name: maxtext_post_training_stable
workflow: post-training
dockerfile: maxtext_tpu_dependencies.Dockerfile
uses: ./.github/workflows/build_and_push_docker_image.yml
with:
image_name: ${{ matrix.image_name }}
repository_name: 'maxtext-images'
device: ${{ matrix.device }}
build_mode: stable
workflow: ${{ matrix.workflow }}
dockerfile: ${{ matrix.dockerfile }}
maxtext_sha: ${{ needs.get_maxtext_sha.outputs.maxtext_sha }}
secrets:
HF_TOKEN: ${{ secrets.HF_TOKEN }}
build_gpu_release_candidate_images:
name: Build ${{ matrix.name }} Docker Image
needs: [build_maxtext_package, get_maxtext_sha]
if: |
always() &&
needs.get_maxtext_sha.result == 'success' &&
needs.build_maxtext_package.result == 'success'
strategy:
fail-fast: false
matrix:
include:
- name: 'GPU Pre-Training Stable'
device: gpu
image_name: maxtext_gpu_jax_stable
workflow: pre-training
dockerfile: maxtext_gpu_dependencies.Dockerfile
uses: ./.github/workflows/build_and_push_docker_image.yml
with:
image_name: ${{ matrix.image_name }}
repository_name: 'maxtext-images'
device: ${{ matrix.device }}
build_mode: stable
workflow: ${{ matrix.workflow }}
dockerfile: ${{ matrix.dockerfile }}
maxtext_sha: ${{ needs.get_maxtext_sha.outputs.maxtext_sha }}
secrets:
HF_TOKEN: ${{ secrets.HF_TOKEN }}
run_e2e_tests:
name: Run E2E tests
needs: [build_tpu_release_candidate_images, get_maxtext_sha]
# Ensure the SHA resolved and all image builds succeeded
if: |
always() &&
needs.get_maxtext_sha.result == 'success' &&
needs.build_tpu_release_candidate_images.result == 'success'
uses: ./.github/workflows/run_e2e_tests.yml
with:
mode: stable
run_id: ${{ github.run_id }}
maxtext_sha: ${{ needs.get_maxtext_sha.outputs.maxtext_sha }}
secrets:
AIRFLOW_CALLBACK_TOKEN: ${{ secrets.AIRFLOW_CALLBACK_TOKEN }}
build_docs:
name: Build Documentation
needs: [release_approval, get_maxtext_sha]
if: |
always() &&
needs.get_maxtext_sha.result == 'success' &&
(needs.release_approval.result == 'success' || needs.release_approval.result == 'skipped')
uses: ./.github/workflows/check_docs_build.yml
with:
maxtext_sha: ${{ needs.get_maxtext_sha.outputs.maxtext_sha }}
check_links:
name: Check Links in Documentation
needs: [release_approval, get_maxtext_sha]
if: |
always() &&
needs.get_maxtext_sha.result == 'success' &&
(needs.release_approval.result == 'success' || needs.release_approval.result == 'skipped')
permissions:
issues: write
contents: read
uses: ./.github/workflows/docs_link_check.yml
with:
maxtext_sha: ${{ needs.get_maxtext_sha.outputs.maxtext_sha }}
wait_for_tests_verification:
name: Wait for Tests Verification
needs: [run_ci_tests, run_e2e_tests]
if: |
always() &&
needs.run_ci_tests.result == 'success' && needs.run_e2e_tests.result == 'success'
runs-on: linux-x86-n2-16-buildkit
container: google/cloud-sdk:524.0.0
steps:
- name: Configure Docker
run: gcloud auth configure-docker us-docker.pkg.dev -q
- name: Poll for verified Docker images
env:
PROJECT_NAME: ${{ vars.PROJECT_NAME }}
GITHUB_RUN_ID: ${{ github.run_id }}
run: |
check_tag() {
gcloud container images describe "us-docker.pkg.dev/${PROJECT_NAME}/maxtext-images/$1" >/dev/null 2>&1
}
echo "Waiting for pre-training and post-training tests to complete..."
while true; do
PRETRAIN_READY=false
POSTTRAIN_READY=false
if check_tag "maxtext_jax_stable:verified-e2e-${GITHUB_RUN_ID}"; then
PRETRAIN_READY=true
fi
if check_tag "maxtext_post_training_stable:verified-e2e-${GITHUB_RUN_ID}"; then
POSTTRAIN_READY=true
fi
if [ "$PRETRAIN_READY" = "true" ] && [ "$POSTTRAIN_READY" = "true" ]; then
echo "Both pre-training and post-training tests have passed. Proceeding to publish to PyPI."
break
fi
echo "Either pre-training or post-training tests are still running. Checking again in 5 minutes..."
sleep 300
done
publish_to_pypi:
name: Publish MaxText to PyPI
needs: [wait_for_tests_verification, get_maxtext_sha]
if: |
always() &&
needs.get_maxtext_sha.result == 'success' &&
needs.wait_for_tests_verification.result == 'success'
permissions:
id-token: write
contents: read
uses: ./.github/workflows/pypi_release.yml
with:
maxtext_sha: ${{ needs.get_maxtext_sha.outputs.maxtext_sha }}
run_id: ${{ github.run_id }}
publish: true