From f499d2d154ea7fdf0ac2b7284938345a26b97a08 Mon Sep 17 00:00:00 2001 From: Geoffrey Gaillard Date: Fri, 6 Sep 2024 13:21:20 +0200 Subject: [PATCH] Cleanup and document cljdoc fix --- deps.edn | 23 +++++++++++++++++------ src-build/build.clj | 28 ++++------------------------ src-build/build.md | 39 +++++++++++++++++++++++++++++++++++++++ 3 files changed, 60 insertions(+), 30 deletions(-) diff --git a/deps.edn b/deps.edn index 13cfa3931..6b522d2b5 100644 --- a/deps.edn +++ b/deps.edn @@ -17,17 +17,28 @@ :test {:extra-paths ["test"] :exec-fn cognitect.test-runner.api/test :jvm-opts ["-Dhyperfiddle.rcf.generate-tests=true" "-XX:-OmitStackTraceInFastThrow"] ;; https://archive.md/NNt9r - :extra-deps {org.clojure/core.async {:mvn/version "1.6.681", :hyperfiddle.electric.cljdoc/include? true} ; for interop helpers only + :extra-deps {org.clojure/core.async {:mvn/version "1.6.681"} ; for interop helpers only ch.qos.logback/logback-classic {:mvn/version "1.4.14"} io.github.cognitect-labs/test-runner {:git/url "https://github.com/cognitect-labs/test-runner.git" :sha "cc75980b43011773162b485f46f939dc5fba91e4"} org.clojure/test.check {:mvn/version "1.1.1"} - com.datomic/local {:mvn/version "1.0.285", :hyperfiddle.electric.cljdoc/include? true} ; for hyperfiddle.transaction-test - com.datomic/client-cloud {:mvn/version "1.0.130", :hyperfiddle.electric.cljdoc/include? true} ; for hyperfiddle.transaction-test + com.datomic/local {:mvn/version "1.0.285"} ; for hyperfiddle.transaction-test + com.datomic/client-cloud {:mvn/version "1.0.130"} ; for hyperfiddle.transaction-test thheller/shadow-cljs {:mvn/version "2.26.2"} ; for hooks tests - ring/ring-core {:mvn/version "1.11.0", :hyperfiddle.electric.cljdoc/include? true} - http-kit/http-kit {:mvn/version "2.5.1", :hyperfiddle.electric.cljdoc/include? true} + ring/ring-core {:mvn/version "1.11.0"} + http-kit/http-kit {:mvn/version "2.5.1"} }} :build {:extra-paths ["src-build"] :ns-default build :extra-deps {io.github.clojure/tools.build {:mvn/version "0.9.6"} - slipset/deps-deploy {:mvn/version "0.2.2"}}}}} + slipset/deps-deploy {:mvn/version "0.2.2"}}} + ;; cljdoc loads all namespaces (even flagged ^:no-doc) and requires all deps to be listed in pom.xml + ;; Our build script will include the following deps. + ;; :pom/scope "provided" means it's up to the artifact's consumer to decide if they actually want + ;; to load the dep at runtime. :pom/scope is not part of standard clojure deps or tools.build, our + ;; build script interprets it. + :cljdoc-extra-deps + {:extra-deps {org.clojure/core.async {:mvn/version "1.6.681", :pom/scope "provided"} + com.datomic/local {:mvn/version "1.0.285", :pom/scope "provided"} + com.datomic/client-cloud {:mvn/version "1.0.130", :pom/scope "provided"} + ring/ring-core {:mvn/version "1.11.0", :pom/scope "provided"} + http-kit/http-kit {:mvn/version "2.5.1", :pom/scope "provided"}}}}} diff --git a/src-build/build.clj b/src-build/build.clj index 0ff55a6d0..87b87b637 100644 --- a/src-build/build.clj +++ b/src-build/build.clj @@ -3,7 +3,6 @@ (:require [clojure.data.xml :as xml] [clojure.tools.build.api :as b] [clojure.tools.build.tasks.write-pom :as wp] - [clojure.tools.deps.util.maven :as maven] [deps-deploy.deps-deploy :as dd])) (def lib 'com.hyperfiddle/electric) @@ -15,10 +14,7 @@ (defn extend-basis [basis deps] (b/create-basis (update (:basis-config basis) :extra merge {:deps deps}))) -(defn cljdoc-deps [deps] - (into {} (filter (fn [[_k v]] (contains? v :hyperfiddle.electric.cljdoc/include?)) deps))) - -(def basis-with-cljdoc-provided-deps (->> (alias-deps basis :test) cljdoc-deps (extend-basis basis))) +(def basis-with-cljdoc-provided-deps (extend-basis basis (alias-deps basis :cljdoc-extra-deps))) (def class-dir "target/classes") @@ -29,9 +25,10 @@ (xml/alias-uri 'pom "http://maven.apache.org/POM/4.0.0") (let [original @#'wp/to-dep] - (defn to-dep [[lib {:keys [hyperfiddle.electric.cljdoc/include?] :as coord}]] + (defn to-dep ; Add support for tools.build POM generation. For cljdoc extra deps. + [[lib {:keys [pom/scope] :as coord}]] (cond-> (original [lib coord]) - include? (conj [::pom/scope "provided"])))) + scope (conj [::pom/scope "provided"])))) (defn jar [{:keys [version] :or {version version}}] (let [jar-file (format "target/%s-%s.jar" (name lib) version) @@ -76,20 +73,3 @@ :basis basis :javac-opts ["-source" "8" "-target" "8"]})) - -;; To run cljdoc analysis locally: -;; 1 - build jar -;; 2 - instal -;; 3 - run next to deps.edn: -;; mkdir -p .cljdoc-preview -;; docker run --rm \ -;; --volume $(pwd) \ -;; --volume "$HOME/.m2:/root/.m2" \ -;; --volume ./.cljdoc-preview \ -;; --platform linux/amd64 \ -;; --entrypoint clojure \ -;; cljdoc/cljdoc -Sforce -M:cli ingest \ -;; --project com.hyperfiddle/electric \ -;; --version $HYPERFIDDLE_ELECTRIC_BUILD -;; --git . \ -;; --rev $(git rev-parse HEAD) diff --git a/src-build/build.md b/src-build/build.md index 4eba6f1cd..114392184 100644 --- a/src-build/build.md +++ b/src-build/build.md @@ -25,3 +25,42 @@ env $(cat .env | xargs) clojure -T:build deploy :version '"'$HYPERFIDDLE_ELECTRI - `CLOJARS_PASSWORD` is not your account password, but rather a genareted token granting deploy rights to the target coordinates. - idea: how to run tests cli? (No need, deployed artifacts already passed CI) + + +# About cljdoc + +Cljdoc always try to generate documentation for all clojars deployments. +It will load and analyze all namespaces on the classpath. +Namespaces tagged with ^:no-doc will not generate documentation, but they will still be loaded. + +Cljdoc requires: +- that all namespaces on the classpath be loadable (as per clojure.core/require), +- that all eventual dependencies required in classpath be listed in pom.xml. + +Consequently, dependencies for all namespaces on classpath must be listed in the +**production** release's pom. This is inconvenient because we ship optional +namespaces in the prod artifact, like `contrib.datomic` and +`contrib.missionary-core-async` but we don't want to force a dependency on +datomic or core.async onto users. + +To mitigate this issue, [cljdoc advises to list optional dependencies in our +pom.xml as `provided`](https://github.com/cljdoc/cljdoc/blob/94cbf3c357695a5a32e3c81a5f2bcdb77b3e2436/doc/userguide/for-library-authors.adoc#getting-dependencies-right), +BUT `clojure.deps` and `tools.build` do not support scopes. +Cljdoc advises to manually edit our pom.xml. We find this too error-prone to be acceptable. + +We adapted our build script to generate the correct pom.xml. The generated pom +will production deps + all deps listed under the `:cljdoc-extra-deps` alias. +These deps should be tagged with `:pom/scope "provided"`: + +```clojure +{:aliases {:cljdoc-extra-deps {:extra-deps {org.clojure/core.async {:mvn/version "1.6.681", :pom/scope "provided"}}}}} +``` + +`:pom/scope` is not supported by clojure.deps nor tools.build. Our build script interprets it. + +## cljdoc and clojurescript analyzis + +cljdoc analyzes cljs and cljc files with cljs.analyzer to detect all defs after +macroexpansion. As of today, cljdoc fails to analyze files containing e/defns. +For now cljdoc do not list cljs namespaces and cljs-only vars. +