mirror of
https://github.com/ivuorinen/tree-sitter-shellspec.git
synced 2026-01-26 11:43:59 +00:00
- Convert GitHub Actions from local to inline actions for better maintainability - Add comprehensive caching for npm dependencies, tree-sitter CLI, and build artifacts - Fix checkout steps missing in test matrix jobs - Apply defensive programming in test coverage validation - Use local tree-sitter CLI via npx instead of global installation - Update tree-sitter-cli to v0.25.0 for compatibility with tree-sitter-bash - Add proper tree-sitter field to package.json with grammar metadata - Fix grammar precedence for Data blocks (#| lines now have higher precedence) - Standardize dates in memory files to September 12, 2025 - Enhance workflow robustness with dynamic workflow ID resolution - Improve test file pattern matching and error handling This commit addresses all CodeRabbit review suggestions and optimizes GitHub Actions workflows for better performance and reliability.
248 lines
7.6 KiB
YAML
248 lines
7.6 KiB
YAML
---
|
|
# yaml-language-server: $schema=https://www.schemastore.org/github-workflow.json
|
|
name: CI
|
|
|
|
on:
|
|
push:
|
|
branches: [main, master]
|
|
pull_request:
|
|
branches: [main, master]
|
|
merge_group:
|
|
|
|
concurrency:
|
|
group: ${{ github.workflow }}-${{ github.ref }}
|
|
cancel-in-progress: true
|
|
|
|
permissions: read-all
|
|
|
|
jobs:
|
|
test:
|
|
name: 🧪 Test Suite
|
|
runs-on: ubuntu-latest
|
|
timeout-minutes: 15
|
|
|
|
strategy:
|
|
matrix:
|
|
node-version: [22, 24]
|
|
fail-fast: false
|
|
|
|
steps:
|
|
- name: Checkout Repository
|
|
uses: actions/checkout@08c6903cd8c0fde910a37f88322edcfb5dd907a8 # v5.0.0
|
|
|
|
- name: Setup Node.js ${{ matrix.node-version }}
|
|
uses: actions/setup-node@7c12f8017d5436eb855f1ed4399f037a36fbd9e8 # v5.2.1
|
|
with:
|
|
node-version: ${{ matrix.node-version }}
|
|
|
|
- name: Cache Node.js dependencies
|
|
uses: actions/cache@0400d5f644dc74513175e3cd8d07132dd4860809 # v4.2.4
|
|
id: cache-npm
|
|
with:
|
|
path: ~/.npm
|
|
key: ${{ runner.os }}-node-${{ matrix.node-version }}-${{ hashFiles('**/package-lock.json') }}
|
|
restore-keys: |
|
|
${{ runner.os }}-node-${{ matrix.node-version }}-
|
|
${{ runner.os }}-node-
|
|
|
|
- name: Install Dependencies
|
|
run: npm ci || { echo "❌ npm install failed"; npm install; }
|
|
shell: bash
|
|
|
|
- name: Cache Tree-sitter CLI
|
|
uses: actions/cache@0400d5f644dc74513175e3cd8d07132dd4860809 # v4.2.4
|
|
id: cache-tree-sitter
|
|
with:
|
|
path: ~/.npm/_npx
|
|
key: ${{ runner.os }}-tree-sitter-cli-${{ hashFiles('package.json') }}
|
|
|
|
- name: Cache Generated Grammar
|
|
uses: actions/cache@0400d5f644dc74513175e3cd8d07132dd4860809 # v4.2.4
|
|
id: cache-grammar
|
|
with:
|
|
path: |
|
|
src/parser.c
|
|
src/tree_sitter/
|
|
binding.gyp
|
|
key: ${{ runner.os }}-grammar-${{ hashFiles('grammar.js', 'package.json') }}
|
|
|
|
- name: Generate Grammar
|
|
if: steps.cache-grammar.outputs.cache-hit != 'true'
|
|
run: npm run generate
|
|
shell: bash
|
|
|
|
- name: Cache Built Parser
|
|
uses: actions/cache@0400d5f644dc74513175e3cd8d07132dd4860809 # v4.2.4
|
|
id: cache-parser
|
|
with:
|
|
path: |
|
|
build/
|
|
node_modules/
|
|
key: ${{ runner.os }}-parser-${{ matrix.node-version }}-${{ hashFiles('src/parser.c', 'binding.gyp', 'package.json') }}
|
|
|
|
- name: Build Parser
|
|
if: steps.cache-parser.outputs.cache-hit != 'true'
|
|
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
|
|
|
|
npx tree-sitter parse --language=shellspec 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
|
|
runs-on: ubuntu-latest
|
|
timeout-minutes: 15
|
|
|
|
steps:
|
|
- 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
|
|
|
|
- name: Cache Node.js dependencies
|
|
uses: actions/cache@0400d5f644dc74513175e3cd8d07132dd4860809 # v4.2.4
|
|
with:
|
|
path: ~/.npm
|
|
key: ${{ runner.os }}-node-24-${{ hashFiles('**/package-lock.json') }}
|
|
restore-keys: |
|
|
${{ runner.os }}-node-24-
|
|
${{ runner.os }}-node-
|
|
|
|
- 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
|
|
|
|
coverage:
|
|
name: 📊 Test Coverage
|
|
runs-on: ubuntu-latest
|
|
timeout-minutes: 15
|
|
needs: test
|
|
|
|
steps:
|
|
- 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
|
|
|
|
- name: Cache Node.js dependencies
|
|
uses: actions/cache@0400d5f644dc74513175e3cd8d07132dd4860809 # v4.2.4
|
|
with:
|
|
path: ~/.npm
|
|
key: ${{ runner.os }}-node-24-${{ hashFiles('**/package-lock.json') }}
|
|
restore-keys: |
|
|
${{ runner.os }}-node-24-
|
|
${{ runner.os }}-node-
|
|
|
|
- name: Install Dependencies
|
|
run: npm ci || { echo "❌ npm install failed"; npm install; }
|
|
|
|
- name: Test Coverage Analysis
|
|
id: coverage
|
|
run: |
|
|
echo "## Test Coverage Report" > coverage_report.md
|
|
echo "" >> coverage_report.md
|
|
|
|
# Run tests and capture output with exit code
|
|
set +e # Don't exit on test failure
|
|
TEST_OUTPUT=$(npm test 2>&1)
|
|
TEST_EXIT=$?
|
|
set -e # Re-enable exit on error
|
|
|
|
TOTAL_TESTS=$(echo "$TEST_OUTPUT" | grep -cE "^\s+[0-9]+\." || echo "0")
|
|
PASSING_TESTS=$(echo "$TEST_OUTPUT" | grep -cE "^\s+[0-9]+\. ✓" || echo "0")
|
|
FAILING_TESTS=$(echo "$TEST_OUTPUT" | grep -cE "^\s+[0-9]+\. ✗" || echo "0")
|
|
|
|
{
|
|
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 "^[[:space:]]+[A-Za-z0-9._/\\-]+:" | 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:-0}" -lt 55 ]; then
|
|
echo "❌ Expected at least 55 tests, found ${TOTAL_TESTS:-0}"
|
|
exit 1
|
|
fi
|
|
|
|
if [ "${FAILING_TESTS:-0}" -gt 0 ] || [ "$TEST_EXIT" -ne 0 ]; then
|
|
echo "❌ Found ${FAILING_TESTS:-0} failing tests or test runner failed (exit code: $TEST_EXIT)"
|
|
exit 1
|
|
fi
|
|
|
|
echo "✅ Test coverage is acceptable: $PASSING_TESTS/$TOTAL_TESTS tests passing ($COVERAGE_PERCENT%)"
|
|
shell: bash
|