--- # yaml-language-server: $schema=https://json.schemastore.org/github-action.json name: ESLint Check description: 'Run ESLint check on the repository with advanced configuration and reporting' author: Ismo Vuorinen branding: icon: check-circle color: blue inputs: working-directory: description: 'Directory containing files to lint' required: false default: '.' eslint-version: description: 'ESLint version to use' required: false default: 'latest' config-file: description: 'Path to ESLint config file' required: false default: '.eslintrc' ignore-file: description: 'Path to ESLint ignore file' required: false default: '.eslintignore' file-extensions: description: 'File extensions to lint (comma-separated)' required: false default: '.js,.jsx,.ts,.tsx' cache: description: 'Enable ESLint caching' required: false default: 'true' max-warnings: description: 'Maximum number of warnings allowed' required: false default: '0' fail-on-error: description: 'Fail workflow if issues are found' required: false default: 'true' report-format: description: 'Output format (stylish, json, sarif)' required: false default: 'sarif' max-retries: description: 'Maximum number of retry attempts' required: false default: '3' outputs: error-count: description: 'Number of errors found' value: ${{ steps.lint.outputs.error_count }} warning-count: description: 'Number of warnings found' value: ${{ steps.lint.outputs.warning_count }} sarif-file: description: 'Path to SARIF report file' value: ${{ steps.lint.outputs.sarif_file }} files-checked: description: 'Number of files checked' value: ${{ steps.lint.outputs.files_checked }} runs: using: composite steps: - name: Validate Inputs id: validate shell: bash run: | set -euo pipefail # Validate working directory if [ ! -d "${{ inputs.working-directory }}" ]; then echo "::error::Working directory does not exist: ${{ inputs.working-directory }}" exit 1 fi # Validate file extensions if ! [[ "${{ inputs.file-extensions }}" =~ ^[.,a-zA-Z0-9]+$ ]]; then echo "::error::Invalid file extensions format" exit 1 fi # Validate max warnings if ! [[ "${{ inputs.max-warnings }}" =~ ^[0-9]+$ ]]; then echo "::error::Invalid max warnings value" exit 1 fi - name: Setup Node.js uses: ivuorinen/actions/node-setup@main - name: Install Dependencies shell: bash run: | set -euo pipefail cd ${{ inputs.working-directory }} # Install ESLint and required dependencies echo "Installing ESLint dependencies..." # Function to install with retries install_with_retries() { local attempt=1 local max_attempts=${{ inputs.max-retries }} while [ $attempt -le $max_attempts ]; do echo "Installation attempt $attempt of $max_attempts" if npm install \ eslint@${{ inputs.eslint-version }} \ @typescript-eslint/parser \ @typescript-eslint/eslint-plugin \ eslint-plugin-import \ eslint-config-prettier \ typescript; then return 0 fi attempt=$((attempt + 1)) if [ $attempt -le $max_attempts ]; then echo "Installation failed, waiting 10 seconds before retry..." sleep 10 fi done echo "::error::Failed to install dependencies after $max_attempts attempts" return 1 } install_with_retries - name: Prepare ESLint Configuration id: config shell: bash run: | set -euo pipefail cd ${{ inputs.working-directory }} # Create default config if none exists if [ ! -f "${{ inputs.config-file }}" ]; then echo "Creating default ESLint configuration..." cat > "${{ inputs.config-file }}" < "${{ inputs.ignore-file }}" <> $GITHUB_OUTPUT echo "warning_count=${warning_count}" >> $GITHUB_OUTPUT if [ "${{ inputs.fail-on-error }}" = "true" ] && [ $error_code -ne 0 ]; then echo "::error::ESLint found ${error_count} errors and ${warning_count} warnings" exit $error_code fi } # Count checked files files_checked=$(find . -type f \( $(printf -- "-name *%s -o " "${EXTENSIONS[@]}") -false \) | wc -l) echo "files_checked=${files_checked}" >> $GITHUB_OUTPUT echo "sarif_file=reports/eslint.sarif" >> $GITHUB_OUTPUT - name: Upload ESLint Results if: always() && inputs.report-format == 'sarif' uses: github/codeql-action/upload-sarif@v2 with: sarif_file: ${{ inputs.working-directory }}/reports/eslint.sarif category: eslint - name: Cache Cleanup if: always() shell: bash run: | set -euo pipefail cd ${{ inputs.working-directory }} # Clean up ESLint cache if it exists if [ -f ".eslintcache" ]; then rm .eslintcache fi # Remove temporary files rm -rf reports/