-
Notifications
You must be signed in to change notification settings - Fork 67
Expand file tree
/
Copy path.gitlab-ci.yml
More file actions
332 lines (296 loc) · 12.4 KB
/
Copy path.gitlab-ci.yml
File metadata and controls
332 lines (296 loc) · 12.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
# SPDX-FileCopyrightText: Copyright (c) 2026, NVIDIA CORPORATION & AFFILIATES. All rights reserved.
# SPDX-License-Identifier: Apache-2.0
# Push a raw SemVer tag, such as `0.1.0` or `0.1.0-alpha.20260515`,
# to run the publishing pipeline.
workflow:
rules:
- if: $CI_PIPELINE_SOURCE == 'push' && $CI_COMMIT_TAG
- if: $CI_PIPELINE_SOURCE == 'push' && $CI_COMMIT_BRANCH
- when: never
stages:
- check
- collect
- publish
variables:
NEMO_RELAY_CI_DEBIAN_VERSION: "trixie"
# Artifactory 7.133 rejects Cargo 1.96's required octet-stream publish header.
NEMO_RELAY_CI_CARGO_PUBLISH_VERSION: "1.93.0"
NEMO_RELAY_CI_JUST_VERSION: "1.40.0"
NEMO_RELAY_CI_NODE_VERSION: "24"
NEMO_RELAY_CI_PYTHON_VERSION: "3.11"
NEMO_RELAY_CI_RUST_VERSION: "1.96.1"
NEMO_RELAY_CI_UV_VERSION: "0.9.28"
NEMO_RELAY_CI_GITHUB_REPOSITORY: "NVIDIA/NeMo-Relay"
NEMO_RELAY_CI_GITHUB_WORKFLOW_FILE: "ci.yaml"
NEMO_RELAY_CI_GITHUB_RUN_WAIT_SECONDS: "7200"
NEMO_RELAY_CI_GITHUB_RUN_POLL_SECONDS: "60"
check:sonar:
stage: check
image:
name: sonarsource/sonar-scanner-cli:latest
pull_policy: if-not-present
entrypoint: [""]
variables:
SONAR_USER_HOME: "${CI_PROJECT_DIR}/.sonar"
GIT_DEPTH: "0"
cache:
key: "${CI_JOB_NAME}"
paths:
- .sonar/cache
rules:
- if: $CI_PIPELINE_SOURCE == 'push' && $CI_COMMIT_BRANCH
- when: never
script:
- sonar-scanner
allow_failure: true
collect:github-artifacts:
stage: collect
image:
name: alpine:3.22
pull_policy: if-not-present
rules:
- if: $CI_PIPELINE_SOURCE == 'push' && $CI_COMMIT_TAG
- when: never
before_script:
- apk add --no-cache findutils github-cli unzip
script:
- |
set -eu
if [ -z "${NEMO_RELAY_CI_GITHUB_TOKEN:-}" ]; then
echo "Error: NEMO_RELAY_CI_GITHUB_TOKEN is required to download GitHub Actions artifacts." >&2
exit 1
fi
export GH_TOKEN="${NEMO_RELAY_CI_GITHUB_TOKEN}"
mkdir -p collected/wheels collected/sdists collected/node downloaded
tag="${CI_COMMIT_TAG:-}"
if [ -z "$tag" ]; then
echo "Error: CI_COMMIT_TAG is required to collect GitHub Actions artifacts for publishing." >&2
exit 1
fi
tag_ref="tags/${tag}"
deadline="$(( $(date -u +%s) + NEMO_RELAY_CI_GITHUB_RUN_WAIT_SECONDS ))"
echo "Waiting for tag ${tag} in ${NEMO_RELAY_CI_GITHUB_REPOSITORY}"
while ! gh api "repos/${NEMO_RELAY_CI_GITHUB_REPOSITORY}/git/ref/${tag_ref}" >/dev/null 2>&1; do
if [ "$(date -u +%s)" -ge "$deadline" ]; then
echo "Error: tag ${tag} did not appear within ${NEMO_RELAY_CI_GITHUB_RUN_WAIT_SECONDS} seconds." >&2
exit 1
fi
sleep "$NEMO_RELAY_CI_GITHUB_RUN_POLL_SECONDS"
done
echo "Waiting for ${NEMO_RELAY_CI_GITHUB_WORKFLOW_FILE} run for tag ${tag}"
run_id=""
while [ -z "$run_id" ]; do
run_id="$(
gh run list \
--repo "$NEMO_RELAY_CI_GITHUB_REPOSITORY" \
--workflow "$NEMO_RELAY_CI_GITHUB_WORKFLOW_FILE" \
--event push \
--branch "$tag" \
--limit 1 \
--json databaseId \
--jq '.[0].databaseId // ""'
)"
if [ -n "$run_id" ]; then
break
fi
if [ "$(date -u +%s)" -ge "$deadline" ]; then
echo "Error: no GitHub Actions run found for tag ${tag} within ${NEMO_RELAY_CI_GITHUB_RUN_WAIT_SECONDS} seconds." >&2
exit 1
fi
sleep "$NEMO_RELAY_CI_GITHUB_RUN_POLL_SECONDS"
done
if [ -z "$run_id" ]; then
echo "Error: no GitHub Actions run found for tag ${tag}." >&2
exit 1
fi
run_html_url="$(
gh run view "$run_id" \
--repo "$NEMO_RELAY_CI_GITHUB_REPOSITORY" \
--json url \
--jq '.url'
)"
echo "Watching GitHub Actions run ${run_id} for tag ${tag}: ${run_html_url}"
if ! timeout "$NEMO_RELAY_CI_GITHUB_RUN_WAIT_SECONDS" \
gh run watch "$run_id" \
--repo "$NEMO_RELAY_CI_GITHUB_REPOSITORY" \
--interval "$NEMO_RELAY_CI_GITHUB_RUN_POLL_SECONDS" \
--exit-status; then
echo "Error: GitHub Actions run ${run_id} for tag ${tag} failed, was cancelled, or did not complete within ${NEMO_RELAY_CI_GITHUB_RUN_WAIT_SECONDS} seconds: ${run_html_url}" >&2
exit 1
fi
gh run download "$run_id" --repo "$NEMO_RELAY_CI_GITHUB_REPOSITORY" --pattern 'wheel-*' --dir downloaded/wheels
gh run download "$run_id" --repo "$NEMO_RELAY_CI_GITHUB_REPOSITORY" --pattern 'cli-python-wheel-*' --dir downloaded/cli-wheels
gh run download "$run_id" --repo "$NEMO_RELAY_CI_GITHUB_REPOSITORY" --name 'plugin-wheel' --dir downloaded/wheels
gh run download "$run_id" --repo "$NEMO_RELAY_CI_GITHUB_REPOSITORY" --name 'python-sdist' --dir downloaded/sdists
gh run download "$run_id" --repo "$NEMO_RELAY_CI_GITHUB_REPOSITORY" --pattern 'node-npm-package-*' --dir downloaded/node
find downloaded/wheels -type f -name '*.whl' -exec cp {} collected/wheels/ \;
find downloaded/cli-wheels -type f -name '*.whl' -exec cp {} collected/wheels/ \;
find downloaded/sdists -type f -name 'nemo_relay-*.tar.gz' -exec cp {} collected/sdists/ \;
find downloaded/node -type f -name '*.tgz' -exec cp {} collected/node/ \;
if ! ls collected/wheels/*.whl >/dev/null 2>&1; then
echo "Error: collected GitHub wheel artifacts did not contain any .whl files." >&2
exit 1
fi
if ! ls collected/sdists/nemo_relay-*.tar.gz >/dev/null 2>&1; then
echo "Error: collected GitHub Python source distribution artifact did not contain a nemo-relay sdist." >&2
exit 1
fi
if ! ls collected/node/*.tgz >/dev/null 2>&1; then
echo "Error: collected GitHub Node artifacts did not contain any .tgz files." >&2
exit 1
fi
{
printf '{\n'
printf ' "run_id": "%s",\n' "$run_id"
printf ' "run_url": "%s",\n' "$run_html_url"
printf ' "workflow": "%s",\n' "$NEMO_RELAY_CI_GITHUB_WORKFLOW_FILE"
printf ' "tag": "%s"\n' "$tag"
printf '}\n'
} > collected/github-run.json
artifacts:
name: github-package-artifacts
when: on_success
expire_in: 7 days
paths:
- collected/wheels/*.whl
- collected/sdists/nemo_relay-*.tar.gz
- collected/node/*.tgz
- collected/github-run.json
publish:artifactory:wheels:
stage: publish
image:
name: ghcr.io/astral-sh/uv:${NEMO_RELAY_CI_UV_VERSION}-${NEMO_RELAY_CI_DEBIAN_VERSION}-slim
pull_policy: if-not-present
rules:
- if: $CI_PIPELINE_SOURCE == 'push' && $CI_COMMIT_TAG
- when: never
needs:
- job: collect:github-artifacts
artifacts: true
script:
- |
set -eu
if [ -z "${NEMO_RELAY_CI_ARTIFACTORY_USER:-}" ] || [ -z "${NEMO_RELAY_CI_ARTIFACTORY_KEY:-}" ] || [ -z "${NEMO_RELAY_CI_ARTIFACTORY_PYPI_URL:-}" ]; then
echo "Error: uploading Python package artifacts to Artifactory requires NEMO_RELAY_CI_ARTIFACTORY_USER, NEMO_RELAY_CI_ARTIFACTORY_KEY, and NEMO_RELAY_CI_ARTIFACTORY_PYPI_URL." >&2
exit 1
fi
if ! ls collected/wheels/*.whl >/dev/null 2>&1 || ! ls collected/sdists/nemo_relay-*.tar.gz >/dev/null 2>&1; then
echo "Error: no complete set of collected Python package artifacts found." >&2
exit 1
fi
UV_PUBLISH_USERNAME="${NEMO_RELAY_CI_ARTIFACTORY_USER}" \
UV_PUBLISH_PASSWORD="${NEMO_RELAY_CI_ARTIFACTORY_KEY}" \
UV_PUBLISH_URL="${NEMO_RELAY_CI_ARTIFACTORY_PYPI_URL}" \
uv publish --no-progress collected/wheels/*.whl collected/sdists/nemo_relay-*.tar.gz
publish:artifactory:cargo:
stage: publish
image:
name: rust:${NEMO_RELAY_CI_RUST_VERSION}-${NEMO_RELAY_CI_DEBIAN_VERSION}
pull_policy: if-not-present
rules:
- if: $CI_PIPELINE_SOURCE == 'push' && $CI_COMMIT_TAG
- when: never
needs:
- job: collect:github-artifacts
artifacts: true
before_script:
- apt-get update -qq && apt-get install -y --no-install-recommends ca-certificates curl git nodejs && rm -rf /var/lib/apt/lists/*
- rustup toolchain install --profile minimal "${NEMO_RELAY_CI_CARGO_PUBLISH_VERSION}"
- cargo install just --version "${NEMO_RELAY_CI_JUST_VERSION}" --locked
- curl -LsSf https://astral.sh/uv/install.sh -o /tmp/install-uv.sh
- UV_VERSION="${NEMO_RELAY_CI_UV_VERSION}" sh /tmp/install-uv.sh
- export PATH="${HOME}/.cargo/bin:${HOME}/.local/bin:${PATH}"
- uv python install "${NEMO_RELAY_CI_PYTHON_VERSION}"
- rustc --version
- just --version
- uv --version
script:
- |
set -eu
if [ -z "${NEMO_RELAY_CI_ARTIFACTORY_KEY:-}" ] || [ -z "${NEMO_RELAY_CI_ARTIFACTORY_CARGO_URL:-}" ]; then
echo "Error: uploading Cargo crates to Artifactory requires NEMO_RELAY_CI_ARTIFACTORY_KEY and NEMO_RELAY_CI_ARTIFACTORY_CARGO_URL." >&2
exit 1
fi
if [ ! -f collected/github-run.json ]; then
echo "Error: no collected GitHub run metadata found." >&2
exit 1
fi
publish_cargo="$(rustup which --toolchain "${NEMO_RELAY_CI_CARGO_PUBLISH_VERSION}" cargo)"
publish_rustc="$(rustup which rustc)"
"$publish_cargo" --version
"$publish_rustc" --version
version="$(
uv run --no-project python - <<'PY'
import json
from pathlib import Path
print(json.loads(Path("collected/github-run.json").read_text()).get("tag", ""))
PY
)"
if [ -z "$version" ]; then
echo "Error: failed to extract package version from collected GitHub tag metadata." >&2
exit 1
fi
just set-version "$version"
cargo_home="${CARGO_HOME:-${HOME}/.cargo}"
mkdir -p "$cargo_home"
cat > "${cargo_home}/config.toml" <<EOF
[registry]
global-credential-providers = ["cargo:token"]
[registries]
artifactory = { index = "sparse+${NEMO_RELAY_CI_ARTIFACTORY_CARGO_URL}" }
EOF
export CARGO_REGISTRIES_ARTIFACTORY_TOKEN="Bearer ${NEMO_RELAY_CI_ARTIFACTORY_KEY}"
export NEMO_RELAY_ARTIFACTORY_CRATE_DIRS="types plugin worker-proto worker core adaptive pii-redaction ffi cli"
crates="$(
uv run --no-project python - <<'PY'
import os
import tomllib
from pathlib import Path
manifest = Path("Cargo.toml")
text = manifest.read_text()
for crate_dir in os.environ["NEMO_RELAY_ARTIFACTORY_CRATE_DIRS"].split():
before = f'path = "crates/{crate_dir}"'
after = f'{before}, registry = "artifactory"'
if after not in text:
text = text.replace(before, after)
manifest.write_text(text)
for crate_dir in os.environ["NEMO_RELAY_ARTIFACTORY_CRATE_DIRS"].split():
crate_manifest = Path("crates") / crate_dir / "Cargo.toml"
print(tomllib.loads(crate_manifest.read_text())["package"]["name"])
PY
)"
for crate in $crates; do
RUSTC="$publish_rustc" "$publish_cargo" publish --package "$crate" --registry artifactory --allow-dirty
done
publish:artifactory:npm:
stage: publish
image:
name: node:${NEMO_RELAY_CI_NODE_VERSION}-${NEMO_RELAY_CI_DEBIAN_VERSION}
pull_policy: if-not-present
rules:
- if: $CI_PIPELINE_SOURCE == 'push' && $CI_COMMIT_TAG
- when: never
needs:
- job: collect:github-artifacts
artifacts: true
script:
- |
set -eu
if [ -z "${NEMO_RELAY_CI_ARTIFACTORY_USER:-}" ] || [ -z "${NEMO_RELAY_CI_ARTIFACTORY_KEY:-}" ] || [ -z "${NEMO_RELAY_CI_ARTIFACTORY_NPM_URL:-}" ]; then
echo "Error: uploading npm packages to Artifactory requires NEMO_RELAY_CI_ARTIFACTORY_USER, NEMO_RELAY_CI_ARTIFACTORY_KEY, and NEMO_RELAY_CI_ARTIFACTORY_NPM_URL." >&2
exit 1
fi
if ! ls collected/node/*.tgz >/dev/null 2>&1; then
echo "Error: no collected split Node package artifacts found." >&2
exit 1
fi
registry_url="${NEMO_RELAY_CI_ARTIFACTORY_NPM_URL%/}/"
registry_key="${registry_url#https:}"
npm_auth="$(printf '%s:%s' "${NEMO_RELAY_CI_ARTIFACTORY_USER}" "${NEMO_RELAY_CI_ARTIFACTORY_KEY}" | base64 | tr -d '\n')"
npm config set registry "$registry_url"
npm config set "${registry_key}:_auth" "$npm_auth"
for platform in linux-x64 linux-arm64 linux-x64-musl linux-arm64-musl darwin-arm64 win32-x64 win32-arm64; do
package="collected/node/nemo-relay-node-npm-${platform}-${CI_COMMIT_TAG}.tgz"
npm publish --tag dev "$package"
done
npm publish --tag dev "collected/node/nemo-relay-node-npm-${CI_COMMIT_TAG}.tgz"