Liking cljdoc? Tell your friends :D

Development

Collet is a Clojure CLI workspace resolved by Kmono 4.12.3. Shared root-only tools.build behavior lives under build/, reusable unpublished test fixtures live in test-fixtures/, and each public or deployable package declares its artifact contract in its own deps.edn under :collet/artifact.

Prerequisites

  • JDK 21 or newer. CI runs on JDK 21.
  • Clojure CLI.
  • Babashka.
  • Docker for PostgreSQL, MySQL, LocalStack, application/CLI startup, and image integration tests.

The workspace pins Kmono and its CLI to 4.12.3, Kaven to 1.0.0, and tools.build to 0.10.14.

Source and published dependencies

Internal dependencies in the root and package deps.edn files are top-level :local/root entries. They make a checkout immediately editable and ensure tests and uberjars use the source currently on disk. Kmono resolves the package graph and replaces each internal local root with that package's exact Maven coordinate and version only when a publishable POM is generated. A generated POM therefore never contains :local/root, and an external consumer continues to use ordinary :mvn/version dependencies.

Do not edit generated POMs or introduce internal Maven pins into source deps.edn files. Versions are derived from package tags; there is no source version file, manual version-bump command, or supported bb version task.

Repository commands

Run build, workspace, verification, and release commands from the repository root:

CommandBehavior
bb kmono queryPrints Kmono's resolved package graph. Additional Kmono query arguments may follow.
bb test:unitRuns build-tool tests once and every package in a separate JVM, excluding ^:integration tests; Docker is not required.
bb test:integrationBuilds app/CLI outputs, then runs only integration tests in integration-bearing packages; Docker is required.
bb testRuns the complete unit and integration suite; Docker is intentionally required.
bb test:module <module>Runs one package's complete :test alias in its own JVM; Docker may be required. Cognitect test-runner options may follow the module.
bb build [module]Builds one package and its dependencies, or every package, in dependency order.
bb install [module]Installs one publishable package and its dependencies, or all publishable packages, into the local Maven repository.
bb verifyBuilds artifacts and checks their public POM coordinates/internal dependency versions, namespace entries, executable entrypoints, CLI archive layout/modes, and Vega golden output.
bb release:planPrints the read-only independent-version plan for every changed package.
bb releaseTests, verifies, builds, publishes, and tags every changed package.

Package selectors are directory names such as collet-core, collet-action-http, collet-actions, collet-app, and collet-cli. Package-local clojure -M:test remains useful while developing one module; the table above is the supported repository orchestration contract.

Build outputs

Library packages produce target/<artifact>-<version>.jar with Clojure sources, runtime resources, LICENSE, Maven metadata, and a publishable POM. In addition:

  • bb build collet-app preserves collet-app/target/collet.jar and main namespace collet.main.
  • bb build collet-cli preserves collet-cli/target/collet.pod.jar, main namespace pod.collet.core, and collet-cli/target/collet-cli.tar.gz.
  • docker build -f collet-app/Dockerfile -t collet . builds the runtime image from the repository-root context. Release images must also receive the exact app/core versions and revision described in the deployment guide.

Build outputs and tests use package-local target and temporary directories. Tests create and remove their own fixtures; no pre-existing tmp directory is required.

Branch names

Create branches from an up-to-date main using this form:

<kind>/<issue-number>-<short-description>

Use lowercase kebab-case and keep the description short enough to scan in GitHub. Use one of these kinds:

KindUse forExample
featureNew user-visible behaviorfeature/43-modular-action-artifacts
fixBug fixesfix/118-odata-pagination
docsDocumentation-only changesdocs/122-release-recovery
testTest-only changestest/96-http-retry
refactorInternal restructuring with no behavior changerefactor/81-action-registration
ciCI and automation changesci/77-jdk-21-cache
choreMaintenance that does not fit another kindchore/update-testcontainers

Include the GitHub issue number when the work has one. For small untracked maintenance, omit only the number, as in chore/update-testcontainers. Tool-managed branches may use the tool's required prefix while keeping the same issue-and-summary shape, for example codex/43-deps-modules.

For example, start issue #43 and publish its branch with:

git switch main
git pull --ff-only origin main
git switch -c feature/43-modular-action-artifacts
git push -u origin feature/43-modular-action-artifacts

Keep one logical change per branch and open its pull request against main. Do not reuse a merged branch for later work; update main and create a new branch instead. The branch kind is for navigation only: Kmono determines release versions from the resulting Git commit messages, not from the branch name.

Pull request titles and Kmono versions

When a pull request is squash-merged, its final title becomes the squash commit's subject and therefore controls Kmono's version calculation. Before merging, edit the title to describe the release impact. If the repository uses rebase or merge commits instead, Kmono reads the commit messages that actually land on main; the live pull request title has no special meaning by itself.

Assuming the changed package's latest tag is 1.2.3, these squash-merge titles produce the following results:

Pull request titlePackage changesKmono result
fix: handle an empty HTTP responseRuntime source or resourcesPatch release 1.2.4
feat: add OAuth bearer-token supportRuntime source or resourcesMinor release 1.3.0
feat!: replace the pipeline configuration schemaBreaking runtime/API changeMajor release 2.0.0
docs: explain HTTP authenticationMarkdown onlyNo release; Markdown is ignored
test: cover retry exhaustionFiles under test/ onlyNo release; test changes are ignored
docs: explain HTTP authenticationRuntime source also changedbb release:plan fails because the runtime change has no release-producing title

For a major release, putting ! before the colon is the clearest title form: fix!: remove a deprecated action option, feat!: change the pipeline API, or refactor!: replace the action registration contract. A conventional commit with a BREAKING CHANGE: footer also produces a major release, but that footer must be present in the final squash commit message; it is not inferred from the pull request description.

When several release-producing commits have accumulated since a package's latest tag, the highest change wins. Starting from 1.2.3, a fix: followed by a feat: produces 1.3.0; adding any ! or BREAKING CHANGE: commit produces 2.0.0.

Kmono also patches unchanged dependent packages whose generated POMs must point to the new exact dependency version. For example, if io.velio/collet-action-lucene is at 0.4.1 and a pull request titled feat: add fuzzy Lucene queries changes it, Kmono plans collet-action-lucene 0.5.0. If io.velio/collet-actions is at 0.7.2, it is automatically planned at 0.7.3 even when that aggregate's source was untouched. A dependent with its own feat: or breaking change receives that higher bump instead of only the automatic patch.

The first modular release is the exception: when no Kmono package tags exist, every package is bootstrapped at 0.2.8. Title-based increments apply after those initial package tags have been created. Always run bb release:plan before merging or releasing to confirm the exact affected packages and versions.

Changing a package

Keep runtime implementation and package-specific tests/resources in the owning directory. Put reusable, unpublished test fixtures in test-fixtures. When changing dependencies or package boundaries:

  1. Add or update the owning package's top-level dependency in deps.edn. Use :local/root for another workspace package and :mvn/version for an external library.
  2. Update that package's :collet/artifact metadata when its namespaces, kind, publishability, main namespace, or exceptional output contract changes.
  3. Use a conventional commit that describes a publishable change: fix: for a patch, feat: for a minor, or !/BREAKING CHANGE: for a major release.
  4. Run bb test:module <module>, then bb test:unit.
  5. Run Docker integrations when affected and finish with bb verify and bb release:plan.

Package Markdown, tests, test resources, sample configs, and development files do not publish. A meaningful package change without a release-producing commit makes release planning fail with guidance; use the correct conventional commit or squash-merge PR title rather than assigning a version manually. Root build and CI files are development-only inputs and do not select package releases. If a root metadata or packaging change is intended to alter a published artifact, include its owning package metadata in the same release-producing commit.

See module migration for artifact boundaries and releasing for independent versions, publication, and recovery.

Can you improve this documentation?Edit on GitHub

cljdoc builds & hosts documentation for Clojure/Script libraries

Keyboard shortcuts
Ctrl+kJump to recent docs
Move to previous article
Move to next article
Ctrl+/Jump to the search field
× close