mirror of
https://github.com/ivuorinen/tree-sitter-shellspec.git
synced 2026-01-26 11:43:59 +00:00
- Add explicit parser build step before sample code testing - Remove --scope parameter that requires parser to be compiled first - Fix tree-sitter CLI v0.25.0 compatibility issue in CI environment The issue was that tree-sitter CLI v0.25.0 requires the parser to be compiled before it can recognize custom language scopes. This fix ensures the parser is always built before attempting to parse test files, resolving the 'Unknown scope' error in GitHub Actions.
251 lines
7.7 KiB
YAML
251 lines
7.7 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: |
|
|
# Ensure parser is built
|
|
npm run build
|
|
|
|
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 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
|