-
Notifications
You must be signed in to change notification settings - Fork 9
317 lines (301 loc) · 11.7 KB
/
pack.yml
File metadata and controls
317 lines (301 loc) · 11.7 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
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
# This workflow packs the Docker images for the GPUStack runner.
# It builds the images based on the matrix defined in `pack/matrix.yaml`.
# It supports multiple backends and targets, and can create manifest lists for multi-arch support.
# It also supports dry runs to check the matrix and Dockerfile without building images.
# The workflow is triggered manually via the GitHub Actions UI.
name: pack
permissions:
actions: write
contents: write
pull-requests: write
defaults:
run:
shell: bash
on:
workflow_dispatch:
inputs:
# Post operation for mutating a released image.
post_operation:
description: 'Post operation (dangerous), which operation to use for mutating a released image.'
required: false
type: string
# Control the Dockerfile and build context.
backend:
description: 'Backend, which accelerated backend to pack for.'
required: false
type: choice
default: all
options:
- all
- cann
- corex
- cuda
- dtk
- hggc
- maca
- musa
- rocm
# Control the build stage.
target:
description: 'Target, which target to pack for, "runtime" is for runtime image, "services" is to build all services, or other specific target.'
required: false
type: choice
default: services
options:
- runtime
- services
- voxbox
- mindie
- vllm
- sglang
# Since specific Backend and Target still result in many tags,
# we can leverage this to control packing one specific tag, even os/arch.
tag:
description: 'Tag (ignore -dev suffix), which tag to pack for. Pack all tags given by Backend and Target if not specified.'
required: false
type: string
default: ""
# Allow to pass arguments to the building,
# but recommended to code into the matrix.yaml.
args:
description: 'Arguments (using space to separate multiple items), which build arguments use for packing.'
required: false
type: string
default: ""
# Debug.
dry_run:
description: 'Dry run, print matrix and check the Dockerfile.'
required: false
type: boolean
default: false
# Do not append a `-dev` suffix to the tag.
for_release:
description: 'For release (without -dev suffix). Always be true if target is "runtime".'
required: false
type: boolean
default: false
# Ignore --cache-from.
with_cache:
description: 'With cache, specially meaning cache from previous built result.'
required: false
type: boolean
default: true
# Choice large GitHub hosted runner.
runner_profile:
description: 'Runner profile, which profile to use for the runner.'
required: false
type: choice
default: normal
options:
- normal
- 8x
- 16x
- 32x
# Clean the runner before packing.
runner_clean:
description: 'Runner clean before packing, which means to clean the runner before packing. Always be true if runner profile is "normal".'
required: false
type: boolean
default: false
env:
INPUT_USERNAME: gpustack
INPUT_PASSWORD: ${{ secrets.CI_DOCKERHUB_PASSWORD }}
INPUT_NAMESPACE: gpustack
INPUT_REPOSITORY: runner
INPUT_CACHE_REPOSITORY: runner-build-cache
jobs:
# Expand the matrix based on the input parameters.
expand-matrix:
runs-on: ubuntu-22.04
outputs:
build_jobs: ${{ steps.expand-matrix.outputs.build_jobs }}
manifest_jobs: ${{ steps.expand-matrix.outputs.manifest_jobs }}
steps:
- name: Checkout
uses: actions/checkout@v4
with:
fetch-depth: 1
persist-credentials: false
- name: Expand Matrix
id: expand-matrix
env:
INPUT_POST_OPERATION: ${{ github.event.inputs.post_operation }}
INPUT_BACKEND: ${{ github.event.inputs.backend }}
INPUT_TARGET: ${{ github.event.inputs.target }}
INPUT_TAG: ${{ github.event.inputs.tag }}
INPUT_ARGS: ${{ github.event.inputs.args }}
INPUT_FOR_RELEASE: ${{ github.event.inputs.for_release }}
INPUT_RUNNER_PROFILE: ${{ github.event.inputs.runner_profile }}
INPUT_WORKSPACE: ${{ github.workspace }}/pack
INPUT_TEMPDIR: ${{ runner.temp }}
run: ${{ github.workspace }}/pack/expand_matrix.sh
# Build the Docker images per OS/ARCH.
build:
timeout-minutes: 360
needs:
- expand-matrix
strategy:
fail-fast: false
matrix:
include: ${{ fromJson(needs.expand-matrix.outputs.build_jobs) }}
runs-on: ${{ matrix.runner }}
steps:
- name: Checkout
uses: actions/checkout@v4
with:
lfs: true
fetch-depth: 1
persist-credentials: false
- name: Maximize Docker Build Space
if: ${{ github.event.inputs.dry_run == 'false' && (github.event.inputs.runner_clean == 'true' || github.event.inputs.runner_profile == 'normal') }}
uses: gpustack/.github/.github/actions/maximize-docker-build-space@main
with:
deep-clean: true
root-reserve-mb: 20480
- name: Setup BuildX
uses: docker/setup-buildx-action@v3
with:
driver-opts: |
network=host
env.BUILDKIT_STEP_LOG_MAX_SIZE=-1
env.BUILDKIT_STEP_LOG_MAX_SPEED=-1
buildkitd-flags: |
--allow-insecure-entitlement=network.host
--allow-insecure-entitlement=security.insecure
--oci-worker-net=host
--oci-worker-gc-keepstorage=204800
- name: Login DockerHub
if: ${{ github.event.inputs.dry_run == 'false' }}
uses: docker/login-action@v3
with:
username: ${{ env.INPUT_USERNAME }}
password: ${{ env.INPUT_PASSWORD }}
- name: Get Metadata
id: metadata
env:
INPUT_POST_OPERATION: ${{ github.event.inputs.post_operation }}
INPUT_WITH_CACHE: ${{ github.event.inputs.with_cache }}
INPUT_PLATFORM_TAG: ${{ matrix.platform_tag }}
INPUT_PLATFORM_TAG_CACHE: ${{ join(matrix.platform_tag_cache, ' ') }}
INPUT_ARGS: ${{ join(matrix.args, ' ') }}
run: |
#!/usr/bin/env bash
set -eo pipefail
# Export tags to GH output.
echo "tags<<EOF" >> $GITHUB_OUTPUT
echo "${INPUT_NAMESPACE}/${INPUT_REPOSITORY}:${INPUT_PLATFORM_TAG}" >> $GITHUB_OUTPUT
echo "EOF" >> $GITHUB_OUTPUT
# Export build_args to GH output.
echo "build_args<<EOF" >> $GITHUB_OUTPUT
for arg in ${INPUT_ARGS}; do
echo "${arg}" >> $GITHUB_OUTPUT
done
echo "EOF" >> $GITHUB_OUTPUT
# Export cache_from to GH output.
echo "cache_from<<EOF" >> $GITHUB_OUTPUT
if [[ "${INPUT_WITH_CACHE}" == "true" ]]; then
for tag_cache in ${INPUT_PLATFORM_TAG_CACHE}; do
echo "type=registry,ref=${INPUT_NAMESPACE}/${INPUT_CACHE_REPOSITORY}:${tag_cache}" >> $GITHUB_OUTPUT
done
fi
echo "EOF" >> $GITHUB_OUTPUT
# Export cache_to to GH output.
echo "cache_to<<EOF" >> $GITHUB_OUTPUT
if [[ -z "${INPUT_POST_OPERATION}" ]]; then
for tag_cache in ${INPUT_PLATFORM_TAG_CACHE}; do
echo "type=registry,ignore-error=true,mode=max,compression=gzip,ref=${INPUT_NAMESPACE}/${INPUT_CACHE_REPOSITORY}:${tag_cache}" >> $GITHUB_OUTPUT
done
fi
echo "EOF" >> $GITHUB_OUTPUT
- name: Package
timeout-minutes: 360
uses: docker/build-push-action@v6
with:
allow: |
network.host
security.insecure
call: ${{ github.event.inputs.dry_run == 'true' && 'check' || 'build' }}
ulimit: |
nofile=65536:65536
shm-size: '16G'
push: ${{ github.event.inputs.dry_run == 'false' }}
provenance: false
sbom: false
context: ${{ github.workspace }}/pack${{ github.event.inputs.post_operation && format('/.post_operation/{0}', github.event.inputs.post_operation) || '' }}/${{ matrix.backend }}
file: ${{ github.workspace }}/pack${{ github.event.inputs.post_operation && format('/.post_operation/{0}', github.event.inputs.post_operation) || '' }}/${{ matrix.backend }}/Dockerfile
platforms: ${{ matrix.platform }}
target: ${{ matrix.service }}
tags: |
${{ steps.metadata.outputs.tags }}
build-args: |
${{ steps.metadata.outputs.build_args }}
cache-from: |
${{ steps.metadata.outputs.cache_from }}
cache-to: |
${{ steps.metadata.outputs.cache_to }}
# Merge all architecture images into manifest list.
manifest:
if: ${{ github.event.inputs.dry_run == 'false' }}
needs:
- expand-matrix
- build
runs-on: ubuntu-22.04
steps:
- name: Login DockerHub
uses: docker/login-action@v3
with:
username: ${{ env.INPUT_USERNAME }}
password: ${{ env.INPUT_PASSWORD }}
- name: Manifest
env:
INPUT_MANIFEST_JOBS: ${{ needs.expand-matrix.outputs.manifest_jobs }}
run: |
#!/usr/bin/env bash
set -eo pipefail
# Iterate all items of manifest jobs.
for TAG in $(echo "${INPUT_MANIFEST_JOBS}" | jq -r 'keys[]'); do
PLATFORM_TAGS="$(echo "${INPUT_MANIFEST_JOBS}" | jq -r \
--arg tag "${TAG}" \
--arg repo "${INPUT_NAMESPACE}/${INPUT_REPOSITORY}" \
'.[$tag] | map($repo + ":" + .) | join(" ")')"
echo "[INFO]: Creating manifest '${INPUT_NAMESPACE}/${INPUT_REPOSITORY}:${TAG}' with '${PLATFORM_TAGS}'"
docker manifest create --amend "${INPUT_NAMESPACE}/${INPUT_REPOSITORY}:${TAG}" ${PLATFORM_TAGS}
docker manifest inspect "${INPUT_NAMESPACE}/${INPUT_REPOSITORY}:${TAG}"
echo "[INFO]: Pushing manifest '${INPUT_NAMESPACE}/${INPUT_REPOSITORY}:${TAG}'"
docker manifest push --purge "${INPUT_NAMESPACE}/${INPUT_REPOSITORY}:${TAG}"
done
# Submit a PR to merge the runner.
merge-runner:
if: ${{ github.event.inputs.dry_run == 'false' && github.event.inputs.target != 'runtime' && github.event.inputs.for_release == 'true' && github.event.inputs.post_operation == '' }}
needs:
- expand-matrix
- manifest
runs-on: ubuntu-22.04
steps:
- name: Checkout
uses: actions/checkout@v4
with:
fetch-depth: 1
persist-credentials: false
- name: Merge Runner
env:
INPUT_BUILD_JOBS: ${{ needs.expand-matrix.outputs.build_jobs }}
run: ${{ github.workspace }}/pack/merge_runner.sh
- name: Generate Pull Request Token
id: generate-prt
uses: actions/create-github-app-token@v2
with:
app-id: ${{ secrets.CI_PRT_GENERATOR_ID }}
private-key: ${{ secrets.CI_PRT_GENERATOR_KEY }}
- name: Pull Request
uses: peter-evans/create-pull-request@v7
with:
token: ${{ steps.generate-prt.outputs.token }}
branch: "create-pull-request/merge-runner-${{ github.run_id }}"
delete-branch: true
commit-message: "chore: update runner by gha workflow ${{ github.run_id }}"
title: "chore: update runner by gha workflow ${{ github.run_id }}"
reviewers: ${{ github.actor }}
assignees: ${{ github.actor }}
body: |
Update runner by GHA workflow [${{ github.run_id }}](https://github.com/${{ github.repository }}/actions/runs/${{ github.run_id }}).