Developer Guide
December 19, 2025 ยท View on GitHub
This guide describes how to develop, test and build Extension Manager (EM).
If you want to embed EM into another application, see the embedding guide. If you want to develop an extension for EM, see the extension developer guide.
Extension Manager
This project uses a mix of different languages and build tools / helpers, so please read the instructions carefully.
Project Keeper and Release Droid
For Java and Go dependency management and documentation this project uses Project Keeper (PK). On the other hand it also uses Release Droid (RD) to create the release. RD is deprecated and will be replaced once PK can handle the complex project setup used in this project.
Updating the Dependency Documentation and Change Log
In this project you cannot run project keeper directly from the main directory like you are used to. Instead, please run the shell script that is also used in the GitHub action:
To verify the current project:
.github/workflows/project-keeper.sh verify
To automatically fix it:
.github/workflows/project-keeper.sh fix
Building
To build the binary, run
go generate ./...
go build -o extension-manager cmd/main.go
To run the extension manager, execute
# Show supported command line arguments
go run cmd/main.go -h
# Start server with custom extension registry
go run cmd/main.go -serverAddress localhost:8080 -extensionRegistryURL /path/to/extensions/
After starting the server you can get the OpenApi definition by executing
curl "http://localhost:8080/openapi.json" -o extension-manager-api.json
Requirement Tracing
You can run requirements tracing by executing:
./ci/trace-requirements.sh
If tracing fails with a org.xml.sax.SAXParseException you might need to run mvn clean before to delete temporary files like target/site/jacoco/jacoco.xml.
Testing
The extension-manager project contains unit and integration tests that verify
- Loading and executing of JavaScript extensions
- Database interactions
- REST API interface
- Server-side parameter validation using
extension-parameter-validator
Tests use dummy extensions, no real extensions.
Non-Parallel Tests
The tests of this project use exasol-test-setup-abstraction-server. There the tests connect to an Exasol database running in a docker container. For performance reasons the test-setup-abstraction reuses that container. This feature is not compatible with running tests in parallel.
Problems would be:
- Name conflicts, e.g. schema names
- Missing isolation, e.g.
EXA_ALL_SCRIPTScontains objects from other tests - Issues with the exasol-test-setup-abstraction-server (the download of the server jar is triggered by the first test. The second one tries to use the unfinished jar)
For that reason parallel tests are currently disabled in the CI with -p 1.
To run test locally use:
go test -p 1 ./...
To run only tests without the database use:
go test -p 1 -short ./...
Please note that also -short tests need -p 1 because extension integration tests share a directory for building a test extension. Tests will fail randomly without -p 1.
Manual Integration Tests With SaaS
Normal integration test EM against an Exasol DB running in a Docker container. There might be differences to a real Exasol SaaS DB. Tests against SaaS are not automated, you need to run them manually:
- Create a Personal Access Token in SaaS with scope
databases:use - Create a new schema you want to use for testing
- Upload required Adapter JARs to BucketFS
- Create file
manual-test.propertieswith the following content:databaseHost = <SaaS DB host> databaseToken = <SaaS DB personal access token> extensionRegistryURL= <Registry URL> extensionSchema = <Extension Schema> bucketFSBasePath = <Bucket FS base path> - Run test with
go test -v ./cmd/...
Static Code Analysis
Go Linter
To install golangci-lint on your machine, follow these instruction.
To run the linter, execute
golangci-lint run
File .golangci.yml contains configuration like enabled or disabled linters.
Sonar
Download sonar-scanner as a zip file from sonarqube.org and unpack it.
Run tests to generate code coverage information:
go test -v -p 1 -count 1 -coverprofile=coverage.out ./...
mvn verify
Then run Sonar with the following command in the project root:
sonar-scanner -Dsonar.token=$SONAR_TOKEN
Using a Local Extension Interface
To use a local, non-published version of the extension interface for testing EM follow these steps:
-
Build
extension-manager-interfaceby runningnpm run build. This is required after each change. -
Edit pkg/integrationTesting/extensionForTesting/package.json and replace the version of
"@exasol/extension-manager-interface"with the path to your local clone of extension-manager-interface. -
Edit pkg/integrationTesting/extensionForTesting/extensionForTestingTemplate.js and adapt it to the new API if necessary.
Note: The file contains placeholders that will be replaced during tests. It is not valid JavaScript, so it's normal that the editor complains about the invalid syntax.
Make sure to not commit the modified package.json.
Extension Registry
The extension registry is an HTTPS service that provides a JSON file containing links to all available extensions. The service consists of an S3 Bucket and a CloudFront distribution deployed via AWS Cloud Development Kit (CDK).
Initial Configuration
- Create file
registry/lib/config.tswith the following content:export const CONFIG = { owner: 'your.email@example.com' } - Run
npm install - Configure AWS profile and region:
export AWS_PROFILE=<profile> export AWS_REGION=eu-central-1
Deploy Changes
Run npm run cdk diff. If the output looks good, run npm run cdk deploy.
To get the output variables of the deployed stack (e.g. bucket name and CloudFront distribution host name), run the following command:
aws cloudformation describe-stacks --stack-name ExtensionManagerRegistry --query "Stacks[0].Outputs[].{key:ExportName,value:OutputValue}"
Deploy Registry Content
Generate Registry Content
Run the following command to generate the registry content using the latest extension versions:
cd registry-upload
npm run generate
Upload Registry
To deploy the content of the Extension Registry to test or prod stage, run the following command:
cd registry-upload
AWS_PROFILE=$profile npm run upload -- --stage=test --no-dry-run
# or
AWS_PROFILE=$profile npm run upload -- --stage=prod --no-dry-run
This will upload the JSON file from the registry-upload/content folder for the given stage to the S3 bucket and invalidate the CloudFront cache. It will also upload the testing-extension.js extension to the test stage.
Upgrade NPM Dependencies
npx npm-check-updates -u && npm install
Python UDF
EM uses a Python UDF located at pkg/extensionController/bfs/udf to list files in BucketFS.
Initial Setup
cd pkg/extensionController/bfs/udf
poetry env use 3.12
poetry install
Run tests
cd pkg/extensionController/bfs/udf
poetry run pytest
# Test coverage
poetry run pytest --cov=list_files_udf
Run Type Check
cd pkg/extensionController/bfs/udf
poetry run mypy .
Run Linter
cd pkg/extensionController/bfs/udf
poetry run pylint ./*.py
Check For Outdated Dependencies
poetry show --outdated
# Upgrade dependencies in pyproject.toml
poetry lock
poetry install
poetry update # Upgrade transitive dependencies