-
Notifications
You must be signed in to change notification settings - Fork 0
192 lines (175 loc) · 8.08 KB
/
Copy pathbuild.yml
File metadata and controls
192 lines (175 loc) · 8.08 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
name: build
on:
schedule:
- cron: "23 5 * * *" # daily: pick up new upstream stable releases
push:
branches: [main]
paths:
- Dockerfile
- patch/**
- .github/workflows/build.yml
workflow_dispatch:
inputs:
litellm_version:
description: "LiteLLM release tag (e.g. v1.93.0). Empty = latest stable release."
required: false
permissions:
contents: read
packages: write
actions: read # notify job reads previous run conclusions
concurrency:
group: build
cancel-in-progress: false
jobs:
build:
runs-on: ubuntu-latest
outputs:
version: ${{ steps.version.outputs.version }}
strategy:
fail-fast: false
matrix:
include:
# plain image: consumed by litellm-lagoon (Lagoon/docker-compose)
- upstream: litellm
package: litellm-lagoon-base
# -database image: consumed by the litellm helm chart (k0rdent)
- upstream: litellm-database
package: litellm-lagoon-base-database
# The docker build pushes to this job-local registry first. Its result
# still DISTRIBUTES the enterprise code: `rm -rf` in the Dockerfile only
# masks files in the top layer, the inherited upstream layers keep the
# content. The publish step crane-flattens it into a single layer at
# $IMAGE, so only the post-rm filesystem ever leaves the runner. (A
# GHCR staging package won't do: packages created from a public repo's
# workflow are born public.)
services:
registry:
image: registry:2
ports:
- 5000:5000
env:
IMAGE: ghcr.io/${{ github.repository_owner }}/${{ matrix.package }}
STAGING: localhost:5000/${{ matrix.package }}
steps:
- uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1
- name: Resolve LiteLLM version
id: version
env:
GH_TOKEN: ${{ github.token }}
run: |
VERSION='${{ inputs.litellm_version }}'
if [ -z "$VERSION" ]; then
VERSION="$(gh api repos/BerriAI/litellm/releases --jq '[.[] | select(.prerelease | not)][0].tag_name')"
fi
[ -n "$VERSION" ] || { echo "could not resolve a LiteLLM version"; exit 1; }
echo "version=$VERSION" | tee -a "$GITHUB_OUTPUT"
- uses: docker/login-action@dbcb813823bdd20940b903addbd779551569679f # v4.6.0
with:
registry: ghcr.io
username: ${{ github.actor }}
password: ${{ secrets.GITHUB_TOKEN }}
# On scheduled runs, skip versions we already published. Pushes to
# main (patch/Dockerfile changes) always republish the current version.
- name: Check if already published
id: published
if: github.event_name == 'schedule'
run: |
if docker manifest inspect "$IMAGE:${{ steps.version.outputs.version }}" >/dev/null 2>&1; then
echo "exists=true" | tee -a "$GITHUB_OUTPUT"
fi
# GHCR shows org.opencontainers.image.description as the package
# description; build it from the patch filenames so the package page
# lists what was applied.
- name: Describe patches
id: patches
run: |
PATCHES="$(ls patch/*.patch 2>/dev/null | xargs -rn1 basename | sed 's/\.patch$//' | paste -sd, -)"
echo "description=LiteLLM ${{ steps.version.outputs.version }}, enterprise code stripped, patches: ${PATCHES:-none}" | tee -a "$GITHUB_OUTPUT"
- uses: docker/setup-qemu-action@96fe6ef7f33517b61c61be40b68a1882f3264fb8 # v4.2.0
if: steps.published.outputs.exists != 'true'
- uses: docker/setup-buildx-action@bb05f3f5519dd87d3ba754cc423b652a5edd6d2c # v4.2.0
if: steps.published.outputs.exists != 'true'
with:
# Let the buildkit container reach the job-local registry service.
driver-opts: network=host
- uses: docker/build-push-action@53b7df96c91f9c12dcc8a07bcb9ccacbed38856a # v7.3.0
if: steps.published.outputs.exists != 'true'
with:
context: .
push: true
platforms: linux/amd64,linux/arm64
build-args: |
LITELLM_IMAGE=ghcr.io/berriai/${{ matrix.upstream }}
LITELLM_VERSION=${{ steps.version.outputs.version }}
# No provenance attestations: crane flatten drops them anyway.
provenance: false
tags: |
${{ env.STAGING }}:${{ steps.version.outputs.version }}
# GHCR reads the description from the image index annotation on
# multi-arch images; the label covers single-manifest consumers.
labels: |
org.opencontainers.image.description=${{ steps.patches.outputs.description }}
org.opencontainers.image.source=${{ github.server_url }}/${{ github.repository }}
annotations: |
index:org.opencontainers.image.description=${{ steps.patches.outputs.description }}
index:org.opencontainers.image.source=${{ github.server_url }}/${{ github.repository }}
- uses: imjasonh/setup-crane@feee3b6bb0d4c68370f256a4502498c9227e5c6b # v0.7
if: steps.published.outputs.exists != 'true'
# Squash to a single layer per arch so the upstream layers containing
# the enterprise code are not part of the public image. Flatten
# preserves the image config (env, entrypoint, labels) and the index
# annotations; crane reuses the docker login from above.
- name: Flatten into public image
if: steps.published.outputs.exists != 'true'
run: |
crane flatten "$STAGING:${{ steps.version.outputs.version }}" -t "$IMAGE:${{ steps.version.outputs.version }}"
crane tag "$IMAGE:${{ steps.version.outputs.version }}" latest
# Keep the Dockerfile's ARG default in sync with the version just
# published, purely for readability — CI always overrides it via
# --build-arg. Stable releases only: pre-release builds (manual rc/dev
# dispatches) shouldn't move the default. [skip ci] stops the push from
# retriggering this workflow.
sync-dockerfile:
runs-on: ubuntu-latest
needs: build
permissions:
contents: write
steps:
- uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1
- name: Sync ARG LITELLM_VERSION with published version
env:
VERSION: ${{ needs.build.outputs.version }}
run: |
case "$VERSION" in *rc*|*dev*|*beta*|*nightly*) echo "pre-release, skipping"; exit 0;; esac
sed -i "s|^ARG LITELLM_VERSION=.*|ARG LITELLM_VERSION=${VERSION}|" Dockerfile
git diff --quiet && exit 0
git config user.name "github-actions[bot]"
git config user.email "github-actions[bot]@users.noreply.github.com"
git commit -am "chore: sync LITELLM_VERSION default to ${VERSION} [skip ci]"
git push
# One Slack message per breakage, not per matrix leg or per scheduled
# retry: skip posting when the previous completed run also failed.
notify:
runs-on: ubuntu-latest
needs: build
if: failure()
steps:
- name: Check previous run conclusion
id: prev
env:
GH_TOKEN: ${{ github.token }}
run: |
PREV="$(gh api "repos/${{ github.repository }}/actions/workflows/build.yml/runs?status=completed&per_page=1" --jq '.workflow_runs[0].conclusion')"
echo "conclusion=$PREV" | tee -a "$GITHUB_OUTPUT"
- name: Post to Slack
if: steps.prev.outputs.conclusion != 'failure'
env:
SLACK_BOT_TOKEN: ${{ secrets.SLACK_BOT_TOKEN }}
SLACK_CHANNEL_ID: ${{ vars.SLACK_CHANNEL_ID }}
TEXT: ":rotating_light: litellm-lagoon-base build failed for LiteLLM ${{ needs.build.outputs.version || 'unknown' }} — the patch may no longer apply. ${{ github.server_url }}/${{ github.repository }}/actions/runs/${{ github.run_id }}"
run: |
curl -fsS -X POST https://slack.com/api/chat.postMessage \
-H "Authorization: Bearer $SLACK_BOT_TOKEN" \
-H 'Content-type: application/json; charset=utf-8' \
--data "$(jq -n --arg c "$SLACK_CHANNEL_ID" --arg t "$TEXT" '{channel:$c,text:$t}')" \
| jq -e '.ok'