Skip to content

Commit 3fb641e

Browse files
authored
Merge pull request #148 from IntelPython/task/coverity
task: opensource coverity
2 parents 63e21f0 + be8eb9f commit 3fb641e

2 files changed

Lines changed: 136 additions & 0 deletions

File tree

‎.github/workflows/coverity.yml‎

Lines changed: 135 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,135 @@
1+
name: Coverity Scan
2+
3+
# Public static analysis via the free Coverity Scan service (scan.coverity.com,
4+
# operated by Black Duck). Coverity is a compiled-language analyzer: it must wrap
5+
# the real C/C++ build with `cov-build`, so this workflow installs MKL, compiles
6+
# the extension under capture, and uploads the result for analysis.
7+
#
8+
# One-time setup required before the first run (see the PR/commit notes):
9+
# 1. Register IntelPython/mkl_random at https://scan.coverity.com/github
10+
# (sign in with GitHub; the project name must match COVERITY_PROJECT below).
11+
# 2. Add two repository secrets (Settings -> Secrets and variables -> Actions):
12+
# COVERITY_SCAN_TOKEN - the project token from the Project Settings tab
13+
# COVERITY_SCAN_EMAIL - a maintainer email for build notifications
14+
#
15+
# Free-tier quota for a project under 100K LOC (mkl_random is ~10K) is 28
16+
# builds/week, max 4/day, so this runs on a weekly schedule plus on demand
17+
# rather than per-push.
18+
19+
on:
20+
schedule:
21+
- cron: "0 1 * * 1" # Mondays 01:00 UTC; well under the free build quota
22+
workflow_dispatch:
23+
24+
permissions:
25+
contents: read
26+
27+
concurrency:
28+
group: coverity-${{ github.ref }}
29+
cancel-in-progress: true
30+
31+
env:
32+
COVERITY_PROJECT: IntelPython/mkl_random
33+
34+
jobs:
35+
coverity-scan:
36+
# Forks lack the COVERITY_SCAN_* secrets; only run on the canonical repo.
37+
if: github.repository == 'IntelPython/mkl_random'
38+
runs-on: ubuntu-latest
39+
# backstop timeout for whole job
40+
timeout-minutes: 60
41+
42+
steps:
43+
- name: Checkout repo
44+
uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1
45+
46+
- name: Setup Python
47+
uses: actions/setup-python@5fda3b95a4ea91299a34e894583c3862153e4b97 # v7.0.0
48+
with:
49+
python-version: "3.12"
50+
architecture: x64
51+
52+
- name: Install build dependencies
53+
run: pip install cython "setuptools>=77" "numpy>=2" mkl-devel
54+
55+
- name: Export MKLROOT
56+
run: |
57+
# mkl-devel installs mkl.h + libmkl_rt into the Python prefix.
58+
MKLROOT="$(python -c 'import sys; print(sys.prefix)')"
59+
if [ ! -f "${MKLROOT}/include/mkl.h" ]; then
60+
echo "::error::mkl.h not found under ${MKLROOT}; mkl-devel did not install as expected."
61+
exit 1
62+
fi
63+
# The wheel ships only the versioned libmkl_rt.so.3, not the bare
64+
# linker name, so `g++ -lmkl_rt` fails until we add the symlink.
65+
if [ ! -e "${MKLROOT}/lib/libmkl_rt.so" ]; then
66+
rt_so=("${MKLROOT}/lib/"libmkl_rt.so.*)
67+
if [ ! -e "${rt_so[0]}" ]; then
68+
echo "::error::libmkl_rt.so.* not found under ${MKLROOT}/lib."
69+
exit 1
70+
fi
71+
ln -s "${rt_so[0]}" "${MKLROOT}/lib/libmkl_rt.so"
72+
fi
73+
echo "MKLROOT=${MKLROOT}" >> "$GITHUB_ENV"
74+
# Only append the inherited value when it is non-empty: a trailing (or
75+
# leading) empty element in LD_LIBRARY_PATH means "current directory"
76+
# to the loader, which is an unwanted search path.
77+
echo "LD_LIBRARY_PATH=${MKLROOT}/lib${LD_LIBRARY_PATH:+:${LD_LIBRARY_PATH}}" >> "$GITHUB_ENV"
78+
79+
- name: Download Coverity Build Tool
80+
timeout-minutes: 15
81+
env:
82+
COVERITY_SCAN_TOKEN: ${{ secrets.COVERITY_SCAN_TOKEN }}
83+
run: |
84+
curl --location --no-progress-meter \
85+
--data-urlencode "token=${COVERITY_SCAN_TOKEN}" \
86+
--data-urlencode "project=${COVERITY_PROJECT}" \
87+
--output cov-analysis.tar.gz \
88+
https://scan.coverity.com/download/linux64
89+
# An invalid token/project returns a small HTML error page, not the
90+
# multi-hundred-MB tarball. Fail loudly with a clear hint if so.
91+
if [ "$(stat -c '%s' cov-analysis.tar.gz)" -lt 1000000 ]; then
92+
echo "::error::Coverity build tool download failed. Verify the COVERITY_SCAN_TOKEN secret and that the registered project name matches '${COVERITY_PROJECT}'."
93+
head -c 512 cov-analysis.tar.gz || true
94+
exit 1
95+
fi
96+
mkdir -p cov-analysis
97+
tar -xzf cov-analysis.tar.gz --strip 1 -C cov-analysis
98+
echo "${PWD}/cov-analysis/bin" >> "$GITHUB_PATH"
99+
100+
- name: Configure Coverity for GCC/G++
101+
run: cov-configure --gcc
102+
103+
- name: Build under cov-build
104+
# cov-build wraps the compiler and can wedge without producing output;
105+
# cap it so a hang fails fast instead of idling until the job timeout.
106+
# 3 translation units normally finish in a couple of minutes.
107+
timeout-minutes: 20
108+
run: |
109+
# Force a clean rebuild so g++ genuinely runs and Coverity can capture
110+
# it. A stale .so or generated .cpp would skip compilation and yield
111+
# "No files were emitted", which the upload rejects.
112+
rm -rf build/ mkl_random/*.so mkl_random/mklrand.cpp
113+
cov-build --dir cov-int pip install -e . --no-build-isolation --no-deps 2>&1 | tee cov-build.log
114+
# The extension has 3 translation units (mklrand.cpp + the two src/*.cpp);
115+
# bail out if none were captured.
116+
if ! grep -qE "Emitted [1-9][0-9]* .*compilation unit" cov-build.log; then
117+
echo "::error::Coverity captured 0 compilation units — the C++ build did not run under cov-build."
118+
exit 1
119+
fi
120+
121+
- name: Submit results to Coverity Scan
122+
timeout-minutes: 15
123+
env:
124+
COVERITY_SCAN_TOKEN: ${{ secrets.COVERITY_SCAN_TOKEN }}
125+
COVERITY_SCAN_EMAIL: ${{ secrets.COVERITY_SCAN_EMAIL }}
126+
run: |
127+
tar -czf cov-int.tgz cov-int
128+
curl --no-progress-meter \
129+
--form token="${COVERITY_SCAN_TOKEN}" \
130+
--form email="${COVERITY_SCAN_EMAIL}" \
131+
--form file=@cov-int.tgz \
132+
--form version="${GITHUB_SHA}" \
133+
--form description="GitHub Actions ${GITHUB_REF_NAME} (run ${GITHUB_RUN_ID})" \
134+
--form project="${COVERITY_PROJECT}" \
135+
https://scan.coverity.com/builds

‎README.md‎

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
## `mkl_random` -- a NumPy-based Python interface to Intel® oneAPI Math Kernel Library (OneMKL) Random Number Generation functionality
22
[![Conda package using conda-forge](https://github.com/IntelPython/mkl_random/actions/workflows/conda-package-cf.yml/badge.svg)](https://github.com/IntelPython/mkl_random/actions/workflows/conda-package-cf.yml)
3+
[![Coverity Scan Build Status](https://scan.coverity.com/projects/33198/badge.svg)](https://scan.coverity.com/projects/intelpython-mkl_random)
34
[![OpenSSF Scorecard](https://api.securityscorecards.dev/projects/github.com/IntelPython/mkl_random/badge)](https://securityscorecards.dev/viewer/?uri=github.com/IntelPython/mkl_random)
45

56
`mkl_random` started as a part of Intel® Distribution for Python optimizations to NumPy.

0 commit comments

Comments
 (0)