Skip to content

Commit af413d4

Browse files
authored
feat: Kernel config validation tool (#16224)
Adds a Python-based kernel config checker that validates kernel .config files against a centralized JSON schema of required configurations. This catches unintentional config regressions during PR review.
1 parent 82530f4 commit af413d4

11 files changed

Lines changed: 4231 additions & 0 deletions

File tree

Lines changed: 114 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,114 @@
1+
# Copyright (c) Microsoft Corporation.
2+
# Licensed under the MIT License.
3+
4+
# This action checks that required kernel configs have not been removed or
5+
# modified to an undesirable value.
6+
name: Kernel Required Configs Check
7+
8+
on:
9+
push:
10+
branches: [3.0*, fasttrack/*]
11+
paths:
12+
- 'SPECS/kernel*/config*'
13+
pull_request:
14+
branches: [3.0*, fasttrack/*]
15+
paths:
16+
- 'SPECS/kernel*/config*'
17+
18+
jobs:
19+
check:
20+
name: Kernel configs check
21+
runs-on: ubuntu-latest
22+
23+
steps:
24+
# Checkout the branch of our repo that triggered this action
25+
- name: Workflow trigger checkout
26+
uses: actions/checkout@v4
27+
28+
- name: Get base commit for PRs
29+
if: ${{ github.event_name == 'pull_request' }}
30+
run: |
31+
git fetch origin ${{ github.base_ref }}
32+
echo "base_sha=$(git rev-parse origin/${{ github.base_ref }})" >> $GITHUB_ENV
33+
echo "Merging ${{ github.sha }} into ${{ github.base_ref }}"
34+
35+
- name: Get base commit for Pushes
36+
if: ${{ github.event_name == 'push' }}
37+
run: |
38+
git fetch origin ${{ github.event.before }}
39+
echo "base_sha=${{ github.event.before }}" >> $GITHUB_ENV
40+
echo "Merging ${{ github.sha }} into ${{ github.event.before }}"
41+
42+
# For consistency, we use the same major/minor version of Python that Azure Linux ships
43+
- name: Setup Python 3.12
44+
uses: actions/setup-python@v5
45+
with:
46+
python-version: 3.12
47+
48+
- name: Get Python dependencies
49+
run: python3 -m pip install -r toolkit/scripts/requirements.txt
50+
51+
# Check if kernel configs changed
52+
- name: Check if config files changed
53+
run: |
54+
echo "Files changed: '$(git diff-tree --no-commit-id --name-only -r ${{ env.base_sha }} ${{ github.sha }})'"
55+
changed_configs=$(git diff-tree --diff-filter=d --no-commit-id --name-only -r ${{ env.base_sha }} ${{ github.sha }} | { grep "SPECS/kernel.*/config.*$" || test $? = 1; })
56+
echo "Files to validate: '${changed_configs}'"
57+
echo "updated_configs<<EOF" >> $GITHUB_ENV
58+
echo "${changed_configs}" >> $GITHUB_ENV
59+
echo "EOF" >> $GITHUB_ENV
60+
61+
# Run kernel config checker against each changed config file
62+
- name: Run kernel config checking script
63+
if: ${{ env.updated_configs != '' }}
64+
run: |
65+
JSON_PATH="toolkit/scripts/kernel_config_checker/kernel_configs_json/azl3-os-required-kernel-configs.json"
66+
67+
# Extract kernel names that have overrides in the JSON (these are the kernels we track)
68+
tracked_kernels=$(python3 -c "
69+
import json
70+
with open('${JSON_PATH}') as f:
71+
data = json.load(f)
72+
for o in data['overrides']:
73+
print(o['name'])
74+
")
75+
echo "Tracked kernels: ${tracked_kernels}"
76+
77+
failed=0
78+
holder="${{ env.updated_configs }}"
79+
for file in $holder; do
80+
# Extract kernel name from path (e.g., SPECS/kernel-hwe/config -> kernel-hwe)
81+
kernel_name=$(echo "$file" | sed 's|SPECS/\([^/]*\)/.*|\1|')
82+
83+
# Skip kernels that don't have overrides in the JSON
84+
if ! echo "${tracked_kernels}" | grep -qx "${kernel_name}"; then
85+
echo "============================================"
86+
echo "Skipping: ${file} (kernel=${kernel_name} not tracked in JSON)"
87+
echo "============================================"
88+
continue
89+
fi
90+
91+
# Determine architecture from filename
92+
if [[ "$file" == *"aarch64"* ]]; then
93+
arch="arm64"
94+
else
95+
arch="x86_64"
96+
fi
97+
98+
echo "============================================"
99+
echo "Checking: ${file} (kernel=${kernel_name}, arch=${arch})"
100+
echo "============================================"
101+
102+
if ! (cd toolkit/scripts && python3 -m kernel_config_checker.check_config \
103+
"../../${file}" \
104+
kernel_config_checker/kernel_configs_json/azl3-os-required-kernel-configs.json \
105+
"${kernel_name}" "${arch}"); then
106+
failed=1
107+
fi
108+
done
109+
110+
if [ "$failed" -eq 1 ]; then
111+
echo ""
112+
echo "✗ One or more kernel config checks failed"
113+
exit 1
114+
fi
Lines changed: 196 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,196 @@
1+
# Kernel Config Checker
2+
3+
A robust kernel configuration validation system using Pydantic v2 schemas. Supports default configurations and per-kernel overrides with architecture-specific settings.
4+
5+
## Features
6+
7+
- **Schema-based validation** - Uses Pydantic v2 for robust config validation
8+
- **Multi-architecture support** - Handles x86_64 and arm64 architectures
9+
- **Flexible overrides** - Default configs with per-kernel overrides
10+
- **Interactive config management** - Add new configs with guided prompts
11+
- **Config querying** - Check config values across all kernels/architectures
12+
- **Legacy conversion** - Tools to migrate existing configurations
13+
14+
## Installation
15+
16+
From the repo root, install the Python dependencies:
17+
18+
```bash
19+
pip install -r toolkit/scripts/requirements.txt
20+
```
21+
22+
All commands below should be run from `toolkit/scripts/`:
23+
24+
```bash
25+
cd toolkit/scripts
26+
```
27+
28+
## Usage
29+
30+
### Check Kernel Config
31+
32+
Validate a `.config` file against intentional configurations:
33+
34+
```bash
35+
python -m kernel_config_checker.check_config /path/to/.config kernel_config_checker/kernel_configs_json/azl3-os-required-kernel-configs.json kernel-name architecture
36+
```
37+
38+
Example:
39+
40+
```bash
41+
python -m kernel_config_checker.check_config kernel.config kernel_config_checker/kernel_configs_json/azl3-os-required-kernel-configs.json kernel x86_64
42+
```
43+
44+
### Add New Config
45+
46+
Interactively add a new kernel configuration:
47+
48+
```bash
49+
python -m kernel_config_checker.check_config --add-config kernel_config_checker/kernel_configs_json/azl3-os-required-kernel-configs.json
50+
```
51+
52+
Features:
53+
54+
- Add to default or override sections
55+
- Support for single or multiple architectures
56+
- Leave architectures blank to omit them from JSON
57+
- Create new override sections or use existing ones
58+
59+
### Query Config Values
60+
61+
Check a config value across all architectures and kernels:
62+
63+
```bash
64+
python -m kernel_config_checker.check_config --check-all kernel_config_checker/kernel_configs_json/azl3-os-required-kernel-configs.json CONFIG_NAME
65+
```
66+
67+
Example:
68+
69+
```bash
70+
python -m kernel_config_checker.check_config --check-all kernel_config_checker/kernel_configs_json/azl3-os-required-kernel-configs.json CONFIG_DRM
71+
```
72+
73+
## Configuration Schema
74+
75+
The system uses a structured JSON schema with default and override sections:
76+
77+
```json
78+
{
79+
"default": {
80+
"kernel_configs": [
81+
{
82+
"name": "CONFIG_EXAMPLE",
83+
"values": [
84+
{
85+
"architecture": "x86_64",
86+
"value": "y"
87+
},
88+
{
89+
"architecture": "arm64",
90+
"value": "m"
91+
}
92+
],
93+
"justification": "Explanation for this config"
94+
}
95+
]
96+
},
97+
"overrides": [
98+
{
99+
"name": "kernel-64k",
100+
"kernel_configs": [
101+
{
102+
"name": "CONFIG_ARM64_64K_PAGES",
103+
"values": [
104+
{
105+
"architecture": "arm64",
106+
"value": "y"
107+
}
108+
],
109+
"justification": "needed for 64k page size"
110+
}
111+
]
112+
}
113+
]
114+
}
115+
```
116+
117+
### Architecture Support
118+
119+
- Configs can specify values for `x86_64`, `arm64`, or both
120+
- When adding configs, leaving an architecture blank omits it from the JSON
121+
- At least one architecture must be specified
122+
123+
### Value Types
124+
125+
- `y` - Built into kernel
126+
- `m` - Built as module
127+
- `n` - Disabled ("is not set" or missing)
128+
- Custom values supported for specific configs
129+
130+
## Project Structure
131+
132+
```text
133+
toolkit/scripts/kernel_config_checker/
134+
├── schema/
135+
│ ├── __init__.py # Package init
136+
│ ├── schema.py # Pydantic schema definitions
137+
│ └── print_schema.py # Schema utility
138+
├── kernel_configs_json/
139+
│ └── azl3-os-required-kernel-configs.json # Main config file
140+
├── __init__.py # Package init
141+
├── check_config.py # Main checker and utilities
142+
└── README.md # This file
143+
```
144+
145+
## Examples
146+
147+
### Adding a Config for Single Architecture
148+
149+
```bash
150+
$ python -m kernel_config_checker.check_config --add-config test.json
151+
Adding new kernel configuration...
152+
Enter config name (e.g., CONFIG_EXAMPLE): CONFIG_X86_ONLY
153+
Enter values for each architecture (y/n/m or specific value, leave blank to skip):
154+
x86_64 value: y
155+
arm64 value:
156+
Enter justification: Only needed on x86_64
157+
Add to [d]efault or [o]verride? [d]: d
158+
✓ Added CONFIG_X86_ONLY to default section
159+
```
160+
161+
Results in:
162+
163+
```json
164+
{
165+
"name": "CONFIG_X86_ONLY",
166+
"values": [
167+
{
168+
"architecture": "x86_64",
169+
"value": "y"
170+
}
171+
],
172+
"justification": "Only needed on x86_64"
173+
}
174+
```
175+
176+
### Querying Config Values
177+
178+
```bash
179+
$ python -m kernel_config_checker.check_config --check-all kernel_config_checker/kernel_configs_json/azl3-os-required-kernel-configs.json CONFIG_DRM
180+
Config: CONFIG_DRM
181+
arm64: default=m, kernel-hwe=y
182+
x86_64: default=m
183+
⚠️ Conflicts in: arm64
184+
Reason: amdgpu - https://github.com/microsoft/azurelinux/pull/10612
185+
```
186+
187+
## Contributing
188+
189+
1. Ensure all configs have proper justifications
190+
2. Test schema validation after changes
191+
3. Use the add-config command for consistency
192+
4. Validate configs against actual kernel .config files
193+
194+
## License
195+
196+
This project follows the same licensing as the Azure Linux project.
Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,2 @@
1+
# Copyright (c) Microsoft Corporation.
2+
# Licensed under the MIT License.

0 commit comments

Comments
 (0)