11<div align =" center " >
22 <p >
3- <img
4- src="https://github.com/user-attachments/assets/4f98b4d2-adcf-412f-bba5-1dbba43604a8"
5- align="center"
6- alt="Logo"
7- height="200px"
8- />
3+ <picture>
4+ <source srcset="https://github.com/user-attachments/assets/a830f291-a7a9-4f63-97ee-11608c1a5dda" media="(prefers-color-scheme: dark)">
5+ <source srcset="https://github.com/user-attachments/assets/842c1901-9fe4-486b-ba83-39f07d373daf" media="(prefers-color-scheme: light)">
6+ <img src="https://github.com/user-attachments/assets/842c1901-9fe4-486b-ba83-39f07d373daf" alt="Logo">
7+ </picture>
98 </p >
109
11- <h1 >Kmono</h1 >
12-
1310 <p >
14- The missing workspace tool for clojure tools.deps projects
11+ A monorepo/ workspace tool for clojure tools.deps projects
1512 </p >
1613
1714[ ![ Clojars Project] ( https://img.shields.io/clojars/v/com.kepler16/kmono-core.svg )] ( https://clojars.org/com.kepler16/kmono-core )
2118Kmono is a suite of tools and API's for working in Clojure (mono)repos. It aims to meet Clojure where it's at by
2219providing a better understanding of deps.edn projects.
2320
24- This project was built with a focus on improving the experience of working in Clojure monorepos but works great in
25- standalone projects too.
21+ While Kmono was designed with a focus on improving the experience of working in Clojure monorepos, care has been taken
22+ to ensure it works great in standalone (non-workspace) projects too.
2623
2724## Index
2825
2926- ** [ Features] ( #features ) **
27+ - ** [ About] ( #about ) **
28+ - ** [ How It Works] ( #how-it-works ) **
29+ - ** [ Workspace Package Graph] ( #workspace-package-graph ) **
30+ - ** [ The Classpath and Package Aliases] ( #The-Classpath-and-Package-Aliases ) **
31+ - ** [ Clojure APIs] ( #clojure-apis ) **
32+ - ** [ Versioning / Change Detection] ( #Versioning--Change-Detection ) **
3033- ** [ Installation] ( #installation ) **
31- - ** [ Documentation] ( #Documentation ) **
34+ - ** [ Documentation] ( #API- Documentation ) **
3235 - ** [ Kmono CLI] ( #kmono-cli ) **
3336 - ** [ Example Project] ( #example-project ) **
37+ - ** [ Configuration] ( #configuration ) **
38+ - ** [ Workspace Configuration] ( #workspace-configuration ) **
39+ - ** [ Package Configuration] ( #package-configuration ) **
40+ - ** [ Local-Only Configuration Overrides] ( #Local-Only-Configuration-Overrides ) **
3441- ** [ Clojure-lsp / Editor Integration] ( #clojure-lsp--editor-integration ) **
3542
3643## Features
3744
3845- ** Workspace features** : Discovers packages and understands relationships between dependencies
3946- ** Aliases** : Allows working with packages aliases defined in ` deps.edn ` in a 'Clojure native' way without having to
40- pull all alias definitions into root ` deps.edn `
41- - ** Build Tools** : Exposes a suite of libs intended to be used from ` tools.build ` programs to build and release
42- monorepos
47+ pull all alias definitions into a root ` deps.edn `
48+ - ** Build Tools** : Exposes a suite of tools and APIs intended to be used from ` tools.build ` programs to build and
49+ release monorepos
4350- ** Command Runner** : Allows executing Clojure and/or external commands in workspace packages
4451- ** Local Deps Overrides** : Allow overriding kmono config and ` deps.edn ` dependencies during local development. Useful
4552 for providing local paths to in-development libs without committing.
46- - ** Editor/Clojure-lsp** : Improves developer/editing experience by augmenting the classpath used by clojure-lsp
53+ - ** Editor/Clojure-lsp** : Integrates with clojure-lsp to provide better classpath information and improve the
54+ developer/editing experience in monorepos
55+
56+ ## About
57+
58+ It's generally a bit of a pain to work with ` deps.edn ` based Clojure monorepos. There is a general lack of good
59+ workspace features that one might find in other languages and that one needs in order to work effectively in a large
60+ monorepo.
61+
62+ Here is a broad list:
63+
64+ - Start a repl with some subset of package aliases (such as ` :test ` ) active
65+ - Have your editor / clojure-lsp know about these subpackage aliases and include their ` :extra-paths ` on the classpath
66+ - Run common commands across packages in a monorepo
67+ - Track and increment package versions.
68+ - Release package jars with with their referenced workspace dependencies/dependent package versions correctly set.
69+ - Run CI build/test/release workflows against only the subset of packages that have changed since the previous version
70+ or revision.
71+ - Be able to define custom workspace configurations and pipelines that make use of the workspace graph / metadata in an
72+ unopinionated way which may differ from workspace to workspace.
73+ - Script against the workspace package graph (run queries against the package graph)
74+
75+ Kmono aims to solve all of these problems.
76+
77+ There are some existing projects out there that are trying to solve for this problem too - but I find that they are
78+ either too opinionated, too rigid, or stray too far from the 'official' tooling too much.
79+
80+ Kmono tries to build on top of ` tools.deps ` and the clojure cli in order to add additional functionality / capabilities
81+ in a way that feels native to ` tools.deps ` based projects. It tries to do this in a way that does not require
82+ configuring the project in a non-standard way, or configuring it in a manner which would render it incompatible with
83+ other tools.deps based tooling.
84+
85+ I see the functionality added here as a kind of proposal to the Clojure core team for how I might want workspace
86+ features to work in the core tools.deps and clojure tooling.
87+
88+ ## How It Works
89+
90+ ### Workspace Package Graph
91+
92+ At the core kmono is a tool which understands how packages in a Clojure workspace relate and depend on each other. This
93+ is done by analysing the ` :deps ` of packages to find ` :local/root ` coordinates to other packages in the same workspace.
94+ Using this information kmono can build up a graph of packages and their dependencies.
95+
96+ All of kmono's features and capabilities are built on top of this package graph.
97+
98+ ### The Classpath and Package Aliases
99+
100+ Using the package graph kmono can augment the clojure cli with additional aliases constructed from the package graph.
101+ This allows 'telling' clojure about the aliases and paths of subpackages in the workspace.
102+
103+ When you run a command like ` kmono cp -P ':*/test' ` kmono will look for packages in the workspace containing a ` :test `
104+ alias, and it will 'lift' these aliases into the root deps.edn config.
105+
106+ If we were to run this command in the [ example workspace project] ( ./examples/workspace/ ) it would result in a call to
107+ the clojure CLI that looks something like:
108+
109+ ``` bash
110+ clojure -Sdeps ' {:aliases {:a/test {:extra-paths ["packages/a/test"]
111+ :extra-deps {lambdaisland/kaocha {:mvn/version "1.91.1392"}}
112+ :main-opts ["-m" "kaocha.runner" "-c" "../../tests.edn"]}
113+ :b/test {:extra-paths ["packages/b/test"]
114+ :extra-deps {lambdaisland/kaocha {:mvn/version "1.91.1392"}}
115+ :main-opts ["-m" "kaocha.runner" "-c" "../../tests.edn"]}
116+ :kmono/packages {:extra-deps {com.kepler16/a {:local/root "packages/a"}
117+ com.kepler16/b {:local/root "packages/b"}}}}}' \
118+ -A:kmono/packages:a/test:b/test -Spath
119+ ```
120+
121+ From this you can see kmono has extended the ` deps.edn ` project configuration using the clojure cli ` -Sdeps ` flag,
122+ passing it a set of aliases dynamically constructed from the package graph.
123+
124+ You should notice that any relative paths defined by package aliases in the workspace have been adjusted to be relative
125+ to the project root instead of to the package.
126+
127+ Using ` -A ` kmono can selectively pick which aliases to apply!
128+
129+ Most kmono cli commands can be run with ` -v ` to print out debug information about what clojure command kmono is
130+ constructing.
131+
132+ ### Clojure APIs
133+
134+ Kmono exposes a large set of clojure APIs which can be used to work with the analyzed workspace package graph. These
135+ APIs are primarily intended to be used within ` tools.build ` pipelines to define custom build + release workflows that
136+ fit the projects requirements, but could be used for building custom tools/clis/scripts.
137+
138+ Most API's are for querying, filtering, or versioning packages in the graph. Two key APIs exposed are
139+ ` k16.kmono.build/for-each-package ` and ` k16.kmono.build/create-basis ` .
140+
141+ #### ` k16.kmono.build/for-each-package `
142+
143+ This allows iterating over the packages in a given package graph and executing a given function in the context of that
144+ package. It allows using the ` tools.build ` API's as if they were executed from the directory of the workspace package.
145+
146+ #### ` k16.kmono.build/create-basis `
147+
148+ This allows constructing a ` tools.build ` basis wherein any references to workspace packages have been replaced with
149+ their maven coordinates. This is key to simplifying the process of incrementing package versions, building and
150+ releasing.
151+
152+ Please see the [ example workspace] ( ./examples/workspace/ ) or kmono itself for some examples on how to use the API's
153+ exposed by kmono.
154+
155+ ### Versioning / Change Detection
156+
157+ Packages in the graph can have a set of ` :commits ` associated with them, as well as a ` :version ` . Various kmono API's
158+ work by populating these fields for packages in a graph or operating over this information.
159+
160+ For example there is ` k16.kmono.version/inc-package-versions ` which will increment the version of packages in a given
161+ package graph.
162+
163+ There is ` k16.kmono.version/package-changed? ` which can be used to filter out packages which have not changed since some
164+ previous revision / version.
165+
166+ This information can be populated into the graph however you want, but there are also some built-in mechanisms for
167+ associating package versions and commits.
168+
169+ For versions the built-in mechanism is to track package versions in git tags. The
170+ ` k16.kmono.version/resolve-package-versions ` will look for git tags following the pattern
171+ ` <group>/<package-name>@<version> ` and will use the ` <version> ` component to populate package version in the graph.
172+
173+ The ` k16.kmono.version/resolve-package-changes ` can be used to find commits that have changed the package since it's
174+ last tagged version.
175+
176+ The ` k16.kmono.version/resolve-package-changes-since ` can be used to find commits that have changed the package since a
177+ given git revision.
178+
179+ These tools and others can be used to build sophisticated build and release pipelines for kmono workspaces.
47180
48181## Installation
49182
@@ -64,7 +197,7 @@ bash < <(curl -s https://raw.githubusercontent.com/kepler16/kmono/master/install
64197Or alternatively binaries for various platforms can be pulled directly from the
65198[ Releases] ( https://github.com/kepler16/kmono/releases ) page.
66199
67- ## Documentation
200+ ## API Documentation
68201
69202- ** [ kmono] ( https://cljdoc.org/d/com.kepler16/kmono ) ** - A BOM package containing all the submodules of kmono. This is
70203 the best one to look at for docs.
@@ -87,7 +220,7 @@ Usage:
87220 kmono [opts] < args>
88221
89222Version:
90- 4.6 .0
223+ 4.9 .0
91224
92225Commands:
93226 cp Produce a classpath string from a clojure project
@@ -108,16 +241,114 @@ Global Options
108241# ### Example project
109242
110243Take a look at ** [the example project](./examples/workspace/)** to get a better idea of the type of project structures
111- kmono is built to support and for references on how to correctly use the kmono API' s and integrate it into your own
244+ kmono is built to support. This should provide a good reference on how to correctly use the kmono API' s and integrate it
245+ into your own project.
246+
247+ ## Configuration
248+
249+ Kmono will work in any `deps.edn` based project, but needs explicit configuration in order to treat a project as a
250+ workspace (or monorepo).
251+
252+ ### Workspace Configuration
253+
254+ To mark a project as a kmono workspace add a `:kmono/workspace {}` field to the root `deps.edn` config file. This
255+ configuration accepts the following properties:
256+
257+ | Field | Type | Default | Description |
258+ | ------------------ | ----------------------- | ----------------- | -------------------------------------------------------------------------------------------------------------------------------------- |
259+ | `:packages` | `string? \| #{string?}` | "./packages/\*\*" | A glob or set of file globs that describe the set of packages included in the workspace |
260+ | `:group` | `symbol?` | `nil` | The mvn group to apply to any packages in the workspace that have not specified a group |
261+ | `:repl-aliases` | `[keyword?]` | `nil` | A set of `deps` aliases to include when running `kmono repl` |
262+ | `:aliases` | `[keyword?]` | `nil` | A set of `deps` aliases to include for all kmono workspace commands by default |
263+ | `:package-aliases` | `[keyword?]` | `nil` | A set of namespaced [alias globs](#alias-globs) that describe the aliases of packages within the workspace to include in the classpath |
264+
265+ Example:
266+
267+ ```clojure
268+ ;; deps.edn
269+ {:kmono/workspace {:group com.example
270+ :packages #{"./(packages|modules)/**"}
271+ ;; Include any `:test` aliases from all (`*`) packages in the workspace
272+ :package-aliases [:*/test]}
273+
274+ :paths ["src" "resources"]
275+
276+ :deps {...}}
277+ ```
278+
279+ ### Package Configuration
280+
281+ Packages in the workspace can optionally provide their own configuration metadata. This is done by setting a
282+ `:kmono/package {}` config field in the packages `deps.edn` file. This config accepts the following properties:
283+
284+ | Field | Type | Default | Description |
285+ | ----------- | -------------------- | ------- | ---------------------------------------------------------------------------------------------------------------------------------------------- |
286+ | `:group` | `symbol?` | `nil` | The mvn group to use for this package. If not specified, the `:group` specified in the root `:kmono/workspace` configuration will be used. |
287+ | `:name` | `string? \| symbol?` | `$dir` | The name of the package. If not set the name of the parent directory containing the packages' ` deps.edn` file will be used as the package name |
288+ | ` :excluded` | ` boolean? ` | ` false` | Whether or not this package is excluded from the project workspace |
289+
290+ Example
291+
292+ ` ` ` clojure
293+ ;; packages/example/deps.edn
294+ {:kmono/package {;; Maven artifacts group
295+ :group com.example
296+ ;; Override the default package name
297+ :name example-lib}
298+
299+ :paths [" src" ]
300+ :deps {...}
301+ :aliases {:test {...}}}
302+ ` ` `
303+
304+ # ## Local-Only Configuration Overrides
305+
306+ Kmono will automatically read in a ` deps.local.edn` file from the project root and deep-merge it with the root
307+ ` deps.edn` file if present.
308+
309+ This is very useful for adding additional configuration such as default-enabled project aliases, new project-specific
310+ dev-only deps aliases or any other metadata in a way that is local to the developers environment and won' t be committed
311+ to the project.
312+
313+ This `deps.local.edn` file should typically be added to `.gitignore`.
314+
315+ The below is a good example of how this `deps.local.edn` config might be used in someones environment:
316+
317+ ```clojure
318+ {:kmono/workspace {;; Add the :nrepl alias from ~/.clojure/deps.edn when running
319+ ;; `kmono repl`
320+ :repl-aliases [:nrepl]
321+ ;; - Include the :dev alias from ~/.clojure/deps.edn
322+ ;;
323+ ;; - Include the :local alias defined below
324+ :aliases [:dev :local]}
325+
326+ :aliases {;; Define a custom local-only alias for this project
327+ :local {;; Override some dependency with a locally checked out copy
328+ ;; for development
329+ :extra-deps {com.example/some-lib {:local/root "/some/local/lib/path"}}}
330+ :extra-paths ["local"]}}
331+ ```
332+
333+ This config will be loaded and included for this project when running commands such as
334+
335+ ```bash
336+ kmono cp
337+ kmono repl
338+ kmono clojure ...
339+ ```
340+
341+ This is especially useful in an editor that has been configured to use
342+ [kmono as the project-specs source](#clojure-lsp--editor-integration), or when using kmono to start a repl for the
112343project.
113344
114345## Clojure-lsp / Editor Integration
115346
116347One of the things that kmono enables is integration into your editor by acting as a drop-in replacement for
117- `clojure -Spath` which is used by default by clojure-lsp.
348+ `clojure -Spath` which is used by clojure-lsp by default .
118349
119350If we instead use `kmono cp` to generate the classpath then your clojure-lsp server will be able to provide better
120- analysis.
351+ analysis that includes information about subpackages of your workspace, as well as package aliases .
121352
122353#### Project local Clojure-LSP config
123354
@@ -142,15 +373,3 @@ lspconfig.clojure_lsp.setup({
142373 },
143374})
144375```
145-
146- ### Package configuration
147-
148- Package-specific configurations are done within each `deps.edn` file under the `:kmono/package` key:
149-
150- ```clj
151- :kmono/package {;; maven artifact' s group
152- :group com.example
153- ;; the package name which is also used as maven' s artifactId
154- ;; this is optional and inferred from a package' s dir name
155- :name my-lib}
156- ` ` `
0 commit comments