-
Notifications
You must be signed in to change notification settings - Fork 9
271 lines (233 loc) · 10.9 KB
/
ci.yml
File metadata and controls
271 lines (233 loc) · 10.9 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
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
name: Continuous Integration
on:
pull_request:
branches:
- main
push:
branches: [main, development, staging]
paths-ignore:
- ".github/**" # We don't want to trigger when we update the workflows.
- "docs/**" # We don't want to trigger when we update the docs.
- "*.md"
- "terraform/**"
jobs:
secret-scanning:
name: Trufflehog Secret Scanning
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6
with:
fetch-depth: 0
- name: TruffleHog OSS
id: trufflehog
uses: trufflesecurity/trufflehog@17456f8c7d042d8c82c9a8ca9e937231f9f42e26 # v3.95.2
env:
GITHUB_HEAD_REF_SAFE: ${{ github.head_ref }}
continue-on-error: true
with:
path: ./
base: "${{ github.event.repository.default_branch }}"
head: "$GITHUB_HEAD_REF_SAFE"
extra_args: --debug --only-verified
# - name: Setup Trufflehog [Docker]
# env:
# GITHUB_HEAD_REF_SAFE: ${{ github.head_ref }}
# run: docker run --rm -v "$PWD:/pwd" trufflesecurity/trufflehog:3.67.1 git file://. --since-commit main --branch "$GITHUB_HEAD_REF_SAFE" --only-verified --fail
unit-tests:
name: Unit Tests
secrets: inherit # https://docs.github.com/en/actions/using-workflows/reusing-workflows#passing-inputs-and-secrets-to-a-reusable-workflow
uses: ./.github/workflows/unit_test_reusable.yml
e2e-tests:
name: End-to-End Tests
secrets: inherit # https://docs.github.com/en/actions/using-workflows/reusing-workflows#passing-inputs-and-secrets-to-a-reusable-workflow
uses: ./.github/workflows/e2e_test_reusable.yml
a11y-regression:
name: A11y Regression Gate
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6
- uses: ./.github/actions/setup-javascript
- name: Cache Cypress binary
uses: actions/cache@27d5ce7f107fe9357f9df03efb73ab90386fccae # v5.0.5
with:
path: ~/.cache/Cypress
key: cypress-${{ runner.os }}-${{ runner.arch }}-${{ hashFiles('frontend/bun.lock') }}
- name: Install Cypress binary
working-directory: ./frontend
run: |
bunx cypress install
bunx cypress verify
- name: Launch Stack
uses: ./.github/actions/run-full-stack
env:
JWT_PRIVATE_KEY: ${{ secrets.JWT_PRIVATE_KEY }}
JWT_PUBLIC_KEY: ${{ secrets.JWT_PUBLIC_KEY }}
- name: Validate a11y suppression metadata
working-directory: ./frontend
run: bun run a11y:validate-suppressions
- name: Install minimal runtime deps for headless browser
run: |
sudo apt-get update
sudo apt-get install -y --no-install-recommends dbus-x11 xvfb libgtk-3-0 libnss3 libxss1 libasound2t64 libgbm1
- name: Run critical accessibility regression specs
working-directory: ./frontend
env:
TERM: xterm
A11Y_REGRESSION_GATE: "true"
JWT_PRIVATE_KEY: ${{ secrets.JWT_PRIVATE_KEY }}
JWT_PUBLIC_KEY: ${{ secrets.JWT_PUBLIC_KEY }}
run: |
dbus-run-session -- npx cypress run \
--config-file ./cypress.config.ci.js \
--headless \
--spec "cypress/e2e/agreementList.cy.js,cypress/e2e/agreementsPagination.cy.js,cypress/e2e/agreementDetails.cy.js,cypress/e2e/portfolioList.cy.js,cypress/e2e/portfolioDetail.cy.js,cypress/e2e/budgetLineItemsList.cy.js,cypress/e2e/createAgreement.cy.js,cypress/e2e/createAgreementWithValidations.cy.js,cypress/e2e/uploadDocument.cy.js,cypress/e2e/notificationCenter.cy.js"
codeql-analysis:
permissions:
actions: read
contents: read
security-events: write
name: CodeQL Scan
uses: ./.github/workflows/security_codeql.yml
semgrep-analysis:
permissions:
security-events: write
name: Semgrep Scan
uses: ./.github/workflows/security_semgrep.yml
lint:
name: Linting
runs-on: ubuntu-latest
permissions:
contents: write
pull-requests: write
steps:
- name: Check out PR head commit
if: github.event_name == 'pull_request'
uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6
with:
ref: ${{ github.event.pull_request.head.ref }}
repository: ${{ github.event.pull_request.head.repo.full_name }}
token: ${{ secrets.GITHUB_TOKEN }}
- name: Check out push commit
if: github.event_name != 'pull_request'
uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6
- name: Detect commit source
id: detect
run: |
COMMITTER_NAME=$(git log -1 --pretty=format:'%cn')
COMMITTER_EMAIL=$(git log -1 --pretty=format:'%ce')
AUTHOR_NAME=$(git log -1 --pretty=format:'%an')
echo "Last committer: $COMMITTER_NAME <$COMMITTER_EMAIL>"
echo "Last author: $AUTHOR_NAME"
if [[ "$AUTHOR_NAME" == *"[bot]"* ]]; then
echo "source=bot" >> $GITHUB_OUTPUT
echo "Bot commit detected — will check formatting (no auto-fix)"
elif [[ "$COMMITTER_NAME" == "GitHub" && "$COMMITTER_EMAIL" == *"noreply@github.com"* ]]; then
echo "source=web-ui" >> $GITHUB_OUTPUT
echo "Web UI commit detected — will auto-format if needed"
else
echo "source=local" >> $GITHUB_OUTPUT
echo "Local commit detected — will check formatting"
fi
- name: Determine formatting strategy
id: strategy
env:
EVENT_NAME: ${{ github.event_name }}
HEAD_REPO: ${{ github.event.pull_request.head.repo.full_name || '' }}
CURRENT_REPO: ${{ github.repository }}
SOURCE: ${{ steps.detect.outputs.source }}
run: |
if [[ "$EVENT_NAME" == "pull_request" && "$SOURCE" == "web-ui" && "$HEAD_REPO" == "$CURRENT_REPO" ]]; then
echo "mode=auto-fix" >> $GITHUB_OUTPUT
echo "Same-repo web UI PR detected — will auto-format and push fixes"
else
echo "mode=check" >> $GITHUB_OUTPUT
echo "Formatting will run in check mode"
fi
- uses: ./.github/actions/setup-python
- name: Lint backend
working-directory: ./backend/ops_api
run: pipenv run nox -s lint
# --- For local commits: check formatting (fail build if wrong) ---
- name: Check backend formatting (Black)
if: steps.strategy.outputs.mode == 'check'
working-directory: ./backend/ops_api
run: pipenv run black --config ./pyproject.toml --check ops tests ./noxfile.py ../../performance_tests/locustfile.py
- name: Check backend import sorting (isort)
if: steps.strategy.outputs.mode == 'check'
working-directory: ./backend/ops_api
run: pipenv run isort --settings-file ./pyproject.toml --check-only --filter-files ops tests ./noxfile.py ../../performance_tests/locustfile.py
- name: Install data_tools dependencies
working-directory: ./backend/data_tools
run: pipenv install --dev
- name: Check data_tools formatting (Black)
if: steps.strategy.outputs.mode == 'check'
working-directory: ./backend/data_tools
run: pipenv run black --config ./pyproject.toml --check .
- name: Check data_tools import sorting (isort)
if: steps.strategy.outputs.mode == 'check'
working-directory: ./backend/data_tools
run: pipenv run isort --settings-file ./pyproject.toml --check-only --filter-files .
- uses: ./.github/actions/setup-javascript
- name: Lint frontend
working-directory: ./frontend
run: bun lint
- name: Check frontend formatting
if: steps.strategy.outputs.mode == 'check'
working-directory: ./frontend
run: bun run prettier --check --ignore-unknown 'src/**/*' '!src/uswds/**'
# --- For web UI commits: auto-fix formatting instead of failing ---
- name: Auto-fix backend formatting (Black)
if: steps.strategy.outputs.mode == 'auto-fix'
working-directory: ./backend/ops_api
run: pipenv run black --config ./pyproject.toml ops tests ./noxfile.py ../../performance_tests/locustfile.py
- name: Auto-fix backend import sorting (isort)
if: steps.strategy.outputs.mode == 'auto-fix'
working-directory: ./backend/ops_api
run: pipenv run isort --settings-file ./pyproject.toml --filter-files ops tests ./noxfile.py ../../performance_tests/locustfile.py
- name: Auto-fix data_tools formatting (Black)
if: steps.strategy.outputs.mode == 'auto-fix'
working-directory: ./backend/data_tools
run: pipenv run black --config ./pyproject.toml .
- name: Auto-fix data_tools import sorting (isort)
if: steps.strategy.outputs.mode == 'auto-fix'
working-directory: ./backend/data_tools
run: pipenv run isort --settings-file ./pyproject.toml --filter-files .
- name: Auto-fix frontend formatting (Prettier)
if: steps.strategy.outputs.mode == 'auto-fix'
working-directory: ./frontend
run: bun run prettier --write --ignore-unknown 'src/**/*' '!src/uswds/**'
- name: Commit and push formatting fixes
id: auto-commit
if: steps.strategy.outputs.mode == 'auto-fix'
run: |
git config user.name "github-actions[bot]"
git config user.email "github-actions[bot]@users.noreply.github.com"
git add -A
if git diff --staged --quiet; then
echo "committed=none" >> $GITHUB_OUTPUT
echo "No formatting changes needed"
else
git commit -m "style: auto-format code (web UI commit)"
git push
echo "committed=true" >> $GITHUB_OUTPUT
echo "Formatting fixes committed and pushed"
fi
- name: Comment on PR — formatting auto-fixed
if: |
steps.detect.outputs.source == 'web-ui' &&
steps.auto-commit.outputs.committed == 'true' &&
github.event_name == 'pull_request'
env:
GH_TOKEN: ${{ secrets.GITHUB_TOKEN }}
PR_NUMBER: ${{ github.event.pull_request.number }}
CONTRIBUTING_URL: ${{ github.server_url }}/${{ github.repository }}/blob/${{ github.event.pull_request.head.sha }}/CONTRIBUTING.md
run: |
BODY=$(cat <<EOF
🤖 **Auto-formatting applied!**
I detected that this PR was edited via the GitHub web UI and had some formatting issues. I automatically applied fixes using:
- **Prettier** (frontend)
- **Black** + **isort** (backend)
The fixes have been committed to this branch. For future contributions, consider setting up the [local development environment]($CONTRIBUTING_URL) to run formatters before pushing - it avoids this extra round-trip.
EOF
)
gh pr comment "$PR_NUMBER" --body "$BODY"