polylith

itaied 2025-11-22T18:35:03.783229Z

hey all how do you manage you ci pipelines? i am migrating our project one service at a time (from multiple repos to a poly monorepo) i have started with creating a single component containing all of the repo stuff and a project that contains the ci file (gitlab ci) how do you execute pipelines for the corresponding project upon changes in the component / base? i know poly can track changes and execute tests accordingly, but it does not offer deployment mechanism

seancorfield 2025-11-22T19:23:29.195319Z

At work, we use the Polylith API in our build.clj to get a list of projects that are affected by changes and we only build uberjars for those projects.

seancorfield 2025-11-22T19:25:16.792429Z

There's a projects-to-deploy function in that API: https://cljdoc.org/d/polylith/clj-poly/0.3.31/api/polylith.clj.core.api.interface#projects-to-deploy

seancorfield 2025-11-22T19:26:02.358849Z

;; in our build.clj:
(defn build-uberjars
  "Build uberjars for specified, or changed, artifacts."
  [params]
  (let [projects (or (:projects params)
                     (changed-projects (get params :since "release")))]
    (uberjars (assoc params :projects projects))))

seancorfield 2025-11-22T19:27:41.789369Z

I talk about this in https://corfield.org/blog/2022/12/07/deps-edn-monorepo-10/ although the API didn't exist back then so changed-projects was a much more complicated fn in our build.clj

seancorfield 2025-11-22T19:27:53.261249Z

LMK if you have any Qs @itai

seancorfield 2025-11-22T19:30:41.139179Z

Our CI is BitBucket Pipelines, and our YAML file just runs certain fns in our build.clj file -- so our CI is essentially Clojure code in that, setting up the DB, running tests (via Polylith and my external test runner), and building just the uberjars that are needed -- and then posting them to S3 for subsequent deployment.

itaied 2025-11-22T19:57:24.983169Z

that's a nice function! i wonder how can i execute some jobs (like deploying to k8s, or building a docker image) based on the result of this api when ill get a better understanding and practice ill probably have more questions thanks!

seancorfield 2025-11-22T20:14:03.425169Z

We still have a bunch of bash/sh scripts from "the old days" that we run as part of dev/test/CI via functions like this:

(defn- run-build-script [script]
  (let [{:keys [exit]}
        (b/process {:command-args ["sh" (str base "/build/" script)]})]
    (when-not (zero? exit)
      (throw (ex-info (str script " aborted!") {:exit exit})))))

seancorfield 2025-11-22T20:15:07.321489Z

At some point, we may rewrite those in Clojure (or bb)...

itaied 2025-11-22T20:55:13.498739Z

where do you place these script files? under the project folder? i understand that "project" is the deployable artifact, so i guess i should place there scripts and config files

itaied 2025-11-22T21:01:07.088489Z

specifically in the current project i'm migrating we use datomic ions so i have this script for deployment

(ns ci
  (:require [datomic.ion.dev :as ion]))

(defn -main []
  (let [{:keys [rev deploy-groups]} (ion/push {})
        _ (println "rev" rev)
        dep (ion/deploy {:rev rev
                         :group (first deploy-groups)})]
    (loop []
      (let [dep-status (ion/deploy-status dep)]
        (case (:deploy-status dep-status)
          "RUNNING" (do (println "waiting for CodeDeploy...")
                        (Thread/sleep 3000)
                        (recur))
          "SUCCEEDED" (println dep-status)
          (throw (Exception. (str dep-status))))))))
and a bunch of other stuff like datomic configs

seancorfield 2025-11-22T21:06:46.192229Z

We have a single build.clj at the root of the workspace and it manages builds for all 20+ projects.

seancorfield 2025-11-22T21:07:24.019419Z

Our repo has a build/ folder and build-related scripts live there.

seancorfield 2025-11-22T21:08:07.303179Z

(Well, we actually moved build.clj to bases/build but we still run it from the workspace root)

seancorfield 2025-11-22T21:29:35.985159Z

Our build.clj file has 27 public functions (tasks) and about 450 lines of code, FYI.

🙏 1
itaied 2025-11-23T12:39:26.144789Z

do you have experience with ions? i'm trying to build and deploy my ions and i get an error for local/root

{:paths ["resources"]

 :mvn/repos {"ossrh-snapshots" {:url ""}
             "datomic-cloud"   {:url ""}}

 :deps {poly/build {:local/root "../../components/build"}
        poly/ions {:local/root "../../components/ions"}

        org.clojure/clojure {:mvn/version "1.12.3"}}

 :aliases {:test {:extra-paths []
                  :extra-deps  {}}
           :migrate {:exec-fn my-ns.build.core/migrate-datomic-schema
                     :exec-args {:schema my-ns.ions.datomic.schema/schema}}
           :deploy {:exec-fn my-ns.build.core/deploy-ions}}}
error:
Execution error at datomic.ion.dev.bundle/require-uname-for-local-root!$fn (bundle.clj:80).
Dependency poly/ions is a :local/root dependency. You must specify a :uname argument to push. :uname builds are unreproducible!
poly.build
(defn deploy-ions [_]
  (let [{:keys [rev deploy-groups]} (ion/push {})
        dep (ion/deploy {:rev rev
                         :group (first deploy-groups)})]
    (println "rev" rev)
    (loop []
      (let [dep-status (ion/deploy-status dep)]
        (case (:deploy-status dep-status)
          "RUNNING" (do (println "waiting for CodeDeploy...")
                        (Thread/sleep 3000)
                        (recur))
          "SUCCEEDED" (println dep-status)
          (throw (Exception. (str dep-status))))))))

itaied 2025-11-23T12:39:46.497519Z

i dont want to provide :uname for it tho...

seancorfield 2025-11-23T17:36:54.529879Z

I can only suggest asking in #datomic or #ions-aws about that restriction. I've never used Datomic in any form (aside from working through the local tutorial when it first came out).

👍 1
2025-11-23T19:57:30.966709Z

Make sure you have a clean git repo, i.e. no uncommitted changes.

2025-11-23T19:59:23.752529Z

Datomic Ions uses the git SHA as the revision/version number, but it requires a clean git repo so that the exact build can be reproduced later.

itaied 2025-11-23T20:41:27.199949Z

it also require not using :local/root