@@ -115,23 +115,46 @@ jobs:
115115 # For debugging, you can force this to true
116116 echo "should_run=true" >> $GITHUB_OUTPUT
117117
118- - name : Checkout Source Code
119- if : steps.should_run.outputs.should_run == 'true'
118+ # Cuda requires git safe.directory configuration and 3 checkout attempts to handle submodule-heavy repos
119+ - name : Configure Git Safe Directory on Cuda
120+ if : steps.should_run.outputs.should_run == 'true' && inputs.platform == 'cuda'
121+ run : /usr/bin/git config --global safe.directory '*'
122+
123+ - name : Checkout Source Code on Cuda (attempt 1)
124+ id : checkout1
125+ if : steps.should_run.outputs.should_run == 'true' && inputs.platform == 'cuda'
120126 uses : actions/checkout@v4
127+ continue-on-error : true
121128 with :
129+ fetch-depth : 0
130+ submodules : recursive
122131 set-safe-directory : true
123132
124- # - name: Activate Python environment
125- # run: |
126- # if [[ "$PLATFORM" == "cuda" ]] && [ -f /opt/miniconda3/etc/profile.d/conda.sh ]; then
127- # source /opt/miniconda3/etc/profile.d/conda.sh
128- # conda activate flagscale-train
129- # elif [ -f /opt/conda/etc/profile.d/conda.sh ]; then
130- # source /opt/conda/etc/profile.d/conda.sh
131- # conda activate base
132- # fi
133- # echo "PATH=$PATH" >> $GITHUB_ENV
134- # echo "Python: $(which python3) ($(python3 --version 2>&1))"
133+ - name : Checkout Source Code on Cuda (attempt 2)
134+ id : checkout2
135+ if : steps.should_run.outputs.should_run == 'true' && inputs.platform == 'cuda' && steps.checkout1.outcome == 'failure'
136+ uses : actions/checkout@v4
137+ continue-on-error : true
138+ with :
139+ fetch-depth : 0
140+ submodules : recursive
141+ set-safe-directory : true
142+
143+ - name : Checkout Source Code on Cuda (attempt 3)
144+ id : checkout3
145+ if : steps.should_run.outputs.should_run == 'true' && inputs.platform == 'cuda' && steps.checkout2.outcome == 'failure'
146+ uses : actions/checkout@v4
147+ with :
148+ fetch-depth : 0
149+ submodules : recursive
150+ set-safe-directory : true
151+
152+ # Metax no need submodules
153+ - name : Checkout Source Code on Metax
154+ if : steps.should_run.outputs.should_run == 'true' && inputs.platform == 'metax'
155+ uses : actions/checkout@v4
156+ with :
157+ fetch-depth : 0
135158
136159 - name : Environment Setup on Cuda
137160 if : steps.should_run.outputs.should_run == 'true' && inputs.platform == 'cuda'
@@ -149,8 +172,10 @@ jobs:
149172
150173 echo "===== Step 2: Build & Install TransformerEngine ====="
151174 cd $GITHUB_WORKSPACE
152- pip install nvdlfw-inspect --no-deps
153- pip install --no-build-isolation . -v --no-deps
175+
176+ pip install nvdlfw-inspect --quiet
177+ pip install expecttest --quiet
178+ pip install . -v --no-deps --no-build-isolation
154179
155180 echo "===== Step 3: Verify Installation ====="
156181 python3 tests/pytorch/test_sanity_import.py
@@ -186,7 +211,8 @@ jobs:
186211 echo "===== Step 4: Remove Existing TransformerEngine ====="
187212 # Prevent conflicts with preinstalled or incompatible versions
188213 python3 -m pip uninstall transformer_engine -y || true
189- python3 -m pip install nvdlfw-inspect --no-deps || true
214+ python3 -m pip install nvdlfw-inspect --quiet
215+ python3 -m pip install expecttest --quiet
190216
191217 # echo "===== Step 5: Install Metax Binary Backend ====="
192218 # # Install prebuilt Metax backend (required for MACA operators)
@@ -229,7 +255,6 @@ jobs:
229255 working-directory : ${{ github.workspace }}
230256 run : |
231257 set -euo pipefail
232- ${{ inputs.setup_commands }}
233258
234259 # Load platform-specific environment variables
235260 while IFS='=' read -r key value; do
@@ -257,11 +282,15 @@ jobs:
257282 # Ensure log directory exists regardless of volume mount state
258283 mkdir -p /logs
259284
260- # Enable coverage collection for all pytest invocations in test.sh
261- # PYTEST_ADDOPTS is automatically appended to every pytest call
262- if [ "${{ inputs.upload_coverage }}" = "true" ]; then
263- pip3 install pytest-cov 2>/dev/null || true
264- export PYTEST_ADDOPTS="--cov=transformer_engine --cov-append --cov-report="
285+ # Coverage setup: install once + configure collection via PYTEST_ADDOPTS
286+ COVERAGE_ENABLED=false
287+ if [ "${{ inputs.upload_coverage }}" = "true" ] && [ "${{ matrix.test_group.test_type }}" = "unittest" ]; then
288+ if pip3 install coverage pytest-cov --quiet 2>/dev/null; then
289+ export PYTEST_ADDOPTS="--cov=transformer_engine --cov-append --cov-report="
290+ COVERAGE_ENABLED=true
291+ else
292+ echo "WARNING: Failed to install coverage/pytest-cov, coverage collection disabled"
293+ fi
265294 fi
266295
267296 if [[ "${{ matrix.test_group.name }}" == *"lint"* ]]; then
@@ -274,55 +303,39 @@ jobs:
274303 fi
275304
276305 bash ${{ matrix.test_group.path }}
277- timeout-minutes : 60
306+ exit_code=$?
307+
308+ # Combine coverage fragments and generate JSON report
309+ if [ "$COVERAGE_ENABLED" = "true" ]; then
310+ python3 -m coverage combine --keep 2>/dev/null || true
311+ python3 -m coverage json \
312+ -o "coverage-${{ inputs.platform }}-${{ inputs.device }}-${{ matrix.test_group.name }}.json" \
313+ --include="transformer_engine/*" 2>/dev/null \
314+ || echo "WARNING: No coverage data found"
315+ fi
278316
279- - name : Generate Coverage Report
280- if : inputs.upload_coverage && matrix.test_group.test_type == 'unittest'
281- working-directory : ${{ github.workspace }}
282- env :
283- PLATFORM : ${{ inputs.platform }}
284- DEVICE : ${{ inputs.device }}
285- run : |
286- # Install coverage (may already be present)
287- pip3 install coverage pytest-cov 2>/dev/null || true
288-
289- # Merge all .coverage* files produced by sub-processes (torchrun spawns workers)
290- python3 -m coverage combine --keep 2>/dev/null || true
291- # Generate JSON coverage report (requires .coverage data from pytest --cov)
292- python3 -m coverage json -o "coverage-${PLATFORM}-${DEVICE}.json" \
293- --include="transformer_engine/*" 2>/dev/null || echo "WARNING: No coverage data found, skipping coverage-${PLATFORM}-${DEVICE}.json"
294- continue-on-error : true
317+ exit $exit_code
318+ timeout-minutes : 60
295319
296320 - name : Upload Coverage Report
297321 if : inputs.upload_coverage && matrix.test_group.test_type == 'unittest'
298322 uses : actions/upload-artifact@v4
299323 continue-on-error : true
300324 with :
301- name : coverage-${{ inputs.platform }}-${{ inputs.device }}
325+ name : coverage-${{ inputs.platform }}-${{ inputs.device }}-${{ matrix.test_group.name }}
302326 path : |
303- coverage-${{ inputs.platform }}-${{ inputs.device }}.json
304-
305- - name : Check FlagCICD Reachability
306- if : inputs.upload_coverage && matrix.test_group.test_type == 'unittest'
307- id : check_flagcicd
308- continue-on-error : true
309- run : |
310- if curl -sf --max-time 3 --connect-timeout 2 \
311- "http://flagcicd-inner.flagos.net:8000/" -o /dev/null 2>/dev/null; then
312- echo "reachable=true" >> $GITHUB_OUTPUT
313- else
314- echo "reachable=false" >> $GITHUB_OUTPUT
315- echo "INFO: flagcicd-inner.flagos.net unreachable from this runner, skipping report upload"
316- fi
327+ coverage-${{ inputs.platform }}-${{ inputs.device }}-${{ matrix.test_group.name }}.json
317328
318329 - name : Upload Coverage Report to FlagCICD
319- if : inputs.upload_coverage && matrix.test_group.test_type == 'unittest' && steps.check_flagcicd.outputs.reachable == 'true'
330+ if : inputs.upload_coverage && matrix.test_group.test_type == 'unittest'
320331 uses : flagos-ai/FlagOps/actions/post-pytest-report@v2
321332 continue-on-error : true
333+ env :
334+ NO_PROXY : " flagcicd-inner.flagos.net"
322335 with :
323336 backend_url : ' http://flagcicd-inner.flagos.net:8000/metrics/'
324337 user_id : ' 000000000000000000'
325- report_path : ' coverage-${{ inputs.platform }}-${{ inputs.device }}.json'
338+ report_path : ' coverage-${{ inputs.platform }}-${{ inputs.device }}-${{ matrix.test_group.name }} .json'
326339 fail_on_error : ' false'
327340
328341 # - name: Debug - keep container alive on failure
0 commit comments