-
-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathpython-package-lint-and-scan.yml
More file actions
184 lines (184 loc) · 6.77 KB
/
python-package-lint-and-scan.yml
File metadata and controls
184 lines (184 loc) · 6.77 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
---
name: Lint and security scan for Python
on:
workflow_call:
inputs:
package-path:
required: false
type: string
description: Path to a Python package or project
default: .
python-version:
required: false
type: string
description: Python version to use (not applicable if uv.lock is present)
default: 3.x
uv-version:
required: false
type: string
description: Version of uv to use (applicable only if uv.lock is present)
default: latest
use-pyright:
required: false
type: boolean
description: Use pyright to check types
default: true
use-ruff-format:
required: false
type: boolean
description: Use ruff format to check code
default: true
use-mypy:
required: false
type: boolean
description: Use mypy to check types
default: false
use-flake8:
required: false
type: boolean
description: Use flake8 to lint the code
default: false
use-bandit:
required: false
type: boolean
description: Use bandit to find security issues
default: false
additional-python-packages:
required: false
type: string
description: Additional Python packages to install
default: null
requirements-txt:
required: false
type: string
description: Path to the requirements.txt file (not applicable if uv.lock is present)
default: null
runs-on:
required: false
type: string
description: GitHub Actions runner to use
default: ubuntu-slim
permissions:
contents: read
defaults:
run:
shell: bash -euo pipefail {0}
working-directory: .
jobs:
lint-and-scan:
runs-on: ${{ inputs.runs-on }}
steps:
- name: Checkout repository
uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2
with:
fetch-depth: 1
persist-credentials: false
- name: Detect uv.lock or poetry.lock
working-directory: ${{ inputs.package-path }}
run: |
if [[ -f uv.lock ]]; then
echo "LOCK_FILE=uv.lock" >> "${GITHUB_ENV}"
elif [[ -f poetry.lock ]]; then
echo "LOCK_FILE=poetry.lock" >> "${GITHUB_ENV}"
else
echo "LOCK_FILE=" >> "${GITHUB_ENV}"
fi
- name: Set up uv
if: env.LOCK_FILE == 'uv.lock'
uses: astral-sh/setup-uv@08807647e7069bb48b6ef5acd8ec9567f424441b # v8.1.0
with:
version: ${{ inputs.uv-version }}
- name: Install packages using uv
if: env.LOCK_FILE == 'uv.lock'
working-directory: ${{ inputs.package-path }}
env:
INPUTS_ADDITIONAL_PYTHON_PACKAGES: ${{ inputs.additional-python-packages }}
run: |
uv sync --all-groups
uv add --dev \
${{ inputs.use-flake8 && 'flake8' || '' }} \
${{ inputs.use-bandit && 'bandit' || '' }} \
${{ inputs.use-mypy && 'mypy' || '' }} \
${{ inputs.use-pyright && 'pyright' || '' }} \
ruff
for p in $(tr ' ' '\n' <<< "${INPUTS_ADDITIONAL_PYTHON_PACKAGES}"); do
if [[ -n "${p}" ]]; then
uv add --dev "${p}"
fi
done
tee -a "${GITHUB_ENV}" <<< "EXECUTOR=uv run --directory ${PWD}"
- name: Set up Python
if: env.LOCK_FILE != 'uv.lock'
uses: actions/setup-python@a309ff8b426b58ec0e2a45f0f869d46889d02405 # v6.2.0
with:
python-version: ${{ inputs.python-version }}
- name: Install packages
if: env.LOCK_FILE != 'uv.lock'
env:
ADDITIONAL_PYTHON_PACKAGES: ${{ inputs.additional-python-packages }}
REQUIREMENTS_TXT_PATH: ${{ inputs.requirements-txt }}
working-directory: ${{ inputs.package-path }}
run: |
pip install -U --no-cache-dir pip
if [[ -n "${REQUIREMENTS_TXT_PATH}" ]]; then
pip install -U --no-cache-dir -r "${REQUIREMENTS_TXT_PATH}"
fi
if [[ "${LOCK_FILE}" == "poetry.lock" ]]; then
pip install --no-cache-dir poetry
poetry lock --no-interaction
poetry add --group=dev --no-interaction \
${{ inputs.use-flake8 && 'flake8' || '' }} \
${{ inputs.use-bandit && 'bandit' || '' }} \
${{ inputs.use-mypy && 'mypy' || '' }} \
${{ inputs.use-pyright && 'pyright' || '' }} \
ruff
for p in $(tr ' ' '\n' <<< "${ADDITIONAL_PYTHON_PACKAGES}"); do
if [[ -n "${p}" ]]; then
poetry add --group=dev --no-interaction "${p}"
fi
done
poetry install --no-interaction --no-root
tee -a "${GITHUB_ENV}" <<< "EXECUTOR=poetry run -C ${PWD}"
else
pip install --no-cache-dir \
${{ inputs.use-flake8 && 'flake8' || '' }} \
${{ inputs.use-bandit && 'bandit' || '' }} \
${{ inputs.use-mypy && 'mypy' || '' }} \
${{ inputs.use-pyright && 'pyright' || '' }} \
ruff
for p in $(tr ' ' '\n' <<< "${ADDITIONAL_PYTHON_PACKAGES}"); do
if [[ -n "${p}" ]]; then
pip install --no-cache-dir "${p}"
fi
done
tee -a "${GITHUB_ENV}" <<< "EXECUTOR="
fi
- name: Lint the code using ruff check
working-directory: ${{ inputs.package-path }}
run: > # zizmor: ignore[template-injection]
${{ env.EXECUTOR }} ruff check --output-format=github .
- name: Check the code using ruff format
if: inputs.use-ruff-format
working-directory: ${{ inputs.package-path }}
run: > # zizmor: ignore[template-injection]
${{ env.EXECUTOR }} ruff format --check .
- name: Lint the code using flake8
if: inputs.use-flake8
working-directory: ${{ inputs.package-path }}
run: > # zizmor: ignore[template-injection]
${{ env.EXECUTOR }} flake8 .
- name: Find security issues using bandit
if: inputs.use-bandit
working-directory: ${{ inputs.package-path }}
run: > # zizmor: ignore[template-injection]
${{ env.EXECUTOR }} bandit --recursive .
- name: Check types using mypy
if: inputs.use-mypy
working-directory: ${{ inputs.package-path }}
run: > # zizmor: ignore[template-injection]
${{ env.EXECUTOR }} mypy --install-types --non-interactive .
- name: Check types using pyright
if: inputs.use-pyright
working-directory: ${{ inputs.package-path }}
run: > # zizmor: ignore[template-injection]
${{ env.EXECUTOR }} pyright --threads=0 .