Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 2 additions & 0 deletions .github/AGENTS.md
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@ All build/test workflows cover Python 3.10-3.15 plus free-threaded 3.14t and 3.1
- **build_pip.yml** — validates editable build
- **pre-commit.yml** — code quality checks (flake8, etc.)
- **openssf-scorecard.yml** — security posture scanning
- **coverity.yml** — weekly Coverity Scan static analysis of the C/Cython extensions (scan.coverity.com)

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The root AGENTS.md workflow list also needs a coverity.yml entry.


## CI/CD policy
- Keep build matrix (Python versions, platforms) in workflow files only
Expand All @@ -24,6 +25,7 @@ All build/test workflows cover Python 3.10-3.15 plus free-threaded 3.14t and 3.1

## Security
- OpenSSF Scorecard runs automatically
- Coverity Scan runs weekly via `coverity.yml` (project `IntelPython/mkl-service` on scan.coverity.com; needs the `COVERITY_SCAN_TOKEN`/`COVERITY_SCAN_EMAIL` secrets)
- CODEOWNERS enforces review policy
- Dependabot monitors dependencies (`.github/dependabot.yml`)

Expand Down
145 changes: 145 additions & 0 deletions .github/workflows/coverity.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,145 @@
name: Coverity Scan

# Public static analysis via the free Coverity Scan service (scan.coverity.com,
# operated by Black Duck). Coverity is a compiled-language analyzer: it must wrap
# the real C build with `cov-build`, so this workflow installs the Meson build
# tooling and oneMKL, compiles all three extensions under capture, and uploads
# the result for analysis.
#
# One-time setup, already done for IntelPython/mkl-service (repeat only if the
# project is ever re-registered):
# 1. Register the repo at https://scan.coverity.com/github (sign in with
# GitHub; the registered project name must match COVERITY_PROJECT below).
# 2. Add two repository secrets (Settings -> Secrets and variables -> Actions):
# COVERITY_SCAN_TOKEN - the project token from the Project Settings tab
# COVERITY_SCAN_EMAIL - a maintainer email for build notifications
#
# Free-tier quota for a project under 100K LOC (mkl-service is a few thousand)
# is 28 builds/week, max 4/day, so this runs on a weekly schedule plus on
# demand rather than per-push.
#
# `workflow_dispatch` only becomes available once this file is on the default
# branch, and there is no push trigger, so the first scan will not happen at
# merge time -- dispatch it manually instead of waiting for the Monday cron.

on:
schedule:
- cron: "0 1 * * 1" # Mondays 01:00 UTC; well under the free build quota
workflow_dispatch:

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

There is no github.ref check, so a run started from a feature branch replaces the master results on the dashboard. Fix: add github.ref == 'refs/heads/master' to the job's if:.


permissions:
contents: read

concurrency:
group: coverity-${{ github.ref }}
cancel-in-progress: true

env:
# Coverity Scan identifies a project by its registered name, which for
# projects registered through GitHub is the `owner/repo` name shown in the
# project page heading. The `intelpython-mkl-service` seen in
# scan.coverity.com URLs is the slug derived from that name, not the name
# itself. mkl_fft's workflow follows the same convention.
COVERITY_PROJECT: IntelPython/mkl-service

jobs:
coverity-scan:
# Forks lack the COVERITY_SCAN_* secrets; only run on the canonical repo.
if: github.repository == 'IntelPython/mkl-service'
runs-on: ubuntu-latest
# backstop timeout for whole job
timeout-minutes: 60

defaults:
run:
# The implicit default is `bash -e {0}`, which has no pipefail, so the
# `| tee` below would report tee's status and hide a cov-build failure.
shell: bash -eo pipefail {0}

steps:
- name: Checkout repo
uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1
with:
persist-credentials: false

- name: Setup Python
uses: actions/setup-python@5fda3b95a4ea91299a34e894583c3862153e4b97 # v7.0.0
with:
python-version: "3.12"

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Can we bump python version? Can we use 3.14t?

architecture: x64

- name: Install build dependencies
# The build below runs with --no-build-isolation, so pyproject.toml's
# build-system.requires (meson-python, ninja, cmake, mkl-devel) must be
# installed up front, as build-with-standard-clang.yml does. The
# mkl-devel wheel ships the oneMKL headers, libraries and CMake config
# that meson.build locates via `dependency('MKL', method: 'cmake')`:
# setup-python puts the interpreter prefix's bin/ on PATH, and CMake's
# find_package searches PATH entries with bin/ stripped as install
# prefixes, so no MKLROOT or setvars.sh is involved. If a scan ever
# fails at configure time, that lookup is the first thing to check.
# Cython is pinned here only (not in pyproject.toml) to keep the generated
# code stable between scans, so Coverity CIDs and their triage survive
run: pip install meson-python ninja cmake "cython==3.3.0" mkl-devel

- name: Download Coverity Build Tool
timeout-minutes: 15
env:
COVERITY_SCAN_TOKEN: ${{ secrets.COVERITY_SCAN_TOKEN }}
run: |
curl --location --no-progress-meter --fail-with-body \
--retry 5 --retry-connrefused --retry-delay 5 \
--data-urlencode "token=${COVERITY_SCAN_TOKEN}" \
--data-urlencode "project=${COVERITY_PROJECT}" \
--output cov-analysis.tar.gz \
https://scan.coverity.com/download/linux64
# An invalid token/project is answered with a small HTML error page and
# HTTP 200, not the multi-hundred-MB tarball, so --fail-with-body does
# not catch it. Fail loudly with a clear hint instead.
if [ "$(stat -c '%s' cov-analysis.tar.gz)" -lt 1000000 ]; then
echo "::error::Coverity build tool download failed. Verify the COVERITY_SCAN_TOKEN secret and that the registered project name matches '${COVERITY_PROJECT}'."
head -c 512 cov-analysis.tar.gz || true
exit 1
fi
mkdir -p cov-analysis
tar -xzf cov-analysis.tar.gz --strip 1 -C cov-analysis
echo "${PWD}/cov-analysis/bin" >> "$GITHUB_PATH"

- name: Configure Coverity for GCC
run: cov-configure --gcc

- name: Build under cov-build
# cov-build wraps the compiler and can wedge without producing output;
# cap it so a hang fails fast instead of idling until the job timeout.
# 3 translation units normally finish in well under a minute.
timeout-minutes: 20
run: |
# A non-editable `pip install .` has meson-python configure and compile
# in a fresh temporary build directory, and pip does not cache wheels
# built from a local directory, so all three C translation units
# (_mklinitmodule.c and the Cython-generated _py_mkl_service.c and
# _mkl_memory.c) are genuinely recompiled under cov-build. An editable
# install reusing a stale build/ would instead yield "No files were
# emitted", which the upload rejects.
cov-build --dir cov-int pip install . --no-build-isolation --no-deps 2>&1 | tee cov-build.log

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Saving cov-build.log and cov-int/build-log.txt as artifacts (if: always()) would make post-merge failures possible to debug.

if ! grep -qE "Emitted [1-9][0-9]* .*compilation unit" cov-build.log; then
echo "::error::Coverity captured 0 compilation units — the C build did not run under cov-build."
exit 1
fi

- name: Submit results to Coverity Scan
timeout-minutes: 15
env:
COVERITY_SCAN_TOKEN: ${{ secrets.COVERITY_SCAN_TOKEN }}
COVERITY_SCAN_EMAIL: ${{ secrets.COVERITY_SCAN_EMAIL }}
run: |
tar -czf cov-int.tgz cov-int
curl --no-progress-meter --fail-with-body \
--retry 5 --retry-connrefused --retry-delay 5 \
--form token="${COVERITY_SCAN_TOKEN}" \
--form email="${COVERITY_SCAN_EMAIL}" \
--form [email protected] \
--form version="${GITHUB_SHA}" \
--form description="GitHub Actions ${GITHUB_REF_NAME} (run ${GITHUB_RUN_ID})" \
--form project="${COVERITY_PROJECT}" \
https://scan.coverity.com/builds
1 change: 1 addition & 0 deletions README.md
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
# `mkl-service` - Python package for run-time control of Intel® oneAPI Math Kernel Library (oneMKL).
[![Conda package](https://github.com/IntelPython/mkl-service/actions/workflows/conda-package.yml/badge.svg)](https://github.com/IntelPython/mkl-service/actions/workflows/conda-package.yml)
[![Build mkl-service with clang](https://github.com/IntelPython/mkl-service/actions/workflows/build-with-clang.yml/badge.svg)](https://github.com/IntelPython/mkl-service/actions/workflows/build-with-clang.yml)
[![Coverity Scan Build Status](https://scan.coverity.com/projects/intelpython-mkl-service/badge.svg)](https://scan.coverity.com/projects/intelpython-mkl-service)

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Is the path to badge.svg correct?
In mkl_fft the link contains a numeric project ID

[![Coverity Scan Build Status](https://scan.coverity.com/projects/33202/badge.svg)](https://scan.coverity.com/projects/intelpython-mkl_fft)

Copy link
Copy Markdown
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yes, both forms resolve. https://scan.coverity.com/projects/intelpython-mkl-service/badge.svg returns HTTP 200 image/svg+xml and currently renders "coverity | pending" because no build has been uploaded yet. Coverity's embed snippet uses the numeric ID, which is what mkl_fft copied, but the slug form works and matches the link target, so I kept it.

[![OpenSSF Scorecard](https://api.securityscorecards.dev/projects/github.com/IntelPython/mkl-service/badge)](https://securityscorecards.dev/viewer/?uri=github.com/IntelPython/mkl-service)


Expand Down
Loading