-
Notifications
You must be signed in to change notification settings - Fork 167
276 lines (254 loc) · 12.9 KB
/
lint.yml
File metadata and controls
276 lines (254 loc) · 12.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
272
273
274
275
276
name: Lint
# This workflow runs linting on files in the repository
# It can be configured to run on all files or just changed files
# It will fail the build if any linter fails
env:
CI: true
on:
pull_request:
workflow_dispatch:
inputs:
lint_mode:
description: 'Linting mode'
required: true
default: 'changed'
type: choice
options:
- all
- changed
jobs:
lint:
name: Lint Files
runs-on: ubuntu-latest
steps:
- name: Checkout
uses: actions/checkout@v6
with:
fetch-depth: 0 # Needed to get all history for comparing changes
- name: Set up environment
uses: ./.github/actions/setup
- name: Determine lint mode
id: lint_mode
run: |
# Default to 'changed' for push and PR events, but allow override via workflow_dispatch
if [ "${{ github.event_name }}" = "workflow_dispatch" ]; then
LINT_MODE="${{ github.event.inputs.lint_mode }}"
else
LINT_MODE="changed"
fi
echo "mode=$LINT_MODE" >> $GITHUB_OUTPUT
echo "Lint mode: $LINT_MODE"
- name: Get changed files
id: changed_files
if: steps.lint_mode.outputs.mode == 'changed'
run: |
if [ "${{ github.event_name }}" = "pull_request" ]; then
# For pull requests, compare with the base branch
BASE_SHA=${{ github.event.pull_request.base.sha }}
HEAD_SHA=${{ github.event.pull_request.head.sha }}
else
# For pushes, compare with the parent commit
BASE_SHA=$(git rev-parse HEAD^)
HEAD_SHA=$(git rev-parse HEAD)
fi
echo "Base SHA: $BASE_SHA"
echo "Head SHA: $HEAD_SHA"
# Get changed files, filtering out deleted files and files in ignored directories
CHANGED_TS_JS=$(git diff --name-only --diff-filter=d $BASE_SHA $HEAD_SHA | grep -E '\.(js|ts|jsx|tsx|cjs|mjs)$' | grep -v -E '(node_modules|dist|build|cache|reports|lib|coverage|artifacts|typechain|hardhat-cache|ignition/deployments|ignition/modules/artifacts)' || true)
CHANGED_SOL=$(git diff --name-only --diff-filter=d $BASE_SHA $HEAD_SHA | grep -E '\.sol$' | grep -v -E '(node_modules|dist|build|cache|reports|lib|coverage|artifacts|typechain|hardhat-cache|ignition/deployments|ignition/modules/artifacts|/test/)' || true)
CHANGED_MD=$(git diff --name-only --diff-filter=d $BASE_SHA $HEAD_SHA | grep -E '\.md$' | grep -v -E '(node_modules|dist|build|cache|reports|lib|coverage|artifacts|typechain|hardhat-cache|ignition/deployments|ignition/modules/artifacts)' || true)
CHANGED_JSON=$(git diff --name-only --diff-filter=d $BASE_SHA $HEAD_SHA | grep -E '\.json$' | grep -v -E '(node_modules|dist|build|cache|reports|lib|coverage|artifacts|typechain|hardhat-cache|ignition/deployments|ignition/modules/artifacts)' || true)
CHANGED_YAML=$(git diff --name-only --diff-filter=d $BASE_SHA $HEAD_SHA | grep -E '\.(yml|yaml)$' | grep -v -E '(node_modules|dist|build|cache|reports|lib|coverage|artifacts|typechain|hardhat-cache|ignition/deployments|ignition/modules/artifacts)' || true)
# Save to files for later use
echo "$CHANGED_TS_JS" > changed_ts_js.txt
echo "$CHANGED_SOL" > changed_sol.txt
echo "$CHANGED_MD" > changed_md.txt
echo "$CHANGED_JSON" > changed_json.txt
echo "$CHANGED_YAML" > changed_yaml.txt
# Count changed files
TS_JS_COUNT=$(echo "$CHANGED_TS_JS" | grep -v '^$' | wc -l)
SOL_COUNT=$(echo "$CHANGED_SOL" | grep -v '^$' | wc -l)
MD_COUNT=$(echo "$CHANGED_MD" | grep -v '^$' | wc -l)
JSON_COUNT=$(echo "$CHANGED_JSON" | grep -v '^$' | wc -l)
YAML_COUNT=$(echo "$CHANGED_YAML" | grep -v '^$' | wc -l)
TOTAL_COUNT=$((TS_JS_COUNT + SOL_COUNT + MD_COUNT + JSON_COUNT + YAML_COUNT))
echo "ts_js_count=$TS_JS_COUNT" >> $GITHUB_OUTPUT
echo "sol_count=$SOL_COUNT" >> $GITHUB_OUTPUT
echo "md_count=$MD_COUNT" >> $GITHUB_OUTPUT
echo "json_count=$JSON_COUNT" >> $GITHUB_OUTPUT
echo "yaml_count=$YAML_COUNT" >> $GITHUB_OUTPUT
echo "total_count=$TOTAL_COUNT" >> $GITHUB_OUTPUT
echo "Found $TOTAL_COUNT changed files to lint:"
echo "- TypeScript/JavaScript: $TS_JS_COUNT"
echo "- Solidity: $SOL_COUNT"
echo "- Markdown: $MD_COUNT"
echo "- JSON: $JSON_COUNT"
echo "- YAML: $YAML_COUNT"
- name: Lint Solidity files
id: lint_sol
continue-on-error: true
run: |
if [ "${{ steps.lint_mode.outputs.mode }}" = "all" ]; then
echo "Linting all Solidity files in each package..."
# Run solhint in each workspace package that has contracts (check mode)
pnpm -r exec bash -c 'if [ -d "contracts" ]; then npx solhint --max-warnings=0 --noPrompt --noPoster "contracts/**/*.sol" 2>/dev/null || exit 1; fi'
# Check formatting with prettier
SOL_FILES=$(git ls-files '*.sol')
if [ -n "$SOL_FILES" ]; then
echo "$SOL_FILES" | tr '\n' '\0' | xargs -0 npx prettier --check --cache --log-level warn
else
echo "No Solidity files found"
fi
elif [ "${{ steps.changed_files.outputs.sol_count }}" -gt "0" ]; then
echo "Linting changed Solidity files..."
# Lint each changed file from its package directory
for file in $(cat changed_sol.txt); do
# Walk up to find package.json
dir="$file"
found=false
while [ "$dir" != "." ]; do
dir=$(dirname "$dir")
if [ -f "$dir/package.json" ]; then
relative_file="${file#$dir/}"
echo " Checking $file"
(cd "$dir" && npx solhint --max-warnings=0 --noPrompt --noPoster "$relative_file")
found=true
break
fi
done
if [ "$found" = false ]; then
echo "::error::No package.json found for $file - workflow needs fixing"
exit 1
fi
done
# Check formatting with prettier
cat changed_sol.txt | tr '\n' '\0' | xargs -0 npx prettier --check --cache --log-level warn
else
echo "No Solidity files to lint"
fi
- name: Lint TypeScript/JavaScript files
id: lint_ts
continue-on-error: true
run: |
if [ "${{ steps.lint_mode.outputs.mode }}" = "all" ]; then
echo "Linting all TypeScript/JavaScript files..."
TS_FILES=$(git ls-files '*.js' '*.ts' '*.cjs' '*.mjs' '*.jsx' '*.tsx')
if [ -n "$TS_FILES" ]; then
echo "$TS_FILES" | tr '\n' '\0' | xargs -0 npx eslint --max-warnings=0 --no-warn-ignored
echo "$TS_FILES" | tr '\n' '\0' | xargs -0 npx prettier --check --cache --log-level warn --no-error-on-unmatched-pattern
else
echo "No TypeScript/JavaScript files found"
fi
elif [ "${{ steps.changed_files.outputs.ts_js_count }}" -gt "0" ]; then
echo "Linting changed TypeScript/JavaScript files..."
cat changed_ts_js.txt | tr '\n' '\0' | xargs -0 npx eslint --max-warnings=0 --no-warn-ignored
cat changed_ts_js.txt | tr '\n' '\0' | xargs -0 npx prettier --check --cache --log-level warn --no-error-on-unmatched-pattern
else
echo "No TypeScript/JavaScript files to lint"
fi
- name: Lint Markdown files
id: lint_md
continue-on-error: true
run: |
if [ "${{ steps.lint_mode.outputs.mode }}" = "all" ]; then
echo "Linting all Markdown files..."
MD_FILES=$(git ls-files '*.md')
if [ -n "$MD_FILES" ]; then
echo "$MD_FILES" | tr '\n' '\0' | xargs -0 npx markdownlint --ignore-path .gitignore --ignore-path .markdownlintignore
echo "$MD_FILES" | tr '\n' '\0' | xargs -0 npx prettier --check --cache --log-level warn --no-error-on-unmatched-pattern
else
echo "No Markdown files found"
fi
elif [ "${{ steps.changed_files.outputs.md_count }}" -gt "0" ]; then
echo "Linting changed Markdown files..."
cat changed_md.txt | tr '\n' '\0' | xargs -0 npx markdownlint --ignore-path .gitignore --ignore-path .markdownlintignore
cat changed_md.txt | tr '\n' '\0' | xargs -0 npx prettier --check --cache --log-level warn --no-error-on-unmatched-pattern
else
echo "No Markdown files to lint"
fi
- name: Lint JSON files
id: lint_json
continue-on-error: true
run: |
if [ "${{ steps.lint_mode.outputs.mode }}" = "all" ]; then
echo "Linting all JSON files..."
# Exclude Ignition deployment artifacts and other build artifacts
JSON_FILES=$(git ls-files '*.json' | { grep -v -E '(ignition/deployments/.*/artifacts/|ignition/deployments/.*/build-info/|/\.openzeppelin/|deployments/.*/solcInputs/)' || true; })
if [ -n "$JSON_FILES" ]; then
echo "$JSON_FILES" | tr '\n' '\0' | xargs -0 npx prettier --check --cache --log-level warn --no-error-on-unmatched-pattern
else
echo "No JSON files found"
fi
elif [ "${{ steps.changed_files.outputs.json_count }}" -gt "0" ]; then
echo "Linting changed JSON files..."
JSON_FILES=$(cat changed_json.txt | { grep -v -E '(ignition/deployments/.*/artifacts/|ignition/deployments/.*/build-info/|/\.openzeppelin/|deployments/.*/solcInputs/)' || true; })
if [ -n "$JSON_FILES" ]; then
echo "$JSON_FILES" | tr '\n' '\0' | xargs -0 npx prettier --check --cache --log-level warn --no-error-on-unmatched-pattern
else
echo "No JSON files to lint (after filtering build artifacts)"
fi
else
echo "No JSON files to lint"
fi
- name: Lint YAML files
id: lint_yaml
continue-on-error: true
run: |
if [ "${{ steps.lint_mode.outputs.mode }}" = "all" ]; then
echo "Linting all YAML files..."
YAML_FILES=$(git ls-files '*.yml' '*.yaml')
if [ -n "$YAML_FILES" ]; then
echo "$YAML_FILES" | tr '\n' '\0' | xargs -0 npx yaml-lint
echo "$YAML_FILES" | tr '\n' '\0' | xargs -0 npx prettier --check --cache --log-level warn --no-error-on-unmatched-pattern
else
echo "No YAML files found"
fi
elif [ "${{ steps.changed_files.outputs.yaml_count }}" -gt "0" ]; then
echo "Linting changed YAML files..."
cat changed_yaml.txt | tr '\n' '\0' | xargs -0 npx yaml-lint
cat changed_yaml.txt | tr '\n' '\0' | xargs -0 npx prettier --check --cache --log-level warn --no-error-on-unmatched-pattern
else
echo "No YAML files to lint"
fi
- name: Lint Forge files
id: lint_forge
continue-on-error: true
run: |
# Find packages with lint:forge script defined
FORGE_PACKAGES=$(find packages -name "package.json" -exec grep -l '"lint:forge"' {} \; | xargs -I{} dirname {} | sort)
if [ -z "$FORGE_PACKAGES" ]; then
echo "No packages with lint:forge script found"
exit 0
fi
echo "Packages with lint:forge: $FORGE_PACKAGES"
if [ "${{ steps.lint_mode.outputs.mode }}" = "all" ]; then
echo "Linting all Forge files..."
pnpm lint:forge
elif [ "${{ steps.changed_files.outputs.sol_count }}" -gt "0" ]; then
# Build regex pattern from packages with lint:forge
FORGE_PATTERN=$(echo "$FORGE_PACKAGES" | tr '\n' '|' | sed 's/|$//')
FORGE_FILES=$(cat changed_sol.txt | grep -E "^($FORGE_PATTERN)/" || true)
if [ -n "$FORGE_FILES" ]; then
echo "Found Forge-related changes, running forge lint..."
pnpm lint:forge
else
echo "No Forge-related Solidity files changed"
fi
else
echo "No Solidity files to lint with Forge"
fi
- name: Check lint results
if: always()
run: |
# Check if any lint step failed
if [ "${{ steps.lint_sol.outcome }}" = "failure" ] || \
[ "${{ steps.lint_ts.outcome }}" = "failure" ] || \
[ "${{ steps.lint_md.outcome }}" = "failure" ] || \
[ "${{ steps.lint_json.outcome }}" = "failure" ] || \
[ "${{ steps.lint_yaml.outcome }}" = "failure" ] || \
[ "${{ steps.lint_forge.outcome }}" = "failure" ]; then
echo "❌ One or more linters failed"
exit 1
else
echo "✅ All linters passed"
fi