# yaml-language-server: $schema=https://json.schemastore.org/github-action.json # permissions: # - contents: write # Required for pushing fixes back to repository --- name: Biome Fix description: Run Biome fix on the repository author: Ismo Vuorinen branding: icon: check-circle color: green inputs: token: description: 'GitHub token for authentication' required: false default: ${{ github.token }} username: description: 'GitHub username for commits' required: false default: 'github-actions' email: description: 'GitHub email for commits' required: false default: 'github-actions@github.com' max-retries: description: 'Maximum number of retry attempts for npm install operations' required: false default: '3' outputs: files_changed: description: 'Number of files changed by formatting' value: ${{ steps.fix.outputs.files_changed }} fix_status: description: 'Fix status (success/failure)' value: ${{ steps.fix.outputs.status }} runs: using: composite steps: - name: Validate Inputs id: validate shell: sh env: GITHUB_TOKEN: ${{ inputs.token }} EMAIL: ${{ inputs.email }} USERNAME: ${{ inputs.username }} MAX_RETRIES: ${{ inputs.max-retries }} run: | set -eu # Validate GitHub token format (basic validation) if [ -n "$GITHUB_TOKEN" ]; then # Skip validation for GitHub expressions (they'll be resolved at runtime) if ! echo "$GITHUB_TOKEN" | grep -Eq '^gh[efpousr]_[a-zA-Z0-9]{36}$' && ! echo "$GITHUB_TOKEN" | grep -q '^\${{'; then echo "::warning::GitHub token format may be invalid. Expected format: gh*_36characters" fi fi # Validate email format (basic check) case "$EMAIL" in *@*.*) ;; *) echo "::error::Invalid email format: '$EMAIL'. Expected valid email address" exit 1 ;; esac # Validate username format (prevent command injection) if echo "$USERNAME" | grep -Eq '[;&|]'; then echo "::error::Invalid username: '$USERNAME'. Command injection patterns not allowed" exit 1 fi # Validate username length username="$USERNAME" username_len=$(echo -n "$username" | wc -c | tr -d ' ') if [ "$username_len" -gt 39 ]; then echo "::error::Username too long: ${username_len} characters. GitHub usernames are max 39 characters" exit 1 fi # Validate max retries (positive integer with reasonable upper limit) if ! echo "$MAX_RETRIES" | grep -Eq '^[0-9]+$' || [ "$MAX_RETRIES" -le 0 ] || [ "$MAX_RETRIES" -gt 10 ]; then echo "::error::Invalid max-retries: '$MAX_RETRIES'. Must be a positive integer between 1 and 10" exit 1 fi echo "Input validation completed successfully" - name: Checkout Repository uses: actions/checkout@08c6903cd8c0fde910a37f88322edcfb5dd907a8 # v5.0.0 with: token: ${{ inputs.token }} - name: Set Git Config uses: ivuorinen/actions/set-git-config@0fa9a68f07a1260b321f814202658a6089a43d42 with: token: ${{ inputs.token }} username: ${{ inputs.username }} email: ${{ inputs.email }} - name: Node Setup id: node-setup uses: ivuorinen/actions/node-setup@0fa9a68f07a1260b321f814202658a6089a43d42 - name: Cache Node Dependencies id: cache uses: ivuorinen/actions/common-cache@0fa9a68f07a1260b321f814202658a6089a43d42 with: type: 'npm' paths: 'node_modules' key-files: 'package-lock.json,yarn.lock,pnpm-lock.yaml,bun.lockb' key-prefix: 'biome-fix-${{ steps.node-setup.outputs.package-manager }}' - name: Install Biome shell: sh env: PACKAGE_MANAGER: ${{ steps.node-setup.outputs.package-manager }} MAX_RETRIES: ${{ inputs.max-retries }} run: | set -eu # Check if biome is already installed if command -v biome >/dev/null 2>&1; then echo "✅ Biome already installed: $(biome --version)" exit 0 fi echo "Installing Biome using $PACKAGE_MANAGER..." for attempt in $(seq 1 "$MAX_RETRIES"); do echo "Attempt $attempt of $MAX_RETRIES" case "$PACKAGE_MANAGER" in "pnpm") if pnpm add -g @biomejs/biome; then echo "✅ Biome installed successfully with pnpm" exit 0 fi ;; "yarn") if yarn global add @biomejs/biome; then echo "✅ Biome installed successfully with yarn" exit 0 fi ;; "bun") if bun add -g @biomejs/biome; then echo "✅ Biome installed successfully with bun" exit 0 fi ;; "npm"|*) if npm install -g @biomejs/biome; then echo "✅ Biome installed successfully with npm" exit 0 fi ;; esac if [ $attempt -lt "$MAX_RETRIES" ]; then echo "❌ Installation failed, retrying in 5 seconds..." sleep 5 fi done echo "::error::Failed to install Biome after $MAX_RETRIES attempts" exit 1 - name: Run Biome Fix id: fix shell: sh run: | set -eu echo "Running Biome fix..." # Run Biome fix and capture exit code biome_exit_code=0 biome check --write . || biome_exit_code=$? # Count changed files using git diff (strip whitespace from wc output) files_changed=$(git diff --name-only | wc -l | tr -d ' ') # Set status based on biome check result and changes if [ $biome_exit_code -eq 0 ] && [ "$files_changed" -eq 0 ]; then status="success" else status="failure" fi echo "files_changed=$files_changed" >> "$GITHUB_OUTPUT" echo "status=$status" >> "$GITHUB_OUTPUT" echo "✅ Biome fix completed. Files changed: $files_changed, Status: $status" - name: Push Fixes if: success() uses: stefanzweifel/git-auto-commit-action@28e16e81777b558cc906c8750092100bbb34c5e3 # v7.0.0 with: commit_message: 'style: autofix Biome violations' add_options: '-u'