# SPDX-FileCopyrightText: Copyright (c) 2025-2026 NVIDIA CORPORATION & AFFILIATES. All rights reserved. # SPDX-License-Identifier: Apache-2.0 # Reusable workflow: generate Allure reports and deploy to GitHub Pages. # Called by pr.yaml (pre-merge) and allure-report.yml (post-merge/nightly/release). name: Generate Allure Report on: workflow_call: inputs: run_id: description: 'Workflow run ID to download allure-results artifacts from' required: true type: string subdir: description: 'Subdirectory under allure/ on gh-pages (e.g. pr, post-merge, nightly, release)' required: true type: string workflow_label: description: 'Workflow label injected into allure results for dashboard filtering' required: true type: string permissions: contents: write actions: read jobs: generate-and-deploy: runs-on: ubuntu-latest steps: - uses: actions/checkout@34e114876b0b11c390a56381ad16ebd13914f8d5 # v4.3.1 - name: Download Allure Results uses: actions/download-artifact@d3f86a106a0bac45b974a628896c90dbdf5c8093 # v4.3.0 with: run-id: ${{ inputs.run_id }} pattern: allure-results-* path: allure-results merge-multiple: true github-token: ${{ github.token }} - name: Check for Allure results id: check-results run: | if [ -d allure-results ] && [ "$(ls -A allure-results 2>/dev/null)" ]; then echo "has_results=true" >> $GITHUB_OUTPUT echo "Found allure results:" ls -la allure-results/ else echo "has_results=false" >> $GITHUB_OUTPUT echo "No allure results found. Skipping report generation." fi - name: Inject workflow label and CI link into allure results if: steps.check-results.outputs.has_results == 'true' env: WORKFLOW_LABEL: ${{ inputs.workflow_label }} RUN_URL: ${{ github.server_url }}/${{ github.repository }}/actions/runs/${{ inputs.run_id }} run: | # Inject dynamo_workflow label (for dashboard filtering) and CI run link # (for tracing test failures to the originating workflow run) into all # result files. Uses the triggering run_id, not the generating run, # so imported results in the unified dashboard link to the correct run. python3 -c " import json, glob, sys wf, run_url = sys.argv[1], sys.argv[2] for f in glob.glob('allure-results/*-result.json'): with open(f, 'r') as fh: data = json.load(fh) labels = data.setdefault('labels', []) if not any(l.get('name') == 'dynamo_workflow' for l in labels): labels.append({'name': 'dynamo_workflow', 'value': wf}) links = data.setdefault('links', []) if not any(l.get('name') == 'CI Run' for l in links): links.append({'name': 'CI Run', 'url': run_url, 'type': 'custom'}) with open(f, 'w') as fh: json.dump(data, fh) " "$WORKFLOW_LABEL" "$RUN_URL" - name: Install Allure 2 CLI if: steps.check-results.outputs.has_results == 'true' run: | ALLURE_VERSION="2.38.0" wget -q "https://github.com/allure-framework/allure2/releases/download/${ALLURE_VERSION}/allure-${ALLURE_VERSION}.tgz" tar -xzf "allure-${ALLURE_VERSION}.tgz" mv "allure-${ALLURE_VERSION}" allure2-cli - name: Install Allure 3 CLI if: steps.check-results.outputs.has_results == 'true' run: | npm install allure@3.3.1 - name: Get Allure history from gh-pages if: steps.check-results.outputs.has_results == 'true' env: SUBDIR: ${{ inputs.subdir }} run: | git fetch --depth=1 origin gh-pages:gh-pages 2>/dev/null || echo "No gh-pages branch yet" # Restore history for Allure 2 report (at allure/v2/${SUBDIR}/) if git show "gh-pages:allure/v2/${SUBDIR}/history" 2>/dev/null; then mkdir -p allure-results/history for f in history.json history-trend.json duration-trend.json categories-trend.json retry-trend.json; do git show "gh-pages:allure/v2/${SUBDIR}/history/$f" > "allure-results/history/$f" 2>/dev/null || true done echo "Restored Allure 2 history from gh-pages/allure/v2/${SUBDIR}" else echo "No previous Allure 2 history found" fi - name: Generate Allure 2 Report if: steps.check-results.outputs.has_results == 'true' run: | ./allure2-cli/bin/allure generate allure-results -o allure-report --clean - name: Generate unified dashboard if: steps.check-results.outputs.has_results == 'true' env: SUBDIR: ${{ inputs.subdir }} run: | # Combine this workflow's results with stored results from other workflows mkdir -p unified-workspace/allure-results # Copy this workflow's results (exclude Allure 2 history dir) rsync -a --exclude='history' allure-results/ unified-workspace/allure-results/ # Fetch stored results from other workflows on gh-pages (redundant if already fetched above, harmless) git fetch --depth=1 origin gh-pages:gh-pages 2>/dev/null || true for dir in pr post-merge nightly release; do if [ "$dir" = "$SUBDIR" ]; then continue; fi if git show "gh-pages:dashboard-results/${dir}" 2>/dev/null; then git archive gh-pages "dashboard-results/${dir}" | tar -x -C /tmp/ cp -r "/tmp/dashboard-results/${dir}/"* "unified-workspace/allure-results/" 2>/dev/null || true fi done # Restore unified dashboard history for trend charts. # historyPath in allurerc.mjs resolves relative to process.cwd(), not --cwd, # so the file must be at $GITHUB_WORKSPACE/history.jsonl. if git show "gh-pages:allure/history.jsonl" 2>/dev/null; then git show "gh-pages:allure/history.jsonl" > "${GITHUB_WORKSPACE}/history.jsonl" echo "Restored unified dashboard history from gh-pages" else echo "No previous unified dashboard history found — Allure 3 will create it" fi # Generate unified dashboard using allurerc.mjs npx allure generate --config="${GITHUB_WORKSPACE}/.github/allurerc.mjs" --cwd unified-workspace -o allure-all-report - name: Deploy to GitHub Pages if: steps.check-results.outputs.has_results == 'true' env: SUBDIR: ${{ inputs.subdir }} run: | DEPLOY_DIR=$(mktemp -d) cd "$DEPLOY_DIR" git init git remote add origin "${GITHUB_SERVER_URL}/${GITHUB_REPOSITORY}.git" git config user.name "github-actions[bot]" git config user.email "github-actions[bot]@users.noreply.github.com" git config http.https://github.com/.extraheader "AUTHORIZATION: basic $(echo -n "x-access-token:${{ github.token }}" | base64)" # Apply all report files on top of the latest gh-pages state. # Extracted as a function so it can be re-run on push conflict. apply_changes() { if git ls-remote --exit-code origin gh-pages &>/dev/null; then git fetch --depth=1 origin gh-pages git checkout -B gh-pages FETCH_HEAD else git checkout --orphan gh-pages git rm -rf . 2>/dev/null || true fi # Deploy Allure 2 report mkdir -p "allure/v2/${SUBDIR}" rm -rf "allure/v2/${SUBDIR}/"* cp -r "${GITHUB_WORKSPACE}/allure-report/"* "allure/v2/${SUBDIR}/" # Store raw results for unified dashboard aggregation (exclude Allure 2 history) mkdir -p "dashboard-results/${SUBDIR}" rm -rf "dashboard-results/${SUBDIR}/"* rsync -a --exclude='history' "${GITHUB_WORKSPACE}/allure-results/" "dashboard-results/${SUBDIR}/" # Deploy unified dashboard (per-workflow tabs generated by allurerc.mjs plugins) # Clean plugin tabs first — each run generates fresh files with unique UUIDs, # and cp -r merges rather than replaces, causing unbounded file accumulation. rm -rf allure/pr allure/postMerge allure/nightly allure/release \ allure/vllm allure/sglang allure/trtllm \ allure/post-merge mkdir -p allure cp -r "${GITHUB_WORKSPACE}/allure-all-report/"* allure/ # Persist history.jsonl for trend charts (written by Allure 3 at process.cwd()) if [ -f "${GITHUB_WORKSPACE}/history.jsonl" ]; then cp "${GITHUB_WORKSPACE}/history.jsonl" allure/history.jsonl fi # Stage and commit git add -A if git diff --cached --quiet; then echo "No changes to deploy" return 1 fi git commit -m "Deploy Allure reports for ${SUBDIR} (run ${{ github.run_id }})" } # Apply changes and push with retry on conflict. # Concurrent deploys can cause push rejection — retry by fetching # the latest gh-pages and re-applying all changes on top. for attempt in 1 2 3; do apply_changes || exit 0 # exit 0 if no changes if git push origin gh-pages; then echo "Deploy successful (attempt $attempt)" exit 0 fi echo "Push failed (attempt $attempt/3), waiting 5s before retrying..." sleep 5 done echo "::error::Deploy failed after 3 attempts" exit 1 - name: Print report URLs if: steps.check-results.outputs.has_results == 'true' env: SUBDIR: ${{ inputs.subdir }} run: | echo "## Allure Reports" >> $GITHUB_STEP_SUMMARY echo "" >> $GITHUB_STEP_SUMMARY echo "- [Allure Dashboard](https://ai-dynamo.github.io/dynamo/allure/)" >> $GITHUB_STEP_SUMMARY echo "- [Allure 2 Report](https://ai-dynamo.github.io/dynamo/allure/v2/${SUBDIR}/)" >> $GITHUB_STEP_SUMMARY