Skip to content

Commit db9bcc8

Browse files
committed
Add GitHub Actions workflows for C ABI compatibility checking
This commit adds automated C ABI compatibility checking to the CI pipeline, building on the check_c_abi.py script from benfred's PR rapidsai#1749. Changes: - Add check-c-abi.yaml workflow to run on PRs modifying C headers - Add store-c-abi-baseline.yaml workflow to store ABI baselines on releases - Integrate ABI check into pr.yaml as a required check - Add comprehensive developer documentation in ci/C_ABI_CHECKING.md - Add implementation summary in GITHUB_ACTIONS_ABI_CHECK_SUMMARY.md The ABI checker automatically detects breaking changes to the C API: - Function signature changes (parameters, return types) - Struct member changes (additions, removals, type changes) - Enum value changes Benefits: - Catch breaking changes before merge, not after release - Automated checking on every PR touching C headers - Clear error messages and guidance for developers - Fast execution (~2-5 minutes) - Stores baselines on releases for future comparisons See GITHUB_ACTIONS_ABI_CHECK_SUMMARY.md for full details.
1 parent f6e13fd commit db9bcc8

File tree

5 files changed

+704
-0
lines changed

5 files changed

+704
-0
lines changed

.github/workflows/check-c-abi.yaml

Lines changed: 137 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,137 @@
1+
name: C ABI Compatibility Check
2+
3+
on:
4+
workflow_call:
5+
pull_request:
6+
paths:
7+
- 'c/include/**'
8+
- 'ci/check_c_abi.py'
9+
- '.github/workflows/check-c-abi.yaml'
10+
11+
concurrency:
12+
group: ${{ github.workflow }}-${{ github.ref }}
13+
cancel-in-progress: true
14+
15+
jobs:
16+
check-c-abi:
17+
runs-on: ubuntu-latest
18+
steps:
19+
- name: Checkout PR branch
20+
uses: actions/checkout@v4
21+
with:
22+
fetch-depth: 0
23+
24+
- name: Set up Python
25+
uses: actions/setup-python@v5
26+
with:
27+
python-version: '3.11'
28+
29+
- name: Install system dependencies
30+
run: |
31+
sudo apt-get update
32+
sudo apt-get install -y \
33+
libclang-dev \
34+
clang \
35+
cmake \
36+
ninja-build
37+
38+
- name: Install Python dependencies
39+
run: |
40+
pip install --upgrade pip
41+
pip install msgspec libclang termcolor
42+
43+
- name: Build C++ project to get dependencies (dlpack)
44+
run: |
45+
mkdir -p cpp/build
46+
cd cpp/build
47+
cmake .. \
48+
-GNinja \
49+
-DCMAKE_BUILD_TYPE=Debug \
50+
-DBUILD_TESTS=OFF \
51+
-DBUILD_EXAMPLES=OFF
52+
# We only need the configure step to fetch dlpack headers
53+
# No need to actually build everything
54+
echo "Build directory created and dependencies fetched"
55+
56+
- name: Download baseline ABI from artifact store
57+
id: download-baseline
58+
continue-on-error: true
59+
uses: actions/download-artifact@v4
60+
with:
61+
name: c-abi-baseline
62+
path: baseline/
63+
64+
- name: Extract baseline ABI from main branch (if artifact not found)
65+
if: steps.download-baseline.outcome == 'failure'
66+
run: |
67+
echo "Baseline ABI artifact not found, extracting from main branch..."
68+
69+
# Checkout main branch to a separate directory
70+
git worktree add ../cuvs-main main
71+
72+
# Build main branch to get dlpack headers
73+
mkdir -p ../cuvs-main/cpp/build
74+
cd ../cuvs-main/cpp/build
75+
cmake .. \
76+
-GNinja \
77+
-DCMAKE_BUILD_TYPE=Debug \
78+
-DBUILD_TESTS=OFF \
79+
-DBUILD_EXAMPLES=OFF
80+
cd ../../..
81+
82+
# Extract baseline ABI from main branch
83+
mkdir -p baseline
84+
python ci/check_c_abi.py extract \
85+
--header_path ../cuvs-main/c/include \
86+
--include_file cuvs/core/all.h \
87+
--output_file baseline/c_abi.json.gz
88+
89+
echo "Baseline ABI extracted from main branch"
90+
91+
- name: Analyze current branch for ABI breaking changes
92+
run: |
93+
python ci/check_c_abi.py analyze \
94+
--abi_file baseline/c_abi.json.gz \
95+
--header_path c/include \
96+
--include_file cuvs/core/all.h
97+
98+
- name: Comment on PR with results
99+
if: failure()
100+
uses: actions/github-script@v7
101+
with:
102+
script: |
103+
const fs = require('fs');
104+
105+
github.rest.issues.createComment({
106+
issue_number: context.issue.number,
107+
owner: context.repo.owner,
108+
repo: context.repo.repo,
109+
body: `## ⚠️ C ABI Breaking Changes Detected
110+
111+
This PR introduces breaking changes to the C ABI. Please review the changes carefully.
112+
113+
Breaking ABI changes are only allowed in major releases. If this is intentional for a major release,
114+
the baseline ABI will need to be updated after merge.
115+
116+
See the job logs for details on what specific changes were detected.
117+
118+
### What are breaking ABI changes?
119+
120+
Breaking ABI changes include:
121+
- Removing functions from the public API
122+
- Changing function signatures (parameters or return types)
123+
- Removing struct members or changing their types
124+
- Removing or changing enum values
125+
126+
### Next steps
127+
128+
1. Review the changes flagged in the CI logs
129+
2. If these changes are unintentional, update your PR to maintain ABI compatibility
130+
3. If these changes are required, ensure:
131+
- This is part of a major version release
132+
- The changes are documented in the changelog
133+
- Migration guide is provided for users
134+
135+
For more information, see the [C ABI documentation](../docs/source/c_developer_guide.md).
136+
`
137+
});

.github/workflows/pr.yaml

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,7 @@ jobs:
1212
- check-nightly-ci
1313
- changed-files
1414
- checks
15+
- check-c-abi
1516
- conda-cpp-build
1617
- conda-cpp-tests
1718
- conda-cpp-checks
@@ -136,6 +137,9 @@ jobs:
136137
with:
137138
enable_check_generated_files: false
138139
ignored_pr_jobs: "telemetry-summarize"
140+
check-c-abi:
141+
needs: telemetry-setup
142+
uses: ./.github/workflows/check-c-abi.yaml
139143
conda-cpp-build:
140144
needs: checks
141145
secrets: inherit
Lines changed: 105 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,105 @@
1+
name: Store C ABI Baseline
2+
3+
on:
4+
release:
5+
types: [published]
6+
workflow_dispatch:
7+
inputs:
8+
version:
9+
description: 'Version tag to store baseline for (e.g., v26.02.00)'
10+
required: true
11+
type: string
12+
13+
jobs:
14+
store-baseline:
15+
runs-on: ubuntu-latest
16+
steps:
17+
- name: Checkout release tag
18+
uses: actions/checkout@v4
19+
with:
20+
ref: ${{ github.event.release.tag_name || inputs.version }}
21+
22+
- name: Set up Python
23+
uses: actions/setup-python@v5
24+
with:
25+
python-version: '3.11'
26+
27+
- name: Install system dependencies
28+
run: |
29+
sudo apt-get update
30+
sudo apt-get install -y \
31+
libclang-dev \
32+
clang \
33+
cmake \
34+
ninja-build
35+
36+
- name: Install Python dependencies
37+
run: |
38+
pip install --upgrade pip
39+
pip install msgspec libclang
40+
41+
- name: Build C++ project to get dependencies (dlpack)
42+
run: |
43+
mkdir -p cpp/build
44+
cd cpp/build
45+
cmake .. \
46+
-GNinja \
47+
-DCMAKE_BUILD_TYPE=Debug \
48+
-DBUILD_TESTS=OFF \
49+
-DBUILD_EXAMPLES=OFF
50+
51+
- name: Extract C ABI baseline
52+
run: |
53+
mkdir -p abi-baselines
54+
python ci/check_c_abi.py extract \
55+
--header_path c/include \
56+
--include_file cuvs/core/all.h \
57+
--output_file abi-baselines/c_abi_${{ github.event.release.tag_name || inputs.version }}.json.gz
58+
59+
- name: Upload ABI baseline as artifact
60+
uses: actions/upload-artifact@v4
61+
with:
62+
name: c-abi-baseline-${{ github.event.release.tag_name || inputs.version }}
63+
path: abi-baselines/c_abi_*.json.gz
64+
retention-days: 400 # ~13 months, enough for patch releases
65+
66+
- name: Commit baseline to repository (for long-term storage)
67+
run: |
68+
git config user.name "github-actions[bot]"
69+
git config user.email "github-actions[bot]@users.noreply.github.com"
70+
71+
# Create a baselines branch if it doesn't exist
72+
git fetch origin baselines:baselines || git checkout -b baselines
73+
git checkout baselines
74+
75+
# Copy the baseline file
76+
mkdir -p c-abi-baselines
77+
cp abi-baselines/c_abi_*.json.gz c-abi-baselines/
78+
79+
# Commit and push
80+
git add c-abi-baselines/
81+
git commit -m "Add C ABI baseline for ${{ github.event.release.tag_name || inputs.version }}"
82+
git push origin baselines
83+
env:
84+
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
85+
86+
- name: Create release comment
87+
if: github.event_name == 'release'
88+
uses: actions/github-script@v7
89+
with:
90+
script: |
91+
const tagName = context.payload.release.tag_name;
92+
93+
github.rest.repos.createCommitComment({
94+
owner: context.repo.owner,
95+
repo: context.repo.repo,
96+
commit_sha: context.payload.release.target_commitish,
97+
body: `✅ C ABI baseline stored for release ${tagName}
98+
99+
This baseline will be used to check for breaking ABI changes in future PRs.
100+
101+
The baseline is stored in:
102+
- Artifact: \`c-abi-baseline-${tagName}\` (available for ~13 months)
103+
- Branch: \`baselines\` (permanent storage)
104+
`
105+
});

0 commit comments

Comments
 (0)