Skip to content

Commit

Permalink
Merge pull request #38 from pitch-io/building-with-tools-build
Browse files Browse the repository at this point in the history
Improve build process
  • Loading branch information
jo-sm authored Jun 16, 2023
2 parents cafc7a3 + b7687cd commit 7f9400c
Show file tree
Hide file tree
Showing 13 changed files with 215 additions and 18 deletions.
20 changes: 20 additions & 0 deletions .github/workflows/tests.yml
Original file line number Diff line number Diff line change
Expand Up @@ -42,6 +42,26 @@ jobs:
- name: Compile and run cljest tests
run: make jest-ci

cljest-analyze:
runs-on: ubuntu-latest
defaults:
run:
working-directory: cljest

steps:
- uses: actions/checkout@v3
- name: Setup java
uses: actions/setup-java@v3
with:
distribution: 'corretto'
java-version: '17'
- name: Setup Clojure
uses: DeLaGuardo/[email protected]
with:
cli: 1.11.1.1224
- name: Analyze with cljdoc-analyzer
run: make analyze

jest-preset-cljest-tests:
runs-on: ubuntu-latest
defaults:
Expand Down
4 changes: 2 additions & 2 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,6 @@ node_modules/
.shadow-cljs/
.cpcache/
.lsp/

cljest/dist/
cljest/reports/
pom.xml
cljest/target
11 changes: 11 additions & 0 deletions changelog.md
Original file line number Diff line number Diff line change
@@ -1,5 +1,16 @@
# Changelog

# Next

## Improvements

- [Fix `cljdoc-analyze` build.](https://github.com/pitch-io/cljest/pull/38)

## Internal

- [Build using `clojure.tools.build` instead of `applied-science/deps-library`.](https://github.com/pitch-io/cljest/pull/38)
- [Migrate from `applied-science/deps-library` to `deps-deploy` for Clojars deployment.](https://github.com/pitch-io/cljest/pull/38)

# 1.1.0

## Features
Expand Down
16 changes: 12 additions & 4 deletions cljest/Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -4,8 +4,7 @@ install:
npm i

clean:
rm -rf .jest
rm -rf .shadow-cljs
rm -rf .jest .shadow-cljs .cpcache dist

lint: install
clojure -A:fmt -M -m nsorg.cli src
Expand All @@ -19,8 +18,17 @@ lint-fix: install
./node_modules/.bin/eslint --fix .
./node_modules/.bin/prettier -w .

publish:
clj -A:publish -M -m deps-library.release
build: clean
clojure -A:dev -X cljest.build/main

analyze: build
clojure -A:dev -X cljest.analyze/main

install-local-jar: build
clj -A:dev -X cljest.deploy/main

publish-to-clojars: build
clj -A:dev -X cljest.deploy/main :clojars? true

server:
clojure -A:test -X cljest.compilation/watch
Expand Down
10 changes: 10 additions & 0 deletions cljest/build.edn
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
{:lib com.pitch/cljest
:version "1.1.0"
:scm {:url "https://github.com/pitch-io/cljest"
:connection "scm:git:https://github.com/pitch-io/cljest.git"
:developerConnection "scm:git:[email protected]:pitch-io/cljest.git"}
:src-dirs ["src"]
:ignore [".*_test.cljs"]
:extra-paths ["../readme.md" "../docs"]
:optional-deps {re-frame/re-frame {:mvn/version "1.3.0"}
reagent/reagent {:mvn/version "1.2.0"}}}
5 changes: 4 additions & 1 deletion cljest/deps.edn
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,10 @@
:paths ["src"]
:aliases {:fmt {:extra-deps {cljfmt/cljfmt {:mvn/version "0.9.2"}
nsorg-cli/nsorg-cli {:mvn/version "0.3.1"}}}
:publish {:extra-deps {appliedscience/deps-library {:mvn/version "0.3.4"}}}
:dev {:extra-deps {io.github.clojure/tools.build {:mvn/version "0.9.4"}
io.github.cljdoc/cljdoc-analyzer {:git/sha "2983ed108d9a44ab1c26cd0f4a0d85425893bb62"}
slipset/deps-deploy {:mvn/version "0.2.1"}}
:extra-paths ["dev"]}
:test {:extra-paths ["example_tests"]
:extra-deps {com.pitch/uix.core {:mvn/version "0.8.1"}
com.pitch/uix.dom {:mvn/version "0.8.1"}
Expand Down
14 changes: 14 additions & 0 deletions cljest/dev/cljest/analyze.clj
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
(ns cljest.analyze
(:require cljdoc-analyzer.cljdoc-main
[cljest.build :as build]))

(defn main
"Runs a `cljdoc-analyzer` analysis. Requires the JAR and POM to be built
(the `cljest.build/main` function needs to be run first)."
[& _]
(let [build-config (build/get-build-config)
analysis-config {:version (:version build-config)
:project (str (:lib build-config))
:jarpath (build/jar-path)
:pompath (build/pom-path)}]
(cljdoc-analyzer.cljdoc-main/-main (str analysis-config))))
111 changes: 111 additions & 0 deletions cljest/dev/cljest/build.clj
Original file line number Diff line number Diff line change
@@ -0,0 +1,111 @@
(ns cljest.build
(:require [clojure.data.xml :as xml]
[clojure.edn :as edn]
[clojure.java.io :as io]
[clojure.string :as str]
[clojure.tools.build.api :as tools.build.api]
[clojure.tools.build.tasks.write-pom :as tools.build.tasks.write-pom]))

;; Adapted from https://github.com/mentat-collective/Mafs.cljs/blob/60a074ee8720c3252f1364cf8ea7a3fdac3e6c87/build.clj#L7-L15
(xml/alias-uri 'pom "http://maven.apache.org/POM/4.0.0")

(alter-var-root
#'tools.build.tasks.write-pom/to-dep
(fn [orig]
;; This isn't really clean. `to-dep` seems to drop `original?` because of the `?`,
;; but that's an implementation detail. Since this whole thing is a hack it's
;; "fine".
(fn [[_ {:keys [optional?]} :as pair]]
(cond-> (orig pair)
optional?
(conj [::pom/scope "provided"])))))

(defn get-build-config
"Reads the build config from `build.edn`. Assumes you execute whatever uses this
in the same pwd as where the file lives."
[]
(-> "build.edn"
io/file
slurp
edn/read-string))

(defn ^:private lib->group-id
[lib]
(-> lib
str
(str/split #"/")
first))

(defn jar-path
"Returns the built JAR path. Throws if a JAR for the current build version
doesn't exist."
[]
(let [{:keys [lib version]} (get-build-config)
raw-file (io/file (str "dist/" lib "-" version ".jar"))]
(if (.exists raw-file)
(.getCanonicalPath raw-file)
(throw (ex-info (str "JAR file for cljest " version " does not exist. Ensure that cljest has been built.") {})))))

(defn pom-path
"Returns the generated POM path. Throws if a POM for the current build version
doesn't exist."
[]
(let [{:keys [lib]} (get-build-config)
group-id (lib->group-id lib)
raw-file (io/file (str "dist/" group-id "/pom.xml"))]
(if (.exists raw-file)
(.getCanonicalPath raw-file)
(throw (ex-info (str "POM file for cljest does not exist. Ensure that cljest has been built.") {})))))

(defn main
"Builds the JAR and POM files for the current version of `cljest`, as defined in `build.edn`."
[& _]
(let [{:keys [version optional-deps lib extra-paths ignore src-dirs scm]} (get-build-config)
basis (tools.build.api/create-basis {:project "deps.edn"
;; `optional-deps` are still added to the POM, so that tools such as
;; `cljdoc-analyzer` can work correctly, but are marked as "provided",
;; meaning they are "provided" by the user. This isn't supported in
;; `deps.edn` or in `write-pom` (yet?), so until it is supported we need
;; to hack around it.
;;
;; This is hacky for a couple of reasons. 1. The obvious: we need to alter
;; `tools.build.tasks.write-pom/to-dep` to understand `optional?`; and,
;; 2. the `optional?` is implicitly dropped from the POM generation because
;; POM properties aren't munged and instead silently dropped at some point if
;; they can't be serialized.
;;
;; I think this is okay since whatever the official solution is will likely
;; require some change anyway, so it's fine to be hacky here.
;;
;; See https://ask.clojure.org/index.php/9110 and https://ask.clojure.org/index.php/12817.
:extra {:deps (->> optional-deps
(map (fn [[k v]]
[k (assoc v :optional? true)]))
(into {}))}})
jar-dir "dist/build_files/jar"
pom-dir (str "dist/" (lib->group-id lib))]
(tools.build.api/copy-dir {:src-dirs src-dirs
:target-dir jar-dir
:ignores (map re-pattern ignore)})

(doseq [path extra-paths]
(let [instance (io/file path)
dir? (.isDirectory instance)]
(if dir?
(tools.build.api/copy-dir {:target-dir (str jar-dir "/" (.getName instance))
:src-dirs [path]})
(tools.build.api/copy-file {:target (str jar-dir "/" (.getName instance))
:src path}))))

(tools.build.api/jar {:class-dir jar-dir
:jar-file (str "dist/" lib "-" version ".jar")})

(tools.build.api/delete {:path "dist/build_files"})

(tools.build.api/write-pom {:target pom-dir
:lib lib
:version version
:basis basis
:scm scm
:src-dirs ["src"]})))

14 changes: 14 additions & 0 deletions cljest/dev/cljest/deploy.clj
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
(ns cljest.deploy
(:require [cljest.build :as build]
[deps-deploy.deps-deploy :as deps-deploy]))

(defn main
"Publishes the library. By default publishes locally, and publishes to
Clojars if called with `:clojars? true`."
[{:keys [clojars?]}]
(prn clojars?)
(let [installer (if clojars? :remote :local)]
(deps-deploy/deploy {:artifact (build/jar-path)
:pom-file (build/pom-path)
:sign-release? false
:installer installer})))
2 changes: 1 addition & 1 deletion cljest/package-lock.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

4 changes: 0 additions & 4 deletions cljest/release.edn

This file was deleted.

4 changes: 2 additions & 2 deletions cljest/src/cljest/compilation/config.clj
Original file line number Diff line number Diff line change
Expand Up @@ -79,7 +79,7 @@
"\n\n"
(str/join "\n" (map humanize-error errors)))))))))

(defn ^:private ^:no-doc load-config!
(defn ^:private load-config!
"Loads the cljest.edn file and coerces based on the Malli schema."
[]
(let [config-io (io/file "cljest.edn")]
Expand All @@ -92,7 +92,7 @@
config (coerce-config-with-pretty-exception! raw-config)]
(reset! !config config))))

(defn ^:no-doc get-config!
(defn get-config!
"Returns the coerced config. If it hasn't been loaded yet, load it."
[]
(if-not @!config
Expand Down
18 changes: 14 additions & 4 deletions cljest/src/cljest/core.clj
Original file line number Diff line number Diff line change
Expand Up @@ -5,12 +5,20 @@
cljs.env
[malli.core :as malli]))

(def ^:private user-defined-formatters-ns (some-> (config/get-config!)
(def ^:dynamic *formatters-set?* false)

(defn ^:private set-formatters!
[]
(when-not *formatters-set?*
(when-let [user-defined-formatters-ns (some-> (config/get-config!)
(get :formatters-ns)
symbol))
symbol)]
(when user-defined-formatters-ns
(require `[~user-defined-formatters-ns])))

(when user-defined-formatters-ns
(require `[~user-defined-formatters-ns]))
;; I don't want this to be set in a binding, I _really_ want this to be set
;; to true once we load the formatters.
(alter-var-root #'*formatters-set?* (constantly true))))

(defmacro describe
"Describes a block of tests. Any `before-each`/`after-each` inside of this block will be scoped to it.
Expand Down Expand Up @@ -203,6 +211,8 @@
(it \"should be true\"
(is (= true (my-fn :some-keyword)))"
[form]
(set-formatters!)

(if (seq? form)
`(complex-is ~form)
`(primitive-is ~form false)))

0 comments on commit 7f9400c

Please sign in to comment.