Skip to content

Development

cite-runner is implemented in Python.

The standalone application depends on the following third-party projects:

  • typer for CLI commands
  • pydantic for models
  • jinja for output format templates
  • httpx for making network requests
  • lxml for parsing teamengine responses
  • mkdocs for documentation

Brief implementation overview

cite-runner runs CITE tests suites by calling teamengine's web API. It requests test suite results in the EARL (AKA the W3C Evaluation and Report Language) format, which is XML-based.

After obtaining a test suite run result in EARL format, cite-runner parses it into an instance of models.TestSuiteResult, its internal data structure.From there, it is able to serialize it into either JSON or markdown.

Setting up a development environment

In a brief nutshell:

  1. Fork the cite-runner repository

  2. Clone your fork to your local environment

  3. Install uv

  4. Use uv to install the cite-runner code locally. This will create a virtualenv and install all dependencies needed for development, including for working on docs:

    uv sync
    
  5. Optionally (but strongly recommended) enable the pre-commit hooks provided by cite-runner:

    uv run pre-commit install
    
  6. Stand up a docker container with a local teamengine instance:

    docker run \
        --rm \
        --name=teamengine \
        --add-host=host.docker.internal:host-gateway \
        --publish=9080:8080 \
        ogccite/teamengine-production:1.0-SNAPSHOT
    

    You should now be able to use http:localhost:9080/teamengine as the teamengine URL in cite-runner.

    Note

    Using docker's --add-host=host.docker.internal:host-gateway is necessary when running docker engine, as discussed in the docker engine docs. If you are using docker desktop on Windows or macOS you can omit this flag.

  7. You can run cite-runner via uv with:

    uv run cite-runner
    

    Warning

    When using cite-runner with a local teamengine instance that is running via docker and also testing an OGC service that is running locally on the same machine, you must not use localhost when providing the service's URL to teamengine, but rather use host.docker.internal.

    As an example:

    uv run cite-runner execute-test-suite \
        http://localhost:9081/teamengine \
        ogcapi-features-1.0 \
        --suite-input iut http://host.docker.internal:9082
    

Running tests

Most tests can be run with:

uv run pytest

cite-runner also includes a workflow for testing itself when running as a GitHub action. This can be run locally with a tool like act.

act \
    --workflows .github/workflows/test-action.yaml \
    --rm \
    --platform ubuntu-24.04=ghcr.io/catthehacker/ubuntu:act-24.04 \
    --container-options="-p 9092:9092" \
    --artifact-server-path $PWD/.artifacts

The .github/workflows/test-action.yaml workflow launches a simple HTTP server which contains a very incomplete implementation of OGC API - Features and then uses the cite-runner GitHub action to run the ogcapi-features-1.0 test suite on it. It then captures the cite-runner output, and runs it through some Python tests to verify the result matches what is expected.

Documentation

If you want to work on documentation, you can start the mkdocs server with:

uv run mkdocs serve

Now edit files under the /docs directory and check whether they match your expected result in the mkdocs dev server, which would be running at `http://localhost:8000/cite-runner/

Release management

cite-runner releases are managed with a GitHub actions workflow, which is set up to run whenever a new tag named v* is pushed to the repository. This workflow will:

  • Call the CI workflow, which takes care of testing and building the application
  • Create a GitHub release
  • Publish the built application to PyPI

Note

The release workflow is not fully automated, requiring the cite-runner maintainers to explicitly provide approval of new runs. This is intentional.