Skip to content

Commit 91d5212

Browse files
committed
fix(ci): fix lint workflow to match local linting behaviour and fail on warnings
The lint workflow had two critical issues: 1. **Did not fail on warnings**: The workflow used continue-on-error with exit code capture via $?, but $? was always 0 because continue-on-error prevents failures. Fixed by checking step outcomes in a final verification step. 2. **Different results than local linting**: CI ran linters from repo root while local 'pnpm lint' runs per-package scripts from package directories. This caused Solhint's import-path-check rule to produce false warnings in CI. Fixed by running Solhint from each package directory using 'pnpm -r exec'. Additional improvements: - Use git ls-files instead of globs to only lint tracked files (much faster) - Exclude Ignition/build artifacts from JSON linting (939 → 102 files, 89% reduction) - Add --no-warn-ignored to ESLint to suppress ignore pattern warnings - Add --no-error-on-unmatched-pattern to Prettier to handle symlinks gracefully - Simplify workflow structure with fewer, clearer steps Also fixed YAML syntax warning in build-test.yml (removed redundant branches filter).
1 parent 4b76a40 commit 91d5212

File tree

2 files changed

+66
-243
lines changed

2 files changed

+66
-243
lines changed

.github/workflows/build-test.yml

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,6 @@ env:
66

77
on:
88
pull_request:
9-
branches: '*'
109
workflow_dispatch:
1110

1211
jobs:

.github/workflows/lint.yml

Lines changed: 66 additions & 242 deletions
Original file line numberDiff line numberDiff line change
@@ -2,14 +2,13 @@ name: Lint
22

33
# This workflow runs linting on files in the repository
44
# It can be configured to run on all files or just changed files
5-
# It will fail the build if there are errors, but only report warnings
5+
# It will fail the build if any linter fails
66

77
env:
88
CI: true
99

1010
on:
1111
pull_request:
12-
branches: '*'
1312
workflow_dispatch:
1413
inputs:
1514
lint_mode:
@@ -99,278 +98,103 @@ jobs:
9998
echo "- JSON: $JSON_COUNT"
10099
echo "- YAML: $YAML_COUNT"
101100
102-
- name: Lint TypeScript/JavaScript files (ESLint)
103-
id: lint_ts_eslint
101+
- name: Lint Solidity files
102+
id: lint_sol
104103
continue-on-error: true
105104
run: |
106105
if [ "${{ steps.lint_mode.outputs.mode }}" = "all" ]; then
107-
echo "Running ESLint on all TypeScript/JavaScript files..."
108-
npx eslint --max-warnings=0 '**/*.{js,ts,cjs,mjs,jsx,tsx}'
109-
echo "ts_eslint_exit_code=$?" >> $GITHUB_OUTPUT
110-
elif [ "${{ steps.changed_files.outputs.ts_js_count }}" -gt "0" ]; then
111-
echo "Running ESLint on changed TypeScript/JavaScript files..."
112-
cat changed_ts_js.txt | xargs npx eslint --max-warnings=0
113-
echo "ts_eslint_exit_code=$?" >> $GITHUB_OUTPUT
114-
else
115-
echo "No TypeScript/JavaScript files to lint with ESLint."
116-
echo "ts_eslint_exit_code=0" >> $GITHUB_OUTPUT
117-
fi
118-
119-
- name: Lint TypeScript/JavaScript files (Prettier)
120-
id: lint_ts_prettier
121-
continue-on-error: true
122-
run: |
123-
if [ "${{ steps.lint_mode.outputs.mode }}" = "all" ]; then
124-
echo "Checking all TypeScript/JavaScript files with Prettier..."
125-
npx prettier --check --cache --log-level warn '**/*.{js,ts,cjs,mjs,jsx,tsx}'
126-
echo "ts_prettier_exit_code=$?" >> $GITHUB_OUTPUT
127-
elif [ "${{ steps.changed_files.outputs.ts_js_count }}" -gt "0" ]; then
128-
echo "Checking changed TypeScript/JavaScript files with Prettier..."
129-
cat changed_ts_js.txt | xargs npx prettier --check --cache --log-level warn
130-
echo "ts_prettier_exit_code=$?" >> $GITHUB_OUTPUT
131-
else
132-
echo "No TypeScript/JavaScript files to check with Prettier."
133-
echo "ts_prettier_exit_code=0" >> $GITHUB_OUTPUT
134-
fi
135-
136-
- name: Lint Solidity files (Solhint)
137-
id: lint_sol_solhint
138-
continue-on-error: true
139-
run: |
140-
if [ "${{ steps.lint_mode.outputs.mode }}" = "all" ]; then
141-
echo "Running Solhint on all Solidity files..."
142-
npx solhint --max-warnings=0 --noPrompt --noPoster 'packages/*/contracts/**/*.sol'
143-
echo "sol_solhint_exit_code=$?" >> $GITHUB_OUTPUT
144-
elif [ "${{ steps.changed_files.outputs.sol_count }}" -gt "0" ]; then
145-
echo "Running Solhint on changed Solidity files..."
146-
cat changed_sol.txt | xargs npx solhint --max-warnings=0 --noPrompt --noPoster
147-
echo "sol_solhint_exit_code=$?" >> $GITHUB_OUTPUT
148-
else
149-
echo "No Solidity files to lint with Solhint."
150-
echo "sol_solhint_exit_code=0" >> $GITHUB_OUTPUT
151-
fi
152-
153-
- name: Lint Solidity files (Prettier)
154-
id: lint_sol_prettier
155-
continue-on-error: true
156-
run: |
157-
if [ "${{ steps.lint_mode.outputs.mode }}" = "all" ]; then
158-
echo "Checking all Solidity files with Prettier..."
159-
npx prettier --check --cache --log-level warn '**/*.sol'
160-
echo "sol_prettier_exit_code=$?" >> $GITHUB_OUTPUT
106+
echo "Linting all Solidity files in each package..."
107+
# Run solhint in each workspace package that has contracts (check mode)
108+
pnpm -r exec bash -c 'if [ -d "contracts" ]; then npx solhint --max-warnings=0 --noPrompt --noPoster "contracts/**/*.sol" 2>/dev/null || exit 1; fi'
109+
# Check formatting with prettier
110+
git ls-files '*.sol' | xargs -r npx prettier --check --cache --log-level warn
161111
elif [ "${{ steps.changed_files.outputs.sol_count }}" -gt "0" ]; then
162-
echo "Checking changed Solidity files with Prettier..."
112+
echo "Linting changed Solidity files..."
113+
# Lint each changed file from its package directory
114+
for file in $(cat changed_sol.txt); do
115+
# Walk up to find package.json
116+
dir="$file"
117+
while [ "$dir" != "." ]; do
118+
dir=$(dirname "$dir")
119+
if [ -f "$dir/package.json" ]; then
120+
relative_file="${file#$dir/}"
121+
echo " Checking $file"
122+
(cd "$dir" && npx solhint --max-warnings=0 --noPrompt --noPoster "$relative_file")
123+
break
124+
fi
125+
done
126+
done
127+
128+
# Check formatting with prettier
163129
cat changed_sol.txt | xargs npx prettier --check --cache --log-level warn
164-
echo "sol_prettier_exit_code=$?" >> $GITHUB_OUTPUT
165-
else
166-
echo "No Solidity files to check with Prettier."
167-
echo "sol_prettier_exit_code=0" >> $GITHUB_OUTPUT
168130
fi
169131
170-
- name: Lint Markdown files (Markdownlint)
171-
id: lint_md_markdownlint
132+
- name: Lint TypeScript/JavaScript files
133+
id: lint_ts
172134
continue-on-error: true
173135
run: |
174136
if [ "${{ steps.lint_mode.outputs.mode }}" = "all" ]; then
175-
echo "Running Markdownlint on all Markdown files..."
176-
npx markdownlint --ignore-path .gitignore --ignore-path .markdownlintignore '**/*.md'
177-
echo "md_markdownlint_exit_code=$?" >> $GITHUB_OUTPUT
178-
elif [ "${{ steps.changed_files.outputs.md_count }}" -gt "0" ]; then
179-
echo "Running Markdownlint on changed Markdown files..."
180-
cat changed_md.txt | xargs npx markdownlint --ignore-path .gitignore --ignore-path .markdownlintignore
181-
echo "md_markdownlint_exit_code=$?" >> $GITHUB_OUTPUT
182-
else
183-
echo "No Markdown files to lint with Markdownlint."
184-
echo "md_markdownlint_exit_code=0" >> $GITHUB_OUTPUT
137+
echo "Linting all TypeScript/JavaScript files..."
138+
git ls-files '*.js' '*.ts' '*.cjs' '*.mjs' '*.jsx' '*.tsx' | xargs -r npx eslint --max-warnings=0 --no-warn-ignored
139+
git ls-files '*.js' '*.ts' '*.cjs' '*.mjs' '*.jsx' '*.tsx' | xargs -r npx prettier --check --cache --log-level warn --no-error-on-unmatched-pattern
140+
elif [ "${{ steps.changed_files.outputs.ts_js_count }}" -gt "0" ]; then
141+
echo "Linting changed TypeScript/JavaScript files..."
142+
cat changed_ts_js.txt | xargs npx eslint --max-warnings=0 --no-warn-ignored
143+
cat changed_ts_js.txt | xargs npx prettier --check --cache --log-level warn --no-error-on-unmatched-pattern
185144
fi
186145
187-
- name: Lint Markdown files (Prettier)
188-
id: lint_md_prettier
146+
- name: Lint Markdown files
147+
id: lint_md
189148
continue-on-error: true
190149
run: |
191150
if [ "${{ steps.lint_mode.outputs.mode }}" = "all" ]; then
192-
echo "Checking all Markdown files with Prettier..."
193-
npx prettier --check --cache --log-level warn '**/*.md'
194-
echo "md_prettier_exit_code=$?" >> $GITHUB_OUTPUT
151+
echo "Linting all Markdown files..."
152+
git ls-files '*.md' | xargs -r npx markdownlint --ignore-path .gitignore --ignore-path .markdownlintignore
153+
git ls-files '*.md' | xargs -r npx prettier --check --cache --log-level warn --no-error-on-unmatched-pattern
195154
elif [ "${{ steps.changed_files.outputs.md_count }}" -gt "0" ]; then
196-
echo "Checking changed Markdown files with Prettier..."
197-
cat changed_md.txt | xargs npx prettier --check --cache --log-level warn
198-
echo "md_prettier_exit_code=$?" >> $GITHUB_OUTPUT
199-
else
200-
echo "No Markdown files to check with Prettier."
201-
echo "md_prettier_exit_code=0" >> $GITHUB_OUTPUT
155+
echo "Linting changed Markdown files..."
156+
cat changed_md.txt | xargs npx markdownlint --ignore-path .gitignore --ignore-path .markdownlintignore
157+
cat changed_md.txt | xargs npx prettier --check --cache --log-level warn --no-error-on-unmatched-pattern
202158
fi
203159
204-
- name: Lint JSON files (Prettier)
205-
id: lint_json_prettier
160+
- name: Lint JSON files
161+
id: lint_json
206162
continue-on-error: true
207163
run: |
208164
if [ "${{ steps.lint_mode.outputs.mode }}" = "all" ]; then
209-
echo "Checking all JSON files with Prettier..."
210-
npx prettier --check --cache --log-level warn '**/*.json'
211-
echo "json_prettier_exit_code=$?" >> $GITHUB_OUTPUT
165+
echo "Linting all JSON files..."
166+
# Exclude Ignition deployment artifacts and other build artifacts
167+
git ls-files '*.json' | grep -v -E '(ignition/deployments/.*/artifacts/|ignition/deployments/.*/build-info/|/\.openzeppelin/|deployments/.*/solcInputs/)' | xargs -r npx prettier --check --cache --log-level warn --no-error-on-unmatched-pattern
212168
elif [ "${{ steps.changed_files.outputs.json_count }}" -gt "0" ]; then
213-
echo "Checking changed JSON files with Prettier..."
214-
cat changed_json.txt | xargs npx prettier --check --cache --log-level warn
215-
echo "json_prettier_exit_code=$?" >> $GITHUB_OUTPUT
216-
else
217-
echo "No JSON files to check with Prettier."
218-
echo "json_prettier_exit_code=0" >> $GITHUB_OUTPUT
169+
echo "Linting changed JSON files..."
170+
cat changed_json.txt | grep -v -E '(ignition/deployments/.*/artifacts/|ignition/deployments/.*/build-info/|/\.openzeppelin/|deployments/.*/solcInputs/)' | xargs -r npx prettier --check --cache --log-level warn --no-error-on-unmatched-pattern
219171
fi
220172
221-
- name: Lint YAML files (yaml-lint)
222-
id: lint_yaml_yamllint
173+
- name: Lint YAML files
174+
id: lint_yaml
223175
continue-on-error: true
224176
run: |
225177
if [ "${{ steps.lint_mode.outputs.mode }}" = "all" ]; then
226-
echo "Running yaml-lint on all YAML files..."
227-
npx yaml-lint .github/**/*.{yml,yaml}
228-
echo "yaml_yamllint_exit_code=$?" >> $GITHUB_OUTPUT
178+
echo "Linting all YAML files..."
179+
git ls-files '*.yml' '*.yaml' | xargs -r npx yaml-lint
180+
git ls-files '*.yml' '*.yaml' | xargs -r npx prettier --check --cache --log-level warn --no-error-on-unmatched-pattern
229181
elif [ "${{ steps.changed_files.outputs.yaml_count }}" -gt "0" ]; then
230-
echo "Running yaml-lint on changed YAML files..."
182+
echo "Linting changed YAML files..."
231183
cat changed_yaml.txt | xargs npx yaml-lint
232-
echo "yaml_yamllint_exit_code=$?" >> $GITHUB_OUTPUT
233-
else
234-
echo "No YAML files to lint with yaml-lint."
235-
echo "yaml_yamllint_exit_code=0" >> $GITHUB_OUTPUT
184+
cat changed_yaml.txt | xargs npx prettier --check --cache --log-level warn --no-error-on-unmatched-pattern
236185
fi
237186
238-
- name: Lint YAML files (Prettier)
239-
id: lint_yaml_prettier
240-
continue-on-error: true
241-
run: |
242-
if [ "${{ steps.lint_mode.outputs.mode }}" = "all" ]; then
243-
echo "Checking all YAML files with Prettier..."
244-
npx prettier --check --cache --log-level warn '**/*.{yml,yaml}'
245-
echo "yaml_prettier_exit_code=$?" >> $GITHUB_OUTPUT
246-
elif [ "${{ steps.changed_files.outputs.yaml_count }}" -gt "0" ]; then
247-
echo "Checking changed YAML files with Prettier..."
248-
cat changed_yaml.txt | xargs npx prettier --check --cache --log-level warn
249-
echo "yaml_prettier_exit_code=$?" >> $GITHUB_OUTPUT
250-
else
251-
echo "No YAML files to check with Prettier."
252-
echo "yaml_prettier_exit_code=0" >> $GITHUB_OUTPUT
253-
fi
254-
255-
- name: Determine overall status
256-
id: status
187+
- name: Check lint results
188+
if: always()
257189
run: |
258-
# Collect all exit codes
259-
TS_ESLINT_EXIT_CODE="${{ steps.lint_ts_eslint.outputs.ts_eslint_exit_code }}"
260-
TS_PRETTIER_EXIT_CODE="${{ steps.lint_ts_prettier.outputs.ts_prettier_exit_code }}"
261-
SOL_SOLHINT_EXIT_CODE="${{ steps.lint_sol_solhint.outputs.sol_solhint_exit_code }}"
262-
SOL_PRETTIER_EXIT_CODE="${{ steps.lint_sol_prettier.outputs.sol_prettier_exit_code }}"
263-
SOL_NATSPEC_EXIT_CODE="${{ steps.lint_sol_natspec.outputs.sol_natspec_exit_code }}"
264-
MD_MARKDOWNLINT_EXIT_CODE="${{ steps.lint_md_markdownlint.outputs.md_markdownlint_exit_code }}"
265-
MD_PRETTIER_EXIT_CODE="${{ steps.lint_md_prettier.outputs.md_prettier_exit_code }}"
266-
JSON_PRETTIER_EXIT_CODE="${{ steps.lint_json_prettier.outputs.json_prettier_exit_code }}"
267-
YAML_YAMLLINT_EXIT_CODE="${{ steps.lint_yaml_yamllint.outputs.yaml_yamllint_exit_code }}"
268-
YAML_PRETTIER_EXIT_CODE="${{ steps.lint_yaml_prettier.outputs.yaml_prettier_exit_code }}"
269-
270-
# Initialize counters
271-
ERRORS=0
272-
WARNINGS=0
273-
274-
# Check each exit code
275-
# Exit code 1 typically indicates errors
276-
# Exit code 2 or higher might indicate warnings or other issues
277-
278-
# TypeScript/JavaScript - ESLint
279-
if [ "$TS_ESLINT_EXIT_CODE" = "1" ]; then
280-
echo "::error::ESLint found errors in TypeScript/JavaScript files"
281-
ERRORS=$((ERRORS+1))
282-
elif [ "$TS_ESLINT_EXIT_CODE" != "0" ]; then
283-
echo "::warning::ESLint found warnings in TypeScript/JavaScript files"
284-
WARNINGS=$((WARNINGS+1))
285-
fi
286-
287-
# TypeScript/JavaScript - Prettier
288-
if [ "$TS_PRETTIER_EXIT_CODE" = "1" ]; then
289-
echo "::error::Prettier found formatting issues in TypeScript/JavaScript files"
290-
ERRORS=$((ERRORS+1))
291-
elif [ "$TS_PRETTIER_EXIT_CODE" != "0" ]; then
292-
echo "::warning::Prettier found warnings in TypeScript/JavaScript files"
293-
WARNINGS=$((WARNINGS+1))
294-
fi
295-
296-
# Solidity - Solhint
297-
if [ "$SOL_SOLHINT_EXIT_CODE" = "1" ]; then
298-
echo "::error::Solhint found errors in Solidity files"
299-
ERRORS=$((ERRORS+1))
300-
elif [ "$SOL_SOLHINT_EXIT_CODE" != "0" ]; then
301-
echo "::warning::Solhint found warnings in Solidity files"
302-
WARNINGS=$((WARNINGS+1))
303-
fi
304-
305-
# Solidity - Prettier
306-
if [ "$SOL_PRETTIER_EXIT_CODE" = "1" ]; then
307-
echo "::error::Prettier found formatting issues in Solidity files"
308-
ERRORS=$((ERRORS+1))
309-
elif [ "$SOL_PRETTIER_EXIT_CODE" != "0" ]; then
310-
echo "::warning::Prettier found warnings in Solidity files"
311-
WARNINGS=$((WARNINGS+1))
312-
fi
313-
314-
# Markdown - Markdownlint
315-
if [ "$MD_MARKDOWNLINT_EXIT_CODE" = "1" ]; then
316-
echo "::error::Markdownlint found errors in Markdown files"
317-
ERRORS=$((ERRORS+1))
318-
elif [ "$MD_MARKDOWNLINT_EXIT_CODE" != "0" ]; then
319-
echo "::warning::Markdownlint found warnings in Markdown files"
320-
WARNINGS=$((WARNINGS+1))
321-
fi
322-
323-
# Markdown - Prettier
324-
if [ "$MD_PRETTIER_EXIT_CODE" = "1" ]; then
325-
echo "::error::Prettier found formatting issues in Markdown files"
326-
ERRORS=$((ERRORS+1))
327-
elif [ "$MD_PRETTIER_EXIT_CODE" != "0" ]; then
328-
echo "::warning::Prettier found warnings in Markdown files"
329-
WARNINGS=$((WARNINGS+1))
330-
fi
331-
332-
# JSON - Prettier
333-
if [ "$JSON_PRETTIER_EXIT_CODE" = "1" ]; then
334-
echo "::error::Prettier found formatting issues in JSON files"
335-
ERRORS=$((ERRORS+1))
336-
elif [ "$JSON_PRETTIER_EXIT_CODE" != "0" ]; then
337-
echo "::warning::Prettier found warnings in JSON files"
338-
WARNINGS=$((WARNINGS+1))
339-
fi
340-
341-
# YAML - yaml-lint
342-
if [ "$YAML_YAMLLINT_EXIT_CODE" = "1" ]; then
343-
echo "::error::yaml-lint found errors in YAML files"
344-
ERRORS=$((ERRORS+1))
345-
elif [ "$YAML_YAMLLINT_EXIT_CODE" != "0" ]; then
346-
echo "::warning::yaml-lint found warnings in YAML files"
347-
WARNINGS=$((WARNINGS+1))
348-
fi
349-
350-
# YAML - Prettier
351-
if [ "$YAML_PRETTIER_EXIT_CODE" = "1" ]; then
352-
echo "::error::Prettier found formatting issues in YAML files"
353-
ERRORS=$((ERRORS+1))
354-
elif [ "$YAML_PRETTIER_EXIT_CODE" != "0" ]; then
355-
echo "::warning::Prettier found warnings in YAML files"
356-
WARNINGS=$((WARNINGS+1))
357-
fi
358-
359-
# Create summary
360-
LINT_MODE="${{ steps.lint_mode.outputs.mode }}"
361-
if [ "$ERRORS" -gt 0 ]; then
362-
echo "summary=❌ Linting ($LINT_MODE files) failed with $ERRORS error types and $WARNINGS warning types." >> $GITHUB_OUTPUT
363-
echo "Linting failed with errors. CI build will fail."
190+
# Check if any lint step failed
191+
if [ "${{ steps.lint_sol.outcome }}" = "failure" ] || \
192+
[ "${{ steps.lint_ts.outcome }}" = "failure" ] || \
193+
[ "${{ steps.lint_md.outcome }}" = "failure" ] || \
194+
[ "${{ steps.lint_json.outcome }}" = "failure" ] || \
195+
[ "${{ steps.lint_yaml.outcome }}" = "failure" ]; then
196+
echo "❌ One or more linters failed"
364197
exit 1
365-
elif [ "$WARNINGS" -gt 0 ]; then
366-
echo "summary=⚠️ Linting ($LINT_MODE files) passed with $WARNINGS warning types. CI build will continue." >> $GITHUB_OUTPUT
367-
echo "Linting found warnings but no errors. CI build will continue."
368-
exit 0
369198
else
370-
echo "summary=✅ All linters ($LINT_MODE files) passed successfully with no errors or warnings." >> $GITHUB_OUTPUT
371-
echo "All linters passed successfully."
372-
exit 0
199+
echo "✅ All linters passed"
373200
fi
374-
375-
- name: Post Summary
376-
run: echo "${{ steps.status.outputs.summary }}" >> $GITHUB_STEP_SUMMARY

0 commit comments

Comments
 (0)