Modernise and cleanup lint configuration and build process #22
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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 there are errors, but only report warnings | |
env: | |
CI: true | |
on: | |
push: | |
branches: '*' | |
pull_request: | |
branches: '*' | |
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@v4 | |
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)' || 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 TypeScript/JavaScript files (ESLint) | |
id: lint_ts_eslint | |
continue-on-error: true | |
run: | | |
if [ "${{ steps.lint_mode.outputs.mode }}" = "all" ]; then | |
echo "Running ESLint on all TypeScript/JavaScript files..." | |
npx eslint --max-warnings=0 '**/*.{js,ts,cjs,mjs,jsx,tsx}' | |
echo "ts_eslint_exit_code=$?" >> $GITHUB_OUTPUT | |
elif [ "${{ steps.changed_files.outputs.ts_js_count }}" -gt "0" ]; then | |
echo "Running ESLint on changed TypeScript/JavaScript files..." | |
cat changed_ts_js.txt | xargs npx eslint --max-warnings=0 | |
echo "ts_eslint_exit_code=$?" >> $GITHUB_OUTPUT | |
else | |
echo "No TypeScript/JavaScript files to lint with ESLint." | |
echo "ts_eslint_exit_code=0" >> $GITHUB_OUTPUT | |
fi | |
- name: Lint TypeScript/JavaScript files (Prettier) | |
id: lint_ts_prettier | |
continue-on-error: true | |
run: | | |
if [ "${{ steps.lint_mode.outputs.mode }}" = "all" ]; then | |
echo "Checking all TypeScript/JavaScript files with Prettier..." | |
npx prettier --check --cache --log-level warn '**/*.{js,ts,cjs,mjs,jsx,tsx}' | |
echo "ts_prettier_exit_code=$?" >> $GITHUB_OUTPUT | |
elif [ "${{ steps.changed_files.outputs.ts_js_count }}" -gt "0" ]; then | |
echo "Checking changed TypeScript/JavaScript files with Prettier..." | |
cat changed_ts_js.txt | xargs npx prettier --check --cache --log-level warn | |
echo "ts_prettier_exit_code=$?" >> $GITHUB_OUTPUT | |
else | |
echo "No TypeScript/JavaScript files to check with Prettier." | |
echo "ts_prettier_exit_code=0" >> $GITHUB_OUTPUT | |
fi | |
- name: Lint Solidity files (Solhint) | |
id: lint_sol_solhint | |
continue-on-error: true | |
run: | | |
if [ "${{ steps.lint_mode.outputs.mode }}" = "all" ]; then | |
echo "Running Solhint on all Solidity files..." | |
npx solhint --max-warnings=0 --noPrompt --noPoster 'packages/*/contracts/**/*.sol' | |
echo "sol_solhint_exit_code=$?" >> $GITHUB_OUTPUT | |
elif [ "${{ steps.changed_files.outputs.sol_count }}" -gt "0" ]; then | |
echo "Running Solhint on changed Solidity files..." | |
cat changed_sol.txt | xargs npx solhint --max-warnings=0 --noPrompt --noPoster | |
echo "sol_solhint_exit_code=$?" >> $GITHUB_OUTPUT | |
else | |
echo "No Solidity files to lint with Solhint." | |
echo "sol_solhint_exit_code=0" >> $GITHUB_OUTPUT | |
fi | |
- name: Lint Solidity files (Prettier) | |
id: lint_sol_prettier | |
continue-on-error: true | |
run: | | |
if [ "${{ steps.lint_mode.outputs.mode }}" = "all" ]; then | |
echo "Checking all Solidity files with Prettier..." | |
npx prettier --check --cache --log-level warn '**/*.sol' | |
echo "sol_prettier_exit_code=$?" >> $GITHUB_OUTPUT | |
elif [ "${{ steps.changed_files.outputs.sol_count }}" -gt "0" ]; then | |
echo "Checking changed Solidity files with Prettier..." | |
cat changed_sol.txt | xargs npx prettier --check --cache --log-level warn | |
echo "sol_prettier_exit_code=$?" >> $GITHUB_OUTPUT | |
else | |
echo "No Solidity files to check with Prettier." | |
echo "sol_prettier_exit_code=0" >> $GITHUB_OUTPUT | |
fi | |
- name: Lint Markdown files (Markdownlint) | |
id: lint_md_markdownlint | |
continue-on-error: true | |
run: | | |
if [ "${{ steps.lint_mode.outputs.mode }}" = "all" ]; then | |
echo "Running Markdownlint on all Markdown files..." | |
npx markdownlint --ignore-path .gitignore --ignore-path .markdownlintignore '**/*.md' | |
echo "md_markdownlint_exit_code=$?" >> $GITHUB_OUTPUT | |
elif [ "${{ steps.changed_files.outputs.md_count }}" -gt "0" ]; then | |
echo "Running Markdownlint on changed Markdown files..." | |
cat changed_md.txt | xargs npx markdownlint --ignore-path .gitignore --ignore-path .markdownlintignore | |
echo "md_markdownlint_exit_code=$?" >> $GITHUB_OUTPUT | |
else | |
echo "No Markdown files to lint with Markdownlint." | |
echo "md_markdownlint_exit_code=0" >> $GITHUB_OUTPUT | |
fi | |
- name: Lint Markdown files (Prettier) | |
id: lint_md_prettier | |
continue-on-error: true | |
run: | | |
if [ "${{ steps.lint_mode.outputs.mode }}" = "all" ]; then | |
echo "Checking all Markdown files with Prettier..." | |
npx prettier --check --cache --log-level warn '**/*.md' | |
echo "md_prettier_exit_code=$?" >> $GITHUB_OUTPUT | |
elif [ "${{ steps.changed_files.outputs.md_count }}" -gt "0" ]; then | |
echo "Checking changed Markdown files with Prettier..." | |
cat changed_md.txt | xargs npx prettier --check --cache --log-level warn | |
echo "md_prettier_exit_code=$?" >> $GITHUB_OUTPUT | |
else | |
echo "No Markdown files to check with Prettier." | |
echo "md_prettier_exit_code=0" >> $GITHUB_OUTPUT | |
fi | |
- name: Lint JSON files (Prettier) | |
id: lint_json_prettier | |
continue-on-error: true | |
run: | | |
if [ "${{ steps.lint_mode.outputs.mode }}" = "all" ]; then | |
echo "Checking all JSON files with Prettier..." | |
npx prettier --check --cache --log-level warn '**/*.json' | |
echo "json_prettier_exit_code=$?" >> $GITHUB_OUTPUT | |
elif [ "${{ steps.changed_files.outputs.json_count }}" -gt "0" ]; then | |
echo "Checking changed JSON files with Prettier..." | |
cat changed_json.txt | xargs npx prettier --check --cache --log-level warn | |
echo "json_prettier_exit_code=$?" >> $GITHUB_OUTPUT | |
else | |
echo "No JSON files to check with Prettier." | |
echo "json_prettier_exit_code=0" >> $GITHUB_OUTPUT | |
fi | |
- name: Lint YAML files (yaml-lint) | |
id: lint_yaml_yamllint | |
continue-on-error: true | |
run: | | |
if [ "${{ steps.lint_mode.outputs.mode }}" = "all" ]; then | |
echo "Running yaml-lint on all YAML files..." | |
npx yaml-lint .github/**/*.{yml,yaml} | |
echo "yaml_yamllint_exit_code=$?" >> $GITHUB_OUTPUT | |
elif [ "${{ steps.changed_files.outputs.yaml_count }}" -gt "0" ]; then | |
echo "Running yaml-lint on changed YAML files..." | |
cat changed_yaml.txt | xargs npx yaml-lint | |
echo "yaml_yamllint_exit_code=$?" >> $GITHUB_OUTPUT | |
else | |
echo "No YAML files to lint with yaml-lint." | |
echo "yaml_yamllint_exit_code=0" >> $GITHUB_OUTPUT | |
fi | |
- name: Lint YAML files (Prettier) | |
id: lint_yaml_prettier | |
continue-on-error: true | |
run: | | |
if [ "${{ steps.lint_mode.outputs.mode }}" = "all" ]; then | |
echo "Checking all YAML files with Prettier..." | |
npx prettier --check --cache --log-level warn '**/*.{yml,yaml}' | |
echo "yaml_prettier_exit_code=$?" >> $GITHUB_OUTPUT | |
elif [ "${{ steps.changed_files.outputs.yaml_count }}" -gt "0" ]; then | |
echo "Checking changed YAML files with Prettier..." | |
cat changed_yaml.txt | xargs npx prettier --check --cache --log-level warn | |
echo "yaml_prettier_exit_code=$?" >> $GITHUB_OUTPUT | |
else | |
echo "No YAML files to check with Prettier." | |
echo "yaml_prettier_exit_code=0" >> $GITHUB_OUTPUT | |
fi | |
- name: Determine overall status | |
id: status | |
run: | | |
# Collect all exit codes | |
TS_ESLINT_EXIT_CODE="${{ steps.lint_ts_eslint.outputs.ts_eslint_exit_code }}" | |
TS_PRETTIER_EXIT_CODE="${{ steps.lint_ts_prettier.outputs.ts_prettier_exit_code }}" | |
SOL_SOLHINT_EXIT_CODE="${{ steps.lint_sol_solhint.outputs.sol_solhint_exit_code }}" | |
SOL_PRETTIER_EXIT_CODE="${{ steps.lint_sol_prettier.outputs.sol_prettier_exit_code }}" | |
MD_MARKDOWNLINT_EXIT_CODE="${{ steps.lint_md_markdownlint.outputs.md_markdownlint_exit_code }}" | |
MD_PRETTIER_EXIT_CODE="${{ steps.lint_md_prettier.outputs.md_prettier_exit_code }}" | |
JSON_PRETTIER_EXIT_CODE="${{ steps.lint_json_prettier.outputs.json_prettier_exit_code }}" | |
YAML_YAMLLINT_EXIT_CODE="${{ steps.lint_yaml_yamllint.outputs.yaml_yamllint_exit_code }}" | |
YAML_PRETTIER_EXIT_CODE="${{ steps.lint_yaml_prettier.outputs.yaml_prettier_exit_code }}" | |
# Initialize counters | |
ERRORS=0 | |
WARNINGS=0 | |
# Check each exit code | |
# Exit code 1 typically indicates errors | |
# Exit code 2 or higher might indicate warnings or other issues | |
# TypeScript/JavaScript - ESLint | |
if [ "$TS_ESLINT_EXIT_CODE" = "1" ]; then | |
echo "::error::ESLint found errors in TypeScript/JavaScript files" | |
ERRORS=$((ERRORS+1)) | |
elif [ "$TS_ESLINT_EXIT_CODE" != "0" ]; then | |
echo "::warning::ESLint found warnings in TypeScript/JavaScript files" | |
WARNINGS=$((WARNINGS+1)) | |
fi | |
# TypeScript/JavaScript - Prettier | |
if [ "$TS_PRETTIER_EXIT_CODE" = "1" ]; then | |
echo "::error::Prettier found formatting issues in TypeScript/JavaScript files" | |
ERRORS=$((ERRORS+1)) | |
elif [ "$TS_PRETTIER_EXIT_CODE" != "0" ]; then | |
echo "::warning::Prettier found warnings in TypeScript/JavaScript files" | |
WARNINGS=$((WARNINGS+1)) | |
fi | |
# Solidity - Solhint | |
if [ "$SOL_SOLHINT_EXIT_CODE" = "1" ]; then | |
echo "::error::Solhint found errors in Solidity files" | |
ERRORS=$((ERRORS+1)) | |
elif [ "$SOL_SOLHINT_EXIT_CODE" != "0" ]; then | |
echo "::warning::Solhint found warnings in Solidity files" | |
WARNINGS=$((WARNINGS+1)) | |
fi | |
# Solidity - Prettier | |
if [ "$SOL_PRETTIER_EXIT_CODE" = "1" ]; then | |
echo "::error::Prettier found formatting issues in Solidity files" | |
ERRORS=$((ERRORS+1)) | |
elif [ "$SOL_PRETTIER_EXIT_CODE" != "0" ]; then | |
echo "::warning::Prettier found warnings in Solidity files" | |
WARNINGS=$((WARNINGS+1)) | |
fi | |
# Markdown - Markdownlint | |
if [ "$MD_MARKDOWNLINT_EXIT_CODE" = "1" ]; then | |
echo "::error::Markdownlint found errors in Markdown files" | |
ERRORS=$((ERRORS+1)) | |
elif [ "$MD_MARKDOWNLINT_EXIT_CODE" != "0" ]; then | |
echo "::warning::Markdownlint found warnings in Markdown files" | |
WARNINGS=$((WARNINGS+1)) | |
fi | |
# Markdown - Prettier | |
if [ "$MD_PRETTIER_EXIT_CODE" = "1" ]; then | |
echo "::error::Prettier found formatting issues in Markdown files" | |
ERRORS=$((ERRORS+1)) | |
elif [ "$MD_PRETTIER_EXIT_CODE" != "0" ]; then | |
echo "::warning::Prettier found warnings in Markdown files" | |
WARNINGS=$((WARNINGS+1)) | |
fi | |
# JSON - Prettier | |
if [ "$JSON_PRETTIER_EXIT_CODE" = "1" ]; then | |
echo "::error::Prettier found formatting issues in JSON files" | |
ERRORS=$((ERRORS+1)) | |
elif [ "$JSON_PRETTIER_EXIT_CODE" != "0" ]; then | |
echo "::warning::Prettier found warnings in JSON files" | |
WARNINGS=$((WARNINGS+1)) | |
fi | |
# YAML - yaml-lint | |
if [ "$YAML_YAMLLINT_EXIT_CODE" = "1" ]; then | |
echo "::error::yaml-lint found errors in YAML files" | |
ERRORS=$((ERRORS+1)) | |
elif [ "$YAML_YAMLLINT_EXIT_CODE" != "0" ]; then | |
echo "::warning::yaml-lint found warnings in YAML files" | |
WARNINGS=$((WARNINGS+1)) | |
fi | |
# YAML - Prettier | |
if [ "$YAML_PRETTIER_EXIT_CODE" = "1" ]; then | |
echo "::error::Prettier found formatting issues in YAML files" | |
ERRORS=$((ERRORS+1)) | |
elif [ "$YAML_PRETTIER_EXIT_CODE" != "0" ]; then | |
echo "::warning::Prettier found warnings in YAML files" | |
WARNINGS=$((WARNINGS+1)) | |
fi | |
# Create summary | |
LINT_MODE="${{ steps.lint_mode.outputs.mode }}" | |
if [ "$ERRORS" -gt 0 ]; then | |
echo "summary=❌ Linting ($LINT_MODE files) failed with $ERRORS error types and $WARNINGS warning types." >> $GITHUB_OUTPUT | |
echo "Linting failed with errors. CI build will fail." | |
exit 1 | |
elif [ "$WARNINGS" -gt 0 ]; then | |
echo "summary=⚠️ Linting ($LINT_MODE files) passed with $WARNINGS warning types. CI build will continue." >> $GITHUB_OUTPUT | |
echo "Linting found warnings but no errors. CI build will continue." | |
exit 0 | |
else | |
echo "summary=✅ All linters ($LINT_MODE files) passed successfully with no errors or warnings." >> $GITHUB_OUTPUT | |
echo "All linters passed successfully." | |
exit 0 | |
fi | |
- name: Post Summary | |
run: echo "${{ steps.status.outputs.summary }}" >> $GITHUB_STEP_SUMMARY |