Skip to content

Conversation

@bilus
Copy link
Contributor

@bilus bilus commented Jan 5, 2026

See if that's ok by you:

Caveats

  1. I still haven't tested it manually much. I suspect at least list-modules will require minor changes. I plan to try to use the workflows in creation of the starter module I had mentioned. Tomorrow is the day I set aside for this.
  2. Sorry for the PR being so big. There are several commits and, if you want, I can split them into separate PRs. Each commit has a description of the changes in its commit message but nothing that isn't covered below.

Post-install hooks

The PR ads post-install hooks, allowing to run scripts after module installs,
along with a framework for adding hooks in other places.

Example config.edn:

{:default {:hooks {:post-install ["echo hello"]}}}

When installing modules, it will prompt the user before executing a hook, as a
safety measure. You can type "all" to accept all hooks.

The following hook actions will be performed:
 $ mv test/resources/generated/install.sh test/resources/generated/post-install.txt
Run the hook?  (y/n/all):

You can also mute the prompt:

(kit/install-module :html {:accept-hooks? true})

You can also set :accept-hooks? to false to skip all hooks.

Dry run mode

Dry-run mode lets the user see the planned changes before applying them:

(kit.api/install-module :meta "test/resources/kit.edn" {:feature-flag :with-hooks
                                                        :dry? true
                                                        :db {:feature-flag :migrations}})
ALREADY INSTALLED (skipped)
  :db
  :hooks

INSTALLATION PLAN
  :migratus
    adds support for migrations
      - create test/resources/generated/src/clj/myapp/db/migratus.clj

  :meta @with-hooks
    meta-module adding support for html and cljs
      - create test/resources/generated/resources/public/css/styles.css
      - modify test/resources/generated/resources/system.edn
      - run post-install hook

SUMMARY
  2 module(s) already installed (skipped)
  2 module(s) to install

Internal changes

These are quite extensive, unfortunately. To cleanly implement the hooks, I
decided to refactor the code so that the changes are planned before they are
applied. In particular, you know the list of modules to be installed, in the
particular order, along with their configurations after resolving
:feature-requires and :feature-flag. This allows collecting hooks and
executing them in the correct order.

Minor breaking changes

  1. Before: :requires were calculated by recursively walking all
    :feature-requires. It wasn't true for other fields, e.g. :actions After: All
    config fields are resolved using the same algorithm, while handling cyclic
    dependencies.
  2. Before: Configs were loaded gradually as dependencies were resolved. After:
    Everything is loaded and resolved in modules.clj, upfront. Dependency
    calculation is now a pure function. This is a substantial change, but I
    believe I haven't changed the logic.
  3. I added babashka/process to deps.edn.

Looking forward to your feedback. :)

@yogthos
Copy link
Collaborator

yogthos commented Jan 5, 2026

I think it's moving in the right direction. Recursively walking everything makes it more consistent, and loading everything up front for configs shouldn't be an issue.

@bilus bilus force-pushed the bilus/post-install-and-dry branch 2 times, most recently from ef70769 to 5fd625b Compare January 6, 2026 21:31
@bilus
Copy link
Contributor Author

bilus commented Jan 6, 2026

Ok, pushed some changes. It turns out that we cannot do without a topological sort to handle dependencies that depend on one another, so that's another change to the existing logic. It's almost ready, give me a bit of time to test it more. I spent the most of the time I had today building support for previews to make developing kit modules easier (it'll be a separate PR). I'll try to carve out some time tomorrow to finalize manual tests.

@bilus bilus force-pushed the bilus/post-install-and-dry branch 4 times, most recently from c181314 to a36f344 Compare January 6, 2026 21:48
bilus added 7 commits January 6, 2026 22:50
<!-- ps-id: 61126e84-56d0-467a-a886-86b08bff4a78 -->
The commit ads post-install hooks, allowing to run scripts after module installs,
along with a framework for adding hooks in other places.

Example `config.edn`:

```edn
{:default {:hooks {:post-install ["echo hello"]}}}
```

When installing modules, it will prompt the user before executing a hook, as a
safety measure. You can type "all" to accept all hooks.

```
The following hook actions will be performed:
 $ mv test/resources/generated/install.sh test/resources/generated/post-install.txt
Run the hook?  (y/n/all):
```

You can also mute the prompt:

```clojure
(kit/install-module :html {:accept-hooks? true})
```

You can always set `:accept-hooks?` to false to skip all hooks.

<!-- ps-id: a1adadcf-5c40-46e7-b4b3-5b9d409cde51 -->
This commit moves I/O out of module dependency resoultion. Before the
changes configs were loaded gradually as dependencies were resolved and
`:feature-requires` and `:feature-flag`s were applied. Now everything is
loaded and resolved in modules.clj, upfront. Dependency calculation is
now a pure function. This is a substantial change, but I believe I
haven't changed the logic.

<!-- ps-id: 4d041d63-cd84-451b-a12d-b5f25c927564 -->
While installing modules, it will prompt the user before executing each hook, as a
safety measure. You can type "all" to accept all hooks.

```
The following hook actions will be performed:
 $ mv test/resources/generated/install.sh test/resources/generated/post-install.txt
Run the hook?  (y/n/all):
```

You can also mute the prompt:

```clojure
(kit/install-module :html {:accept-hooks? true})
```

You can always set `:accept-hooks?` to false to skip all hooks.

<!-- ps-id: 2a209106-f576-4ee4-8fe1-04c8e8f2428c -->
<!-- ps-id: eba192d3-88ab-440d-aa47-d83fea910c60 -->
Dry-run mode lets the user see the planned changes before applying them:

```
(kit.api/install-module :meta "test/resources/kit.edn" {:feature-flag :with-hooks
                                                        :dry? true
                                                        :db {:feature-flag :migrations}})
ALREADY INSTALLED (skipped)
  :db
  :hooks

INSTALLATION PLAN
  :migratus
    adds support for migrations
      - create test/resources/generated/src/clj/myapp/db/migratus.clj

  :meta @with-hooks
    meta-module adding support for html and cljs
      - create test/resources/generated/resources/public/css/styles.css
      - modify test/resources/generated/resources/system.edn
      - run post-install hook

SUMMARY
  2 module(s) already installed (skipped)
  2 module(s) to install
```

<!-- ps-id: 8ae0336a-27e4-4a95-b671-d18aecc78109 -->
<!-- ps-id: 57ca589f-e08b-4542-8b0d-55d14e954ff1 -->
@bilus bilus force-pushed the bilus/post-install-and-dry branch from a36f344 to 824bc1a Compare January 6, 2026 21:50
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants