Improve release automation.#466
Conversation
a4c8db8 to
805d813
Compare
|
|
|
@frenchy64 Addressed all your comments. Thanks! |
| #?(:clj [ctim.lib.generators :as gen]) | ||
| [ctim.lib.predicates :as pred] | ||
| [ctim.schemas.vocabularies :as v] | ||
| #?(:clj [ctim.version :refer [ctim-version]]) |
There was a problem hiding this comment.
This might work as-is in cljs. https://clojurescript.org/guides/ns-forms#_implicit_refer
Try removing the reader conditionals. If not, maybe we need to bump our cljs version.
There was a problem hiding this comment.
Okay, so this doesn't work either. I think I understand why both this and :include-macros true don't work now.
Why ':include-macros true' doesn't work
Given an ns defined in file bar.clj (note extension .clj)
Given a file foo.cljs(note extension .cljs) with the following content:
(ns foo (:require [bar :include-macros true]))
desugars to:
(ns foo (:require-macros [bar])
(:require [bar]))
The presence of both :require and :require-macros causes the cljs compiler to look for both clj and cljs namespaces foo, but there's only the clojure one.
Why implicit refer doesn't work
IIUC, the implicit refer also only works for scenarios where there is both a clj and cljs ns (with the additional constraint that the cljs dependency ns declares :require-macros on the clj ns of the same name).
There was a problem hiding this comment.
So, given that the macro is defined in a plain clj ns and that we are working in a cljc file where both of the resulting clj and cljs namespaces depend on the same macro, it is necessary for the cljs ns to declare a dependency on the macro ns using only :require-macros. And the only way to achieve that (I think) is for the cljc file to have separate :clj and :cljs conditionals.
There was a problem hiding this comment.
Another possibility is doing it all in the same file:
(ns ctim.schemas.common
#?(:cljs (:require-macros [ctim.schemas.common :refer [ctim-version]]))
...
#?(:clj
(defmacro ctim-version
"This is a macro to support cljs compile-time inlining of the version string
from the JVM resource."
[]
(slurp (io/resource "ctim/version.txt"))))
(def ctim-schema-version (ctim-version))
Which I actually don't hate. It looks a little convoluted. But I'm not sure its worse than the separate file solution. If anything it's just making the quirks easier to see.
There was a problem hiding this comment.
I meant I think there's a way to avoid reader conditionals and :require-macros altogether.
i.e., instead of
(ns ctim.schemas.common
#?(:cljs (:require-macros [ctim.version :refer [ctim-version]]))
(:require [ctim.version :refer [ctim-version]]))try
(ns ctim.schemas.common
(:require [ctim.version :refer [ctim-version]]))or
(ns ctim.schemas.common
(:require [ctim.version :as cv]))Failing all that, this might work:
(ns ctim.schemas.common
(#?(:clj :require :cljs :require-macros) [ctim.version :refer [ctim-version]]))There was a problem hiding this comment.
Yeah, I had tried your first suggestion. That's what I'm calling "implicit refer" (term is from that clojurescript doc) in my message above.
Your second suggestion does work fine, let's do it. I didn't realize it would let you have multiple :requires.
| (:require [clj-momo.lib.clj-time.coerce :refer [to-long]] | ||
| #?(:clj [clojure.java.io :as io]) | ||
| [clojure.set :refer [map-invert]] | ||
| [clojure.string :as str] |
There was a problem hiding this comment.
Can remove requires of clojure.java.io and clojure.string.
There was a problem hiding this comment.
I'm not sure what the state of things was at the time of this comment, but as it stands:
clojure.stringis still imported because it's used.clojure.java.iois removed.
| ["vcs" "tag" "--no-sign"] | ||
| ["deploy" "clojars"] | ||
| ["change" "version" "leiningen.release/bump-version"] | ||
| ["sync-schema-version"] |
There was a problem hiding this comment.
I think we always want to update the docs when we bump versions, and vice-versa.
Please redefine the "doc" alias to do the equivalent of running ctim.change-schema-version/-main followed by ctim.document/-main.
| # Patch version releases (minor and major increments require a manual edit of version). | ||
| # Expect this task to modify project files and deploy to Clojars. | ||
| # See `release-tasks` in project.clj for details. | ||
| lein release |
There was a problem hiding this comment.
This is already recommended a few lines down. Could you consolidate them and separate the instructions so it doesn't look like you should execute them blindly top-to-bottom? I'm often in a hurry when reading this section.
There was a problem hiding this comment.
Yeah, I'll work on this tomorrow morning when my brain is fresh. I think there is more to do here too, such as warn about the mistakes I made when doing my release 😃 .
Includes automation for synchronizing the project version and CTIM schema version.
ac2e12b to
84a901e
Compare
- Simplify cljs macro require using reader conditional on :require/:require-macros - Remove unused clojure.java.io require - Consolidate "doc" alias to sync schema version and generate docs together - Restructure README release instructions for clarity Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
- Fix change_schema_version to write to resources/ctim/version.txt - Sync version.txt to current project version (1.3.30-SNAPSHOT) - Remove stale resources/version.txt - Rewrite release docs: add pre-release steps, split recovery scenarios Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
frenchy64
left a comment
There was a problem hiding this comment.
I like that the project.clj is the source of truth.
| (ns ctim.version | ||
| (:require [clojure.java.io :as io])) | ||
|
|
||
| (defmacro ctim-version |
There was a problem hiding this comment.
This may be me misunderstanding how cljs works, but I'm unclear why this needs to be a macro
There was a problem hiding this comment.
The initial problem here was that you'd need to manually update (def ctim-schema-version "1.3.30") every release with the new version. If you forgot, the version was desynced from project.clj
We considered two main solutions.
- Have leiningen write the new version directly to this def on version change.
- Create a separate file with the version that we refer to.
This implements 2. The reason it needs to be a macro is that cljs doesn't implement io/resource or slurp, so we need get the version string via JVM Clojure. Macros are expanded in JVM Clojure.
There was a problem hiding this comment.
It's been a minute since I wrote this, but I think what's happening is that clojurescript needs to read the resource that holds the version at compile time, and having it as a macro allows the code to be evaluated at compile time instead of runtime.
There was a problem hiding this comment.
If I recall correctly, @frenchy64 and I had a lot of back-and-forth about how to keep the CTIM library and schema versions in sync, only some of which seems to be captured in the PR comments. Several ideas were considered, and the one we ended up with involves this version file and the need for the clj/cljs code to read from it to get the schema version.
There was a problem hiding this comment.
Oh, I hadn't seen @frenchy64's comment. He explains it better.
Updated 2026-03-16 to reflect all changes made during the review process.
Made these changes in consultation with @frenchy64.
resources/ctim/version.txtvia actim-versionmacro (supports both clj and cljs).sync-schema-versionlein alias to updateresources/ctim/version.txtto match the lein project version.sync-schema-versioninto:release-tasksso the version file stays in sync across version bumps."doc"lein alias to sync the schema version before generating documentation.script/release.shand rewrite README release instructions.