{{ message }}
Repository navigation
212 lines (205 loc) · 8.86 KB
/
Copy pathbase-image.yml
File metadata and controls
212 lines (205 loc) · 8.86 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
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
# This workflow packs for dependent container images of the project.
name: Base Image
permissions:
actions: read
contents: write
pull-requests: write
defaults:
run:
shell: bash
on:
workflow_dispatch:
inputs:
repository:
description: 'Repository of packed image.'
required: true
type: choice
options:
- llm-router
- mirrored-mooncake
- ssh-server
- thead-ppu-devel
tag:
description: 'Tag of packed image.'
required: true
type: string
# Empty means build to the Dockerfile's final stage, which is today's default image. A
# non-empty value names an earlier stage of the Dockerfile, e.g. one of mirrored-mooncake's
# vendor variants.
target:
description: 'Docker build target within the image Dockerfile. Empty builds to the final stage (the default image).'
required: false
type: string
default: ""
# Allow passing build arguments at pack time, for an image input that must not be
# committed. Required by thead-ppu-devel: "PPU_SDK_URL=<presigned url>".
args:
description: 'Build arguments (space-separated KEY=VALUE), e.g. PPU_SDK_URL=<presigned url>.'
required: false
type: string
default: ""
# Additional tags the manifest job publishes from the same per-platform images,
# e.g. tag "0.3.13.post1-cann9.1-910b" with alias "0.3.13.post1-cann9.1-a2".
alias:
description: 'Alias tags (space-separated) published as extra manifests over the same images.'
required: false
type: string
default: ""
heavy:
description: 'Build on the larger "-8x" runners: "auto" decides from the changed files, "true" forces them, "false" keeps the standard runners.'
required: false
type: choice
options:
- "auto"
- "true"
- "false"
default: "auto"
env:
INPUT_REPOSITORY: ${{ inputs.repository }}
INPUT_TARGET: ${{ inputs.target }}
jobs:
expand-matrix:
runs-on: ubuntu-24.04
outputs:
matrix: ${{ steps.expand-matrix.outputs.matrix }}
steps:
- name: Checkout
uses: actions/checkout@v4
with:
# Two commits: the tip and its parent, which is all "auto" needs to see what the
# tip changed.
fetch-depth: 2
persist-credentials: false
- name: Validate Inputs
env:
INPUT_TAG: ${{ inputs.tag }}
INPUT_ALIAS: ${{ inputs.alias }}
run: |
#
# The manifest job publishes by tag: "docker manifest create --amend" plus a push
# assembles the tag from whatever platforms this dispatch built. A variant
# dispatched under the default image's tag would therefore rewrite that tag's
# multi-arch manifest with the variant's platforms alone. Require a non-empty
# target's slug in the tag: "0.3.13.post1-cuda13.0" passes for the generic cuda
# target, the bare default tag fails, and a versioned target wants its slugged
# form ("0.3.13.post1-cuda13.0" for target cuda13.0). The slug pipeline is
# duplicated from the cache-ref step in _image.yml, fallback included; keep
# the two in sync.
#
if [[ -n "${INPUT_TARGET}" ]]; then
TARGET_SLUG="$(tr '[:upper:]' '[:lower:]' <<<"${INPUT_TARGET}" | tr -c 'a-z0-9.-' '-' | tr -s '-' | sed 's/^[.-]*//; s/[.-]*$//')"
[[ -n "${TARGET_SLUG}" ]] || TARGET_SLUG="variant"
if [[ "${INPUT_TAG}" != *"${TARGET_SLUG}"* ]]; then
echo "[ERROR] target '${INPUT_TARGET}' requires the tag to contain '${TARGET_SLUG}' (got '${INPUT_TAG}')." >&2
echo " A variant pushed under the default image's tag would overwrite that tag's multi-arch manifest." >&2
exit 1
fi
# An alias rewrites the alias tag's manifest with this dispatch's platforms,
# the same hazard under another name, so every alias answers to the slug too.
read -ra ALIASES <<<"${INPUT_ALIAS}" || true
for ALIAS in "${ALIASES[@]}"; do
[[ -n "${ALIAS}" ]] || continue
if [[ "${ALIAS}" != *"${TARGET_SLUG}"* ]]; then
echo "[ERROR] target '${INPUT_TARGET}' requires every alias to contain '${TARGET_SLUG}' (got '${ALIAS}')." >&2
exit 1
fi
done
fi
- name: Detect Heavy Changes
id: detect-heavy
env:
HEAVY_INPUT: ${{ github.event.inputs.heavy || 'auto' }}
run: |
#
# A change to the image's own Dockerfile rebuilds it from its base, which needs a
# bigger runner. This workflow is only ever dispatched, so there is no event base
# to diff against: read the tip commit alone, which is the commit whose Dockerfile
# change is normally the reason for dispatching in the first place.
#
# An explicit input overrides that, because the detection can only see this
# repository: a vendor base image moving under a mutable tag, or a build argument
# naming a new upstream artifact, makes the build a full one without changing any
# file here.
#
if [[ "${HEAVY_INPUT}" != "auto" ]]; then
echo "heavy=${HEAVY_INPUT}" >>"$GITHUB_OUTPUT"
echo "DEBUG: heavy=${HEAVY_INPUT} (forced by input)"
exit 0
fi
HEAVY="false"
#
# Some images are heavy whatever changed, and for them the detection below cannot be the
# answer: it reads the TIP COMMIT ONLY, so an image whose Dockerfile landed a few commits
# earlier is dispatched onto standard runners for a build that never fits.
#
# - mirrored-mooncake: compiles the store from source for two architectures, and the
# parallelism is bounded by memory rather than by cores.
# - llm-router: compiles three routers from three separate upstream sources, two of them
# Rust release builds, so it is the sum of three from-source builds rather than one.
#
case "${INPUT_REPOSITORY}" in
llm-router) HEAVY="true" ;;
mirrored-mooncake) HEAVY="true" ;;
esac
CHANGED="$(git show --name-only --format='' HEAD)"
if grep -qxF "pack/${INPUT_REPOSITORY}/Dockerfile" <<<"${CHANGED}"; then
HEAVY="true"
fi
echo "heavy=${HEAVY}" >>"$GITHUB_OUTPUT"
echo "DEBUG: CHANGED=${CHANGED}"
echo "DEBUG: heavy=${HEAVY}"
- name: Set Matrix
id: expand-matrix
env:
HEAVY: ${{ steps.detect-heavy.outputs.heavy }}
run: |
#
# Platform coverage is per image, and also per build target: an image whose
# upstream ships only one architecture must not be built for the others,
# otherwise that leg fails and the manifest job cannot assemble a complete
# list.
#
# - thead-ppu-devel: the T-Head PPU SDK ships targets/x86_64-linux only.
# - mirrored-mooncake target rocm: the rocm/dev base images publish
# linux/amd64 only (there is no arm64 ROCm build; upstream Mooncake's own
# ROCm release job builds amd64-only too, and gpustack/runner's ROCm
# Dockerfile builds with --platform=linux/amd64).
#
# The manifest job derives its platform list from this output, so it follows
# automatically.
#
# A heavy build targets the "-8x" runner variant (4x resources), matching ci.yml.
#
SUFFIX=""
if [[ "${HEAVY}" == "true" ]]; then
SUFFIX="-8x"
fi
AMD64='{"runner":"ubuntu-24.04'"${SUFFIX}"'","platform":"linux/amd64"}'
ARM64='{"runner":"ubuntu-24.04-arm'"${SUFFIX}"'","platform":"linux/arm64"}'
case "${INPUT_REPOSITORY}:${INPUT_TARGET}" in
thead-ppu-devel:*) ENTRIES="${AMD64}" ;;
mirrored-mooncake:rocm*) ENTRIES="${AMD64}" ;;
*) ENTRIES="${AMD64},${ARM64}" ;;
esac
MATRIX="$(jq -cr . <<<"[${ENTRIES}]")"
echo "matrix=${MATRIX}" >>"$GITHUB_OUTPUT"
echo "DEBUG: MATRIX=${MATRIX}"
image:
needs:
- expand-matrix
uses: ./.github/workflows/_image.yml
with:
repository: ${{ inputs.repository }}
target: ${{ inputs.target }}
matrix: ${{ needs.expand-matrix.outputs.matrix }}
# A dispatch exists in order to publish the image, so it always pushes.
push: true
tags: |
type=raw,value=${{ inputs.tag }}
flavor: |
latest=false
suffix-on-latest: true
build-args-secret: ${{ inputs.args }}
alias: ${{ inputs.alias }}
secrets:
dockerhub-password: ${{ secrets.CI_DOCKERHUB_PASSWORD }}
You can’t perform that action at this time.
