Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -4,3 +4,4 @@ hephaistox.wiki
landing
sasu
old
xoro_test
84 changes: 84 additions & 0 deletions CLAUDE.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,84 @@
# Hephaistox monorepo (orchestration root)

This directory is **not a single repo**. Each subdirectory is its
**own independent git repo**, wired together by `deps.edn` `:git/sha` refs. This root is
only the orchestration layer: `monorepo/src/tasks/{local,latest,status,projects}.clj`
driven by the root `bb.edn`. Each project has its own `CLAUDE.md` — look there for
per-project detail; keep this file about cross-repo mechanics.

## Projects & dependency DAG

All are publishable libs except `landing` (leaf app). Edges below are `deps.edn` deps
(consumed via `:git/sha`, or `:local/root` after `bb local`). `auto_build` is special:
it is consumed by **every** repo's `bb.edn`, not `deps.edn` (see Gotcha).

| repo | role | deps.edn → (hephaistox) |
|--------------|-----------------------------------------|------------------------------------------------------------------|
| `auto_build` | shared lib — bb/cicd tooling | (none) |
| `auto_core` | shared lib — core utilities | (none) |
| `auto_opti` | shared lib — optimization | auto_core |
| `auto_js` | shared lib | auto_opti |
| `auto_web` | shared lib — web (clj/cljc/cljs) | cljc → auto_core; top → its own clj+cljc submodules (local/root) |
| `auto_sim` | shared lib — simulation | auto_opti; auto_web (cljs-deps) |
| `landing` | **leaf app** — public website (uberjar) | auto_web clj/cljc/cljs |

Build bottom-up: `auto_build`/`auto_core` → `auto_opti`/`auto_web` → `auto_js`/`auto_sim`
→ `landing`.

## local ↔ latest workflow

`bb <task> <project>` walks the target's monorepo deps transitively (`flatten-deps`
matches `com.github.hephaistox` coords) and rewrites **only `deps.edn`**:

- `bb local <p>` — swaps each hephaistox `:git/sha`/`:git/url` dep to `:local/root`
(pointing at the sibling dir). Use while developing across repos so edits are picked
up without committing.
- `bb latest <p>` — reverse: drops `:local/root`, re-pins `:git/sha` to each sibling's
**current local commit** (`actual-sha`), restoring `:git/url`/`:deps/root`. Use before
pushing to publish-and-pin.

Both also rewrite the `auto-build` tooling pin in each scanned project's **`bb.edn`**
(`:deps com.github.hephaistox/auto-build`): `local` → `:local/root "../auto_build"`,
`latest` → `:git/sha <auto_build HEAD>` (see below).

**Publish→pin loop (cadence: on demand).** When a shared lib changes: commit & push it,
then re-pin its sha in every consumer (run `bb latest` on the consumer, commit & push
that). Propagate bottom-up through the DAG.

## auto-build pin lives in bb.edn, not deps.edn

`auto-build` (the bb tooling) is declared only in each repo's **`bb.edn`**
(`:deps {com.github.hephaistox/auto-build {:git/sha …}}`), so it is **not** part of the
`deps.edn` dependency graph the scan walks. `bb local`/`bb latest` therefore handle it
separately, via dedicated `bb.edn` helpers in `project/deps.clj`
(`read-bb`/`update-bb-edn`/`bb-hephaistox-deps`) — `deps-edn-filename`/`read`/`write-edn`
remain `deps.edn`-only. The `bb-deps-to-local`/`bb-deps-to-latest` steps in
`tasks.local`/`tasks.latest` run once per scanned project.

Notes:
- The **root** `bb.edn` is not a scanned project, so its `auto-build` pin
(`:local/root "auto_build"`) is left alone — that's what lets the tasks run on local
tooling.
- `write-edn` reflows the whole file on write; a following `bb format` (which `bp` runs
before push anyway) collapses the diff back to just the changed pin.

## Per-repo git lifecycle

A cross-cutting change = a **separate branch / commit / push in each affected repo**;
there is no umbrella commit. **No branch-naming convention** is enforced (repos sit on
unrelated names). After pushing a lib, re-pin its sha in consumers (above).

## Root bb tasks (run from here)

- `bb projects` — list the local git repos available as targets.
- `bb status <p>` — for `<p>` and its transitive monorepo deps: report uncommitted
changes + deps whose pinned sha ≠ the sibling's actual sha, and
flag any `:local/root` deps. Run before pushing.
- `bb local <p>` — point `<p>`'s hephaistox deps at local siblings (dev).
- `bb latest <p>` — re-pin `<p>`'s hephaistox deps to siblings' latest commits (publish).

`<p>` is a project **directory name** (e.g. `auto_opti`, `landing`).

## Notes

- `bb format` is idempotent on edn — safe to run after `local`/`latest` rewrites.
43 changes: 23 additions & 20 deletions bb.edn
Original file line number Diff line number Diff line change
@@ -1,24 +1,27 @@
{:deps {com.github.hephaistox/auto-build
{:git/sha "319337735ac9f23be4b4dabdc610b5b0095b5ed2"}},
{:deps {com.github.hephaistox/auto-build {:local/root "auto_build"},
#_{:git/sha "0c5a81483005c393094ca557fa0f43e1175ad57d"}},
:paths ["monorepo/src"],
:tasks
{:init
(defn to-dir [dir prj] (or dir (str/replace prj (re-pattern "-") "_"))),
:requires [[clojure.edn :as edn] [clojure.string :as str]],
copy {:doc "Execute copies defined in `reference/copy.edn`",
:requires [[tasks.copy :refer [do-copy]]],
:task (do-copy)},
delegate
{:requires [[clojure.edn :as edn] [clojure.string :as str]],
latest
{:doc
"Delegate command to projects defined in `monorepo/reference/deps.edn`",
"References of monorepo target and its dependencies are moved to latest commit.",
:requires [[auto-build.echo :refer [level1-header]]
[tasks.delegate :refer [do-delegate]]],
:task (do-delegate level1-header *command-line-args*)},
push {:doc "Push a ref to all projects",
:requires [[auto-build.echo :refer [level1-header]]
[tasks.push :refer [do-push]]],
:task (do-push level1-header *command-line-args*)},
status {:doc "Show status",
:requires [[auto-build.echo :refer [level1-header]]
[tasks.show :refer [do-show]]],
:task (do-show level1-header)}}}
[tasks.latest :as tl]],
:task (tl/run level1-header *command-line-args*)},
local
{:doc
"References of monorepo target and its dependencies are moved to local version",
:requires [[auto-build.echo :refer [level1-header]]
[tasks.local :as tl]],
:task (tl/run level1-header *command-line-args*)},
projects {:doc "List existing projects that are git repo",
:requires [[tasks.projects :as tp]
[auto-build.echo :refer [level1-header]]],
:task (tp/print-repos level1-header)},
status
{:doc
"Show status of monorepo target project: list non commited modifications and non aligned deps references",
:requires [[auto-build.echo :refer [level1-header]]
[tasks.status :as ts]],
:task (ts/run level1-header *command-line-args*)}}}
22 changes: 0 additions & 22 deletions monorepo/reference/copy_files.edn

This file was deleted.

40 changes: 0 additions & 40 deletions monorepo/reference/deps.edn

This file was deleted.

16 changes: 16 additions & 0 deletions monorepo/src/tasks/common.clj
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
(ns tasks.common)

(def local-deps-repo (atom {}))

(defn retrieve-local-git
[prj-dir retriever]
(if-let [prj-deps (get @local-deps-repo prj-dir)]
prj-deps
(when-let [prj-data (retriever prj-dir)]
(swap! local-deps-repo assoc prj-dir prj-data)
prj-data)))

(comment
(retrieve-local-git "landing" git-data)
;;
)
15 changes: 0 additions & 15 deletions monorepo/src/tasks/copy.clj

This file was deleted.

137 changes: 137 additions & 0 deletions monorepo/src/tasks/latest.clj
Original file line number Diff line number Diff line change
@@ -0,0 +1,137 @@
(ns tasks.latest
"Move ref to latest"
(:require [auto-build.project.cfg-mgt :refer
[project-dir extract-project is-git-repo? git-subdir-data]]
[clojure.set]
[auto-build.project.deps :as pd :refer
[extract-paths-to-deps flatten-deps update-deps-edn]]
[tasks.projects :refer [print-repos]]))

(def ^:private local-deps-repo
"Cache of local repos used to limit git usage"
(atom {}))

(defn- retrieve-local-git
"Use `retriever` in project-dir if cache is not present."
[prj-dir retriever]
(if-let [prj-deps (get @local-deps-repo prj-dir)]
prj-deps
(when-let [prj-data (retriever prj-dir)]
(swap! local-deps-repo assoc prj-dir prj-data)
prj-data)))

(defn- monorepo-deps
"Returns monorepo dependencies

Read in the `deps.edn` file in directory `local-app-dir`. All dependencies are gathered, and the one matching is-monorepo-app? are returned."
[local-app-dir printers]
(-> (pd/read printers local-app-dir)
:edn
extract-paths-to-deps
(flatten-deps local-app-dir)))


;; ********************************************************************************
;; Latest
;; ********************************************************************************

(defn- bb-deps-to-latest
"Re-pin the hephaistox tooling dependencies (e.g. `auto-build`) declared in the
`bb.edn` of `local-app-dir` to the latest commit of their local sibling.

This is needed because `bb.edn` is not part of the `deps.edn` dependency graph."
[{:keys [normalln], :as printers} local-app-dir]
(doseq [{:keys [dep-alias dep path]} (pd/bb-hephaistox-deps printers
local-app-dir)]
(let [{:git/keys [sha]} dep
build-dir (-> dep-alias
str
extract-project
project-dir)
{:keys [actual-sha]} (retrieve-local-git build-dir git-subdir-data)]
(when actual-sha
(if (= sha actual-sha)
(normalln (format "`%s` (bb.edn) is already uptodate sha `%s`"
dep-alias
actual-sha))
(do (normalln (format "`%s` (bb.edn) is moved to sha `%s`"
dep-alias
actual-sha))
(pd/update-bb-edn printers
local-app-dir
path
(-> dep
(dissoc :local/root)
(assoc :git/sha actual-sha)))))))))

(defn- move-to-latest
[{:keys [normalln uri-str subtitle], :as printers} target-dir]
(normalln "Target project:" (uri-str target-dir))
(loop [[local-app-dir & rlocal-app-dirs] #{target-dir}
local-app-dir-done #{}]
(when local-app-dir
(let [local-app-git (retrieve-local-git local-app-dir git-subdir-data)
{local-deps true, git-deps false} (->> (monorepo-deps local-app-dir
printers)
(group-by :is-local?))]
(-> (format "Scan app in directory `%s`, branch `%s`"
local-app-dir
(:actual-branch local-app-git))
subtitle)
(doseq [local-dep local-deps]
(let [{:keys [dep-alias dep path dir]} local-dep
{:hephaistox/keys [url root]} dep
{:keys [actual-sha]} (retrieve-local-git dir git-subdir-data)]
(normalln (format "`%s` is moved from local version to sha `%s`"
dep-alias
actual-sha))
(update-deps-edn printers
local-app-dir
path
(-> dep
(dissoc :local/root)
(assoc :git/sha actual-sha
:git/url url)
(cond-> root (assoc :deps/root root))))))
(doseq [git-dep git-deps]
(let [{:keys [dep dep-alias path dir]} git-dep
{:git/keys [sha], :hephaistox/keys [url root]} dep
{:keys [actual-sha]} (retrieve-local-git dir git-subdir-data)]
(if (= sha actual-sha)
(normalln (format "`%s` is already uptodate sha `%s`"
dep-alias
actual-sha))
(do (normalln (format "`%s` is moved from sha `%s` to sha `%s`"
dep-alias
sha
actual-sha))
(update-deps-edn printers
local-app-dir
path
(-> dep
(dissoc :local/root)
(assoc :git/sha actual-sha
:git/url url)
(cond-> root (assoc :deps/root
root))))))))
(bb-deps-to-latest printers local-app-dir)
(recur (clojure.set/difference (into #{}
(concat rlocal-app-dirs
(mapv :dir git-deps)
(mapv :dir local-deps)))
local-app-dir-done)
(conj local-app-dir-done local-app-dir))))))

(defn run
"Move local references to latest git"
[{:keys [errorln uri-str], :as printers} cli-args]
(let [target (-> cli-args
first
str)
target-dir (project-dir target)]
(if-not (is-git-repo? target-dir)
(do (errorln "The target project"
(uri-str target-dir)
" s not a valid monorepo git repo")
(print-repos printers))
(move-to-latest printers target-dir))))
Loading