2626 required : false
2727 type : string
2828 default : ' '
29+ # New input for hardware-specific initialization (e.g., conda activate)
30+ setup_commands :
31+ required : false
32+ type : string
33+ default : ' '
2934 # Platform-specific build environment variables (JSON object from config)
3035 build_env :
3136 required : false
@@ -115,6 +120,18 @@ jobs:
115120 uses : actions/checkout@v4
116121 with :
117122 set-safe-directory : true
123+
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))"
118135
119136 - name : Environment Setup on Cuda
120137 if : steps.should_run.outputs.should_run == 'true' && inputs.platform == 'cuda'
@@ -212,6 +229,7 @@ jobs:
212229 working-directory : ${{ github.workspace }}
213230 run : |
214231 set -euo pipefail
232+ ${{ inputs.setup_commands }}
215233
216234 # Load platform-specific environment variables
217235 while IFS='=' read -r key value; do
@@ -239,12 +257,11 @@ jobs:
239257 # Ensure log directory exists regardless of volume mount state
240258 mkdir -p /logs
241259
242- # Coverage setup: install once + configure collection via PYTEST_ADDOPTS
243- COVERAGE_ENABLED=false
244- if [ "${{ inputs.upload_coverage }}" = "true" ] && [ "${{ matrix.test_group.test_type }}" = "unittest" ] ; then
245- pip3 install coverage pytest-cov --quiet 2>/dev/null || true
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
246264 export PYTEST_ADDOPTS="--cov=transformer_engine --cov-append --cov-report="
247- COVERAGE_ENABLED=true
248265 fi
249266
250267 if [[ "${{ matrix.test_group.name }}" == *"lint"* ]]; then
@@ -257,39 +274,55 @@ jobs:
257274 fi
258275
259276 bash ${{ matrix.test_group.path }}
260- exit_code=$?
261-
262- # Combine coverage fragments and generate JSON report
263- if [ "$COVERAGE_ENABLED" = "true" ]; then
264- python3 -m coverage combine --keep 2>/dev/null || true
265- python3 -m coverage json \
266- -o "coverage-${{ inputs.platform }}-${{ inputs.device }}-${{ matrix.test_group.name }}.json" \
267- --include="transformer_engine/*" 2>/dev/null \
268- || echo "WARNING: No coverage data found"
269- fi
270-
271- exit $exit_code
272277 timeout-minutes : 60
273278
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
295+
274296 - name : Upload Coverage Report
275297 if : inputs.upload_coverage && matrix.test_group.test_type == 'unittest'
276298 uses : actions/upload-artifact@v4
277299 continue-on-error : true
278300 with :
279- name : coverage-${{ inputs.platform }}-${{ inputs.device }}-${{ matrix.test_group.name }}
301+ name : coverage-${{ inputs.platform }}-${{ inputs.device }}
280302 path : |
281- coverage-${{ inputs.platform }}-${{ inputs.device }}-${{ matrix.test_group.name }} .json
303+ coverage-${{ inputs.platform }}-${{ inputs.device }}.json
282304
283- - name : Upload Coverage Report to FlagCICD
305+ - name : Check FlagCICD Reachability
284306 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
317+
318+ - name : Upload Coverage Report to FlagCICD
319+ if : inputs.upload_coverage && matrix.test_group.test_type == 'unittest' && steps.check_flagcicd.outputs.reachable == 'true'
285320 uses : flagos-ai/FlagOps/actions/post-pytest-report@v2
286321 continue-on-error : true
287- env :
288- NO_PROXY : " flagcicd-inner.flagos.net"
289322 with :
290323 backend_url : ' http://flagcicd-inner.flagos.net:8000/metrics/'
291324 user_id : ' 000000000000000000'
292- report_path : ' coverage-${{ inputs.platform }}-${{ inputs.device }}-${{ matrix.test_group.name }} .json'
325+ report_path : ' coverage-${{ inputs.platform }}-${{ inputs.device }}.json'
293326 fail_on_error : ' false'
294327
295328 # - name: Debug - keep container alive on failure
0 commit comments