From eb1c04bf18b5a4e4ade8fa803992699307fc8d88 Mon Sep 17 00:00:00 2001 From: Christoph Pirkl Date: Wed, 5 Aug 2026 06:22:22 +0200 Subject: [PATCH 1/2] Ignore bin folder --- .gitignore | 1 + 1 file changed, 1 insertion(+) diff --git a/.gitignore b/.gitignore index 8f1d0fe..21c7a23 100644 --- a/.gitignore +++ b/.gitignore @@ -14,3 +14,4 @@ /build/ /server/build/ /.settings/org.eclipse.buildship.core.prefs +/server/bin/ From c24b4899fb1633a956e8b31eebf95e03f91a7544 Mon Sep 17 00:00:00 2001 From: Christoph Pirkl Date: Wed, 5 Aug 2026 06:32:02 +0200 Subject: [PATCH 2/2] Integrate extension build into gradle --- .github/workflows/build.yml | 14 +------- doc/design.md | 10 ++++-- doc/developer_guide.md | 30 ++++++++++++++++ extension/build.gradle | 68 +++++++++++++++++++++++++++++++++++++ 4 files changed, 106 insertions(+), 16 deletions(-) create mode 100644 extension/build.gradle diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml index 4583c5b..f9e0f9e 100644 --- a/.github/workflows/build.yml +++ b/.github/workflows/build.yml @@ -55,21 +55,9 @@ jobs: path: extension/.vscode-test/ key: ${{ runner.os }}-vscode-test-${{ hashFiles('extension/package-lock.json') }} - - name: Build server + - name: Build and test run: ./gradlew build --info - - name: Install dependencies - run: cd extension && npm ci --ignore-scripts - - - name: Lint - run: cd extension && npm run lint - - - name: Run unit tests - run: cd extension && npm run test:unit - - - name: Run integration tests - run: cd extension && xvfb-run -a npm run test:integration - - name: SonarQube Scan if: ${{ env.DEFAULT_OS == matrix.os }} env: diff --git a/doc/design.md b/doc/design.md index 66e7b5b..4dd900e 100644 --- a/doc/design.md +++ b/doc/design.md @@ -27,9 +27,13 @@ material advantage for this standalone, standard-protocol server. The server is a Gradle project using the Groovy DSL and the `application` plugin. Gradle produces the runnable distribution that the VS Code extension -launches. The server targets Java 21. The OpenFastTrace Gradle plugin runs the -requirements trace as an independent verification task and does not define the -language-server build. +launches. The server targets Java 21. The VS Code extension is also a Gradle +subproject: its lifecycle tasks install locked Node.js dependencies, compile, +lint, and test the TypeScript adapter. When available, extension integration +tests run under Xvfb; otherwise they run directly. Consequently, `./gradlew +build` verifies both the server and extension. The OpenFastTrace Gradle plugin +runs the requirements trace as an independent verification task and does not +define the language-server build. VS Code extensions execute in a Node.js extension host and do not receive a Java runtime from VS Code. The extension therefore obtains a Java 21 runtime diff --git a/doc/developer_guide.md b/doc/developer_guide.md index 6c3bd35..2f94fbc 100644 --- a/doc/developer_guide.md +++ b/doc/developer_guide.md @@ -1,5 +1,35 @@ # Developer Guide +## Build And Test + +Prerequisites: + +* Java 21 +* Node.js 24 and its bundled `npm` +* On Linux, `xvfb-run` is optional and enables headless VS Code integration + tests + +Build and test the complete server and extension with one command: + +```sh +./gradlew build +``` + +The `extension` Gradle subproject installs locked Node.js dependencies with +`npm ci --ignore-scripts`, then compiles, lints, and tests the extension. Use +these focused tasks when needed: + +```sh +./gradlew :extension:compileExtension +./gradlew :extension:lintExtension +./gradlew :extension:unitTestExtension +./gradlew :extension:integrationTestExtension +``` + +When `xvfb-run` is available, `integrationTestExtension` launches the VS Code +test runtime through `xvfb-run -a`; otherwise it invokes the npm +integration-test script directly. + ## Trace Requirements Run the current MVP requirements trace locally with Java 17 or later: diff --git a/extension/build.gradle b/extension/build.gradle new file mode 100644 index 0000000..969c258 --- /dev/null +++ b/extension/build.gradle @@ -0,0 +1,68 @@ +plugins { + id 'base' +} + +def npmCommand = System.getProperty('os.name').toLowerCase().contains('windows') ? 'npm.cmd' : 'npm' +def isLinux = System.getProperty('os.name').toLowerCase().contains('linux') +def xvfbRun = isLinux ? System.getenv('PATH').split(File.pathSeparator) + .collect { new File(it, 'xvfb-run') } + .find { it.canExecute() } : null + +def npmInstall = tasks.register('npmInstall', Exec) { + group = 'build setup' + description = 'Installs the extension Node.js dependencies.' + commandLine npmCommand, 'ci', '--ignore-scripts' + inputs.files('package.json', 'package-lock.json') + outputs.dir('node_modules') +} + +def compileExtension = tasks.register('compileExtension', Exec) { + group = 'build' + description = 'Compiles the VS Code extension.' + dependsOn npmInstall + commandLine npmCommand, 'run', 'compile' + inputs.files('package.json', 'tsconfig.json') + inputs.dir('src') + outputs.dir('out') +} + +def lintExtension = tasks.register('lintExtension', Exec) { + group = 'verification' + description = 'Lints the VS Code extension.' + dependsOn npmInstall + commandLine npmCommand, 'run', 'lint' + inputs.files('package.json', 'eslint.config.mjs', 'tsconfig.json') + inputs.dir('src') +} + +def unitTestExtension = tasks.register('unitTestExtension', Exec) { + group = 'verification' + description = 'Runs the VS Code extension unit tests.' + dependsOn compileExtension + commandLine npmCommand, 'run', 'test:unit' + inputs.files('package.json', 'tsconfig.json') + inputs.dir('src') + outputs.file('coverage/unit.lcov') +} + +def integrationTestExtension = tasks.register('integrationTestExtension', Exec) { + group = 'verification' + description = 'Runs the VS Code extension integration tests.' + dependsOn compileExtension + if (xvfbRun) { + commandLine xvfbRun.absolutePath, '-a', npmCommand, 'run', 'test:integration' + } else { + commandLine npmCommand, 'run', 'test:integration' + } + inputs.files('package.json', 'tsconfig.json') + inputs.dir('src') + outputs.dir('coverage/integration') +} + +tasks.named('assemble') { + dependsOn compileExtension +} + +tasks.named('check') { + dependsOn lintExtension, unitTestExtension, integrationTestExtension +}