Contributing to Gemara

August 27, 2026 ยท View on GitHub

The project welcomes your contributions whether they be:

PR guidelines

All changes to the repository should be made via PR (OSPS-AC-03).

PRs MUST meet the following criteria:

Useful make tasks when making schema changes

Make sure to update schema-nav.yml in the website repository, after making any changes to the schemas in the layer.cue files For instance: You have added a new schema 'newschema' in layerN.cue( where N is a number from 1 - 7), the website's schema-nav.yml should look like:

- title: "Layer N"
    filename: "layer-N"
    schemas:
      - "SchemaA"
      - "SchemaB"
      - "SchemaC"
      - newschema //new schema added

Use cue fmt . and make cuefmtcheck to ensure proper formatting and make lintcue to validate the syntax of your changes. If you forget to do this before opening a PR and your changes are invalid, the CI workflow will fail and alert you.

Adding a new artifact type

Adding a new artifact type requires schema changes, test data, and documentation updates. Follow the checklist below.

StepAction
1Define the new #YourArtifact definition in the appropriate layer-N.cue file
2Add "YourArtifact" to the #ArtifactType enum in base.cue
3Add new enum or alias types to schema-nav.yml in the website repo under the correct layer
4Create a valid test data file in test/test-data/ (prefix with good-)
5Add positive and/or negative test cases to test/schema_test.go
6Run cue vet -d '#YourArtifact' . test/test-data/good-your-artifact.yaml to validate locally
7Run cue fmt . and make cuefmtcheck to verify formatting
8Run make lintcue and make test to confirm all checks pass

Schema compatibility

The schemas form a public contract. A CI gate compares an OpenAPI projection of the current schema against the latest released v1 baseline and fails the check on any backward-incompatible change. The gate enforces compatibility in both directions: it is consumer-safe (a response may not drop a property or a guarantee that existing readers depend on) and producer-safe (a request may not add a new requirement that existing writers cannot satisfy).

Run the check locally before opening a PR:

make breaking-check

This generates the OpenAPI projection, fetches the latest v1 release as the baseline, and reports any breaking changes with their oasdiff check IDs.

Making an intentional breaking change

Sometimes a breaking change is deliberate. There are exactly two sanctioned ways to introduce one:

  1. Bump the module major version to @v2. A major bump establishes a new baseline lineage, so v1 consumers are never silently broken. Use this when the breaking change is part of a broader, intentional evolution of the contract.

  2. Allowlist the specific change. Add the offending exception to a .oasdiff-allow file at the repository root; make breaking-check passes it to the check via --allow automatically when the file exists. Each entry is a schema-scoped <check-id> <schema> pair, one per line, so the exception applies only to that one schema. The check ID and schema are both printed for every reported change, so you can copy them straight from the output โ€” e.g. a change reported as:

    ERR[request-property-enum-value-removed] ControlEvaluation: removed the enum value ...
    

    is allowlisted with:

    request-property-enum-value-removed ControlEvaluation
    

    This MUST be done in a reviewed PR, and the file MUST include a justification comment (lines beginning with #) explaining why the change is acceptable. Use this for narrowly scoped, well-understood exceptions.

Do not work around the gate by any other means.

Releases

Releases are automatically created when a PR is merged into main with the release label. To trigger a release:

  1. Add the release label to your PR before merging
  2. Merge the PR into main

The release workflow will automatically:

  • Create a GitHub release with the appropriate version tag
  • Generate release notes from the PR using release-drafter
  • Publish the CUE module to the central registry

Note: Only PRs merged into main with the release label will trigger a release. Other labels (such as breaking, feature, or vuln) will not trigger releases.