--- # yaml-language-server: $schema=https://json.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 }} cache: npm - 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 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 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 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 cache: npm - 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