Skip to content

Modernise and cleanup lint configuration and build process #22

Modernise and cleanup lint configuration and build process

Modernise and cleanup lint configuration and build process #22

Workflow file for this run

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