@@ -3,6 +3,7 @@ set -euo pipefail
33
44dockerfile=" ${1:- docker/ Dockerfile.ci} "
55workflow=" ${2:- .github/ workflows/ cicd-main.yml} "
6+ fw_final_dockerfile=" ${3:- docker/ Dockerfile.fw_final} "
67
78baseline_arg_line=$( grep -n ' ^ARG BASELINE_MCORE_REF$' " $dockerfile " | cut -d: -f1)
89baseline_clone_line=$( grep -n ' git clone --filter=blob:none --no-checkout' " $dockerfile " | cut -d: -f1)
@@ -24,14 +25,23 @@ trap 'rm -rf "$temporary_dir"' EXIT
2425(( baseline_line < dispatched_copy_line))
2526(( dispatched_copy_line < delta_line))
2627
28+ fw_final_from_line=$( grep -n ' ^FROM ${NEMO_FW_FINAL_BASE_IMAGE} AS nemo_fw_final$' " $fw_final_dockerfile " | cut -d: -f1)
29+ fw_final_root_line=$( grep -n ' ^USER root$' " $fw_final_dockerfile " | cut -d: -f1)
30+ fw_final_clone_line=$( grep -n ' ^RUN git clone --depth 1 https://github.com/NVIDIA-NeMo/NeMo.git' " $fw_final_dockerfile " | cut -d: -f1)
31+ [[ -n " $fw_final_from_line " ]]
32+ [[ -n " $fw_final_root_line " ]]
33+ [[ -n " $fw_final_clone_line " ]]
34+ (( fw_final_from_line < fw_final_root_line))
35+ (( fw_final_root_line < fw_final_clone_line))
36+
2737grep -q -- ' --mount=type=cache,target=/root/.cache/uv' " $dockerfile "
2838if grep -q -- ' --mount=type=secret,id=GH_TOKEN' " $dockerfile " ; then
2939 echo " Baseline MCore clone must not require a GitHub token" >&2
3040 exit 1
3141fi
3242mcore_reinstall_line=$( grep -n ' uv pip install --no-deps --reinstall -e 3rdparty/Megatron-LM' " $dockerfile " | cut -d: -f1)
3343helper_assertion_line=$( grep -n " find 3rdparty/Megatron-LM/megatron/core/datasets -maxdepth 1 -name 'helpers_cpp\*\.so'" " $dockerfile " | cut -d: -f1)
34- final_copy_line=$( grep -n ' ^COPY --chmod=644 \. /opt/Megatron-Bridge$' " $dockerfile " | cut -d: -f1)
44+ final_copy_line=$( grep -nE ' ^COPY ( --chmod=644|--chown=1000:1000) \. /opt/Megatron-Bridge$' " $dockerfile " | cut -d: -f1)
3545[[ -n " $mcore_reinstall_line " ]]
3646[[ -n " $helper_assertion_line " ]]
3747[[ -n " $final_copy_line " ]]
@@ -232,17 +242,59 @@ if "$temporary_dir/revision-validator" "$revision_repo" not-a-full-sha; then
232242 exit 1
233243fi
234244
245+ if ! grep -A1 ' ^te = \[$' pyproject.toml | grep -Fxq ' "megatron-core[te]",' ; then
246+ echo " Bridge's TE extra must enable the selected MCore ref's TE extra" >&2
247+ exit 1
248+ fi
249+ if ! grep -Fq \
250+ ' { name = "megatron-core", extras = ["te"], marker = "extra == ' \' ' te' \' ' ", editable = "3rdparty/Megatron-LM" }' \
251+ uv.lock; then
252+ echo " Bridge's lock metadata must preserve the MCore TE extra" >&2
253+ exit 1
254+ fi
235255if grep -q ' transformer-engine @ git+https://github.com/NVIDIA/TransformerEngine.git@' pyproject.toml || \
236256 grep -q ' ^name = "transformer-engine"$' pyproject.toml; then
237257 echo " Bridge must inherit the TransformerEngine source and metadata from the selected MCore ref" >&2
238258 exit 1
239259fi
240260
261+ lock_package_field () {
262+ local lock_file=" $1 "
263+ local package=" $2 "
264+ local field=" $3 "
265+
266+ awk -v package=" $package " -v field=" $field " '
267+ $0 == "[[package]]" { in_package = 1; package_matches = 0; next }
268+ in_package && $0 ~ /^\[\[/ { in_package = 0; package_matches = 0 }
269+ in_package && $0 == "name = \"" package "\"" { package_matches = 1; next }
270+ package_matches && index($0, field " = ") == 1 { print; exit }
271+ ' " $lock_file "
272+ }
273+
274+ mlm_te_source=$( lock_package_field 3rdparty/Megatron-LM/uv.lock transformer-engine source)
275+ bridge_te_source=$( lock_package_field uv.lock transformer-engine source)
276+ if [[ ! " $mlm_te_source " =~ ^source\ = \ \{\ git\ = \ \" https://github.com/NVIDIA/TransformerEngine\. git\? rev= [0-9a-f]{40}# [0-9a-f]{40}\"\ \}$ ]]; then
277+ echo " Selected MCore lock must pin TransformerEngine to a full source revision" > & 2
278+ exit 1
279+ fi
280+ if [[ " $bridge_te_source " != " $mlm_te_source " ]]; then
281+ echo " Bridge must lock the TransformerEngine source selected by MCore" >&2
282+ exit 1
283+ fi
284+
241285composite_action= " .github/actions/test-template/action.yml"
242286if grep -qE ' mcore_(commit|ref)|MCORE_COMMIT|uv sync --all-extras --all-groups' " $composite_action " ; then
243287 echo " Test template must use the already-validated MCore in the built image" >&2
244288 exit 1
245289fi
290+ grep -Fq ' VOLUME_ARGS="--volume ${{ inputs.test-data-path }}:/home/TestData --env HF_HUB_OFFLINE=1"' " $composite_action "
291+ grep -q ' MOUNT_FS: ${{ inputs.is_unit_test == ' \' ' false' \' ' }}' " $composite_action "
292+ grep -q ' HF_HOME=/home/TestData/HF_HOME' " $composite_action "
293+ grep -q ' NEMO_HOME=/home/TestData/nemo_home' " $composite_action "
294+ grep -q ' HF_HOME=/home/ubuntu/.cache/huggingface' " $composite_action "
295+ grep -q ' NEMO_HOME=/home/ubuntu/.cache/nemo' " $composite_action "
296+ grep -q ' HF_MODULES_CACHE=/home/ubuntu/.cache/huggingface/modules' " $composite_action "
297+ grep -q -- ' --env HF_MODULES_CACHE=\$HF_MODULES_CACHE' " $composite_action "
246298
247299# The baseline dependency layer must be structurally independent of the mutable
248300# dispatched checkout. CI validates the ordering statically so this regression
0 commit comments