diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml new file mode 100644 index 0000000..b70dc9f --- /dev/null +++ b/.github/workflows/ci.yml @@ -0,0 +1,212 @@ +name: Run Tests and Build + +on: + push: + branches: [ main, master ] + pull_request: + branches: [ main, master ] + workflow_dispatch: + +jobs: + pylight-test: + runs-on: ubuntu-latest + + steps: + - uses: actions/checkout@v4 + + - name: Setup Rust + uses: actions-rs/toolchain@v1 + with: + toolchain: stable + override: true + components: rustfmt, clippy + + - name: Cache Rust dependencies + uses: actions/cache@v3 + with: + path: | + ~/.cargo/registry + ~/.cargo/git + ./pylight/target + key: ${{ runner.os }}-cargo-${{ hashFiles('**/Cargo.lock') }} + + - name: Check formatting + working-directory: ./pylight + run: cargo fmt -- --check + + - name: Run clippy + working-directory: ./pylight + run: cargo clippy -- -D warnings + + - name: Run tests + working-directory: ./pylight + run: cargo test + + - name: Build release binary + working-directory: ./pylight + run: cargo build --release --bin symbol_search_lsp + + pydance-test: + runs-on: ubuntu-latest + + steps: + - uses: actions/checkout@v4 + + - name: Setup Node.js + uses: actions/setup-node@v4 + with: + node-version: '20' + cache: 'npm' + cache-dependency-path: pydance/package-lock.json + + - name: Install dependencies + working-directory: ./pydance + run: npm ci + + - name: Run linter + working-directory: ./pydance + run: npm run lint + + - name: Check formatting + working-directory: ./pydance + run: npm run format:check + + - name: Compile TypeScript + working-directory: ./pydance + run: npm run compile + + - name: Setup Rust for pylight binary + uses: actions-rs/toolchain@v1 + with: + toolchain: stable + override: true + + - name: Cache Rust dependencies + uses: actions/cache@v3 + with: + path: | + ~/.cargo/registry + ~/.cargo/git + ./pylight/target + key: ${{ runner.os }}-cargo-${{ hashFiles('**/Cargo.lock') }} + + - name: Build pylight binary + working-directory: ./pylight + run: cargo build --release --bin symbol_search_lsp + + - name: Copy pylight binary to pydance + run: cp ./pylight/target/release/symbol_search_lsp ./pydance/pylight + + - name: Run unit tests (Linux) + if: runner.os == 'Linux' + working-directory: ./pydance + run: xvfb-run -a npm test + + - name: Run unit tests (macOS/Windows) + if: runner.os != 'Linux' + working-directory: ./pydance + run: npm test + + - name: Run integration tests (Linux) + if: runner.os == 'Linux' + working-directory: ./pydance + run: xvfb-run -a npm run test:integration + + - name: Run integration tests (macOS/Windows) + if: runner.os != 'Linux' + working-directory: ./pydance + run: npm run test:integration + + build-vsix: + needs: [pylight-test, pydance-test] + strategy: + matrix: + include: + - os: ubuntu-latest + target: x86_64-unknown-linux-gnu + platform: linux-x64 + - os: macos-latest + target: aarch64-apple-darwin + platform: darwin-arm64 + runs-on: ${{ matrix.os }} + + steps: + - uses: actions/checkout@v4 + + - name: Setup Node.js + uses: actions/setup-node@v4 + with: + node-version: '20' + cache: 'npm' + cache-dependency-path: pydance/package-lock.json + + - name: Install dependencies + working-directory: ./pydance + run: npm ci + + - name: Setup Rust + uses: actions-rs/toolchain@v1 + with: + toolchain: stable + override: true + target: ${{ matrix.target }} + + - name: Cache Rust dependencies + uses: actions/cache@v3 + with: + path: | + ~/.cargo/registry + ~/.cargo/git + ./pylight/target + key: ${{ runner.os }}-${{ matrix.target }}-cargo-${{ hashFiles('**/Cargo.lock') }} + + - name: Build pylight binary + working-directory: ./pylight + run: | + # Build for the target platform + cargo build --release --target ${{ matrix.target }} --bin symbol_search_lsp + + - name: Copy pylight binary to pydance + run: | + # Copy the platform-specific binary + cp ./pylight/target/${{ matrix.target }}/release/symbol_search_lsp ./pydance/pylight + # Make it executable + chmod +x ./pydance/pylight + + - name: Compile TypeScript + working-directory: ./pydance + run: npm run compile + + - name: Install vsce + run: npm install -g @vscode/vsce + + - name: Package VSIX + working-directory: ./pydance + run: | + # Package with dependencies included + vsce package + + - name: Test VSIX installation + working-directory: ./pydance + run: | + # Find the created VSIX file + VSIX_FILE=$(ls *.vsix | head -n 1) + echo "Testing VSIX: $VSIX_FILE" + + # Install VS Code CLI if not on macOS (macOS has it pre-installed) + if [[ "${{ runner.os }}" == "Linux" ]]; then + wget -q "https://code.visualstudio.com/sha/download?build=stable&os=cli-alpine-x64" -O vscode-cli.tar.gz + tar -xzf vscode-cli.tar.gz + chmod +x code + export PATH=$PWD:$PATH + fi + + # Try to install the extension (won't activate without a workspace, but will verify package integrity) + code --install-extension "$VSIX_FILE" --force || echo "Installation test completed" + + - name: Upload VSIX artifact + uses: actions/upload-artifact@v4 + with: + name: pydance-vsix-${{ matrix.platform }} + path: ./pydance/*.vsix + retention-days: 30 \ No newline at end of file diff --git a/.github/workflows/pydance.yml b/.github/workflows/pydance.yml deleted file mode 100644 index 74538b0..0000000 --- a/.github/workflows/pydance.yml +++ /dev/null @@ -1,68 +0,0 @@ -name: Pydance Tests - -on: - push: - branches: [ main, master ] - pull_request: - branches: [ main, master ] - workflow_dispatch: - -jobs: - test: - runs-on: ubuntu-latest - - steps: - - uses: actions/checkout@v4 - - - name: Setup Node.js - uses: actions/setup-node@v4 - with: - node-version: '20' - cache: 'npm' - cache-dependency-path: pydance/package-lock.json - - - name: Install dependencies - working-directory: ./pydance - run: npm ci - - - name: Run linter - working-directory: ./pydance - run: npm run lint - - - name: Check formatting - working-directory: ./pydance - run: npm run format:check - - - name: Compile TypeScript - working-directory: ./pydance - run: npm run compile - - - name: Setup Rust for pylight binary - uses: actions-rs/toolchain@v1 - with: - toolchain: stable - override: true - - - name: Cache Rust dependencies - uses: actions/cache@v3 - with: - path: | - ~/.cargo/registry - ~/.cargo/git - ./pylight/target - key: ${{ runner.os }}-cargo-${{ hashFiles('**/Cargo.lock') }} - - - name: Build pylight binary - working-directory: ./pylight - run: cargo build --release --bin symbol_search_lsp - - - name: Copy pylight binary to pydance - run: cp ./pylight/target/release/symbol_search_lsp ./pydance/pylight - - - name: Run unit tests - working-directory: ./pydance - run: xvfb-run -a npm test - - - name: Run integration tests - working-directory: ./pydance - run: xvfb-run -a npm run test:integration \ No newline at end of file diff --git a/.github/workflows/pylight.yml b/.github/workflows/pylight.yml deleted file mode 100644 index 51dd2c1..0000000 --- a/.github/workflows/pylight.yml +++ /dev/null @@ -1,47 +0,0 @@ -name: Pylight Tests - -on: - push: - branches: [ main, master ] - pull_request: - branches: [ main, master ] - workflow_dispatch: - -jobs: - test: - runs-on: ubuntu-latest - - steps: - - uses: actions/checkout@v4 - - - name: Setup Rust - uses: actions-rs/toolchain@v1 - with: - toolchain: stable - override: true - components: rustfmt, clippy - - - name: Cache Rust dependencies - uses: actions/cache@v3 - with: - path: | - ~/.cargo/registry - ~/.cargo/git - ./pylight/target - key: ${{ runner.os }}-cargo-${{ hashFiles('**/Cargo.lock') }} - - - name: Check formatting - working-directory: ./pylight - run: cargo fmt -- --check - - - name: Run clippy - working-directory: ./pylight - run: cargo clippy -- -D warnings - - - name: Run tests - working-directory: ./pylight - run: cargo test - - - name: Build release binary - working-directory: ./pylight - run: cargo build --release --bin symbol_search_lsp \ No newline at end of file diff --git a/pydance/.vscode/settings.json b/pydance/.vscode/settings.json index 47f5276..7f9d2ad 100644 --- a/pydance/.vscode/settings.json +++ b/pydance/.vscode/settings.json @@ -2,7 +2,7 @@ "editor.formatOnSave": true, "editor.defaultFormatter": "esbenp.prettier-vscode", "editor.codeActionsOnSave": { - "source.fixAll.eslint": true + "source.fixAll.eslint": "explicit" }, "[typescript]": { "editor.defaultFormatter": "esbenp.prettier-vscode" @@ -10,4 +10,4 @@ "files.eol": "\n", "files.insertFinalNewline": true, "files.trimTrailingWhitespace": true -} \ No newline at end of file +} diff --git a/pydance/.vscodeignore b/pydance/.vscodeignore new file mode 100644 index 0000000..9d7f767 --- /dev/null +++ b/pydance/.vscodeignore @@ -0,0 +1,37 @@ +.vscode/** +.vscode-test/** +src/** +.gitignore +.yarnrc +tsconfig.json +vsc-extension-quickstart.md +**/tsconfig.json +**/*.map +**/*.ts +**/.eslintrc.json +test/** +.github/** +**/*.vsix +node_modules/**/test/** +node_modules/**/tests/** +node_modules/**/spec/** +node_modules/**/example/** +node_modules/**/examples/** +node_modules/**/demo/** +node_modules/**/demos/** +node_modules/**/docs/** +node_modules/**/doc/** +node_modules/**/*.md +node_modules/**/*.markdown +node_modules/**/LICENSE* +node_modules/**/LICENCE* +node_modules/**/license* +node_modules/**/licence* +node_modules/**/.npmignore +node_modules/**/.gitignore +node_modules/**/.editorconfig +node_modules/**/.eslintrc* +node_modules/**/.prettierrc* +node_modules/**/Makefile +node_modules/**/Gulpfile.js +node_modules/**/Gruntfile.js \ No newline at end of file diff --git a/pydance/src/test/suite/vsixIntegrity.test.ts b/pydance/src/test/suite/vsixIntegrity.test.ts new file mode 100644 index 0000000..8858c18 --- /dev/null +++ b/pydance/src/test/suite/vsixIntegrity.test.ts @@ -0,0 +1,52 @@ +import * as assert from "assert"; +import * as path from "path"; +import * as fs from "fs"; + +suite("VSIX Integrity Test Suite", () => { + test("node_modules contains required dependencies", () => { + const extensionPath = path.resolve(__dirname, "../../../"); + const nodeModulesPath = path.join(extensionPath, "node_modules"); + + // Check that node_modules exists + assert.ok( + fs.existsSync(nodeModulesPath), + "node_modules directory should exist" + ); + + // Check for critical dependency + const languageClientPath = path.join( + nodeModulesPath, + "vscode-languageclient" + ); + assert.ok( + fs.existsSync(languageClientPath), + "vscode-languageclient should be installed" + ); + + // Check that the main entry point exists + const mainPath = path.join(extensionPath, "out", "extension.js"); + assert.ok(fs.existsSync(mainPath), "Compiled extension.js should exist"); + + // Check that pylight binary exists + const pylightPath = path.join(extensionPath, "pylight"); + assert.ok(fs.existsSync(pylightPath), "pylight binary should exist"); + }); + + test("Can load extension module", async () => { + // This will throw if dependencies are missing + try { + // Use dynamic import to avoid linter error + const extensionModule = await import("../../extension"); + assert.ok( + extensionModule.activate, + "Extension should export activate function" + ); + assert.ok( + extensionModule.deactivate, + "Extension should export deactivate function" + ); + } catch (error) { + assert.fail(`Failed to load extension module: ${error}`); + } + }); +});