diff --git a/.github/actions/README.md b/.github/actions/README.md deleted file mode 100644 index 69e85ae..0000000 --- a/.github/actions/README.md +++ /dev/null @@ -1,120 +0,0 @@ -# Composite Actions - -This directory contains reusable composite actions to reduce duplication across workflows. - -## Available Actions - -### setup-node - -Sets up Node.js with caching and installs dependencies. - -**Inputs:** - -- `node-version` (optional): Node.js version, defaults to '24' -- `registry-url` (optional): NPM registry URL - -**Usage:** - -```yaml -- uses: ./.github/actions/setup-node - with: - node-version: 22 -``` - -### setup-treesitter - -Installs Tree-sitter CLI and generates the grammar. - -**Usage:** - -```yaml -- uses: ./.github/actions/setup-treesitter -``` - -### setup-dev - -Complete development environment setup (combines setup-node + setup-treesitter). - -**Inputs:** - -- `node-version` (optional): Node.js version, defaults to '24' -- `registry-url` (optional): NPM registry URL -- `skip-checkout` (optional): Skip repository checkout, defaults to 'false' - -**Usage:** - -```yaml -- uses: ./.github/actions/setup-dev - with: - node-version: 24 - skip-checkout: 'true' -``` - -### test-grammar - -Runs comprehensive grammar tests including parser validation. - -**Inputs:** - -- `skip-sample-test` (optional): Skip complex sample test, defaults to 'false' - -**Usage:** - -```yaml -- uses: ./.github/actions/test-grammar - with: - skip-sample-test: 'true' -``` - -### test-coverage - -Analyzes test coverage and validates minimum requirements. - -**Inputs:** - -- `minimum-tests` (optional): Minimum tests required, defaults to '55' - -**Outputs:** - -- `total-tests`: Total number of tests found -- `passing-tests`: Number of passing tests -- `coverage-percent`: Test coverage percentage - -**Usage:** - -```yaml -- uses: ./.github/actions/test-coverage - with: - minimum-tests: 60 -``` - -## Workflow Usage Examples - -### Test Workflow (Simplified) - -```yaml -jobs: - test: - steps: - - uses: ./.github/actions/setup-dev - with: - node-version: ${{ matrix.node-version }} - - uses: ./.github/actions/test-grammar -``` - -### Release Workflow (Simplified) - -```yaml -jobs: - test: - steps: - - uses: ./.github/actions/setup-dev - - uses: ./.github/actions/test-grammar - with: - skip-sample-test: 'true' - - lint: - steps: - - uses: ./.github/actions/setup-node - - uses: ivuorinen/actions/pr-lint@latest -``` diff --git a/.github/actions/setup-dev/action.yml b/.github/actions/setup-dev/action.yml deleted file mode 100644 index 88ea594..0000000 --- a/.github/actions/setup-dev/action.yml +++ /dev/null @@ -1,43 +0,0 @@ ---- -name: "Setup Development Environment" -description: "Complete setup for tree-sitter-shellspec development including Node.js and Tree-sitter" - -inputs: - node-version: - description: "Node.js version to setup" - required: false - default: "24" - registry-url: - description: "NPM registry URL" - required: false - default: "" - skip-checkout: - description: "Skip repository checkout (if already done)" - required: false - default: "false" - -runs: - using: "composite" - steps: - - name: Checkout Repository - if: inputs.skip-checkout != 'true' - uses: actions/checkout@08c6903cd8c0fde910a37f88322edcfb5dd907a8 # v5.0.0 - - - name: Setup Node.js ${{ inputs.node-version }} - uses: actions/setup-node@7c12f8017d5436eb855f1ed4399f037a36fbd9e8 # v5.2.1 - with: - node-version: ${{ inputs.node-version }} - cache: npm - registry-url: ${{ inputs.registry-url }} - - - name: Install Dependencies - run: npm ci || { echo "❌ npm install failed" && npm install } - shell: bash - - - name: Install Tree-sitter CLI - run: npm install -g tree-sitter-cli - shell: bash - - - name: Generate Grammar - run: npm run generate - shell: bash diff --git a/.github/actions/setup-node/action.yml b/.github/actions/setup-node/action.yml deleted file mode 100644 index fe76730..0000000 --- a/.github/actions/setup-node/action.yml +++ /dev/null @@ -1,30 +0,0 @@ ---- -name: "Setup Node.js Environment" -description: "Sets up Node.js with caching and installs dependencies" - -inputs: - node-version: - description: "Node.js version to setup" - required: false - default: "24" - registry-url: - description: "NPM registry URL" - required: false - default: "" - -runs: - using: "composite" - steps: - - name: Checkout Repository - uses: actions/checkout@08c6903cd8c0fde910a37f88322edcfb5dd907a8 # v5.0.0 - - - name: Setup Node.js ${{ inputs.node-version }} - uses: actions/setup-node@7c12f8017d5436eb855f1ed4399f037a36fbd9e8 # v5.2.1 - with: - node-version: ${{ inputs.node-version }} - cache: npm - registry-url: ${{ inputs.registry-url }} - - - name: Install Dependencies - run: npm ci || { echo "❌ npm install failed" && npm install } - shell: bash diff --git a/.github/actions/test-coverage/action.yml b/.github/actions/test-coverage/action.yml deleted file mode 100644 index 42991da..0000000 --- a/.github/actions/test-coverage/action.yml +++ /dev/null @@ -1,71 +0,0 @@ ---- -name: "Test Coverage Analysis" -description: "Analyzes test coverage and generates coverage report" - -inputs: - minimum-tests: - description: "Minimum number of tests required" - required: false - default: "55" - -outputs: - total-tests: - description: "Total number of tests found" - value: ${{ steps.coverage.outputs.total-tests }} - passing-tests: - description: "Number of passing tests" - value: ${{ steps.coverage.outputs.passing-tests }} - coverage-percent: - description: "Test coverage percentage" - value: ${{ steps.coverage.outputs.coverage-percent }} - -runs: - using: "composite" - steps: - - name: Test Coverage Analysis - id: coverage - run: | - echo "## Test Coverage Report" > coverage_report.md - echo "" >> coverage_report.md - - # Run tests and capture output - TEST_OUTPUT=$(npm test 2>&1) - TOTAL_TESTS=$(echo "$TEST_OUTPUT" | grep -E "^\s+[0-9]+\." | wc -l) - PASSING_TESTS=$(echo "$TEST_OUTPUT" | grep -E "^\s+[0-9]+\. ✓" | wc -l) - FAILING_TESTS=$(echo "$TEST_OUTPUT" | grep -E "^\s+[0-9]+\. ✗" | wc -l) - - echo "- **Total Tests:** $TOTAL_TESTS" >> coverage_report.md - echo "- **Passing:** $PASSING_TESTS ✅" >> coverage_report.md - echo "- **Failing:** $FAILING_TESTS ❌" >> coverage_report.md - - if [ $TOTAL_TESTS -gt 0 ]; then - COVERAGE_PERCENT=$(( (PASSING_TESTS * 100) / TOTAL_TESTS )) - echo "- **Coverage:** $COVERAGE_PERCENT%" >> coverage_report.md - else - COVERAGE_PERCENT=0 - fi - - echo "" >> coverage_report.md - echo "### Test Files" >> coverage_report.md - echo "$TEST_OUTPUT" | grep -E "^\s+[a-z_]+:" | sed 's/^/- /' >> coverage_report.md - - cat coverage_report.md - - # Set outputs - echo "total-tests=$TOTAL_TESTS" >> $GITHUB_OUTPUT - echo "passing-tests=$PASSING_TESTS" >> $GITHUB_OUTPUT - echo "coverage-percent=$COVERAGE_PERCENT" >> $GITHUB_OUTPUT - - # Validate test coverage requirements - if [ $TOTAL_TESTS -lt ${{ inputs.minimum-tests }} ]; then - echo "❌ Expected at least ${{ inputs.minimum-tests }} tests, found $TOTAL_TESTS" - exit 1 - fi - - if [ $FAILING_TESTS -gt 0 ]; then - echo "❌ Found $FAILING_TESTS failing tests" - exit 1 - fi - - echo "✅ Test coverage is acceptable: $PASSING_TESTS/$TOTAL_TESTS tests passing ($COVERAGE_PERCENT%)" - shell: bash diff --git a/.github/actions/test-grammar/action.yml b/.github/actions/test-grammar/action.yml deleted file mode 100644 index 945612e..0000000 --- a/.github/actions/test-grammar/action.yml +++ /dev/null @@ -1,77 +0,0 @@ ---- -name: "Test Tree-sitter Grammar" -description: "Runs comprehensive grammar tests including parser validation" - -inputs: - skip-sample-test: - description: "Skip the sample ShellSpec code test" - required: false - default: "false" - -runs: - using: "composite" - steps: - - name: Run Tests - run: npm test - shell: bash - - - name: Build Parser - run: npm run build - shell: bash - - - name: Test Parser with Sample Code - if: inputs.skip-sample-test != 'true' - run: | - cat << 'EOF' > test_sample.shellspec - #!/usr/bin/env shellspec - - Describe 'Calculator' - Include ./lib/calculator.sh - - Before 'setup_calculator' - After 'cleanup_calculator' - - Context 'when adding numbers' - It 'adds two positive numbers' - When call add 2 3 - The output should eq 5 - End - - It 'handles zero' - When call add 0 5 - The output should eq 5 - End - End - - Context 'when input is invalid' - Skip if "validation not implemented" ! command -v validate - - It 'handles empty input' - When call add "" "" - The status should be failure - End - End - End - - It 'works without describe block' - When call echo "test" - The output should eq "test" - End - EOF - - tree-sitter parse test_sample.shellspec --quiet || { - echo "❌ Parser failed on sample ShellSpec code" - exit 1 - } - echo "✅ Parser successfully handled sample code" - shell: bash - - - name: Validate Parser (Simple) - if: inputs.skip-sample-test == 'true' - run: | - echo "Describe 'test' It 'works' End End" | tree-sitter parse --language=shellspec || { - echo "❌ Parser validation failed" - exit 1 - } - echo "✅ Parser validation successful" - shell: bash diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml index 49f442e..e680e09 100644 --- a/.github/workflows/release.yml +++ b/.github/workflows/release.yml @@ -100,8 +100,17 @@ jobs: needs: validate steps: - - name: 🏗️ Setup Node.js Environment - uses: ./.github/actions/setup-node + - name: Checkout Repository + uses: actions/checkout@08c6903cd8c0fde910a37f88322edcfb5dd907a8 # v5.0.0 + + - name: Setup Node.js 24 + uses: actions/setup-node@7c12f8017d5436eb855f1ed4399f037a36fbd9e8 # v5.2.1 + with: + node-version: 24 + cache: npm + + - name: Install Dependencies + run: npm ci || { echo "❌ npm install failed"; npm install; } - name: 🔍 Run Security Audit run: npm audit --audit-level=high @@ -124,11 +133,21 @@ jobs: with: fetch-depth: 0 - - name: 🏗️ Setup Development Environment - uses: ./.github/actions/setup-dev + - name: Setup Node.js 24 + uses: actions/setup-node@7c12f8017d5436eb855f1ed4399f037a36fbd9e8 # v5.2.1 with: + node-version: 24 + cache: npm registry-url: "https://registry.npmjs.org" - skip-checkout: "true" + + - name: Install Dependencies + run: npm ci || { echo "❌ npm install failed"; npm install; } + + - name: Install Tree-sitter CLI + run: npm install -g tree-sitter-cli + + - name: Generate Grammar + run: npm run generate - name: 🏗️ Build Parser run: npm run build diff --git a/.github/workflows/test.yml b/.github/workflows/test.yml index b85fd90..7848da9 100644 --- a/.github/workflows/test.yml +++ b/.github/workflows/test.yml @@ -38,13 +38,73 @@ jobs: fail-fast: false steps: - - name: 🏗️ Setup Development Environment - uses: ./.github/actions/setup-dev + - name: Setup Node.js ${{ matrix.node-version }} + uses: actions/setup-node@7c12f8017d5436eb855f1ed4399f037a36fbd9e8 # v5.2.1 with: node-version: ${{ matrix.node-version }} + cache: npm - - name: 🧪 Test Grammar - uses: ./.github/actions/test-grammar + - name: Install Dependencies + run: npm ci || { echo "❌ npm install failed"; npm install; } + shell: bash + + - name: Install Tree-sitter CLI + run: npm install -g tree-sitter-cli + shell: bash + + - name: Generate Grammar + run: npm run generate + shell: bash + + - name: Build Parser + run: npm run build + shell: bash + + - name: Test Parser with Sample Code + run: | + cat << 'EOF' > test_sample.shellspec + #!/usr/bin/env shellspec + + Describe 'Calculator' + Include ./lib/calculator.sh + + Before 'setup_calculator' + After 'cleanup_calculator' + + Context 'when adding numbers' + It 'adds two positive numbers' + When call add 2 3 + The output should eq 5 + End + + It 'handles zero' + When call add 0 5 + The output should eq 5 + End + End + + Context 'when input is invalid' + Skip if "validation not implemented" ! command -v validate + + It 'handles empty input' + When call add "" "" + The status should be failure + End + End + End + + It 'works without describe block' + When call echo "test" + The output should eq "test" + End + EOF + + tree-sitter parse test_sample.shellspec --quiet || { + echo "❌ Parser failed on sample ShellSpec code" + exit 1 + } + echo "✅ Parser successfully handled sample code" + shell: bash lint: name: 🧹 Code Quality @@ -52,8 +112,18 @@ jobs: timeout-minutes: 15 steps: - - name: 🏗️ Setup Node.js Environment - uses: ./.github/actions/setup-node + - name: Checkout Repository + uses: actions/checkout@08c6903cd8c0fde910a37f88322edcfb5dd907a8 # v5.0.0 + + - name: Setup Node.js 24 + uses: actions/setup-node@7c12f8017d5436eb855f1ed4399f037a36fbd9e8 # v5.2.1 + with: + node-version: 24 + cache: npm + + - name: Install Dependencies + run: npm ci || { echo "❌ npm install failed"; npm install; } + shell: bash - name: 🧹 Run Linter uses: ivuorinen/actions/pr-lint@22e6add79fabcca4bf5761452a51e4fa0207e155 # 25.9.8 @@ -65,12 +135,65 @@ jobs: needs: test steps: - - name: 🏗️ Setup Development Environment - uses: ./.github/actions/setup-dev + - name: Checkout Repository + uses: actions/checkout@08c6903cd8c0fde910a37f88322edcfb5dd907a8 # v5.0.0 + + - name: Setup Node.js 24 + uses: actions/setup-node@7c12f8017d5436eb855f1ed4399f037a36fbd9e8 # v5.2.1 with: node-version: 24 + cache: npm - - name: 📊 Test Coverage Analysis - uses: ./.github/actions/test-coverage - with: - minimum-tests: 55 + - name: Test Coverage Analysis + id: coverage + run: | + echo "## Test Coverage Report" > coverage_report.md + echo "" >> coverage_report.md + + # Run tests and capture output + TEST_OUTPUT=$(npm test 2>&1) + TOTAL_TESTS=$(echo "$TEST_OUTPUT" | grep -cE "^\s+[0-9]+\.") + PASSING_TESTS=$(echo "$TEST_OUTPUT" | grep -cE "^\s+[0-9]+\. ✓") + FAILING_TESTS=$(echo "$TEST_OUTPUT" | grep -cE "^\s+[0-9]+\. ✗") + + { + echo "- **Total Tests:** $TOTAL_TESTS" + echo "- **Passing:** $PASSING_TESTS ✅" + echo "- **Failing:** $FAILING_TESTS ❌" + } >> coverage_report.md + + if [ "$TOTAL_TESTS" -gt 0 ]; then + COVERAGE_PERCENT=$(( (PASSING_TESTS * 100) / TOTAL_TESTS )) + echo "- **Coverage:** $COVERAGE_PERCENT%" >> coverage_report.md + else + COVERAGE_PERCENT=0 + fi + + { + echo "" + echo "### Test Files" + } >> coverage_report.md + echo "$TEST_OUTPUT" | grep -E "^\s+[a-z_]+:" | sed 's/^/- /' >> coverage_report.md + + cat coverage_report.md + + # Set outputs + { + echo "total-tests=$TOTAL_TESTS" + echo "passing-tests=$PASSING_TESTS" + echo "coverage-percent=$COVERAGE_PERCENT" + } >> "$GITHUB_OUTPUT" + + # Validate test coverage requirements + if [ "$TOTAL_TESTS" -lt 55 ]; then + echo "❌ Expected at least 55 tests, found $TOTAL_TESTS" + exit 1 + fi + + if [ "$FAILING_TESTS" -gt 0 ]; then + echo "❌ Found $FAILING_TESTS failing tests" + exit 1 + fi + + echo "✅ Test coverage is acceptable: $PASSING_TESTS/$TOTAL_TESTS tests passing ($COVERAGE_PERCENT%)" + shell: bash