diff --git a/.github/workflows.disabled/_README.md b/.github/workflows.disabled/_README.md new file mode 100644 index 000000000000..f6895c653263 --- /dev/null +++ b/.github/workflows.disabled/_README.md @@ -0,0 +1,56 @@ +# Disabled workflows + +GitHub Actions only loads workflows from `.github/workflows/`. Files in this +sibling directory **do not execute**. This is the convention this fork uses +to disable upstream-inherited workflows without deleting them, so they remain +available for diff/reference against upstream and can be re-enabled by moving +back to `.github/workflows/` if needed. + +## Why disabled + +The fork ships internal-only changes against a pinned upstream tag +(`v1.83.10-stable`) and runs **only release workflows** in CI: + +| Active workflow | Trigger | Purpose | +|---|---|---| +| `release-docker.yml` | tag push `v*-internal.*` | Build + publish multi-arch Docker image to Docker Hub | +| `release-swr.yml` | tag push `v*-internal.*` / `v*-ghisha.*`, workflow_dispatch | Mirror image to Huawei Cloud SWR | + +All other workflows were inherited from upstream and one of: + +- Filter to `main` / `litellm_**` branches and skip our `ship/v1.83.10` PRs + anyway (effectively dead weight on our actions UI / billing) +- Operate on upstream concerns (auto price update, daily staging branch, + GitHub issue automation, supply-chain scoring, docs) +- Are workflow_call helpers only consumed by the above + +Rather than maintain branch-filter overrides on 40+ files (each requires +a per-file diff and a maintenance burden when rebasing from upstream), +this fork chooses to disable them wholesale. Test discipline relies on: + +1. Local `make lint` + `make test-unit` before commit (mandatory per CLAUDE.md) +2. Manual `vitest run` for UI changes +3. Local e2e via `e2e/tools/proxy start` + `e2e/tools/run-all-cases` + +## To re-enable a workflow + +```bash +git mv .github/workflows.disabled/.yml .github/workflows/ +``` + +That's it — GitHub Actions picks it up on next push. + +## To re-enable a class of workflows (e.g. all unit tests) + +The unit test workflows filter their `pull_request.branches` to: + +```yaml +- 'main' +- 'litellm_internal_staging' +- 'litellm_oss_branch' +- 'litellm_**' +``` + +Note that `ship/v1.83.10` does NOT match `litellm_**` (literal glob). If you +re-enable them and want them to fire on PRs targeting `ship/v1.83.10`, add +`'ship/**'` to the branches list in each workflow first. diff --git a/.github/workflows/_test-unit-base.yml b/.github/workflows.disabled/_test-unit-base.yml similarity index 100% rename from .github/workflows/_test-unit-base.yml rename to .github/workflows.disabled/_test-unit-base.yml diff --git a/.github/workflows/_test-unit-services-base.yml b/.github/workflows.disabled/_test-unit-services-base.yml similarity index 100% rename from .github/workflows/_test-unit-services-base.yml rename to .github/workflows.disabled/_test-unit-services-base.yml diff --git a/.github/workflows/auto_update_price_and_context_window.yml b/.github/workflows.disabled/auto_update_price_and_context_window.yml similarity index 100% rename from .github/workflows/auto_update_price_and_context_window.yml rename to .github/workflows.disabled/auto_update_price_and_context_window.yml diff --git a/.github/workflows/auto_update_price_and_context_window_file.py b/.github/workflows.disabled/auto_update_price_and_context_window_file.py similarity index 100% rename from .github/workflows/auto_update_price_and_context_window_file.py rename to .github/workflows.disabled/auto_update_price_and_context_window_file.py diff --git a/.github/workflows/check-schema-sync.yml b/.github/workflows.disabled/check-schema-sync.yml similarity index 100% rename from .github/workflows/check-schema-sync.yml rename to .github/workflows.disabled/check-schema-sync.yml diff --git a/.github/workflows/check_duplicate_issues.yml b/.github/workflows.disabled/check_duplicate_issues.yml similarity index 100% rename from .github/workflows/check_duplicate_issues.yml rename to .github/workflows.disabled/check_duplicate_issues.yml diff --git a/.github/workflows/codeql.yml b/.github/workflows.disabled/codeql.yml similarity index 100% rename from .github/workflows/codeql.yml rename to .github/workflows.disabled/codeql.yml diff --git a/.github/workflows/codspeed.yml b/.github/workflows.disabled/codspeed.yml similarity index 100% rename from .github/workflows/codspeed.yml rename to .github/workflows.disabled/codspeed.yml diff --git a/.github/workflows/create-release-branch.yml b/.github/workflows.disabled/create-release-branch.yml similarity index 100% rename from .github/workflows/create-release-branch.yml rename to .github/workflows.disabled/create-release-branch.yml diff --git a/.github/workflows/create-release.yml b/.github/workflows.disabled/create-release.yml similarity index 100% rename from .github/workflows/create-release.yml rename to .github/workflows.disabled/create-release.yml diff --git a/.github/workflows/create_daily_staging_branch.yml b/.github/workflows.disabled/create_daily_staging_branch.yml similarity index 100% rename from .github/workflows/create_daily_staging_branch.yml rename to .github/workflows.disabled/create_daily_staging_branch.yml diff --git a/.github/workflows/guard-fork-dependencies.yml b/.github/workflows.disabled/guard-fork-dependencies.yml similarity index 100% rename from .github/workflows/guard-fork-dependencies.yml rename to .github/workflows.disabled/guard-fork-dependencies.yml diff --git a/.github/workflows/guard-main-branch.yml b/.github/workflows.disabled/guard-main-branch.yml similarity index 100% rename from .github/workflows/guard-main-branch.yml rename to .github/workflows.disabled/guard-main-branch.yml diff --git a/.github/workflows/helm_unit_test.yml b/.github/workflows.disabled/helm_unit_test.yml similarity index 100% rename from .github/workflows/helm_unit_test.yml rename to .github/workflows.disabled/helm_unit_test.yml diff --git a/.github/workflows/issue-keyword-labeler.yml b/.github/workflows.disabled/issue-keyword-labeler.yml similarity index 100% rename from .github/workflows/issue-keyword-labeler.yml rename to .github/workflows.disabled/issue-keyword-labeler.yml diff --git a/.github/workflows/label-component.yml b/.github/workflows.disabled/label-component.yml similarity index 100% rename from .github/workflows/label-component.yml rename to .github/workflows.disabled/label-component.yml diff --git a/.github/workflows/mutation-test.yml b/.github/workflows.disabled/mutation-test.yml similarity index 100% rename from .github/workflows/mutation-test.yml rename to .github/workflows.disabled/mutation-test.yml diff --git a/.github/workflows.disabled/release-docker.yml b/.github/workflows.disabled/release-docker.yml new file mode 100644 index 000000000000..aeefb1459943 --- /dev/null +++ b/.github/workflows.disabled/release-docker.yml @@ -0,0 +1,336 @@ +name: Release Docker Image + +on: + push: + tags: + # Internal release tags only: v1.83.10-internal.1, v1.83.10-internal.2, etc. + - 'v*-internal.*' + +permissions: + contents: read + +env: + # Change this if you want a different Docker Hub repo name. + IMAGE_NAME: zsk2026/litellm + +jobs: + # --------------------------------------------------------------------------- + # 1. Build multi-arch image and push to Docker Hub + # --------------------------------------------------------------------------- + build-and-push: + name: Build and push multi-arch image + runs-on: ubuntu-latest + timeout-minutes: 90 + # To require manual approval before pushing, create a GitHub Environment + # named e.g. "docker-release" with required reviewers, then add: + # environment: docker-release + outputs: + digest: ${{ steps.build.outputs.digest }} + tag: ${{ steps.version.outputs.tag }} + base_version: ${{ steps.version.outputs.base_version }} + git_sha: ${{ steps.version.outputs.git_sha }} + git_sha_full: ${{ steps.version.outputs.git_sha_full }} + + steps: + - name: Checkout repository + uses: actions/checkout@08eba0b27e820071cde6df949e0beb9ba4906955 # v4.3.0 + with: + persist-credentials: false + fetch-depth: 0 # need full history for changelog generation in release job + + - name: Free up disk space + run: | + sudo rm -rf /usr/local/lib/android /usr/share/dotnet /opt/ghc /usr/local/share/boost + sudo apt-get clean + df -h / + + - name: Verify tag is reachable from ship/* branch + run: | + TAG="${GITHUB_REF_NAME}" + echo "Validating tag: ${TAG}" + git fetch origin '+refs/heads/ship/*:refs/remotes/origin/ship/*' --no-tags + CONTAINING=$(git branch -r --contains "${TAG}" | grep 'origin/ship/' || true) + if [ -z "${CONTAINING}" ]; then + echo "::error::Tag ${TAG} is not on any ship/* branch. Refusing to publish." + exit 1 + fi + echo "Tag is on:${CONTAINING}" + + - name: Extract version components + id: version + run: | + TAG="${GITHUB_REF_NAME}" + BASE_VERSION="${TAG%-internal.*}" + GIT_SHA=$(git rev-parse --short HEAD) + GIT_SHA_FULL=$(git rev-parse HEAD) + + echo "tag=${TAG}" >> "$GITHUB_OUTPUT" + echo "base_version=${BASE_VERSION}" >> "$GITHUB_OUTPUT" + echo "git_sha=${GIT_SHA}" >> "$GITHUB_OUTPUT" + echo "git_sha_full=${GIT_SHA_FULL}" >> "$GITHUB_OUTPUT" + + - name: Set up QEMU (for arm64 emulation) + uses: docker/setup-qemu-action@29109295f81e9208d7d86ff1c6c12d2833863392 # v3.6.0 + + - name: Set up Docker Buildx + uses: docker/setup-buildx-action@8d2750c68a42422c14e847fe6c8ac0403b4cbd6f # v3.12 + + - name: Log in to Docker Hub + uses: docker/login-action@9780b0c442fbb1117ed29e0efdff1e18412f7567 # v3.3.0 + with: + username: ${{ secrets.DOCKERHUB_USERNAME }} + password: ${{ secrets.DOCKERHUB_TOKEN }} + + - name: Build and push + id: build + uses: docker/build-push-action@0adf9959216b96bec444f325f1e493d4aa344497 # v6.14 + with: + context: . + file: ./Dockerfile + platforms: linux/amd64,linux/arm64 + push: true + tags: | + ${{ env.IMAGE_NAME }}:${{ steps.version.outputs.tag }} + ${{ env.IMAGE_NAME }}:${{ steps.version.outputs.tag }}-${{ steps.version.outputs.git_sha }} + ${{ env.IMAGE_NAME }}:${{ steps.version.outputs.base_version }}-stable + labels: | + org.opencontainers.image.title=litellm + org.opencontainers.image.source=${{ github.server_url }}/${{ github.repository }} + org.opencontainers.image.revision=${{ steps.version.outputs.git_sha_full }} + org.opencontainers.image.version=${{ steps.version.outputs.tag }} + org.opencontainers.image.created=${{ github.event.repository.updated_at }} + cache-from: type=gha + cache-to: type=gha,mode=max + # provenance=true would attach SLSA provenance attestation. We're + # using cosign signing in the next job instead. + provenance: false + + - name: Build summary + run: | + cat >> "$GITHUB_STEP_SUMMARY" < /dev/null + echo "Signature verified." + + - name: Sign summary + env: + DIGEST: ${{ needs.build-and-push.outputs.digest }} + run: | + cat >> "$GITHUB_STEP_SUMMARY" </dev/null 2>&1; then + PREV_TAG="${BASE_VERSION}-stable" + RANGE="${PREV_TAG}..${TAG}" + echo "First internal tag, using upstream pin: ${PREV_TAG}" + else + RANGE="HEAD~20..${TAG}" + echo "No baseline tag found, using last 20 commits" + fi + fi + + # Build changelog. Use HEREDOC delimiter for multi-line output. + { + echo "changelog<> "$GITHUB_OUTPUT" + + - name: Compose release notes + id: notes + env: + TAG: ${{ needs.build-and-push.outputs.tag }} + BASE_VERSION: ${{ needs.build-and-push.outputs.base_version }} + GIT_SHA: ${{ needs.build-and-push.outputs.git_sha }} + GIT_SHA_FULL: ${{ needs.build-and-push.outputs.git_sha_full }} + DIGEST: ${{ needs.build-and-push.outputs.digest }} + CHANGELOG: ${{ steps.changelog.outputs.changelog }} + PREV_TAG: ${{ steps.changelog.outputs.prev_tag }} + run: | + cat > release-notes.md <> "$GITHUB_STEP_SUMMARY" <> "$GITHUB_OUTPUT" + echo "base_version=${BASE_VERSION}" >> "$GITHUB_OUTPUT" + echo "git_sha=${GIT_SHA}" >> "$GITHUB_OUTPUT" + echo "Tag: ${TAG}, Base: ${BASE_VERSION}, SHA: ${GIT_SHA}" + + - name: Verify tag is reachable from ship/* branch + if: github.event_name != 'workflow_dispatch' + run: | + TAG="${{ steps.version.outputs.tag }}" + git fetch origin '+refs/heads/ship/*:refs/remotes/origin/ship/*' --no-tags + CONTAINING=$(git branch -r --contains "${TAG}" | grep 'origin/ship/' || true) + if [ -z "${CONTAINING}" ]; then + echo "::error::Tag ${TAG} is not on any ship/* branch. Refusing to publish." + exit 1 + fi + echo "Tag is on:${CONTAINING}" + + - name: Set up Docker Buildx + uses: docker/setup-buildx-action@v3 + + - name: Login to Huawei Cloud SWR + env: + HUAWEI_AK: ${{ secrets.HUAWEI_AK }} + HUAWEI_TOKEN: ${{ secrets.HUAWEI_TOKEN }} + run: | + echo "$HUAWEI_TOKEN" | docker login ${{ env.SWR_REGISTRY }} -u "${{ env.SWR_REGION }}@$HUAWEI_AK" --password-stdin + + - name: Build and push to SWR + uses: docker/build-push-action@v5 + with: + context: . + file: ./Dockerfile + push: true + platforms: linux/amd64 + provenance: false + build-args: | + LITELLM_BUILD_TAG=${{ steps.version.outputs.tag }} + LITELLM_BUILD_SHA=${{ steps.version.outputs.git_sha }} + tags: | + ${{ env.SWR_REGISTRY }}/${{ env.SWR_ORG }}/${{ env.IMAGE_NAME }}:${{ steps.version.outputs.tag }} + ${{ env.SWR_REGISTRY }}/${{ env.SWR_ORG }}/${{ env.IMAGE_NAME }}:${{ steps.version.outputs.tag }}-${{ steps.version.outputs.git_sha }} + ${{ env.SWR_REGISTRY }}/${{ env.SWR_ORG }}/${{ env.IMAGE_NAME }}:${{ steps.version.outputs.base_version }}-stable + labels: | + org.opencontainers.image.title=litellm + org.opencontainers.image.source=${{ github.server_url }}/${{ github.repository }} + org.opencontainers.image.revision=${{ steps.version.outputs.git_sha }} + org.opencontainers.image.version=${{ steps.version.outputs.tag }} + cache-from: type=gha + cache-to: type=gha,mode=max + + - name: Build summary + run: | + cat >> "$GITHUB_STEP_SUMMARY" <&2 + exit 2 +fi + +# Tag format: v..-internal. +if ! [[ "${VERSION}" =~ ^v[0-9]+\.[0-9]+\.[0-9]+-internal\.[0-9]+$ ]]; then + echo "Error: tag must match vX.Y.Z-internal.N (got: ${VERSION})" >&2 + exit 2 +fi + +BRANCH=$(git rev-parse --abbrev-ref HEAD) +if [[ "${BRANCH}" != ship/* ]]; then + echo "Error: must release from a ship/* branch (currently on: ${BRANCH})" >&2 + exit 2 +fi + +if [[ -n "$(git status --porcelain)" ]]; then + echo "Error: worktree is dirty. Commit or stash first." >&2 + exit 2 +fi + +# Ensure local branch is up to date with origin +git fetch origin "${BRANCH}" +LOCAL=$(git rev-parse HEAD) +REMOTE=$(git rev-parse "origin/${BRANCH}") +if [[ "${LOCAL}" != "${REMOTE}" ]]; then + echo "Error: local ${BRANCH} is not in sync with origin (local=${LOCAL} remote=${REMOTE})" >&2 + echo "Run: git pull --ff-only origin ${BRANCH}" >&2 + exit 2 +fi + +# Refuse to overwrite an existing tag +if git rev-parse "refs/tags/${VERSION}" >/dev/null 2>&1; then + echo "Error: tag ${VERSION} already exists locally." >&2 + exit 2 +fi +if git ls-remote --tags origin "${VERSION}" | grep -q "${VERSION}"; then + echo "Error: tag ${VERSION} already exists on origin." >&2 + exit 2 +fi + +# Auto-generate changelog body from commits since the last internal tag +BASE_VERSION="${VERSION%-internal.*}" +LAST_TAG=$(git tag --list "${BASE_VERSION}-internal.*" --sort=-v:refname | head -n1 || true) +if [[ -n "${LAST_TAG}" ]]; then + RANGE="${LAST_TAG}..HEAD" + echo "Generating changelog from ${LAST_TAG}..HEAD" +else + RANGE="HEAD~10..HEAD" + echo "No previous internal tag found, using last 10 commits" +fi + +CHANGELOG=$(git log --pretty=format:'- %s (%h)' "${RANGE}" --no-merges | head -n 30) + +cat </litellm:${VERSION} + docker pull /litellm:${BASE_VERSION}-stable +EOF