Skip to content

Nightly Quality Jobs #41

Nightly Quality Jobs

Nightly Quality Jobs #41

# *******************************************************************************
# Copyright (c) 2026 Contributors to the Eclipse Foundation
#
# See the NOTICE file(s) distributed with this work for additional
# information regarding copyright ownership.
#
# This program and the accompanying materials are made available under the
# terms of the Apache License Version 2.0 which is available at
# https://www.apache.org/licenses/LICENSE-2.0
#
# SPDX-License-Identifier: Apache-2.0
# *******************************************************************************
# Workflow: Run nightly quality jobs and publish results to GitHub Pages.
#
# Runs every night at midnight UTC:
# - Coverage : full C++ test suite with llvm-cov → HTML report
# - Clang-Tidy: static analysis across all C++ targets → SARIF findings
# - Clippy : static analysis across all Rust targets → SARIF findings
# - CodeQL : MISRA C++ compliance analysis → CSV findings
#
# After all jobs complete, deploy-quality-reports:
# 1. Downloads the coverage HTML artifact, clang-tidy/clippy SARIF findings, and CodeQL CSV
# 2. Runs `bazel run //quality/dashboard:generate_dashboard` to produce the KPI dashboard
# 3. Uploads everything as nightly-quality-reports artifact for docs.yml to deploy
#
# Deployed URL structure:
# https://eclipse-score.github.io/communication/latest/quality/index.html ← dashboard
# https://eclipse-score.github.io/communication/latest/quality/coverage/index.html ← lcov HTML
# https://eclipse-score.github.io/communication/latest/quality/clang-tidy.sarif ← clang-tidy SARIF
# https://eclipse-score.github.io/communication/latest/quality/clippy.sarif ← clippy SARIF
# https://eclipse-score.github.io/communication/latest/quality/codeql/index.html ← CodeQL report
name: Nightly Quality Jobs
on:
schedule:
- cron: "0 0 * * *" # every day at midnight UTC
workflow_dispatch:
workflow_call:
secrets:
UBUNTU_SNAPSHOT_MIRROR_URL:
required: false
SCORE_QNX_LICENSE:
required: false
SCORE_QNX_USER:
required: false
SCORE_QNX_PASSWORD:
required: false
permissions:
contents: write
env:
FORCE_JAVASCRIPT_ACTIONS_TO_NODE24: true
jobs:
# --------------------------------------------------------------------
# Quality job 1: Coverage
# --------------------------------------------------------------------
run-coverage:
uses: ./.github/workflows/_coverage_report.yml
permissions:
contents: read
actions: write
secrets:
UBUNTU_SNAPSHOT_MIRROR_URL: ${{ secrets.UBUNTU_SNAPSHOT_MIRROR_URL }}
# --------------------------------------------------------------------
# Quality job 2: Linters
# --------------------------------------------------------------------
run-linters:
uses: ./.github/workflows/_linter.yml
permissions:
contents: read
actions: write
security-events: write
secrets:
UBUNTU_SNAPSHOT_MIRROR_URL: ${{ secrets.UBUNTU_SNAPSHOT_MIRROR_URL }}
# --------------------------------------------------------------------
# Quality job 3: CodeQL
# --------------------------------------------------------------------
run-codeql:
uses: ./.github/workflows/_codeql.yml
permissions:
contents: read
actions: write
security-events: write
secrets:
UBUNTU_SNAPSHOT_MIRROR_URL: ${{ secrets.UBUNTU_SNAPSHOT_MIRROR_URL }}
SCORE_QNX_LICENSE: ${{ secrets.SCORE_QNX_LICENSE }}
SCORE_QNX_USER: ${{ secrets.SCORE_QNX_USER }}
SCORE_QNX_PASSWORD: ${{ secrets.SCORE_QNX_PASSWORD }}
# --------------------------------------------------------------------
# Collect results, build the dashboard, upload artifact for docs.yml
# --------------------------------------------------------------------
deploy-quality-reports:
needs: [run-coverage, run-linters, run-codeql]
# Always run even if individual quality jobs fail, so the dashboard
# still reflects which jobs passed and which failed.
if: ${{ !cancelled() }}
runs-on: ubuntu-24.04
permissions:
contents: write
steps:
- name: Checkout repository
uses: actions/checkout@v6.0.2
- name: Setup Bazel
uses: ./.github/actions/00_infrastructure/prepare_bazel_environment
with:
disk-cache: ""
ubuntu-snapshot-mirror-url: ${{ secrets.UBUNTU_SNAPSHOT_MIRROR_URL }}
- name: Allow linux-sandbox
id: setup
uses: eclipse-score/cicd-actions/unblock-user-namespace-for-linux-sandbox@f89865691445b60e9229c36adb1c37b675e1ca85
# ------------------------------------------------------------------
# Download Coverage artifacts (only if the upstream job succeeded)
# ------------------------------------------------------------------
- name: Download coverage artifact
id: download-coverage
if: needs.run-coverage.result == 'success'
uses: actions/download-artifact@v4
with:
name: ${{ github.event.repository.name }}_coverage_report_${{ github.sha }}
path: /tmp/coverage_zip
# ------------------------------------------------------------------
# Extract coverage artifact to a known location for the dashboard generator
# ------------------------------------------------------------------
- name: Extract coverage HTML report
if: needs.run-coverage.result == 'success' && steps.download-coverage.outcome == 'success'
run: |
bash quality/scripts/extract_coverage_artifact.sh \
/tmp/coverage_zip \
"${GITHUB_WORKSPACE}/_quality/coverage"
# ------------------------------------------------------------------
# Download clang-tidy findings artifact
# ------------------------------------------------------------------
- name: Download clang-tidy findings
if: ${{ !cancelled() }}
continue-on-error: true
uses: actions/download-artifact@v4
with:
name: clang-tidy-findings
path: /tmp/clang_tidy
- name: Copy clang-tidy SARIF into quality output
if: ${{ !cancelled() }}
run: |
mkdir -p "${GITHUB_WORKSPACE}/_quality"
if [[ -f /tmp/clang_tidy/clang-tidy.sarif ]]; then
cp /tmp/clang_tidy/clang-tidy.sarif \
"${GITHUB_WORKSPACE}/_quality/clang-tidy.sarif"
else
echo "::warning::clang-tidy.sarif not found in downloaded artifact; skipping copy."
fi
# ------------------------------------------------------------------
# Download clippy findings artifact
# ------------------------------------------------------------------
- name: Download clippy findings
if: ${{ !cancelled() }}
continue-on-error: true
uses: actions/download-artifact@v4
with:
name: clippy-findings
path: /tmp/clippy
- name: Copy clippy SARIF into quality output
if: ${{ !cancelled() }}
run: |
mkdir -p "${GITHUB_WORKSPACE}/_quality"
if [[ -f /tmp/clippy/clippy.sarif ]]; then
cp /tmp/clippy/clippy.sarif \
"${GITHUB_WORKSPACE}/_quality/clippy.sarif"
else
echo "::warning::clippy.sarif not found in downloaded artifact; skipping copy."
fi
# ------------------------------------------------------------------
# Download CodeQL SARIF artifact
# ------------------------------------------------------------------
- name: Download CodeQL SARIF artifact
if: ${{ !cancelled() }}
continue-on-error: true
uses: actions/download-artifact@v4
with:
name: codeql-sarif-results
path: /tmp/codeql
- name: Copy CodeQL SARIF into quality output
if: ${{ !cancelled() }}
run: |
mkdir -p "${GITHUB_WORKSPACE}/_quality"
if [[ -f /tmp/codeql/codeql-nightly.sarif ]]; then
cp /tmp/codeql/codeql-nightly.sarif \
"${GITHUB_WORKSPACE}/_quality/codeql_findings.sarif"
fi
# ------------------------------------------------------------------
# Download CodeQL MISRA compliance reports artifact
# ------------------------------------------------------------------
- name: Download CodeQL MISRA reports artifact
if: ${{ !cancelled() }}
continue-on-error: true
uses: actions/download-artifact@v4
with:
name: codeql-misra-reports
path: /tmp/codeql_reports
- name: Copy CodeQL MISRA reports into quality output
if: ${{ !cancelled() }}
run: |
mkdir -p "${GITHUB_WORKSPACE}/_quality/codeql"
find /tmp/codeql_reports -name '*.md' -type f -exec cp {} "${GITHUB_WORKSPACE}/_quality/codeql/" \;
# ------------------------------------------------------------------
# Generate coverage KPI dashboard via generate_dashboard py_binary
# ------------------------------------------------------------------
- name: Generate quality dashboard
if: ${{ !cancelled() && steps.setup.outcome == 'success' }}
run: |
# Pass LCOV data and SARIF findings; generate_dashboard handles
# absent files gracefully (shows N/A for that metric).
bazel run --config=ci //quality/dashboard:generate_dashboard -- \
--lcov /tmp/coverage_zip/extracted/artifacts/coverage_report.dat \
--clang-tidy /tmp/clang_tidy/clang-tidy.sarif \
--clippy /tmp/clippy/clippy.sarif \
--codeql "${GITHUB_WORKSPACE}/_quality/codeql_findings.sarif" \
--html "${GITHUB_WORKSPACE}/_quality/index.html" \
--github-summary
# ------------------------------------------------------------------
# Upload all quality reports as a single artifact for docs.yml to
# pick up and deploy as part of the unified Sphinx site.
# ------------------------------------------------------------------
- name: Upload quality reports artifact
if: ${{ !cancelled() && steps.setup.outcome == 'success' }}
uses: actions/upload-artifact@v4
with:
name: nightly-quality-reports
path: _quality/
retention-days: 7
- name: Print dashboard URL
if: ${{ !cancelled() }}
run: |
OWNER="${{ github.repository_owner }}"
REPO="${{ github.event.repository.name }}"
echo "::notice::Quality reports will be published at https://${OWNER}.github.io/${REPO}/latest/quality/index.html once deploy_docs.yml completes."