|
| 1 | +# SPDX-License-Identifier: PMPL-1.0-or-later |
| 2 | +# lsp-dap-bsp.yml — Dedicated CI for Language Server, Debug Adapter, and Build Server cartridges |
| 3 | +# Validates ABI specs, FFI builds, adapter compilation, and panel manifests |
| 4 | +# for the three protocol cartridges (lsp-mcp, dap-mcp, bsp-mcp). |
| 5 | + |
| 6 | +name: LSP/DAP/BSP CI |
| 7 | + |
| 8 | +on: |
| 9 | + push: |
| 10 | + paths: |
| 11 | + - 'cartridges/lsp-mcp/**' |
| 12 | + - 'cartridges/dap-mcp/**' |
| 13 | + - 'cartridges/bsp-mcp/**' |
| 14 | + - 'src/abi/Boj/Protocol.idr' |
| 15 | + - '.github/workflows/lsp-dap-bsp.yml' |
| 16 | + pull_request: |
| 17 | + paths: |
| 18 | + - 'cartridges/lsp-mcp/**' |
| 19 | + - 'cartridges/dap-mcp/**' |
| 20 | + - 'cartridges/bsp-mcp/**' |
| 21 | + |
| 22 | +permissions: read-all |
| 23 | + |
| 24 | +jobs: |
| 25 | + abi-check: |
| 26 | + name: ABI Specification Check (Idris2) |
| 27 | + runs-on: ubuntu-latest |
| 28 | + steps: |
| 29 | + - uses: actions/checkout@93cb6efe18208431cddfb8368fd83d5badbf9bfd # v5 |
| 30 | + - name: Validate ABI modules exist |
| 31 | + run: | |
| 32 | + echo "=== Checking LSP/DAP/BSP ABI modules ===" |
| 33 | + for cart in lsp-mcp dap-mcp bsp-mcp; do |
| 34 | + echo "--- $cart ---" |
| 35 | + abi_dir="cartridges/$cart/abi" |
| 36 | + if [ ! -d "$abi_dir" ]; then |
| 37 | + echo "ERROR: $abi_dir directory missing" |
| 38 | + exit 1 |
| 39 | + fi |
| 40 | + idr_count=$(find "$abi_dir" -name '*.idr' | wc -l) |
| 41 | + echo " Found $idr_count .idr files" |
| 42 | + if [ "$idr_count" -eq 0 ]; then |
| 43 | + echo "ERROR: No .idr files in $abi_dir" |
| 44 | + exit 1 |
| 45 | + fi |
| 46 | + # Check for banned patterns |
| 47 | + if grep -r 'believe_me\|assert_total\|sorry' "$abi_dir" 2>/dev/null; then |
| 48 | + echo "ERROR: Banned pattern found in $abi_dir" |
| 49 | + exit 1 |
| 50 | + fi |
| 51 | + echo " No banned patterns — OK" |
| 52 | + done |
| 53 | +
|
| 54 | + ffi-build: |
| 55 | + name: FFI Build & Test (Zig) |
| 56 | + runs-on: ubuntu-latest |
| 57 | + steps: |
| 58 | + - uses: actions/checkout@93cb6efe18208431cddfb8368fd83d5badbf9bfd # v5 |
| 59 | + - name: Install Zig 0.15.2 |
| 60 | + run: | |
| 61 | + curl -L https://ziglang.org/builds/zig-linux-x86_64-0.15.2.tar.xz | tar -xJ |
| 62 | + echo "$PWD/zig-linux-x86_64-0.15.2" >> "$GITHUB_PATH" |
| 63 | + - name: Build LSP/DAP/BSP cartridge FFI |
| 64 | + run: | |
| 65 | + for cart in lsp-mcp dap-mcp bsp-mcp; do |
| 66 | + echo "=== Building $cart FFI ===" |
| 67 | + ffi_dir="cartridges/$cart/ffi" |
| 68 | + if [ ! -f "$ffi_dir/build.zig" ]; then |
| 69 | + echo "ERROR: $ffi_dir/build.zig missing" |
| 70 | + exit 1 |
| 71 | + fi |
| 72 | + cd "$ffi_dir" |
| 73 | + zig build 2>&1 || { echo "ERROR: Zig build failed for $cart"; exit 1; } |
| 74 | + echo " Build succeeded" |
| 75 | + # Check .so output exists |
| 76 | + so_file=$(find zig-out/lib/ -name '*.so' 2>/dev/null | head -1) |
| 77 | + if [ -n "$so_file" ]; then |
| 78 | + echo " Shared library: $so_file" |
| 79 | + else |
| 80 | + echo " WARNING: No .so output (may be static-only)" |
| 81 | + fi |
| 82 | + cd "$GITHUB_WORKSPACE" |
| 83 | + done |
| 84 | + - name: Run FFI tests |
| 85 | + run: | |
| 86 | + for cart in lsp-mcp dap-mcp bsp-mcp; do |
| 87 | + echo "=== Testing $cart FFI ===" |
| 88 | + cd "cartridges/$cart/ffi" |
| 89 | + zig build test 2>&1 || { echo "ERROR: Tests failed for $cart"; exit 1; } |
| 90 | + echo " Tests passed" |
| 91 | + cd "$GITHUB_WORKSPACE" |
| 92 | + done |
| 93 | +
|
| 94 | + adapter-check: |
| 95 | + name: V-lang Adapter Check |
| 96 | + runs-on: ubuntu-latest |
| 97 | + steps: |
| 98 | + - uses: actions/checkout@93cb6efe18208431cddfb8368fd83d5badbf9bfd # v5 |
| 99 | + - name: Install V-lang |
| 100 | + run: | |
| 101 | + sudo apt-get update && sudo apt-get install -y libgc-dev |
| 102 | + git clone --depth=1 https://github.com/vlang/v |
| 103 | + cd v && make && sudo ./v symlink |
| 104 | + - name: Check LSP/DAP/BSP adapters |
| 105 | + run: | |
| 106 | + for cart in lsp-mcp dap-mcp bsp-mcp; do |
| 107 | + echo "=== Checking $cart adapter ===" |
| 108 | + adapter_dir="cartridges/$cart/adapter" |
| 109 | + if [ ! -d "$adapter_dir" ]; then |
| 110 | + echo "ERROR: $adapter_dir missing" |
| 111 | + exit 1 |
| 112 | + fi |
| 113 | + v_files=$(find "$adapter_dir" -name '*.v' | wc -l) |
| 114 | + if [ "$v_files" -eq 0 ]; then |
| 115 | + echo "ERROR: No .v files in $adapter_dir" |
| 116 | + exit 1 |
| 117 | + fi |
| 118 | + v check "$adapter_dir"/*.v 2>&1 || { echo "ERROR: V check failed for $cart"; exit 1; } |
| 119 | + echo " V-lang check passed ($v_files files)" |
| 120 | + done |
| 121 | +
|
| 122 | + panel-validation: |
| 123 | + name: Panel Manifest Validation |
| 124 | + runs-on: ubuntu-latest |
| 125 | + steps: |
| 126 | + - uses: actions/checkout@93cb6efe18208431cddfb8368fd83d5badbf9bfd # v5 |
| 127 | + - name: Validate LSP/DAP/BSP panel manifests |
| 128 | + run: | |
| 129 | + for cart in lsp-mcp dap-mcp bsp-mcp; do |
| 130 | + echo "=== Validating $cart panel manifest ===" |
| 131 | + manifest="cartridges/$cart/panels/manifest.json" |
| 132 | + if [ ! -f "$manifest" ]; then |
| 133 | + echo "ERROR: $manifest missing" |
| 134 | + exit 1 |
| 135 | + fi |
| 136 | + # Validate JSON |
| 137 | + python3 -m json.tool "$manifest" > /dev/null 2>&1 || { |
| 138 | + echo "ERROR: Invalid JSON in $manifest" |
| 139 | + exit 1 |
| 140 | + } |
| 141 | + # Check required fields |
| 142 | + for field in cartridge domain version panels; do |
| 143 | + if ! python3 -c "import json; d=json.load(open('$manifest')); assert '$field' in d" 2>/dev/null; then |
| 144 | + echo "ERROR: Missing field '$field' in $manifest" |
| 145 | + exit 1 |
| 146 | + fi |
| 147 | + done |
| 148 | + # Count panels |
| 149 | + panel_count=$(python3 -c "import json; print(len(json.load(open('$manifest'))['panels']))") |
| 150 | + echo " Valid JSON, $panel_count panels defined" |
| 151 | + done |
| 152 | +
|
| 153 | + completeness: |
| 154 | + name: Cartridge Completeness Check |
| 155 | + runs-on: ubuntu-latest |
| 156 | + needs: [abi-check, ffi-build, adapter-check, panel-validation] |
| 157 | + steps: |
| 158 | + - uses: actions/checkout@93cb6efe18208431cddfb8368fd83d5badbf9bfd # v5 |
| 159 | + - name: Verify triadic structure |
| 160 | + run: | |
| 161 | + echo "=== LSP/DAP/BSP Triadic Structure Audit ===" |
| 162 | + all_pass=true |
| 163 | + for cart in lsp-mcp dap-mcp bsp-mcp; do |
| 164 | + echo "--- $cart ---" |
| 165 | + layers=("abi" "ffi" "adapter" "panels") |
| 166 | + for layer in "${layers[@]}"; do |
| 167 | + dir="cartridges/$cart/$layer" |
| 168 | + if [ -d "$dir" ]; then |
| 169 | + echo " ✓ $layer/" |
| 170 | + else |
| 171 | + echo " ✗ $layer/ MISSING" |
| 172 | + all_pass=false |
| 173 | + fi |
| 174 | + done |
| 175 | + done |
| 176 | + if [ "$all_pass" != "true" ]; then |
| 177 | + echo "ERROR: Incomplete triadic structure" |
| 178 | + exit 1 |
| 179 | + fi |
| 180 | + echo "" |
| 181 | + echo "All 3 protocol cartridges have complete ABI+FFI+Adapter+Panel stacks." |
0 commit comments