refactor: inline node-setup across Node.js actions

Phase 6A: Remove node-setup abstraction layer and inline Node.js setup.

Changes:
- Replace node-setup calls with direct actions/setup-node@v6.0.0
- Inline package manager detection (lockfile-based)
- Add Corepack enablement and package manager installation
- Use Node.js 22 as default version

Actions migrated (5):
- prettier-lint: Inline Node.js setup + package manager detection
- biome-lint: Inline Node.js setup + package manager detection
- eslint-lint: Inline Node.js setup + package manager detection
- pr-lint: Inline Node.js setup (conditional on package.json)
- npm-publish: Inline Node.js setup + package manager detection

Removed:
- node-setup/action.yml (371 lines)
- node-setup/README.md, rules.yml, CustomValidator.py
- _tests/unit/node-setup/validation.spec.sh
- _tests/integration/workflows/node-setup-test.yml
- validate-inputs/tests/test_node-setup_custom.py

Documentation updates:
- CLAUDE.md: Remove node-setup from action list (26 actions)
- generate_listing.cjs: Remove node-setup mappings
- update-validators.py: Remove node-setup custom validator

Result: 26 actions (down from 27), eliminated internal dependency layer.
This commit is contained in:
2025-11-20 21:17:37 +02:00
parent 97238212eb
commit 49d232f590
50 changed files with 419 additions and 1607 deletions

View File

@@ -71,7 +71,7 @@
Flat structure. Each action self-contained with `action.yml`.
**30 Actions**: Setup (node-setup, language-version-detect), Utilities (action-versioning, version-file-parser),
**26 Actions**: Setup (language-version-detect), Utilities (action-versioning, version-file-parser),
Linting (ansible-lint-fix, biome-lint, csharp-lint-check, eslint-lint, go-lint, pr-lint, pre-commit, prettier-lint, python-lint-fix, terraform-lint-fix),
Testing (php-tests, php-laravel-phpunit, php-composer), Build (csharp-build, go-build, docker-build),
Publishing (npm-publish, docker-publish, csharp-publish),

View File

@@ -1,510 +0,0 @@
---
name: Integration Test - Node Setup
on:
workflow_dispatch:
push:
paths:
- 'node-setup/**'
- '_tests/integration/workflows/node-setup-test.yml'
jobs:
test-node-setup-version-validation:
name: Test Version Validation
runs-on: ubuntu-latest
steps:
- name: Checkout repository
uses: actions/checkout@v4
- name: Test invalid default version format (alphabetic)
run: |
VERSION="abc"
if [[ "$VERSION" =~ ^[0-9]+(\.[0-9]+(\.[0-9]+)?)?$ ]]; then
echo "❌ ERROR: Should reject alphabetic version"
exit 1
fi
echo "✓ Alphabetic version correctly rejected"
- name: Test invalid default version (too low)
run: |
VERSION="10"
major=$(echo "$VERSION" | cut -d'.' -f1)
if [ "$major" -lt 14 ] || [ "$major" -gt 30 ]; then
echo "✓ Version $VERSION correctly rejected (major < 14)"
else
echo "❌ ERROR: Should reject Node.js $VERSION"
exit 1
fi
- name: Test invalid default version (too high)
run: |
VERSION="50"
major=$(echo "$VERSION" | cut -d'.' -f1)
if [ "$major" -lt 14 ] || [ "$major" -gt 30 ]; then
echo "✓ Version $VERSION correctly rejected (major > 30)"
else
echo "❌ ERROR: Should reject Node.js $VERSION"
exit 1
fi
- name: Test valid version formats
run: |
for version in "20" "20.9" "20.9.0" "18" "22.1.0"; do
if [[ "$version" =~ ^[0-9]+(\.[0-9]+(\.[0-9]+)?)?$ ]]; then
major=$(echo "$version" | cut -d'.' -f1)
if [ "$major" -ge 14 ] && [ "$major" -le 30 ]; then
echo "✓ Version $version accepted"
else
echo "❌ ERROR: Version $version should be accepted"
exit 1
fi
else
echo "❌ ERROR: Version $version format validation failed"
exit 1
fi
done
test-node-setup-package-manager-validation:
name: Test Package Manager Validation
runs-on: ubuntu-latest
steps:
- name: Checkout repository
uses: actions/checkout@v4
- name: Test valid package managers
run: |
for pm in "npm" "yarn" "pnpm" "bun" "auto"; do
case "$pm" in
"npm"|"yarn"|"pnpm"|"bun"|"auto")
echo "✓ Package manager $pm accepted"
;;
*)
echo "❌ ERROR: Valid package manager $pm rejected"
exit 1
;;
esac
done
- name: Test invalid package manager
run: |
PM="invalid-pm"
case "$PM" in
"npm"|"yarn"|"pnpm"|"bun"|"auto")
echo "❌ ERROR: Invalid package manager should be rejected"
exit 1
;;
*)
echo "✓ Invalid package manager correctly rejected"
;;
esac
test-node-setup-url-validation:
name: Test URL Validation
runs-on: ubuntu-latest
steps:
- name: Checkout repository
uses: actions/checkout@v4
- name: Test valid registry URLs
run: |
for url in "https://registry.npmjs.org" "http://localhost:4873" "https://npm.custom.com/"; do
if [[ "$url" == "https://"* ]] || [[ "$url" == "http://"* ]]; then
echo "✓ Registry URL $url accepted"
else
echo "❌ ERROR: Valid URL $url rejected"
exit 1
fi
done
- name: Test invalid registry URLs
run: |
for url in "ftp://registry.com" "not-a-url" "registry.com"; do
if [[ "$url" == "https://"* ]] || [[ "$url" == "http://"* ]]; then
echo "❌ ERROR: Invalid URL $url should be rejected"
exit 1
else
echo "✓ Invalid URL $url correctly rejected"
fi
done
test-node-setup-retries-validation:
name: Test Retries Validation
runs-on: ubuntu-latest
steps:
- name: Checkout repository
uses: actions/checkout@v4
- name: Test valid retry counts
run: |
for retries in "1" "3" "5" "10"; do
if [[ "$retries" =~ ^[0-9]+$ ]] && [ "$retries" -gt 0 ] && [ "$retries" -le 10 ]; then
echo "✓ Max retries $retries accepted"
else
echo "❌ ERROR: Valid retry count $retries rejected"
exit 1
fi
done
- name: Test invalid retry counts
run: |
for retries in "0" "11" "abc" "-1"; do
if [[ "$retries" =~ ^[0-9]+$ ]] && [ "$retries" -gt 0 ] && [ "$retries" -le 10 ]; then
echo "❌ ERROR: Invalid retry count $retries should be rejected"
exit 1
else
echo "✓ Invalid retry count $retries correctly rejected"
fi
done
test-node-setup-boolean-validation:
name: Test Boolean Validation
runs-on: ubuntu-latest
steps:
- name: Checkout repository
uses: actions/checkout@v4
- name: Test valid boolean values
run: |
for value in "true" "false"; do
if [[ "$value" == "true" ]] || [[ "$value" == "false" ]]; then
echo "✓ Boolean value $value accepted"
else
echo "❌ ERROR: Valid boolean $value rejected"
exit 1
fi
done
- name: Test invalid boolean values
run: |
for value in "yes" "no" "1" "0" "True" "FALSE" ""; do
if [[ "$value" != "true" ]] && [[ "$value" != "false" ]]; then
echo "✓ Invalid boolean value '$value' correctly rejected"
else
echo "❌ ERROR: Invalid boolean $value should be rejected"
exit 1
fi
done
test-node-setup-token-validation:
name: Test Auth Token Validation
runs-on: ubuntu-latest
steps:
- name: Checkout repository
uses: actions/checkout@v4
- name: Test injection pattern detection
run: |
for token in "token;malicious" "token&&command" "token|pipe"; do
if [[ "$token" == *";"* ]] || [[ "$token" == *"&&"* ]] || [[ "$token" == *"|"* ]]; then
echo "✓ Injection pattern in token correctly detected"
else
echo "❌ ERROR: Should detect injection pattern in: $token"
exit 1
fi
done
- name: Test valid tokens
run: |
for token in "npm_AbCdEf1234567890" "github_pat_12345abcdef" "simple-token"; do
if [[ "$token" == *";"* ]] || [[ "$token" == *"&&"* ]] || [[ "$token" == *"|"* ]]; then
echo "❌ ERROR: Valid token should not be rejected: $token"
exit 1
else
echo "✓ Valid token accepted"
fi
done
test-node-setup-package-manager-resolution:
name: Test Package Manager Resolution
runs-on: ubuntu-latest
steps:
- name: Checkout repository
uses: actions/checkout@v4
- name: Test auto detection with detected PM
run: |
INPUT_PM="auto"
DETECTED_PM="pnpm"
if [ "$INPUT_PM" = "auto" ]; then
if [ -n "$DETECTED_PM" ]; then
FINAL_PM="$DETECTED_PM"
else
FINAL_PM="npm"
fi
else
FINAL_PM="$INPUT_PM"
fi
if [[ "$FINAL_PM" != "pnpm" ]]; then
echo "❌ ERROR: Should use detected PM (pnpm)"
exit 1
fi
echo "✓ Auto-detected package manager correctly resolved"
- name: Test auto detection without detected PM
run: |
INPUT_PM="auto"
DETECTED_PM=""
if [ "$INPUT_PM" = "auto" ]; then
if [ -n "$DETECTED_PM" ]; then
FINAL_PM="$DETECTED_PM"
else
FINAL_PM="npm"
fi
else
FINAL_PM="$INPUT_PM"
fi
if [[ "$FINAL_PM" != "npm" ]]; then
echo "❌ ERROR: Should default to npm"
exit 1
fi
echo "✓ Defaults to npm when no detection"
- name: Test explicit package manager
run: |
INPUT_PM="yarn"
DETECTED_PM="pnpm"
if [ "$INPUT_PM" = "auto" ]; then
if [ -n "$DETECTED_PM" ]; then
FINAL_PM="$DETECTED_PM"
else
FINAL_PM="npm"
fi
else
FINAL_PM="$INPUT_PM"
fi
if [[ "$FINAL_PM" != "yarn" ]]; then
echo "❌ ERROR: Should use explicit PM (yarn)"
exit 1
fi
echo "✓ Explicit package manager correctly used"
test-node-setup-feature-detection:
name: Test Feature Detection
runs-on: ubuntu-latest
steps:
- name: Checkout repository
uses: actions/checkout@v4
- name: Create test package.json with ESM
run: |
mkdir -p test-esm
cd test-esm
cat > package.json <<'EOF'
{
"name": "test-esm",
"version": "1.0.0",
"type": "module"
}
EOF
- name: Test ESM detection
run: |
cd test-esm
if command -v jq >/dev/null 2>&1; then
pkg_type=$(jq -r '.type // "commonjs"' package.json 2>/dev/null)
if [[ "$pkg_type" == "module" ]]; then
echo "✓ ESM support correctly detected"
else
echo "❌ ERROR: Should detect ESM support"
exit 1
fi
else
echo "⚠️ jq not available, skipping ESM detection test"
echo "✓ ESM detection logic verified (jq would be required in actual action)"
fi
- name: Create test with TypeScript
run: |
mkdir -p test-ts
cd test-ts
touch tsconfig.json
cat > package.json <<'EOF'
{
"name": "test-ts",
"devDependencies": {
"typescript": "^5.0.0"
}
}
EOF
- name: Test TypeScript detection
run: |
cd test-ts
typescript_support="false"
if [ -f tsconfig.json ]; then
typescript_support="true"
fi
if [[ "$typescript_support" != "true" ]]; then
echo "❌ ERROR: Should detect TypeScript"
exit 1
fi
echo "✓ TypeScript support correctly detected"
- name: Create test with frameworks
run: |
mkdir -p test-frameworks
cd test-frameworks
cat > package.json <<'EOF'
{
"name": "test-frameworks",
"dependencies": {
"react": "^18.0.0",
"next": "^14.0.0"
}
}
EOF
- name: Test framework detection
run: |
cd test-frameworks
if command -v jq >/dev/null 2>&1; then
has_next=$(jq -e '.dependencies.next or .devDependencies.next' package.json >/dev/null 2>&1 && echo "yes" || echo "no")
has_react=$(jq -e '.dependencies.react or .devDependencies.react' package.json >/dev/null 2>&1 && echo "yes" || echo "no")
if [[ "$has_next" == "yes" ]] && [[ "$has_react" == "yes" ]]; then
echo "✓ Frameworks (Next.js, React) correctly detected"
else
echo "❌ ERROR: Should detect Next.js and React"
exit 1
fi
else
echo "⚠️ jq not available, skipping framework detection test"
echo "✓ Framework detection logic verified (jq would be required in actual action)"
fi
test-node-setup-security:
name: Test Security Measures
runs-on: ubuntu-latest
steps:
- name: Checkout repository
uses: actions/checkout@v4
- name: Test token sanitization
run: |
TOKEN="test-token
with-newline"
# Should remove newlines
sanitized=$(echo "$TOKEN" | tr -d '\n\r')
if [[ "$sanitized" == *$'\n'* ]] || [[ "$sanitized" == *$'\r'* ]]; then
echo "❌ ERROR: Newlines not removed"
exit 1
fi
echo "✓ Token sanitization works correctly"
- name: Test package manager sanitization
run: |
PM="npm
with-newline"
# Should remove newlines
sanitized=$(echo "$PM" | tr -d '\n\r')
if [[ "$sanitized" == *$'\n'* ]] || [[ "$sanitized" == *$'\r'* ]]; then
echo "❌ ERROR: Newlines not removed from PM"
exit 1
fi
echo "✓ Package manager sanitization works correctly"
test-node-setup-integration-workflow:
name: Test Integration Workflow
runs-on: ubuntu-latest
steps:
- name: Checkout repository
uses: actions/checkout@v4
- name: Simulate complete workflow
run: |
echo "=== Simulating Node Setup Workflow ==="
# 1. Validation
echo "Step 1: Validate inputs"
DEFAULT_VERSION="20"
PACKAGE_MANAGER="npm"
REGISTRY_URL="https://registry.npmjs.org"
CACHE="true"
INSTALL="true"
MAX_RETRIES="3"
echo "✓ Inputs validated"
# 2. Version parsing
echo "Step 2: Parse Node.js version"
NODE_VERSION="20.9.0"
echo "✓ Version parsed: $NODE_VERSION"
# 3. Package manager resolution
echo "Step 3: Resolve package manager"
if [ "$PACKAGE_MANAGER" = "auto" ]; then
FINAL_PM="npm"
else
FINAL_PM="$PACKAGE_MANAGER"
fi
echo "✓ Package manager resolved: $FINAL_PM"
# 4. Setup Node.js
echo "Step 4: Setup Node.js $NODE_VERSION"
if command -v node >/dev/null 2>&1; then
echo "✓ Node.js available: $(node --version)"
fi
# 5. Enable Corepack
echo "Step 5: Enable Corepack"
if command -v corepack >/dev/null 2>&1; then
echo "✓ Corepack available"
else
echo "⚠️ Corepack not available in test environment"
fi
# 6. Cache dependencies
if [[ "$CACHE" == "true" ]]; then
echo "Step 6: Cache dependencies"
echo "✓ Would use actions/cache action"
fi
# 7. Install dependencies
if [[ "$INSTALL" == "true" ]]; then
echo "Step 7: Install dependencies"
echo "✓ Would run: $FINAL_PM install"
fi
echo "=== Workflow simulation completed ==="
integration-test-summary:
name: Integration Test Summary
runs-on: ubuntu-latest
needs:
- test-node-setup-version-validation
- test-node-setup-package-manager-validation
- test-node-setup-url-validation
- test-node-setup-retries-validation
- test-node-setup-boolean-validation
- test-node-setup-token-validation
- test-node-setup-package-manager-resolution
- test-node-setup-feature-detection
- test-node-setup-security
- test-node-setup-integration-workflow
steps:
- name: Summary
run: |
echo "=========================================="
echo "Node Setup Integration Tests - PASSED"
echo "=========================================="
echo ""
echo "✓ Version validation tests"
echo "✓ Package manager validation tests"
echo "✓ URL validation tests"
echo "✓ Retries validation tests"
echo "✓ Boolean validation tests"
echo "✓ Token validation tests"
echo "✓ Package manager resolution tests"
echo "✓ Feature detection tests"
echo "✓ Security measure tests"
echo "✓ Integration workflow tests"
echo ""
echo "All node-setup integration tests completed successfully!"

View File

@@ -1,242 +0,0 @@
#!/usr/bin/env shellspec
# Unit tests for node-setup action
# Framework is automatically loaded via spec_helper.sh
Describe "node-setup action"
ACTION_DIR="node-setup"
ACTION_FILE="$ACTION_DIR/action.yml"
# Framework is automatically initialized via spec_helper.sh
Context "when validating inputs"
It "accepts valid Node.js version"
When call validate_input_python "node-setup" "default-version" "18.17.0"
The status should be success
End
It "accepts valid package manager"
When call validate_input_python "node-setup" "package-manager" "npm"
The status should be success
End
It "accepts yarn as package manager"
When call validate_input_python "node-setup" "package-manager" "yarn"
The status should be success
End
It "accepts pnpm as package manager"
When call validate_input_python "node-setup" "package-manager" "pnpm"
The status should be success
End
It "accepts bun as package manager"
When call validate_input_python "node-setup" "package-manager" "bun"
The status should be success
End
It "rejects invalid package manager"
When call validate_input_python "node-setup" "package-manager" "invalid-manager"
The status should be failure
End
It "rejects malformed Node.js version"
When call validate_input_python "node-setup" "default-version" "not-a-version"
The status should be failure
End
It "rejects command injection in inputs"
When call validate_input_python "node-setup" "default-version" "18.0.0; rm -rf /"
The status should be failure
End
End
Context "when checking action structure"
It "has valid YAML syntax"
When call validate_action_yml_quiet "$ACTION_FILE"
The status should be success
End
It "has correct action name"
When call get_action_name "$ACTION_FILE"
The output should equal "Node Setup"
End
It "defines expected inputs"
When call get_action_inputs "$ACTION_FILE"
The output should include "default-version"
The output should include "package-manager"
End
It "defines expected outputs"
When call get_action_outputs "$ACTION_FILE"
The output should include "node-version"
The output should include "package-manager"
The output should include "cache-hit"
End
End
Context "when testing Node.js version detection"
BeforeEach "shellspec_setup_test_env 'node-version-detection'"
AfterEach "shellspec_cleanup_test_env 'node-version-detection'"
It "detects version from package.json engines field"
create_mock_node_repo
# Mock action output based on package.json
echo "node-version=18.0.0" >>"$GITHUB_OUTPUT"
When call shellspec_validate_action_output "node-version" "18.0.0"
The status should be success
End
It "detects version from .nvmrc file"
create_mock_node_repo
echo "18.17.1" >.nvmrc
# Mock action output
echo "node-version=18.17.1" >>"$GITHUB_OUTPUT"
When call shellspec_validate_action_output "node-version" "18.17.1"
The status should be success
End
It "uses default version when none specified"
create_mock_node_repo
# Remove engines field simulation
# Mock default version output
echo "node-version=20.0.0" >>"$GITHUB_OUTPUT"
When call shellspec_validate_action_output "node-version" "20.0.0"
The status should be success
End
End
Context "when testing package manager detection"
BeforeEach "shellspec_setup_test_env 'package-manager-detection'"
AfterEach "shellspec_cleanup_test_env 'package-manager-detection'"
It "detects bun from bun.lockb"
create_mock_node_repo
touch bun.lockb
echo "package-manager=bun" >>"$GITHUB_OUTPUT"
When call shellspec_validate_action_output "package-manager" "bun"
The status should be success
End
It "detects pnpm from pnpm-lock.yaml"
create_mock_node_repo
touch pnpm-lock.yaml
echo "package-manager=pnpm" >>"$GITHUB_OUTPUT"
When call shellspec_validate_action_output "package-manager" "pnpm"
The status should be success
End
It "detects yarn from yarn.lock"
create_mock_node_repo
touch yarn.lock
echo "package-manager=yarn" >>"$GITHUB_OUTPUT"
When call shellspec_validate_action_output "package-manager" "yarn"
The status should be success
End
It "detects npm from package-lock.json"
create_mock_node_repo
touch package-lock.json
echo "package-manager=npm" >>"$GITHUB_OUTPUT"
When call shellspec_validate_action_output "package-manager" "npm"
The status should be success
End
It "detects packageManager field from package.json"
create_mock_node_repo
# Add packageManager field to package.json
cat >package.json <<EOF
{
"name": "test-project",
"version": "1.0.0",
"packageManager": "pnpm@8.0.0",
"engines": {
"node": ">=18.0.0"
}
}
EOF
echo "package-manager=pnpm" >>"$GITHUB_OUTPUT"
When call shellspec_validate_action_output "package-manager" "pnpm"
The status should be success
End
End
Context "when testing Corepack integration"
BeforeEach "shellspec_setup_test_env 'corepack-test'"
AfterEach "shellspec_cleanup_test_env 'corepack-test'"
It "enables Corepack when packageManager is specified"
create_mock_node_repo
# Simulate packageManager field
cat >package.json <<EOF
{
"name": "test-project",
"version": "1.0.0",
"packageManager": "yarn@3.6.0"
}
EOF
# Mock Corepack enabled output
echo "corepack-enabled=true" >>"$GITHUB_OUTPUT"
When call shellspec_validate_action_output "corepack-enabled" "true"
The status should be success
End
End
Context "when testing cache functionality"
BeforeEach "shellspec_setup_test_env 'cache-test'"
AfterEach "shellspec_cleanup_test_env 'cache-test'"
It "reports cache hit when dependencies are cached"
create_mock_node_repo
touch package-lock.json
mkdir -p node_modules
# Mock cache hit
echo "cache-hit=true" >>"$GITHUB_OUTPUT"
When call shellspec_validate_action_output "cache-hit" "true"
The status should be success
End
It "reports cache miss when no cache exists"
create_mock_node_repo
touch package-lock.json
# Mock cache miss
echo "cache-hit=false" >>"$GITHUB_OUTPUT"
When call shellspec_validate_action_output "cache-hit" "false"
The status should be success
End
End
Context "when testing output consistency"
It "produces all expected outputs"
When call test_action_outputs "$ACTION_DIR" "node-version" "18.0.0" "package-manager" "npm"
The status should be success
The stderr should include "Testing action outputs for: node-setup"
The stderr should include "Output test passed for: node-setup"
End
End
End

View File

@@ -1,4 +1,3 @@
---
# Validation rules for action-versioning action
# Generated by update-validators.py v1.0.0 - DO NOT EDIT MANUALLY
# Schema version: 1.0
@@ -8,7 +7,6 @@
# Rules are automatically applied by validate-inputs action when this
# action is used.
#
schema_version: '1.0'
action: action-versioning
description: Automatically update SHA-pinned action references to match latest version tags

View File

@@ -1,4 +1,3 @@
---
# Validation rules for ansible-lint-fix action
# Generated by update-validators.py v1.0.0 - DO NOT EDIT MANUALLY
# Schema version: 1.0
@@ -8,7 +7,6 @@
# Rules are automatically applied by validate-inputs action when this
# action is used.
#
schema_version: '1.0'
action: ansible-lint-fix
description: Lints and fixes Ansible playbooks, commits changes, and uploads SARIF report.

View File

@@ -137,24 +137,76 @@ runs:
with:
token: ${{ inputs.token || github.token }}
- name: Node Setup
id: node-setup
uses: ivuorinen/actions/node-setup@0fa9a68f07a1260b321f814202658a6089a43d42
- name: Detect Package Manager
id: detect-pm
shell: sh
run: |
set -eu
# Detect package manager from lockfiles
if [ -f bun.lockb ]; then
package_manager="bun"
elif [ -f pnpm-lock.yaml ]; then
package_manager="pnpm"
elif [ -f yarn.lock ]; then
package_manager="yarn"
else
package_manager="npm"
fi
printf 'package-manager=%s\n' "$package_manager" >> "$GITHUB_OUTPUT"
echo "Detected package manager: $package_manager"
- name: Setup Node.js
uses: actions/setup-node@2028fbc5c25fe9cf00d9f06a71cc4710d4507903 # v6.0.0
with:
node-version: '22'
- name: Enable Corepack
shell: sh
run: |
set -eu
corepack enable
- name: Install Package Manager
shell: sh
env:
PACKAGE_MANAGER: ${{ steps.detect-pm.outputs.package-manager }}
run: |
set -eu
case "$PACKAGE_MANAGER" in
pnpm)
corepack prepare pnpm@latest --activate
;;
yarn)
corepack prepare yarn@stable --activate
;;
bun|npm)
# Bun installed separately, npm built-in
;;
esac
- name: Setup Bun
if: steps.detect-pm.outputs.package-manager == 'bun'
uses: oven-sh/setup-bun@735343b667d3e6f658f44d0eca948eb6282f2b76 # v2.0.2
with:
bun-version: latest
- name: Cache Node Dependencies
id: cache
uses: actions/cache@0057852bfaa89a56745cba8c7296529d2fc39830 # v4.3.0
with:
path: node_modules
key: ${{ runner.os }}-biome-lint-${{ inputs.mode }}-${{ steps.node-setup.outputs.package-manager }}-${{ hashFiles('package-lock.json', 'yarn.lock', 'pnpm-lock.yaml', 'bun.lockb') }}
key: ${{ runner.os }}-biome-lint-${{ inputs.mode }}-${{ steps.detect-pm.outputs.package-manager }}-${{ hashFiles('package-lock.json', 'yarn.lock', 'pnpm-lock.yaml', 'bun.lockb') }}
restore-keys: |
${{ runner.os }}-biome-lint-${{ inputs.mode }}-${{ steps.node-setup.outputs.package-manager }}-
${{ runner.os }}-biome-lint-${{ inputs.mode }}-${{ steps.detect-pm.outputs.package-manager }}-
${{ runner.os }}-biome-lint-${{ inputs.mode }}-
- name: Install Biome
shell: bash
env:
PACKAGE_MANAGER: ${{ steps.node-setup.outputs.package-manager }}
PACKAGE_MANAGER: ${{ steps.detect-pm.outputs.package-manager }}
MAX_RETRIES: ${{ inputs.max-retries }}
run: |
set -euo pipefail

View File

@@ -1,4 +1,3 @@
---
# Validation rules for biome-lint action
# Generated by update-validators.py v1.0.0 - DO NOT EDIT MANUALLY
# Schema version: 1.0
@@ -8,7 +7,6 @@
# Rules are automatically applied by validate-inputs action when this
# action is used.
#
schema_version: '1.0'
action: biome-lint
description: Run Biome linter in check or fix mode

View File

@@ -1,4 +1,3 @@
---
# Validation rules for codeql-analysis action
# Generated by update-validators.py v1.0.0 - DO NOT EDIT MANUALLY
# Schema version: 1.0
@@ -8,7 +7,6 @@
# Rules are automatically applied by validate-inputs action when this
# action is used.
#
schema_version: '1.0'
action: codeql-analysis
description: Run CodeQL security analysis for a single language with configurable query suites

View File

@@ -1,4 +1,3 @@
---
# Validation rules for compress-images action
# Generated by update-validators.py v1.0.0 - DO NOT EDIT MANUALLY
# Schema version: 1.0
@@ -8,7 +7,6 @@
# Rules are automatically applied by validate-inputs action when this
# action is used.
#
schema_version: '1.0'
action: compress-images
description: Compress images on demand (workflow_dispatch), and at 11pm every Sunday (schedule).

View File

@@ -1,4 +1,3 @@
---
# Validation rules for csharp-build action
# Generated by update-validators.py v1.0.0 - DO NOT EDIT MANUALLY
# Schema version: 1.0
@@ -8,7 +7,6 @@
# Rules are automatically applied by validate-inputs action when this
# action is used.
#
schema_version: '1.0'
action: csharp-build
description: Builds and tests C# projects.

View File

@@ -8,18 +8,18 @@ Runs linters like StyleCop or dotnet-format for C# code style checks.
### Inputs
| name | description | required | default |
|------------------|----------------------------------------|----------|---------|
| `dotnet-version` | <p>Version of .NET SDK to use.</p> | `false` | `""` |
| `token` | <p>GitHub token for authentication</p> | `false` | `""` |
| name | description | required | default |
| --- | --- | --- | --- |
| `dotnet-version` | <p>Version of .NET SDK to use.</p> | `false` | `""` |
| `token` | <p>GitHub token for authentication</p> | `false` | `""` |
### Outputs
| name | description |
|------------------|----------------------------------------------|
| `lint_status` | <p>Overall lint status (success/failure)</p> |
| `errors_count` | <p>Number of formatting errors found</p> |
| `warnings_count` | <p>Number of formatting warnings found</p> |
| name | description |
| --- | --- |
| `lint_status` | <p>Overall lint status (success/failure)</p> |
| `errors_count` | <p>Number of formatting errors found</p> |
| `warnings_count` | <p>Number of formatting warnings found</p> |
### Runs

View File

@@ -1,4 +1,3 @@
---
# Validation rules for csharp-lint-check action
# Generated by update-validators.py v1.0.0 - DO NOT EDIT MANUALLY
# Schema version: 1.0
@@ -8,7 +7,6 @@
# Rules are automatically applied by validate-inputs action when this
# action is used.
#
schema_version: '1.0'
action: csharp-lint-check
description: Runs linters like StyleCop or dotnet-format for C# code style checks.

View File

@@ -8,19 +8,19 @@ Publishes a C# project to GitHub Packages.
### Inputs
| name | description | required | default |
|------------------|----------------------------------------------------|----------|-------------|
| `dotnet-version` | <p>Version of .NET SDK to use.</p> | `false` | `""` |
| `namespace` | <p>GitHub namespace for the package.</p> | `true` | `ivuorinen` |
| `token` | <p>GitHub token with package write permissions</p> | `false` | `""` |
| name | description | required | default |
| --- | --- | --- | --- |
| `dotnet-version` | <p>Version of .NET SDK to use.</p> | `false` | `""` |
| `namespace` | <p>GitHub namespace for the package.</p> | `true` | `ivuorinen` |
| `token` | <p>GitHub token with package write permissions</p> | `false` | `""` |
### Outputs
| name | description |
|-------------------|-------------------------------------------------|
| `publish_status` | <p>Overall publish status (success/failure)</p> |
| `package_version` | <p>Version of the published package</p> |
| `package_url` | <p>URL of the published package</p> |
| name | description |
| --- | --- |
| `publish_status` | <p>Overall publish status (success/failure)</p> |
| `package_version` | <p>Version of the published package</p> |
| `package_url` | <p>URL of the published package</p> |
### Runs

View File

@@ -1,4 +1,3 @@
---
# Validation rules for csharp-publish action
# Generated by update-validators.py v1.0.0 - DO NOT EDIT MANUALLY
# Schema version: 1.0
@@ -8,7 +7,6 @@
# Rules are automatically applied by validate-inputs action when this
# action is used.
#
schema_version: '1.0'
action: csharp-publish
description: Publishes a C# project to GitHub Packages.

View File

@@ -1,4 +1,3 @@
---
# Validation rules for docker-build action
# Generated by update-validators.py v1.0.0 - DO NOT EDIT MANUALLY
# Schema version: 1.0
@@ -8,7 +7,6 @@
# Rules are automatically applied by validate-inputs action when this
# action is used.
#
schema_version: '1.0'
action: docker-build
description: Builds a Docker image for multiple architectures with enhanced security and reliability.

View File

@@ -8,28 +8,28 @@ Simple wrapper to publish Docker images to GitHub Packages and/or Docker Hub
### Inputs
| name | description | required | default |
|----------------------|-------------------------------------------------------------------|----------|---------------------------|
| `registry` | <p>Registry to publish to (dockerhub, github, or both)</p> | `false` | `both` |
| `image-name` | <p>Docker image name (defaults to repository name)</p> | `false` | `""` |
| `tags` | <p>Comma-separated list of tags (e.g., latest,v1.0.0)</p> | `false` | `latest` |
| `platforms` | <p>Platforms to build for (comma-separated)</p> | `false` | `linux/amd64,linux/arm64` |
| `context` | <p>Build context path</p> | `false` | `.` |
| `dockerfile` | <p>Path to Dockerfile</p> | `false` | `Dockerfile` |
| `build-args` | <p>Build arguments (newline-separated KEY=VALUE pairs)</p> | `false` | `""` |
| `push` | <p>Whether to push the image</p> | `false` | `true` |
| `token` | <p>GitHub token for authentication (for GitHub registry)</p> | `false` | `""` |
| `dockerhub-username` | <p>Docker Hub username (required if publishing to Docker Hub)</p> | `false` | `""` |
| `dockerhub-token` | <p>Docker Hub token (required if publishing to Docker Hub)</p> | `false` | `""` |
| name | description | required | default |
| --- | --- | --- | --- |
| `registry` | <p>Registry to publish to (dockerhub, github, or both)</p> | `false` | `both` |
| `image-name` | <p>Docker image name (defaults to repository name)</p> | `false` | `""` |
| `tags` | <p>Comma-separated list of tags (e.g., latest,v1.0.0)</p> | `false` | `latest` |
| `platforms` | <p>Platforms to build for (comma-separated)</p> | `false` | `linux/amd64,linux/arm64` |
| `context` | <p>Build context path</p> | `false` | `.` |
| `dockerfile` | <p>Path to Dockerfile</p> | `false` | `Dockerfile` |
| `build-args` | <p>Build arguments (newline-separated KEY=VALUE pairs)</p> | `false` | `""` |
| `push` | <p>Whether to push the image</p> | `false` | `true` |
| `token` | <p>GitHub token for authentication (for GitHub registry)</p> | `false` | `""` |
| `dockerhub-username` | <p>Docker Hub username (required if publishing to Docker Hub)</p> | `false` | `""` |
| `dockerhub-token` | <p>Docker Hub token (required if publishing to Docker Hub)</p> | `false` | `""` |
### Outputs
| name | description |
|--------------|--------------------------------------|
| name | description |
| --- | --- |
| `image-name` | <p>Full image name with registry</p> |
| `tags` | <p>Tags that were published</p> |
| `digest` | <p>Image digest</p> |
| `metadata` | <p>Build metadata</p> |
| `tags` | <p>Tags that were published</p> |
| `digest` | <p>Image digest</p> |
| `metadata` | <p>Build metadata</p> |
### Runs

View File

@@ -1,4 +1,3 @@
---
# Validation rules for docker-publish action
# Generated by update-validators.py v1.0.0 - DO NOT EDIT MANUALLY
# Schema version: 1.0
@@ -8,7 +7,6 @@
# Rules are automatically applied by validate-inputs action when this
# action is used.
#
schema_version: '1.0'
action: docker-publish
description: Simple wrapper to publish Docker images to GitHub Packages and/or Docker Hub

View File

@@ -242,25 +242,77 @@ runs:
with:
token: ${{ inputs.token || github.token }}
- name: Node Setup
id: node-setup
uses: ivuorinen/actions/node-setup@0fa9a68f07a1260b321f814202658a6089a43d42
- name: Detect Package Manager
id: detect-pm
shell: sh
run: |
set -eu
# Detect package manager from lockfiles
if [ -f bun.lockb ]; then
package_manager="bun"
elif [ -f pnpm-lock.yaml ]; then
package_manager="pnpm"
elif [ -f yarn.lock ]; then
package_manager="yarn"
else
package_manager="npm"
fi
printf 'package-manager=%s\n' "$package_manager" >> "$GITHUB_OUTPUT"
echo "Detected package manager: $package_manager"
- name: Setup Node.js
uses: actions/setup-node@2028fbc5c25fe9cf00d9f06a71cc4710d4507903 # v6.0.0
with:
node-version: '22'
- name: Enable Corepack
shell: sh
run: |
set -eu
corepack enable
- name: Install Package Manager
shell: sh
env:
PACKAGE_MANAGER: ${{ steps.detect-pm.outputs.package-manager }}
run: |
set -eu
case "$PACKAGE_MANAGER" in
pnpm)
corepack prepare pnpm@latest --activate
;;
yarn)
corepack prepare yarn@stable --activate
;;
bun|npm)
# Bun installed separately, npm built-in
;;
esac
- name: Setup Bun
if: steps.detect-pm.outputs.package-manager == 'bun'
uses: oven-sh/setup-bun@735343b667d3e6f658f44d0eca948eb6282f2b76 # v2.0.2
with:
bun-version: latest
- name: Cache Node Dependencies
id: cache
uses: actions/cache@0057852bfaa89a56745cba8c7296529d2fc39830 # v4.3.0
with:
path: node_modules
key: ${{ runner.os }}-eslint-lint-${{ inputs.mode }}-${{ steps.node-setup.outputs.package-manager }}-${{ hashFiles('package-lock.json', 'yarn.lock', 'pnpm-lock.yaml', 'bun.lockb') }}
key: ${{ runner.os }}-eslint-lint-${{ inputs.mode }}-${{ steps.detect-pm.outputs.package-manager }}-${{ hashFiles('package-lock.json', 'yarn.lock', 'pnpm-lock.yaml', 'bun.lockb') }}
restore-keys: |
${{ runner.os }}-eslint-lint-${{ inputs.mode }}-${{ steps.node-setup.outputs.package-manager }}-
${{ runner.os }}-eslint-lint-${{ inputs.mode }}-${{ steps.detect-pm.outputs.package-manager }}-
${{ runner.os }}-eslint-lint-${{ inputs.mode }}-
- name: Install Dependencies
if: steps.cache.outputs.cache-hit != 'true'
shell: bash
env:
PACKAGE_MANAGER: ${{ steps.node-setup.outputs.package-manager }}
PACKAGE_MANAGER: ${{ steps.detect-pm.outputs.package-manager }}
run: |
set -euo pipefail
@@ -293,7 +345,7 @@ runs:
shell: bash
working-directory: ${{ inputs.working-directory }}
env:
PACKAGE_MANAGER: ${{ steps.node-setup.outputs.package-manager }}
PACKAGE_MANAGER: ${{ steps.detect-pm.outputs.package-manager }}
ESLINT_VERSION: ${{ inputs.eslint-version }}
CONFIG_FILE: ${{ inputs.config-file }}
CACHE: ${{ inputs.cache }}
@@ -377,7 +429,7 @@ runs:
shell: bash
working-directory: ${{ inputs.working-directory }}
env:
PACKAGE_MANAGER: ${{ steps.node-setup.outputs.package-manager }}
PACKAGE_MANAGER: ${{ steps.detect-pm.outputs.package-manager }}
run: |
set -euo pipefail

View File

@@ -1,4 +1,3 @@
---
# Validation rules for eslint-lint action
# Generated by update-validators.py v1.0.0 - DO NOT EDIT MANUALLY
# Schema version: 1.0
@@ -8,7 +7,6 @@
# Rules are automatically applied by validate-inputs action when this
# action is used.
#
schema_version: '1.0'
action: eslint-lint
description: Run ESLint in check or fix mode with advanced configuration and reporting

View File

@@ -8,7 +8,6 @@ const { markdownTable } = require('markdown-table');
// Category mappings
const CATEGORIES = {
// Setup & Environment
'node-setup': 'Setup',
'language-version-detect': 'Setup',
// Utilities
@@ -55,7 +54,6 @@ const CATEGORIES = {
// Language support mappings
const LANGUAGE_SUPPORT = {
'node-setup': ['Node.js', 'JavaScript', 'TypeScript'],
'language-version-detect': ['PHP', 'Python', 'Go', '.NET', 'Node.js'],
'php-tests': ['PHP'],
'php-laravel-phpunit': ['PHP', 'Laravel'],

View File

@@ -8,22 +8,22 @@ Builds the Go project.
### Inputs
| name | description | required | default |
|---------------|------------------------------------------------------------------------|----------|---------|
| `go-version` | <p>Go version to use.</p> | `false` | `""` |
| `destination` | <p>Build destination directory.</p> | `false` | `./bin` |
| `max-retries` | <p>Maximum number of retry attempts for go mod download operations</p> | `false` | `3` |
| `token` | <p>GitHub token for authentication</p> | `false` | `""` |
| name | description | required | default |
| --- | --- | --- | --- |
| `go-version` | <p>Go version to use.</p> | `false` | `""` |
| `destination` | <p>Build destination directory.</p> | `false` | `./bin` |
| `max-retries` | <p>Maximum number of retry attempts for go mod download operations</p> | `false` | `3` |
| `token` | <p>GitHub token for authentication</p> | `false` | `""` |
### Outputs
| name | description |
|-----------------|--------------------------------------------------------|
| `build_status` | <p>Build completion status (success/failure)</p> |
| `test_status` | <p>Test execution status (success/failure/skipped)</p> |
| `go_version` | <p>Version of Go used</p> |
| `binary_path` | <p>Path to built binaries</p> |
| `coverage_path` | <p>Path to coverage report</p> |
| name | description |
| --- | --- |
| `build_status` | <p>Build completion status (success/failure)</p> |
| `test_status` | <p>Test execution status (success/failure/skipped)</p> |
| `go_version` | <p>Version of Go used</p> |
| `binary_path` | <p>Path to built binaries</p> |
| `coverage_path` | <p>Path to coverage report</p> |
### Runs

View File

@@ -1,4 +1,3 @@
---
# Validation rules for go-build action
# Generated by update-validators.py v1.0.0 - DO NOT EDIT MANUALLY
# Schema version: 1.0
@@ -8,7 +7,6 @@
# Rules are automatically applied by validate-inputs action when this
# action is used.
#
schema_version: '1.0'
action: go-build
description: Builds the Go project.

View File

@@ -1,4 +1,3 @@
---
# Validation rules for go-lint action
# Generated by update-validators.py v1.0.0 - DO NOT EDIT MANUALLY
# Schema version: 1.0
@@ -8,7 +7,6 @@
# Rules are automatically applied by validate-inputs action when this
# action is used.
#
schema_version: '1.0'
action: go-lint
description: Run golangci-lint with advanced configuration, caching, and reporting

View File

@@ -1,4 +1,3 @@
---
# Validation rules for language-version-detect action
# Generated by update-validators.py v1.0.0 - DO NOT EDIT MANUALLY
# Schema version: 1.0
@@ -8,11 +7,9 @@
# Rules are automatically applied by validate-inputs action when this
# action is used.
#
schema_version: '1.0'
action: language-version-detect
description: 'DEPRECATED: This action is deprecated. Inline version detection directly in your actions instead. Detects language
version from project configuration files with support for PHP, Python, Go, and .NET.'
description: 'DEPRECATED: This action is deprecated. Inline version detection directly in your actions instead. Detects language version from project configuration files with support for PHP, Python, Go, and .NET.'
generator_version: 1.0.0
required_inputs:
- language

View File

@@ -1,80 +0,0 @@
#!/usr/bin/env python3
"""Custom validator for node-setup action."""
from __future__ import annotations
from pathlib import Path
import sys
# Add validate-inputs directory to path to import validators
validate_inputs_path = Path(__file__).parent.parent / "validate-inputs"
sys.path.insert(0, str(validate_inputs_path))
from validators.base import BaseValidator
from validators.version import VersionValidator
class CustomValidator(BaseValidator):
"""Custom validator for node-setup action."""
def __init__(self, action_type: str = "node-setup") -> None:
"""Initialize node-setup validator."""
super().__init__(action_type)
self.version_validator = VersionValidator()
def validate_inputs(self, inputs: dict[str, str]) -> bool:
"""Validate node-setup action inputs."""
valid = True
# Validate default-version if provided
if "default-version" in inputs:
value = inputs["default-version"]
# Empty string should fail validation
if value == "":
self.add_error("Node version cannot be empty")
valid = False
elif value:
# Use the Node version validator
result = self.version_validator.validate_node_version(value, "default-version")
# Propagate errors from the version validator
for error in self.version_validator.errors:
if error not in self.errors:
self.add_error(error)
# Clear the version validator's errors after propagating
self.version_validator.clear_errors()
if not result:
valid = False
# Validate package-manager if provided
if "package-manager" in inputs:
value = inputs["package-manager"]
if value and value not in ["npm", "yarn", "pnpm", "bun"]:
self.add_error(
f"Invalid package manager: {value}. Must be one of: npm, yarn, pnpm, bun"
)
valid = False
return valid
def get_required_inputs(self) -> list[str]:
"""Get list of required inputs."""
return []
def get_validation_rules(self) -> dict:
"""Get validation rules."""
return {
"default-version": {
"type": "node_version",
"required": False,
"description": "Default Node.js version to use",
},
"package-manager": {
"type": "string",
"required": False,
"description": "Package manager to use",
},
}

View File

@@ -1,72 +0,0 @@
# ivuorinen/actions/node-setup
## Node Setup
### Description
Sets up Node.js environment with version detection and package manager configuration.
### Inputs
| name | description | required | default |
|-------------------|--------------------------------------------------------------------------|----------|------------------------------|
| `default-version` | <p>Default Node.js version to use if no configuration file is found.</p> | `false` | `22` |
| `package-manager` | <p>Node.js package manager to use (npm, yarn, pnpm, bun, auto)</p> | `false` | `auto` |
| `registry-url` | <p>Custom NPM registry URL</p> | `false` | `https://registry.npmjs.org` |
| `token` | <p>Auth token for private registry</p> | `false` | `""` |
| `node-mirror` | <p>Custom Node.js binary mirror</p> | `false` | `""` |
| `force-version` | <p>Force specific Node.js version regardless of config files</p> | `false` | `""` |
### Outputs
| name | description |
|-------------------|-------------------------------------|
| `node-version` | <p>Installed Node.js version</p> |
| `package-manager` | <p>Selected package manager</p> |
| `node-path` | <p>Path to Node.js installation</p> |
### Runs
This action is a `composite` action.
### Usage
```yaml
- uses: ivuorinen/actions/node-setup@main
with:
default-version:
# Default Node.js version to use if no configuration file is found.
#
# Required: false
# Default: 22
package-manager:
# Node.js package manager to use (npm, yarn, pnpm, bun, auto)
#
# Required: false
# Default: auto
registry-url:
# Custom NPM registry URL
#
# Required: false
# Default: https://registry.npmjs.org
token:
# Auth token for private registry
#
# Required: false
# Default: ""
node-mirror:
# Custom Node.js binary mirror
#
# Required: false
# Default: ""
force-version:
# Force specific Node.js version regardless of config files
#
# Required: false
# Default: ""
```

View File

@@ -1,370 +0,0 @@
# yaml-language-server: $schema=https://json.schemastore.org/github-action.json
# permissions:
# - (none required) # Setup action, no repository writes
---
name: Node Setup
description: 'Sets up Node.js environment with version detection and package manager configuration.'
author: 'Ismo Vuorinen'
branding:
icon: server
color: green
inputs:
default-version:
description: 'Default Node.js version to use if no configuration file is found.'
required: false
default: '22'
package-manager:
description: 'Node.js package manager to use (npm, yarn, pnpm, bun, auto)'
required: false
default: 'auto'
registry-url:
description: 'Custom NPM registry URL'
required: false
default: 'https://registry.npmjs.org'
token:
description: 'Auth token for private registry'
required: false
node-mirror:
description: 'Custom Node.js binary mirror'
required: false
force-version:
description: 'Force specific Node.js version regardless of config files'
required: false
outputs:
node-version:
description: 'Installed Node.js version'
value: ${{ steps.setup.outputs.node-version }}
package-manager:
description: 'Selected package manager'
value: ${{ steps.package-manager-resolution.outputs.final-package-manager }}
node-path:
description: 'Path to Node.js installation'
value: ${{ steps.final-outputs.outputs.node-path }}
runs:
using: composite
steps:
- name: Validate Inputs
id: validate
shell: bash
env:
DEFAULT_VERSION: ${{ inputs.default-version }}
FORCE_VERSION: ${{ inputs.force-version }}
PACKAGE_MANAGER: ${{ inputs.package-manager }}
REGISTRY_URL: ${{ inputs.registry-url }}
NODE_MIRROR: ${{ inputs.node-mirror }}
AUTH_TOKEN: ${{ inputs.token }}
run: |
set -euo pipefail
# Validate default-version format
if [[ -n "$DEFAULT_VERSION" ]]; then
if ! [[ "$DEFAULT_VERSION" =~ ^[0-9]+(\.[0-9]+(\.[0-9]+)?)?$ ]]; then
echo "::error::Invalid default-version format: '$DEFAULT_VERSION'. Expected format: X or X.Y or X.Y.Z (e.g., 22, 20.9, 18.17.1)"
exit 1
fi
# Check for reasonable version range (prevent malicious inputs)
major_version=$(echo "$DEFAULT_VERSION" | cut -d'.' -f1)
if [ "$major_version" -lt 14 ] || [ "$major_version" -gt 30 ]; then
echo "::error::Invalid default-version: '$DEFAULT_VERSION'. Node.js major version should be between 14 and 30"
exit 1
fi
fi
# Validate force-version format if provided
if [[ -n "$FORCE_VERSION" ]]; then
if ! [[ "$FORCE_VERSION" =~ ^[0-9]+(\.[0-9]+(\.[0-9]+)?)?$ ]]; then
echo "::error::Invalid force-version format: '$FORCE_VERSION'. Expected format: X or X.Y or X.Y.Z (e.g., 22, 20.9, 18.17.1)"
exit 1
fi
# Check for reasonable version range
major_version=$(echo "$FORCE_VERSION" | cut -d'.' -f1)
if [ "$major_version" -lt 14 ] || [ "$major_version" -gt 30 ]; then
echo "::error::Invalid force-version: '$FORCE_VERSION'. Node.js major version should be between 14 and 30"
exit 1
fi
fi
# Validate package-manager
case "$PACKAGE_MANAGER" in
"npm"|"yarn"|"pnpm"|"bun"|"auto")
# Valid package managers
;;
*)
echo "::error::Invalid package-manager: '$PACKAGE_MANAGER'. Must be one of: npm, yarn, pnpm, bun, auto"
exit 1
;;
esac
# Validate registry-url format (basic URL validation)
if [[ "$REGISTRY_URL" != "https://"* ]] && [[ "$REGISTRY_URL" != "http://"* ]]; then
echo "::error::Invalid registry-url: '$REGISTRY_URL'. Must be a valid HTTP/HTTPS URL"
exit 1
fi
# Validate node-mirror format if provided
if [[ -n "$NODE_MIRROR" ]]; then
if [[ "$NODE_MIRROR" != "https://"* ]] && [[ "$NODE_MIRROR" != "http://"* ]]; then
echo "::error::Invalid node-mirror: '$NODE_MIRROR'. Must be a valid HTTP/HTTPS URL"
exit 1
fi
fi
# Validate auth token format if provided (basic check for NPM tokens)
if [[ -n "$AUTH_TOKEN" ]]; then
if [[ "$AUTH_TOKEN" == *";"* ]] || [[ "$AUTH_TOKEN" == *"&&"* ]] || [[ "$AUTH_TOKEN" == *"|"* ]]; then
echo "::error::Invalid token format: command injection patterns not allowed"
exit 1
fi
fi
echo "Input validation completed successfully"
- name: Checkout Repository
uses: actions/checkout@71cf2267d89c5cb81562390fa70a37fa40b1305e # v6-beta
with:
token: ${{ inputs.token || github.token }}
- name: Detect Node.js Version
id: version
shell: sh
env:
DEFAULT_VERSION: "${{ inputs.force-version != '' && inputs.force-version || inputs.default-version }}"
run: |
set -eu
# Function to validate version format
validate_version() {
version=$1
case "$version" in
[0-9]*.[0-9]* | [0-9]*.[0-9]*.[0-9]*)
return 0
;;
*)
return 1
;;
esac
}
# Function to clean version string
clean_version() {
printf '%s' "$1" | sed 's/^[vV]//' | tr -d ' \n\r'
}
detected_version=""
detected_package_manager=""
# Parse .nvmrc file (highest priority for Node.js)
if [ -f .nvmrc ]; then
echo "Checking .nvmrc..." >&2
version=$(tr -d '\r' < .nvmrc | head -1)
if [ -n "$version" ]; then
version=$(clean_version "$version")
if validate_version "$version"; then
echo "Found Node.js version in .nvmrc: $version" >&2
detected_version="$version"
fi
fi
fi
# Parse package.json
if [ -z "$detected_version" ] && [ -f package.json ]; then
echo "Checking package.json for Node.js version..." >&2
if command -v jq >/dev/null 2>&1; then
version=$(jq -r '.engines.node // empty' package.json 2>/dev/null | sed -n 's/[^0-9]*\([0-9]\+\.[0-9]\+\(\.[0-9]\+\)\?\).*/\1/p')
if [ -n "$version" ]; then
version=$(clean_version "$version")
if validate_version "$version"; then
echo "Found Node.js version in package.json: $version" >&2
detected_version="$version"
fi
fi
else
echo "jq not found; skipping package.json version parsing" >&2
fi
fi
# Parse .tool-versions file
if [ -z "$detected_version" ] && [ -f .tool-versions ]; then
echo "Checking .tool-versions for nodejs..." >&2
version=$(awk '/^nodejs[[:space:]]/ {gsub(/#.*/, ""); print $2; exit}' .tool-versions 2>/dev/null || echo "")
if [ -n "$version" ]; then
version=$(clean_version "$version")
if validate_version "$version"; then
echo "Found Node.js version in .tool-versions: $version" >&2
detected_version="$version"
fi
fi
fi
# Parse Dockerfile
if [ -z "$detected_version" ] && [ -f Dockerfile ]; then
echo "Checking Dockerfile for node..." >&2
version=$(grep -iF "FROM" Dockerfile | grep -F "node:" | head -1 | \
sed -n -E "s/.*node:([0-9]+(\.[0-9]+)*)(-[^:]*)?.*/\1/p" || echo "")
if [ -n "$version" ]; then
version=$(clean_version "$version")
if validate_version "$version"; then
echo "Found Node.js version in Dockerfile: $version" >&2
detected_version="$version"
fi
fi
fi
# Parse devcontainer.json
if [ -z "$detected_version" ] && [ -f .devcontainer/devcontainer.json ]; then
echo "Checking devcontainer.json for node..." >&2
if command -v jq >/dev/null 2>&1; then
version=$(jq -r '.image // empty' .devcontainer/devcontainer.json 2>/dev/null | sed -n -E "s/.*node:([0-9]+(\.[0-9]+)*)(-[^:]*)?.*/\1/p" || echo "")
if [ -n "$version" ]; then
version=$(clean_version "$version")
if validate_version "$version"; then
echo "Found Node.js version in devcontainer: $version" >&2
detected_version="$version"
fi
fi
else
echo "jq not found; skipping devcontainer.json parsing" >&2
fi
fi
# Detect package manager
if [ -f bun.lockb ]; then
detected_package_manager="bun"
elif [ -f pnpm-lock.yaml ]; then
detected_package_manager="pnpm"
elif [ -f yarn.lock ]; then
detected_package_manager="yarn"
elif [ -f package-lock.json ]; then
detected_package_manager="npm"
elif [ -f package.json ]; then
if command -v jq >/dev/null 2>&1; then
pkg_manager=$(jq -r '.packageManager // empty' package.json 2>/dev/null | sed 's/@.*//')
if [ -n "$pkg_manager" ]; then
detected_package_manager="$pkg_manager"
else
detected_package_manager="npm"
fi
else
detected_package_manager="npm"
fi
else
detected_package_manager="npm"
fi
# Use default version if nothing detected
if [ -z "$detected_version" ]; then
detected_version="$DEFAULT_VERSION"
echo "Using default Node.js version: $detected_version" >&2
fi
# Set outputs
printf 'detected-version=%s\n' "$detected_version" >> "$GITHUB_OUTPUT"
printf 'package-manager=%s\n' "$detected_package_manager" >> "$GITHUB_OUTPUT"
echo "Final detected Node.js version: $detected_version" >&2
echo "Detected package manager: $detected_package_manager" >&2
- name: Resolve Package Manager
id: package-manager-resolution
shell: bash
env:
INPUT_PM: ${{ inputs.package-manager }}
DETECTED_PM: ${{ steps.version.outputs.package-manager }}
run: |
set -euo pipefail
input_pm="$INPUT_PM"
detected_pm="$DETECTED_PM"
final_pm=""
if [ "$input_pm" = "auto" ]; then
if [ -n "$detected_pm" ]; then
final_pm="$detected_pm"
echo "Auto-detected package manager: $final_pm"
else
final_pm="npm"
echo "No package manager detected, using default: $final_pm"
fi
else
final_pm="$input_pm"
echo "Using specified package manager: $final_pm"
fi
echo "final-package-manager=$final_pm" >> $GITHUB_OUTPUT
echo "Final package manager: $final_pm"
- name: Setup Node.js
id: setup
uses: actions/setup-node@2028fbc5c25fe9cf00d9f06a71cc4710d4507903 # v6.0.0
with:
node-version: ${{ steps.version.outputs.detected-version }}
registry-url: ${{ inputs.registry-url }}
- name: Enable Corepack
id: corepack
shell: bash
run: |
set -euo pipefail
echo "Enabling Corepack for package manager management..."
corepack enable
echo "✅ Corepack enabled successfully"
- name: Set Auth Token
if: inputs.token != ''
shell: bash
env:
TOKEN: ${{ inputs.token }}
run: |
# Sanitize token by removing newlines to prevent env var injection
sanitized_token="$(echo "$TOKEN" | tr -d '\n\r')"
printf 'NODE_AUTH_TOKEN=%s\n' "$sanitized_token" >> "$GITHUB_ENV"
- name: Setup Package Manager
shell: bash
env:
PACKAGE_MANAGER: ${{ steps.package-manager-resolution.outputs.final-package-manager }}
run: |
set -euo pipefail
package_manager="$PACKAGE_MANAGER"
echo "Setting up package manager: $package_manager"
case "$package_manager" in
"pnpm")
echo "Installing PNPM via Corepack..."
corepack prepare pnpm@latest --activate
echo "✅ PNPM installed successfully"
;;
"yarn")
echo "Installing Yarn via Corepack..."
corepack prepare yarn@stable --activate
echo "✅ Yarn installed successfully"
;;
"bun")
# Bun installation handled by separate step below
echo "Bun will be installed via official setup-bun action"
;;
"npm")
echo "Using built-in NPM"
;;
*)
echo "::warning::Unknown package manager: $package_manager, using NPM"
;;
esac
- name: Setup Bun
if: steps.package-manager-resolution.outputs.final-package-manager == 'bun'
uses: oven-sh/setup-bun@735343b667d3e6f658f44d0eca948eb6282f2b76 # v2.0.2
with:
bun-version: latest
- name: Set Final Outputs
id: final-outputs
shell: bash
run: |
echo "node-path=$(which node)" >> $GITHUB_OUTPUT

View File

@@ -1,45 +0,0 @@
---
# Validation rules for node-setup action
# Generated by update-validators.py v1.0.0 - DO NOT EDIT MANUALLY
# Schema version: 1.0
# Coverage: 83% (5/6 inputs)
#
# This file defines validation rules for the node-setup GitHub Action.
# Rules are automatically applied by validate-inputs action when this
# action is used.
#
schema_version: '1.0'
action: node-setup
description: Sets up Node.js environment with version detection and package manager configuration.
generator_version: 1.0.0
required_inputs: []
optional_inputs:
- default-version
- force-version
- node-mirror
- package-manager
- registry-url
- token
conventions:
default-version: semantic_version
force-version: semantic_version
package-manager: boolean
registry-url: url
token: github_token
overrides:
package-manager: package_manager_enum
statistics:
total_inputs: 6
validated_inputs: 5
skipped_inputs: 0
coverage_percentage: 83
validation_coverage: 83
auto_detected: true
manual_review_required: false
quality_indicators:
has_required_inputs: false
has_token_validation: true
has_version_validation: true
has_file_validation: false
has_security_validation: true

View File

@@ -8,21 +8,21 @@ Publishes the package to the NPM registry with configurable scope and registry U
### Inputs
| name | description | required | default |
|-------------------|----------------------------------------|----------|----------------------------------------|
| `npm_token` | <p>NPM token.</p> | `true` | `""` |
| `registry-url` | <p>Registry URL for publishing.</p> | `false` | `https://registry.npmjs.org/` |
| `scope` | <p>Package scope to use.</p> | `false` | `@ivuorinen` |
| `package-version` | <p>The version to publish.</p> | `false` | `${{ github.event.release.tag_name }}` |
| `token` | <p>GitHub token for authentication</p> | `false` | `""` |
| name | description | required | default |
| --- | --- | --- | --- |
| `npm_token` | <p>NPM token.</p> | `true` | `""` |
| `registry-url` | <p>Registry URL for publishing.</p> | `false` | `https://registry.npmjs.org/` |
| `scope` | <p>Package scope to use.</p> | `false` | `@ivuorinen` |
| `package-version` | <p>The version to publish.</p> | `false` | `${{ github.event.release.tag_name }}` |
| `token` | <p>GitHub token for authentication</p> | `false` | `""` |
### Outputs
| name | description |
|-------------------|-------------------------------------|
| `registry-url` | <p>Registry URL for publishing.</p> |
| `scope` | <p>Package scope to use.</p> |
| `package-version` | <p>The version to publish.</p> |
| name | description |
| --- | --- |
| `registry-url` | <p>Registry URL for publishing.</p> |
| `scope` | <p>Package scope to use.</p> |
| `package-version` | <p>The version to publish.</p> |
### Runs

View File

@@ -100,24 +100,76 @@ runs:
with:
token: ${{ inputs.token || github.token }}
- name: Detect Package Manager
id: detect-pm
shell: sh
run: |
set -eu
# Detect package manager from lockfiles
if [ -f bun.lockb ]; then
package_manager="bun"
elif [ -f pnpm-lock.yaml ]; then
package_manager="pnpm"
elif [ -f yarn.lock ]; then
package_manager="yarn"
else
package_manager="npm"
fi
printf 'package-manager=%s\n' "$package_manager" >> "$GITHUB_OUTPUT"
echo "Detected package manager: $package_manager"
- name: Setup Node.js
id: node-setup
uses: ivuorinen/actions/node-setup@0fa9a68f07a1260b321f814202658a6089a43d42
uses: actions/setup-node@2028fbc5c25fe9cf00d9f06a71cc4710d4507903 # v6.0.0
with:
node-version: '22'
- name: Enable Corepack
shell: sh
run: |
set -eu
corepack enable
- name: Install Package Manager
shell: sh
env:
PACKAGE_MANAGER: ${{ steps.detect-pm.outputs.package-manager }}
run: |
set -eu
case "$PACKAGE_MANAGER" in
pnpm)
corepack prepare pnpm@latest --activate
;;
yarn)
corepack prepare yarn@stable --activate
;;
bun|npm)
# Bun installed separately, npm built-in
;;
esac
- name: Setup Bun
if: steps.detect-pm.outputs.package-manager == 'bun'
uses: oven-sh/setup-bun@735343b667d3e6f658f44d0eca948eb6282f2b76 # v2.0.2
with:
bun-version: latest
- name: Cache Node Dependencies
id: cache
uses: actions/cache@0057852bfaa89a56745cba8c7296529d2fc39830 # v4.3.0
with:
path: node_modules
key: ${{ runner.os }}-npm-publish-${{ steps.node-setup.outputs.package-manager }}-${{ hashFiles('package-lock.json', 'yarn.lock', 'pnpm-lock.yaml', 'bun.lockb') }}
key: ${{ runner.os }}-npm-publish-${{ steps.detect-pm.outputs.package-manager }}-${{ hashFiles('package-lock.json', 'yarn.lock', 'pnpm-lock.yaml', 'bun.lockb') }}
restore-keys: |
${{ runner.os }}-npm-publish-${{ steps.node-setup.outputs.package-manager }}-
${{ runner.os }}-npm-publish-${{ steps.detect-pm.outputs.package-manager }}-
- name: Install Dependencies
if: steps.cache.outputs.cache-hit != 'true'
shell: sh
env:
PACKAGE_MANAGER: ${{ steps.node-setup.outputs.package-manager }}
PACKAGE_MANAGER: ${{ steps.detect-pm.outputs.package-manager }}
run: |
set -eu

View File

@@ -1,4 +1,3 @@
---
# Validation rules for npm-publish action
# Generated by update-validators.py v1.0.0 - DO NOT EDIT MANUALLY
# Schema version: 1.0
@@ -8,7 +7,6 @@
# Rules are automatically applied by validate-inputs action when this
# action is used.
#
schema_version: '1.0'
action: npm-publish
description: Publishes the package to the NPM registry with configurable scope and registry URL.

View File

@@ -1,4 +1,3 @@
---
# Validation rules for php-composer action
# Generated by update-validators.py v1.0.0 - DO NOT EDIT MANUALLY
# Schema version: 1.0
@@ -8,7 +7,6 @@
# Rules are automatically applied by validate-inputs action when this
# action is used.
#
schema_version: '1.0'
action: php-composer
description: Runs Composer install on a repository with advanced caching and configuration.

View File

@@ -8,22 +8,22 @@ Setup PHP, install dependencies, generate key, create database and run composer
### Inputs
| name | description | required | default |
|--------------------|-----------------------------------------------------------------------------------------------------------------------|----------|---------------------------------------------|
| `php-version` | <p>PHP Version to use, see https://github.com/marketplace/actions/setup-php-action#php-version-optional</p> | `false` | `latest` |
| `php-version-file` | <p>PHP Version file to use, see https://github.com/marketplace/actions/setup-php-action#php-version-file-optional</p> | `false` | `.php-version` |
| `extensions` | <p>PHP extensions to install, see https://github.com/marketplace/actions/setup-php-action#extensions-optional</p> | `false` | `mbstring, intl, json, pdo_sqlite, sqlite3` |
| `coverage` | <p>Specify code-coverage driver, see https://github.com/marketplace/actions/setup-php-action#coverage-optional</p> | `false` | `none` |
| `token` | <p>GitHub token for authentication</p> | `false` | `""` |
| name | description | required | default |
| --- | --- | --- | --- |
| `php-version` | <p>PHP Version to use, see https://github.com/marketplace/actions/setup-php-action#php-version-optional</p> | `false` | `latest` |
| `php-version-file` | <p>PHP Version file to use, see https://github.com/marketplace/actions/setup-php-action#php-version-file-optional</p> | `false` | `.php-version` |
| `extensions` | <p>PHP extensions to install, see https://github.com/marketplace/actions/setup-php-action#extensions-optional</p> | `false` | `mbstring, intl, json, pdo_sqlite, sqlite3` |
| `coverage` | <p>Specify code-coverage driver, see https://github.com/marketplace/actions/setup-php-action#coverage-optional</p> | `false` | `none` |
| `token` | <p>GitHub token for authentication</p> | `false` | `""` |
### Outputs
| name | description |
|--------------------|------------------------------------------------|
| `php-version` | <p>The PHP version that was setup</p> |
| `php-version-file` | <p>The PHP version file that was used</p> |
| `extensions` | <p>The PHP extensions that were installed</p> |
| `coverage` | <p>The code-coverage driver that was setup</p> |
| name | description |
| --- | --- |
| `php-version` | <p>The PHP version that was setup</p> |
| `php-version-file` | <p>The PHP version file that was used</p> |
| `extensions` | <p>The PHP extensions that were installed</p> |
| `coverage` | <p>The code-coverage driver that was setup</p> |
### Runs

View File

@@ -1,4 +1,3 @@
---
# Validation rules for php-laravel-phpunit action
# Generated by update-validators.py v1.0.0 - DO NOT EDIT MANUALLY
# Schema version: 1.0
@@ -8,7 +7,6 @@
# Rules are automatically applied by validate-inputs action when this
# action is used.
#
schema_version: '1.0'
action: php-laravel-phpunit
description: Setup PHP, install dependencies, generate key, create database and run composer test

View File

@@ -8,20 +8,20 @@ Run PHPUnit tests on the repository
### Inputs
| name | description | required | default |
|------------|----------------------------------------|----------|-----------------------------|
| `token` | <p>GitHub token for authentication</p> | `false` | `""` |
| `username` | <p>GitHub username for commits</p> | `false` | `github-actions` |
| `email` | <p>GitHub email for commits</p> | `false` | `github-actions@github.com` |
| name | description | required | default |
| --- | --- | --- | --- |
| `token` | <p>GitHub token for authentication</p> | `false` | `""` |
| `username` | <p>GitHub username for commits</p> | `false` | `github-actions` |
| `email` | <p>GitHub email for commits</p> | `false` | `github-actions@github.com` |
### Outputs
| name | description |
|-----------------|--------------------------------------------------------|
| `test_status` | <p>Test execution status (success/failure/skipped)</p> |
| `tests_run` | <p>Number of tests executed</p> |
| `tests_passed` | <p>Number of tests passed</p> |
| `coverage_path` | <p>Path to coverage report</p> |
| name | description |
| --- | --- |
| `test_status` | <p>Test execution status (success/failure/skipped)</p> |
| `tests_run` | <p>Number of tests executed</p> |
| `tests_passed` | <p>Number of tests passed</p> |
| `coverage_path` | <p>Path to coverage report</p> |
### Runs

View File

@@ -1,4 +1,3 @@
---
# Validation rules for php-tests action
# Generated by update-validators.py v1.0.0 - DO NOT EDIT MANUALLY
# Schema version: 1.0
@@ -8,7 +7,6 @@
# Rules are automatically applied by validate-inputs action when this
# action is used.
#
schema_version: '1.0'
action: php-tests
description: Run PHPUnit tests on the repository

View File

@@ -76,10 +76,65 @@ runs:
printf '%s\n' "found=true" >> "$GITHUB_OUTPUT"
fi
- name: Setup Node.js environment
- name: Detect Package Manager
if: steps.detect-node.outputs.found == 'true'
id: node-setup
uses: ivuorinen/actions/node-setup@0fa9a68f07a1260b321f814202658a6089a43d42
id: detect-pm
shell: sh
run: |
set -eu
# Detect package manager from lockfiles
if [ -f bun.lockb ]; then
package_manager="bun"
elif [ -f pnpm-lock.yaml ]; then
package_manager="pnpm"
elif [ -f yarn.lock ]; then
package_manager="yarn"
else
package_manager="npm"
fi
printf 'package-manager=%s\n' "$package_manager" >> "$GITHUB_OUTPUT"
echo "Detected package manager: $package_manager"
- name: Setup Node.js
if: steps.detect-node.outputs.found == 'true'
uses: actions/setup-node@2028fbc5c25fe9cf00d9f06a71cc4710d4507903 # v6.0.0
with:
node-version: '22'
- name: Enable Corepack
if: steps.detect-node.outputs.found == 'true'
shell: sh
run: |
set -eu
corepack enable
- name: Install Package Manager
if: steps.detect-node.outputs.found == 'true'
shell: sh
env:
PACKAGE_MANAGER: ${{ steps.detect-pm.outputs.package-manager }}
run: |
set -eu
case "$PACKAGE_MANAGER" in
pnpm)
corepack prepare pnpm@latest --activate
;;
yarn)
corepack prepare yarn@stable --activate
;;
bun|npm)
# Bun installed separately, npm built-in
;;
esac
- name: Setup Bun
if: steps.detect-node.outputs.found == 'true' && steps.detect-pm.outputs.package-manager == 'bun'
uses: oven-sh/setup-bun@735343b667d3e6f658f44d0eca948eb6282f2b76 # v2.0.2
with:
bun-version: latest
- name: Cache Node Dependencies
if: steps.detect-node.outputs.found == 'true'
@@ -87,15 +142,15 @@ runs:
uses: actions/cache@0057852bfaa89a56745cba8c7296529d2fc39830 # v4.3.0
with:
path: node_modules
key: ${{ runner.os }}-pr-lint-${{ steps.node-setup.outputs.package-manager }}-${{ hashFiles('package-lock.json', 'yarn.lock', 'pnpm-lock.yaml', 'bun.lockb') }}
key: ${{ runner.os }}-pr-lint-${{ steps.detect-pm.outputs.package-manager }}-${{ hashFiles('package-lock.json', 'yarn.lock', 'pnpm-lock.yaml', 'bun.lockb') }}
restore-keys: |
${{ runner.os }}-pr-lint-${{ steps.node-setup.outputs.package-manager }}-
${{ runner.os }}-pr-lint-${{ steps.detect-pm.outputs.package-manager }}-
- name: Install Node Dependencies
if: steps.detect-node.outputs.found == 'true' && steps.node-cache.outputs.cache-hit != 'true'
shell: sh
env:
PACKAGE_MANAGER: ${{ steps.node-setup.outputs.package-manager }}
PACKAGE_MANAGER: ${{ steps.detect-pm.outputs.package-manager }}
run: |
set -eu

View File

@@ -1,4 +1,3 @@
---
# Validation rules for pr-lint action
# Generated by update-validators.py v1.0.0 - DO NOT EDIT MANUALLY
# Schema version: 1.0
@@ -8,7 +7,6 @@
# Rules are automatically applied by validate-inputs action when this
# action is used.
#
schema_version: '1.0'
action: pr-lint
description: Runs MegaLinter against pull requests

View File

@@ -1,4 +1,3 @@
---
# Validation rules for pre-commit action
# Generated by update-validators.py v1.0.0 - DO NOT EDIT MANUALLY
# Schema version: 1.0
@@ -8,7 +7,6 @@
# Rules are automatically applied by validate-inputs action when this
# action is used.
#
schema_version: '1.0'
action: pre-commit
description: Runs pre-commit on the repository and pushes the fixes back to the repository

View File

@@ -8,32 +8,32 @@ Run Prettier in check or fix mode with advanced configuration and reporting
### Inputs
| name | description | required | default |
|---------------------|------------------------------------------------------------|----------|--------------------------------------------------|
| `mode` | <p>Mode to run (check or fix)</p> | `false` | `check` |
| `working-directory` | <p>Directory containing files to format</p> | `false` | `.` |
| `prettier-version` | <p>Prettier version to use</p> | `false` | `latest` |
| `config-file` | <p>Path to Prettier config file</p> | `false` | `.prettierrc` |
| `ignore-file` | <p>Path to Prettier ignore file</p> | `false` | `.prettierignore` |
| `file-pattern` | <p>Files to include (glob pattern)</p> | `false` | `**/*.{js,jsx,ts,tsx,css,scss,json,md,yaml,yml}` |
| `cache` | <p>Enable Prettier caching</p> | `false` | `true` |
| `fail-on-error` | <p>Fail workflow if issues are found (check mode only)</p> | `false` | `true` |
| `report-format` | <p>Output format for check mode (json, sarif)</p> | `false` | `sarif` |
| `max-retries` | <p>Maximum number of retry attempts</p> | `false` | `3` |
| `plugins` | <p>Comma-separated list of Prettier plugins to install</p> | `false` | `""` |
| `token` | <p>GitHub token for authentication</p> | `false` | `""` |
| `username` | <p>GitHub username for commits (fix mode only)</p> | `false` | `github-actions` |
| `email` | <p>GitHub email for commits (fix mode only)</p> | `false` | `github-actions@github.com` |
| name | description | required | default |
| --- | --- | --- | --- |
| `mode` | <p>Mode to run (check or fix)</p> | `false` | `check` |
| `working-directory` | <p>Directory containing files to format</p> | `false` | `.` |
| `prettier-version` | <p>Prettier version to use</p> | `false` | `latest` |
| `config-file` | <p>Path to Prettier config file</p> | `false` | `.prettierrc` |
| `ignore-file` | <p>Path to Prettier ignore file</p> | `false` | `.prettierignore` |
| `file-pattern` | <p>Files to include (glob pattern)</p> | `false` | `**/*.{js,jsx,ts,tsx,css,scss,json,md,yaml,yml}` |
| `cache` | <p>Enable Prettier caching</p> | `false` | `true` |
| `fail-on-error` | <p>Fail workflow if issues are found (check mode only)</p> | `false` | `true` |
| `report-format` | <p>Output format for check mode (json, sarif)</p> | `false` | `sarif` |
| `max-retries` | <p>Maximum number of retry attempts</p> | `false` | `3` |
| `plugins` | <p>Comma-separated list of Prettier plugins to install</p> | `false` | `""` |
| `token` | <p>GitHub token for authentication</p> | `false` | `""` |
| `username` | <p>GitHub username for commits (fix mode only)</p> | `false` | `github-actions` |
| `email` | <p>GitHub email for commits (fix mode only)</p> | `false` | `github-actions@github.com` |
### Outputs
| name | description |
|---------------------|-----------------------------------------------------------------|
| `status` | <p>Overall status (success/failure)</p> |
| `files-checked` | <p>Number of files checked (check mode only)</p> |
| name | description |
| --- | --- |
| `status` | <p>Overall status (success/failure)</p> |
| `files-checked` | <p>Number of files checked (check mode only)</p> |
| `unformatted-files` | <p>Number of files with formatting issues (check mode only)</p> |
| `sarif-file` | <p>Path to SARIF report file (check mode only)</p> |
| `files-changed` | <p>Number of files changed (fix mode only)</p> |
| `sarif-file` | <p>Path to SARIF report file (check mode only)</p> |
| `files-changed` | <p>Number of files changed (fix mode only)</p> |
### Runs

View File

@@ -223,25 +223,77 @@ runs:
with:
token: ${{ inputs.token || github.token }}
- name: Node Setup
id: node-setup
uses: ivuorinen/actions/node-setup@0fa9a68f07a1260b321f814202658a6089a43d42
- name: Detect Package Manager
id: detect-pm
shell: sh
run: |
set -eu
# Detect package manager from lockfiles
if [ -f bun.lockb ]; then
package_manager="bun"
elif [ -f pnpm-lock.yaml ]; then
package_manager="pnpm"
elif [ -f yarn.lock ]; then
package_manager="yarn"
else
package_manager="npm"
fi
printf 'package-manager=%s\n' "$package_manager" >> "$GITHUB_OUTPUT"
echo "Detected package manager: $package_manager"
- name: Setup Node.js
uses: actions/setup-node@2028fbc5c25fe9cf00d9f06a71cc4710d4507903 # v6.0.0
with:
node-version: '22'
- name: Enable Corepack
shell: sh
run: |
set -eu
corepack enable
- name: Install Package Manager
shell: sh
env:
PACKAGE_MANAGER: ${{ steps.detect-pm.outputs.package-manager }}
run: |
set -eu
case "$PACKAGE_MANAGER" in
pnpm)
corepack prepare pnpm@latest --activate
;;
yarn)
corepack prepare yarn@stable --activate
;;
bun|npm)
# Bun installed separately, npm built-in
;;
esac
- name: Setup Bun
if: steps.detect-pm.outputs.package-manager == 'bun'
uses: oven-sh/setup-bun@735343b667d3e6f658f44d0eca948eb6282f2b76 # v2.0.2
with:
bun-version: latest
- name: Cache Node Dependencies
id: cache
uses: actions/cache@0057852bfaa89a56745cba8c7296529d2fc39830 # v4.3.0
with:
path: node_modules
key: ${{ runner.os }}-prettier-lint-${{ inputs.mode }}-${{ steps.node-setup.outputs.package-manager }}-${{ hashFiles('package-lock.json', 'yarn.lock', 'pnpm-lock.yaml', 'bun.lockb') }}
key: ${{ runner.os }}-prettier-lint-${{ inputs.mode }}-${{ steps.detect-pm.outputs.package-manager }}-${{ hashFiles('package-lock.json', 'yarn.lock', 'pnpm-lock.yaml', 'bun.lockb') }}
restore-keys: |
${{ runner.os }}-prettier-lint-${{ inputs.mode }}-${{ steps.node-setup.outputs.package-manager }}-
${{ runner.os }}-prettier-lint-${{ inputs.mode }}-${{ steps.detect-pm.outputs.package-manager }}-
${{ runner.os }}-prettier-lint-${{ inputs.mode }}-
- name: Install Dependencies
if: steps.cache.outputs.cache-hit != 'true'
shell: bash
env:
PACKAGE_MANAGER: ${{ steps.node-setup.outputs.package-manager }}
PACKAGE_MANAGER: ${{ steps.detect-pm.outputs.package-manager }}
run: |
set -euo pipefail

View File

@@ -1,4 +1,3 @@
---
# Validation rules for prettier-lint action
# Generated by update-validators.py v1.0.0 - DO NOT EDIT MANUALLY
# Schema version: 1.0
@@ -8,7 +7,6 @@
# Rules are automatically applied by validate-inputs action when this
# action is used.
#
schema_version: '1.0'
action: prettier-lint
description: Run Prettier in check or fix mode with advanced configuration and reporting

View File

@@ -8,25 +8,25 @@ Lints and fixes Python files, commits changes, and uploads SARIF report.
### Inputs
| name | description | required | default |
|---------------------|-----------------------------------------------------------------------|----------|-----------------------------|
| `python-version` | <p>Python version to use</p> | `false` | `3.11` |
| `flake8-version` | <p>Flake8 version to use</p> | `false` | `7.0.0` |
| `autopep8-version` | <p>Autopep8 version to use</p> | `false` | `2.0.4` |
| `max-retries` | <p>Maximum number of retry attempts for installations and linting</p> | `false` | `3` |
| `working-directory` | <p>Directory containing Python files to lint</p> | `false` | `.` |
| `fail-on-error` | <p>Whether to fail the action if linting errors are found</p> | `false` | `true` |
| `token` | <p>GitHub token for authentication</p> | `false` | `""` |
| `username` | <p>GitHub username for commits</p> | `false` | `github-actions` |
| `email` | <p>GitHub email for commits</p> | `false` | `github-actions@github.com` |
| name | description | required | default |
| --- | --- | --- | --- |
| `python-version` | <p>Python version to use</p> | `false` | `3.11` |
| `flake8-version` | <p>Flake8 version to use</p> | `false` | `7.0.0` |
| `autopep8-version` | <p>Autopep8 version to use</p> | `false` | `2.0.4` |
| `max-retries` | <p>Maximum number of retry attempts for installations and linting</p> | `false` | `3` |
| `working-directory` | <p>Directory containing Python files to lint</p> | `false` | `.` |
| `fail-on-error` | <p>Whether to fail the action if linting errors are found</p> | `false` | `true` |
| `token` | <p>GitHub token for authentication</p> | `false` | `""` |
| `username` | <p>GitHub username for commits</p> | `false` | `github-actions` |
| `email` | <p>GitHub email for commits</p> | `false` | `github-actions@github.com` |
### Outputs
| name | description |
|---------------|--------------------------------------------------------|
| name | description |
| --- | --- |
| `lint-result` | <p>Result of the linting process (success/failure)</p> |
| `fixed-files` | <p>Number of files that were fixed</p> |
| `error-count` | <p>Number of errors found</p> |
| `fixed-files` | <p>Number of files that were fixed</p> |
| `error-count` | <p>Number of errors found</p> |
### Runs

View File

@@ -1,4 +1,3 @@
---
# Validation rules for python-lint-fix action
# Generated by update-validators.py v1.0.0 - DO NOT EDIT MANUALLY
# Schema version: 1.0
@@ -8,7 +7,6 @@
# Rules are automatically applied by validate-inputs action when this
# action is used.
#
schema_version: '1.0'
action: python-lint-fix
description: Lints and fixes Python files, commits changes, and uploads SARIF report.

View File

@@ -1,4 +1,3 @@
---
# Validation rules for release-monthly action
# Generated by update-validators.py v1.0.0 - DO NOT EDIT MANUALLY
# Schema version: 1.0
@@ -8,7 +7,6 @@
# Rules are automatically applied by validate-inputs action when this
# action is used.
#
schema_version: '1.0'
action: release-monthly
description: Creates a release for the current month, incrementing patch number if necessary.

View File

@@ -1,4 +1,3 @@
---
# Validation rules for stale action
# Generated by update-validators.py v1.0.0 - DO NOT EDIT MANUALLY
# Schema version: 1.0
@@ -8,7 +7,6 @@
# Rules are automatically applied by validate-inputs action when this
# action is used.
#
schema_version: '1.0'
action: stale
description: A GitHub Action to close stale issues and pull requests.

View File

@@ -1,4 +1,3 @@
---
# Validation rules for sync-labels action
# Generated by update-validators.py v1.0.0 - DO NOT EDIT MANUALLY
# Schema version: 1.0
@@ -8,7 +7,6 @@
# Rules are automatically applied by validate-inputs action when this
# action is used.
#
schema_version: '1.0'
action: sync-labels
description: Sync labels from a YAML file to a GitHub repository

View File

@@ -1,4 +1,3 @@
---
# Validation rules for terraform-lint-fix action
# Generated by update-validators.py v1.0.0 - DO NOT EDIT MANUALLY
# Schema version: 1.0
@@ -8,7 +7,6 @@
# Rules are automatically applied by validate-inputs action when this
# action is used.
#
schema_version: '1.0'
action: terraform-lint-fix
description: Lints and fixes Terraform files with advanced validation and security checks.

View File

@@ -311,9 +311,6 @@ class ValidationRuleGenerator:
"backoff-strategy": "backoff_strategy",
"shell": "shell_type",
},
"node-setup": {
"package-manager": "package_manager_enum",
},
"docker-publish": {
"registry": "registry_enum",
"cache-mode": "cache_mode",

View File

@@ -1,74 +0,0 @@
"""Tests for node-setup custom validator.
Generated by generate-tests.py - Do not edit manually.
"""
# pylint: disable=invalid-name # Test file name matches action name
import sys
from pathlib import Path
# Add action directory to path to import custom validator
action_path = Path(__file__).parent.parent.parent / "node-setup"
sys.path.insert(0, str(action_path))
# pylint: disable=wrong-import-position
from CustomValidator import CustomValidator
class TestCustomNodeSetupValidator:
"""Test cases for node-setup custom validator."""
def setup_method(self):
"""Set up test fixtures."""
self.validator = CustomValidator("node-setup")
def teardown_method(self):
"""Clean up after tests."""
self.validator.clear_errors()
def test_validate_inputs_valid(self):
"""Test validation with valid inputs."""
# TODO: Add specific valid inputs for node-setup
inputs = {}
result = self.validator.validate_inputs(inputs)
# Adjust assertion based on required inputs
assert isinstance(result, bool)
def test_validate_inputs_invalid(self):
"""Test validation with invalid inputs."""
# TODO: Add specific invalid inputs for node-setup
inputs = {"invalid_key": "invalid_value"}
result = self.validator.validate_inputs(inputs)
# Custom validators may have specific validation rules
assert isinstance(result, bool)
def test_required_inputs(self):
"""Test required inputs detection."""
required = self.validator.get_required_inputs()
assert isinstance(required, list)
# TODO: Assert specific required inputs for node-setup
def test_validation_rules(self):
"""Test validation rules."""
rules = self.validator.get_validation_rules()
assert isinstance(rules, dict)
# TODO: Assert specific validation rules for node-setup
def test_github_expressions(self):
"""Test GitHub expression handling."""
inputs = {
"test_input": "${{ github.token }}",
}
result = self.validator.validate_inputs(inputs)
assert isinstance(result, bool)
# GitHub expressions should generally be accepted
def test_error_propagation(self):
"""Test error propagation from sub-validators."""
# Custom validators often use sub-validators
# Test that errors are properly propagated
inputs = {"test": "value"}
self.validator.validate_inputs(inputs)
# Check error handling
if self.validator.has_errors():
assert len(self.validator.errors) > 0