# 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 into allure results if: steps.check-results.outputs.has_results == 'true' env: WORKFLOW_LABEL: ${{ inputs.workflow_label }} run: | # The conftest.py hook doesn't fire for all tests, so inject # dynamo_workflow label into all result files to ensure workflow # tiles in the unified dashboard capture every test. python3 -c " import json, glob, sys wf = sys.argv[1] 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}) with open(f, 'w') as fh: json.dump(data, fh) " "$WORKFLOW_LABEL" - 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 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 git fetch 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" # Reuse the checkout token for push access git config http.https://github.com/.extraheader "AUTHORIZATION: basic $(echo -n "x-access-token:${{ github.token }}" | base64)" # Pull existing gh-pages content or start fresh if git ls-remote --exit-code origin gh-pages &>/dev/null; then git fetch origin gh-pages git checkout gh-pages else git checkout --orphan gh-pages 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) 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 # Commit and push git add -A if git diff --cached --quiet; then echo "No changes to deploy" else git commit -m "Deploy Allure reports for ${SUBDIR} (run ${{ github.run_id }})" # Retry push with rebase to handle concurrent gh-pages updates for i in 1 2 3; do if git push origin gh-pages; then break fi echo "Push failed, retrying with rebase (attempt $i/3)..." git fetch origin gh-pages git rebase origin/gh-pages done fi - 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