Skip to content

Commit dc088d8

Browse files
committed
Adding precommit hook and workflow for checking code quality
1 parent 695719d commit dc088d8

File tree

5 files changed

+176
-1
lines changed

5 files changed

+176
-1
lines changed
Lines changed: 141 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,141 @@
1+
name: Code Quality
2+
3+
permissions:
4+
contents: read
5+
issues: write
6+
7+
on:
8+
pull_request:
9+
types: [opened, edited, reopened, synchronize]
10+
paths:
11+
- '**.py'
12+
- '**.cpp'
13+
- '**.h'
14+
15+
jobs:
16+
lint:
17+
name: Code Linting
18+
runs-on: ubuntu-latest
19+
steps:
20+
- name: Checkout Code
21+
uses: actions/checkout@v3
22+
23+
- name: Set up Python
24+
uses: actions/setup-python@v4
25+
with:
26+
python-version: '3.11'
27+
28+
- name: Cache pip dependencies
29+
uses: actions/cache@v3
30+
with:
31+
path: ~/.cache/pip
32+
key: ${{ runner.os }}-pip-${{ hashFiles('**/requirements*.txt') }}
33+
restore-keys: |
34+
${{ runner.os }}-pip-
35+
36+
- name: Install dependencies
37+
run: |
38+
python -m pip install --upgrade pip
39+
pip install -e .
40+
pip install pylint cpplint
41+
42+
- name: Run Python Linter
43+
id: pylint
44+
continue-on-error: true
45+
run: |
46+
echo "Running pylint with threshold 8.5..."
47+
python -m pylint --fail-under=8.5 --disable=fixme,no-member,too-many-arguments,too-many-positional-arguments,invalid-name,useless-parent-delegation --output-format=colorized mssql_python
48+
echo "pylint_status=$?" >> $GITHUB_ENV
49+
50+
- name: Run C++ Linter
51+
id: cpplint
52+
continue-on-error: true
53+
run: |
54+
echo "Running cpplint with maximum 10 errors per file..."
55+
56+
# Find C++ files excluding build directories
57+
FILES=$(find mssql_python -name "*.cpp" -o -name "*.h" | grep -v "/build/")
58+
if [ -z "$FILES" ]; then
59+
echo "No C++ files found to check!"
60+
echo "cpplint_status=0" >> $GITHUB_ENV
61+
exit 0
62+
fi
63+
64+
echo "Found files to check:"
65+
echo "$FILES"
66+
67+
# Process each file individually with better error handling
68+
MAX_ERRORS=10
69+
FAILED_FILES=""
70+
71+
for FILE in $FILES; do
72+
echo "Checking $FILE..."
73+
74+
# Run cpplint on a single file and capture output
75+
OUTPUT=$(python -m cpplint --filter=-readability/todo --linelength=100 "$FILE" 2>&1 || true)
76+
77+
# Display the output for this file
78+
echo "$OUTPUT"
79+
80+
# Extract error count more reliably
81+
ERROR_COUNT=$(echo "$OUTPUT" | grep -o 'Total errors found: [0-9]*' | grep -o '[0-9]*' || echo "0")
82+
83+
# If we couldn't extract a count, default to 0
84+
if [ -z "$ERROR_COUNT" ]; then
85+
ERROR_COUNT=0
86+
fi
87+
88+
echo "File $FILE has $ERROR_COUNT errors"
89+
90+
# Check if over threshold
91+
if [ "$ERROR_COUNT" -gt "$MAX_ERRORS" ]; then
92+
FAILED_FILES="$FAILED_FILES\n- $FILE ($ERROR_COUNT errors)"
93+
fi
94+
done
95+
96+
# Output results
97+
if [ ! -z "$FAILED_FILES" ]; then
98+
echo -e "\n⛔ The following files have more than $MAX_ERRORS errors:$FAILED_FILES"
99+
echo "cpplint_status=1" >> $GITHUB_ENV
100+
else
101+
echo -e "\n✅ All files have $MAX_ERRORS or fewer errors."
102+
echo "cpplint_status=0" >> $GITHUB_ENV
103+
fi
104+
105+
- name: Determine overall status
106+
run: |
107+
if [[ "${{ env.pylint_status }}" != "0" || "${{ env.cpplint_status }}" != "0" ]]; then
108+
echo "Linting checks failed!"
109+
exit 1
110+
else
111+
echo "All linting checks passed!"
112+
fi
113+
114+
- name: Comment on PR
115+
if: github.event_name == 'pull_request'
116+
uses: actions/github-script@v7
117+
with:
118+
github-token: ${{ secrets.GITHUB_TOKEN }}
119+
script: |
120+
let comment = '## Code Quality Check Results\n\n';
121+
122+
if ('${{ env.pylint_status }}' !== '0') {
123+
comment += '⚠️ **Python linting failed** - Please check the [workflow logs](${{ github.server_url }}/${{ github.repository }}/actions/runs/${{ github.run_id }}) for details.\n\n';
124+
} else {
125+
comment += '✅ **Python linting passed**\n\n';
126+
}
127+
128+
if ('${{ env.cpplint_status }}' !== '0') {
129+
comment += '⚠️ **C++ linting failed** - Some files exceed the maximum error threshold of 10.\n\n';
130+
} else {
131+
comment += '✅ **C++ linting passed**\n\n';
132+
}
133+
134+
comment += 'See [code quality guidelines](https://github.com/microsoft/mssql-python/blob/main/CONTRIBUTING.md) for more information.';
135+
136+
github.rest.issues.createComment({
137+
issue_number: context.issue.number,
138+
owner: context.repo.owner,
139+
repo: context.repo.repo,
140+
body: comment
141+
});

.pre-commit-config.yml

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,16 @@
1+
repos:
2+
- repo: https://github.com/pre-commit/mirrors-pylint
3+
rev: v3.0.0a5
4+
hooks:
5+
- id: pylint
6+
args: [--fail-under=8.5, --disable=fixme,no-member,too-many-arguments,too-many-positional-arguments,invalid-name,useless-parent-delegation]
7+
8+
- repo: local
9+
hooks:
10+
- id: cpplint
11+
name: cpplint
12+
entry: python -m cpplint
13+
language: python
14+
types: [c++]
15+
args: [--filter=-readability/todo, --linelength=100]
16+
exclude: ^.*build/.*$

cpplint.cfg

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,4 @@
1+
set noparent
2+
filter=-readability/todo
3+
linelength=100
4+
exclude_files=build

pyproject.toml

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,11 @@
1+
[tool.pylint]
2+
disable = [
3+
"fixme",
4+
"no-member",
5+
"too-many-arguments",
6+
"too-many-positional-arguments",
7+
"invalid-name",
8+
"useless-parent-delegation"
9+
]
10+
fail-under = 8.5
11+
max-line-length = 100

requirements.txt

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,4 +4,7 @@ pybind11
44
coverage
55
unittest-xml-reporting
66
setuptools
7-
psutil
7+
psutil
8+
pylint
9+
cpplint
10+
pre-commit

0 commit comments

Comments
 (0)