forked from raman325/lock_code_manager
-
Notifications
You must be signed in to change notification settings - Fork 0
333 lines (319 loc) · 18.4 KB
/
Copy pathbuild-from-source.yml
File metadata and controls
333 lines (319 loc) · 18.4 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
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
# UNIVERSAL build-from-source workflow — BYTE-IDENTICAL across every Model B fork.
#
# DO NOT customize this file per-fork. If a fork needs different behavior, use
# GitHub Actions repository Variables (Settings → Secrets and variables →
# Actions → Variables):
#
# DOCKERFILE override auto-detected path (default: root Dockerfile, then shallowest)
# BUILD_CONTEXT override docker build context (default: . — repo root)
# PLATFORMS override platform list (default: linux/amd64,linux/arm64)
# BUILD_ARGS multi-line KEY=VALUE pairs passed to docker build (default: none).
# Used by forks whose upstream Dockerfile declares an ARG with no
# default that the upstream's own CI passes externally (e.g.
# tika-docker's TIKA_VERSION via republish-images.sh).
# IS_SOURCE_BUILT job-level gate: build runs only when set to 'true'. Plain-mirror
# forks set 'false' so the workflow file stays installed (uniform
# scaffolding) but the job no-ops; fork-publish.yml owns :latest.
# FREE_DISK_SPACE opt-in (set 'true') for forks whose images blow past the
# 14GB default disk on ubuntu-latest (vllm-class CUDA images).
# Adds ~3 min per build; reclaims ~30GB by removing pre-installed
# Android SDK / .NET / Haskell / large npm caches.
# RUNS_ON per-fork runner-label override (default: "ubuntu-latest").
# JSON-encoded — single string for one label, or JSON array for
# multiple. Set to '["self-hosted","lan-docker","big-build"]'
# for forks that exceed hosted-runner capacity (vllm).
# BUILD_TIMEOUT_MINUTES per-fork job-timeout override (default 360, the
# GitHub-hosted-runner ceiling). Raise as a ONE-SHOT bootstrap
# on forks whose first cold-cache build exceeds 360min (vllm
# single-arch CUDA: ~5-6h first run, ~30-45m once :buildcache
# is populated). Revert to default after first green run.
# Honest-fact #97.
# PRECOMPILED_WHEEL_BASE_URL master switch for the upstream-prebuilt-wheel
# build path. Set to e.g. `https://wheels.vllm.ai` on forks
# whose upstream publishes per-commit prebuilt wheels AND
# whose carry stack is 100% non-compiled (Python/MD only).
# When set, the build passes ${PREFIX}_USE_PRECOMPILED=1 + the
# resolved commit + variant as build-args, and the fork's
# Dockerfile carry can early-out the local C++/CUDA compile.
# When unset (default for all forks), build path is unchanged.
# sync-upstream.yml writes PRECOMPILED_WHEEL_COMMIT after
# curl-verifying the wheel exists; if no variant in
# PRECOMPILED_WHEEL_VARIANT_CHAIN publishes, sync CLEARS
# PRECOMPILED_WHEEL_COMMIT to empty so the build falls back
# to source compile rather than serving stale-ABI binaries
# (the only safe semantics — a wheel built against SHA-N-1
# with Python carries against SHA-N's APIs segfaults at
# runtime with no build-time signal). Honest-fact #99.
# PRECOMPILED_WHEEL_COMMIT SHA of the upstream commit whose wheel to fetch.
# Managed by sync-upstream — operator should NOT set this
# directly UNLESS PRECOMPILED_WHEEL_COMMIT_FROZEN=true (then
# sync respects the manual pin). Empty when no wheel is
# currently available; build falls back to source compile.
# PRECOMPILED_WHEEL_VARIANT wheel build variant (e.g. `cu130`, `cu128`).
# Operator-set initial value; sync-upstream updates in-place
# when the variant chain falls through to a different one
# (unless PRECOMPILED_WHEEL_COMMIT_FROZEN=true).
# PRECOMPILED_WHEEL_VARIANT_CHAIN optional. Space-separated fallback list
# (e.g. `cu130 cu128`). Sync-upstream tries each in order;
# first one whose wheel exists wins. Defaults to the single
# PRECOMPILED_WHEEL_VARIANT value.
# PRECOMPILED_WHEEL_BUILD_ARG_PREFIX prefix for the synthesized build-arg
# env names. Default `VLLM` — synthesizes VLLM_USE_PRECOMPILED,
# VLLM_PRECOMPILED_WHEEL_COMMIT, etc. For forks whose upstream
# uses a different convention (MinerU, torchao, future), set
# to that project's prefix (e.g. `MINERU`) → MINERU_USE_PRECOMPILED.
# Keeps the template generic across vendor opt-ins.
# PRECOMPILED_WHEEL_COMMIT_FROZEN set to `true` to pin
# PRECOMPILED_WHEEL_COMMIT/_VARIANT manually — sync-upstream
# will NOT overwrite them when set. Use for testing a specific
# wheel SHA, or for rolling back from a bad upstream commit.
# Default unset (sync auto-manages).
#
# If a fork's Dockerfile needs out-of-context pre-build steps, the right fix is
# to cherry-pick a multi-stage self-contained Dockerfile from upstream into our
# intarweb-dev — NOT to add pre-build logic here.
#
# Codified in oss-contributing:ghcr-fork-mirror skill honest-fact #52.
name: Build from source → GHCR
on:
push:
branches: [intarweb-dev]
workflow_dispatch:
# Single-flight per repo: schedule-driven sync push + Heal K dispatch + manual
# workflow_dispatch can all converge. cancel-in-progress: false because builds
# are expensive (vllm 30-45 min, bifrost 45 min) — let the in-flight one finish,
# queue the next behind it. Honest-fact #74.
concurrency:
group: build-from-source-${{ github.repository }}
cancel-in-progress: false
permissions:
contents: read
packages: write
jobs:
build:
# IS_SOURCE_BUILT Variable is the authoritative source-vs-mirror switch
# for the fleet. Setting it to anything other than 'true' (or leaving it
# unset) skips the build entirely. This keeps the WORKFLOW FILE itself
# byte-identical across every fork (uniform infra scaffolding) while
# giving operators a per-fork Variable to control source-build vs
# plain-mirror behavior without removing files or disabling workflows.
# Plain-mirror forks (docker-neo4j etc) still have build-from-source.yml
# installed but the job no-ops; fork-publish.yml owns :latest for them.
#
# Branch gate: when triggered by a push, only run on intarweb-dev. The
# `on.push.branches: [intarweb-dev]` filter above is supposed to handle
# this, but in practice GitHub still records 0-second false-failure runs
# against build-from-source.yml when sync-upstream's bot pushes to main
# (empty jobs[], shows red in Actions UI, head_branch=main, name=workflow
# path rather than display name). Belt-and-suspenders branch gate here
# ensures the job no-ops cleanly to a green "skipped" rather than a
# mysterious red failure if the trigger ever evaluates against main /
# master / any other ref. Manual workflow_dispatch and workflow_call
# paths remain unaffected. Honest-fact #109.
if: >-
vars.IS_SOURCE_BUILT == 'true'
&& (
github.event_name == 'workflow_dispatch'
|| github.event_name == 'workflow_call'
|| (github.event_name == 'push' && github.ref == 'refs/heads/intarweb-dev')
)
# Per-fork override via repo Variable RUNS_ON (default: ubuntu-latest hosted).
# Set to '["self-hosted","lan-docker","big-build"]' (JSON array, single line)
# for forks whose builds exceed hosted-runner capacity (16GB RAM / 14GB disk
# — vllm's CUDA csrc-build is the canonical case). Honest-fact #89.
runs-on: ${{ fromJSON(vars.RUNS_ON || '"ubuntu-latest"') }}
# Per-fork override via repo Variable BUILD_TIMEOUT_MINUTES (default 360, the
# GitHub-hosted-runner hard ceiling). Raise to 720 as a ONE-SHOT bootstrap on
# forks whose first build needs to populate :buildcache from scratch (vllm
# at single-arch CUDA: ~5-6h cold-cache vs ~30-45m warm). Revert to 360 once
# warm. Codified after 27340784996 / 27373307060 cancelled at 360min on the
# vllm fork's first cold-cache run. Honest-fact #91.
timeout-minutes: ${{ fromJSON(vars.BUILD_TIMEOUT_MINUTES || '360') }}
# Read-once capture of precompiled-wheel Variables at job start. Subsequent
# steps reference $PRECOMPILED_* env vars (resolved once at job-init) rather
# than ${{ vars.* }} (re-resolved per-step expression). This makes an
# in-flight build immune to mid-job Variable mutations from a concurrent
# sync-upstream writing PRECOMPILED_WHEEL_COMMIT/_VARIANT. Eliminates the
# read/write race architect-review #1 flagged. Honest-fact #99.
env:
PRECOMPILED_BASE_URL: ${{ vars.PRECOMPILED_WHEEL_BASE_URL }}
PRECOMPILED_COMMIT: ${{ vars.PRECOMPILED_WHEEL_COMMIT }}
PRECOMPILED_VARIANT: ${{ vars.PRECOMPILED_WHEEL_VARIANT }}
PRECOMPILED_PREFIX: ${{ vars.PRECOMPILED_WHEEL_BUILD_ARG_PREFIX || 'VLLM' }}
OPERATOR_BUILD_ARGS: ${{ vars.BUILD_ARGS }}
steps:
- uses: actions/checkout@v4
with:
persist-credentials: false
# Optional disk reclamation for forks whose images blow past the 14GB
# default disk on ubuntu-latest hosted runners (vllm being the canonical
# offender — its CUDA build artifacts + intermediate layers exceed 20GB
# easily). Frees ~30GB by removing pre-installed Android SDK, .NET,
# Haskell, large npm caches, and codeql databases. Costs ~3 min — gated
# behind FREE_DISK_SPACE Variable so non-vllm-class forks don't pay it.
- name: 🧹 Free disk space (opt-in via FREE_DISK_SPACE Variable)
if: vars.FREE_DISK_SPACE == 'true'
uses: jlumbroso/free-disk-space@v1.3.1
with:
tool-cache: true
android: true
dotnet: true
haskell: true
large-packages: true
docker-images: false
swap-storage: false
- name: 🔍 Resolve Dockerfile
id: df
env:
DOCKERFILE_VAR: ${{ vars.DOCKERFILE }}
run: |
set -euo pipefail
# 1. Explicit override (repo Variable) always wins.
if [ -n "${DOCKERFILE_VAR}" ]; then
echo " ✓ using DOCKERFILE override: ${DOCKERFILE_VAR}"
echo "path=${DOCKERFILE_VAR}" >> "$GITHUB_OUTPUT"
echo "skip=false" >> "$GITHUB_OUTPUT"
exit 0
fi
# 2. Prefer a root Dockerfile.
if [ -f Dockerfile ]; then
echo " ✓ found root Dockerfile"
echo "path=Dockerfile" >> "$GITHUB_OUTPUT"
echo "skip=false" >> "$GITHUB_OUTPUT"
exit 0
fi
# 3. Deterministic discovery: shallowest non-test Dockerfile.
cand="$(find . -maxdepth 4 -type f -name Dockerfile \
-not -path './node_modules/*' \
-not -path './.git/*' \
-not -path '*/test/*' \
-not -path '*/tests/*' \
-not -path '*/example*/*' \
-not -path './vendor/*' \
-not -path './third_party/*' \
| sed 's|^\./||' \
| awk '{print gsub(/\//,"/"), $0}' \
| sort -n | head -n1 | cut -d' ' -f2- || true)"
if [ -z "$cand" ]; then
echo " ✗ no Dockerfile found → plain-mirror fallback (no image built)"
echo "skip=true" >> "$GITHUB_OUTPUT"
exit 0
fi
echo " ✓ auto-found: $cand"
echo "path=$cand" >> "$GITHUB_OUTPUT"
echo "skip=false" >> "$GITHUB_OUTPUT"
- name: Set up QEMU
if: steps.df.outputs.skip != 'true'
uses: docker/setup-qemu-action@v3
- name: Set up Buildx
if: steps.df.outputs.skip != 'true'
uses: docker/setup-buildx-action@v3
- name: Log in to ghcr.io
if: steps.df.outputs.skip != 'true'
uses: docker/login-action@v3
with:
registry: ghcr.io
username: ${{ github.actor }}
password: ${{ secrets.GITHUB_TOKEN }}
- name: 🔡 Compute image (lowercase — GHCR requires lowercase repo names)
id: imgname
run: |
# vars.IMAGE_NAME may already be lowercase (set as such manually), but
# the github.event.repository.name fallback can be CamelCase if the fork
# repo name has uppercase letters (e.g. RetroSaveManager). docker/build-push
# rejects ANY uppercase in the image path. fork-publish.yml does the same
# via tr; we do it here. Honest-fact #63.
NAME="${{ vars.IMAGE_NAME || github.event.repository.name }}"
NAME_LOWER=$(echo "$NAME" | tr '[:upper:]' '[:lower:]')
echo "image=ghcr.io/${{ github.repository_owner }}/${NAME_LOWER}" >> "$GITHUB_OUTPUT"
- name: 🏷️ Docker metadata
id: meta
if: steps.df.outputs.skip != 'true'
uses: docker/metadata-action@v5
with:
# Per-fork override via repo Variable IMAGE_NAME — for forks where the
# published image name differs from the repo name (docker-autoheal repo →
# autoheal image). Falls back to repo name. Same as fork-publish.yml so
# ONE image per fork. Lowercased above (metadata-action's lowercase only
# applies to tags, not to the images input — uppercase repo names slip
# through and break build-push with "repository name must be lowercase").
images: ${{ steps.imgname.outputs.image }}
tags: |
type=raw,value=latest,enable=${{ github.ref == 'refs/heads/intarweb-dev' }}
type=sha,prefix=sha-,format=short
- name: 🧩 Synthesize build-args (BUILD_ARGS + optional precompiled-wheel envs)
# Combines operator-set BUILD_ARGS with auto-derived precompiled-wheel
# build-args when PRECOMPILED_WHEEL_BASE_URL is set on the fork. For
# forks WITHOUT that Variable (the default), output is byte-identical to
# the pre-existing `build-args: ${{ vars.BUILD_ARGS || '' }}` behavior.
# Uses $PRECOMPILED_* env vars captured at job start (job-level env
# block) — immune to mid-build Variable mutations. Synthesizes envs with
# the configured PREFIX (default `VLLM`), so non-vllm forks adopting this
# pattern (MinerU, torchao, future) just set
# PRECOMPILED_WHEEL_BUILD_ARG_PREFIX without template surgery.
# Honest-fact #99/#104.
id: bargs
if: steps.df.outputs.skip != 'true'
run: |
set -euo pipefail
BARGS="${OPERATOR_BUILD_ARGS:-}"
if [ -n "${PRECOMPILED_BASE_URL:-}" ] && [ -n "${PRECOMPILED_COMMIT:-}" ]; then
# Build the precompiled-wheel envs via printf so the multi-line
# KEY=VALUE block doesn't dedent the surrounding YAML run block
# (honest-fact #104 — broken-yaml-from-bash-multiline-assignment
# 0-second-failed all 22 forks 2026-06-12).
#
# Emit BOTH ${PREFIX}_PRECOMPILED_WHEEL_COMMIT and
# ${PREFIX}_MERGE_BASE_COMMIT to the same SHA — different
# Dockerfile carries may key off either name (vllm-bot's carry
# uses MERGE_BASE_COMMIT; theoretical future carries may use
# the more-explicit PRECOMPILED_WHEEL_COMMIT). Both work.
# Honest-fact #105.
PREFIX="${PRECOMPILED_PREFIX:-VLLM}"
EXTRA=$(printf '%s_USE_PRECOMPILED=1\n%s_PRECOMPILED_WHEEL_COMMIT=%s\n%s_MERGE_BASE_COMMIT=%s\n%s_PRECOMPILED_WHEEL_VARIANT=%s\n%s_PRECOMPILED_WHEEL_BASE_URL=%s' "$PREFIX" "$PREFIX" "$PRECOMPILED_COMMIT" "$PREFIX" "$PRECOMPILED_COMMIT" "$PREFIX" "$PRECOMPILED_VARIANT" "$PREFIX" "$PRECOMPILED_BASE_URL")
if [ -n "$BARGS" ]; then
BARGS="${BARGS}"$'\n'"${EXTRA}"
else
BARGS="${EXTRA}"
fi
echo " ✓ precompiled-wheel build-args appended (prefix=${PREFIX} commit=${PRECOMPILED_COMMIT} variant=${PRECOMPILED_VARIANT})"
elif [ -n "${PRECOMPILED_BASE_URL:-}" ] && [ -z "${PRECOMPILED_COMMIT:-}" ]; then
# Master switch on, but no resolved commit. Sync-upstream cleared it
# because no wheel published for the current upstream SHA. Build will
# fall back to source compile — degraded perf, but correct binaries
# (vs the silent-ABI-break risk of serving a stale wheel).
echo "::warning::PRECOMPILED_WHEEL_BASE_URL set but PRECOMPILED_WHEEL_COMMIT empty — sync-upstream couldn't find a wheel for current upstream SHA. Falling back to source compile."
fi
{
echo "build_args<<__EOB__"
echo "$BARGS"
echo "__EOB__"
} >> "$GITHUB_OUTPUT"
- name: 🚀 Build & push
if: steps.df.outputs.skip != 'true'
uses: docker/build-push-action@v6
with:
context: ${{ vars.BUILD_CONTEXT || '.' }}
file: ${{ steps.df.outputs.path }}
platforms: ${{ vars.PLATFORMS || 'linux/amd64,linux/arm64' }}
# build-args synthesized above. Combines operator-set BUILD_ARGS with
# auto-derived precompiled-wheel envs when PRECOMPILED_WHEEL_BASE_URL
# is set. For forks without it, equivalent to BUILD_ARGS alone.
# Honest-facts #88, #99.
build-args: ${{ steps.bargs.outputs.build_args }}
# BuildKit registry-cache. Reuses prior build's intermediate layers
# across runs to dramatically cut wall time on warm builds (vllm:
# ~30min → ~10-12min target). cache-from is read-only — first run on
# a fresh fork misses everything (cold cache, no penalty). cache-to
# `mode=max` exports ALL intermediate stages (not just the final
# image), so the next run can resume mid-stage. `compression=zstd`
# for faster decompression on cache pulls.
# ignore-error=true on cache-to: if the push to :buildcache fails
# (perms, network), the build still succeeds; just warm cache misses
# on next run. Honest-fact #107.
cache-from: type=registry,ref=${{ steps.imgname.outputs.image }}:buildcache
cache-to: type=registry,ref=${{ steps.imgname.outputs.image }}:buildcache,mode=max,compression=zstd,ignore-error=true
push: true
tags: ${{ steps.meta.outputs.tags }}
labels: ${{ steps.meta.outputs.labels }}
provenance: false