{"id":19167530,"url":"https://github.com/tomekw/cdeps","last_synced_at":"2025-05-07T13:41:35.734Z","repository":{"id":137921854,"uuid":"195408776","full_name":"tomekw/cdeps","owner":"tomekw","description":"Clojure + deps.edn, a basic guide.","archived":false,"fork":false,"pushed_at":"2020-06-09T07:39:07.000Z","size":4,"stargazers_count":21,"open_issues_count":2,"forks_count":2,"subscribers_count":1,"default_branch":"master","last_synced_at":"2025-04-19T23:31:50.602Z","etag":null,"topics":["clojure","edn"],"latest_commit_sha":null,"homepage":"https://tomekw.com/clojure-deps-edn-a-basic-guide/","language":"Clojure","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":null,"status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/tomekw.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":".github/FUNDING.yml","license":null,"code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null},"funding":{"github":["tomekw"]}},"created_at":"2019-07-05T12:51:07.000Z","updated_at":"2024-12-12T14:09:11.000Z","dependencies_parsed_at":null,"dependency_job_id":"5996fd0c-8526-4a22-a6f1-f74602164792","html_url":"https://github.com/tomekw/cdeps","commit_stats":null,"previous_names":[],"tags_count":0,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/tomekw%2Fcdeps","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/tomekw%2Fcdeps/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/tomekw%2Fcdeps/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/tomekw%2Fcdeps/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/tomekw","download_url":"https://codeload.github.com/tomekw/cdeps/tar.gz/refs/heads/master","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":252889119,"owners_count":21820119,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["clojure","edn"],"created_at":"2024-11-09T09:38:07.922Z","updated_at":"2025-05-07T13:41:35.712Z","avatar_url":"https://github.com/tomekw.png","language":"Clojure","funding_links":["https://github.com/sponsors/tomekw"],"categories":[],"sub_categories":[],"readme":"# cdeps\nClojure + deps.edn, a basic guide.\n\nAfter a rather long break from programming and Clojure I decided give them another go. When it comes to managing Clojure\nprojects, [Leiningen](https://leiningen.org/) is de-facto standard tool. Recently,\n[Clojure CLI tools](https://clojure.org/guides/deps_and_cli) are becoming more and more popular, though. Switching to \nyet-another-build-tool doesn't have any pragmatic value, but it's perfect for learning purposes.\n\nFrom a build tool I expect it to perform certain tasks:\n1. Creating a project.\n1. Managing source and tests paths.\n1. Managing dependencies.\n1. Running tests.\n1. Building a self-contained JAR, a.k.a. uberjar.\n1. Managing outdated dependencies.\n\nLet's see how it's performed using Clojure CLI tools, a.k.a. deps.edn.\n\n## Creating a project\nLeiningen allows to generate a project structure simply by invoking:\n```bash\n$ lein new [template] [project-name]\n```\nWe get a lot for free, but is it really needed? How is it done with Clojure CLI tools?\n\nImagine a simple project. It allows add and divide numbers, it also prints some example calculations when invoked.\nWe can start by simply creating a new directory:\n```bash\n$ mkdir cdeps \u0026\u0026 cd cdeps\n```\nNow, let's add an empty `deps.edn` file:\n```clojure\n;; /deps.edn\n{}\n```\nAnd now we can start adding some actual code to the project.\n\n## Managing source and tests paths\nTo demonstrate the feature of managing source paths we will put our code at `src/main/clojure`.\n```bash\n$ mkdir -p src/main/clojure\n```\n`deps.edn` is no magic so we can just set the path in the file:\n```clojure\n;; deps.edn\n{:paths [\"src/main/clojure\"]}\n```\nNow, we can write the calculator code:\n```clojure\n;; src/main/clojure/com/tomekw/cdeps/calculator.clj\n(ns com.tomekw.cdeps.calculator)\n\n(defn plus [a b]\n  (+ a b))\n\n(defn divide [a b]\n  (/ a b))\n```\n\n## Managing dependencies\nIn such a simple project there is no real need to add external dependencies. We can always specify the Clojure version\nwe would like to use, though:\n```clojure\n;; deps.edn\n{:paths [\"src/main/clojure\"]\n :deps  {org.clojure/clojure {:mvn/version \"1.10.1\"}}}\n```\nClojure CLI tools allow to specify local and git dependencies too, see\n[documentation and more examples](https://clojure.org/guides/deps_and_cli#_using_local_libraries).\n\n## Running tests\nThe calculator we wrote is super simple but we can still write some tests:\n```clojure\n;; test/main/clojure/com/tomekw/cdeps/calculator_test.clj\n(ns com.tomekw.cdeps.calculator-test\n  (:require [clojure.test :refer :all]\n            [com.tomekw.cdeps.calculator :refer :all]))\n\n(deftest adding-numbers\n  (is (= 4 (plus 2 2))))\n\n(deftest dividing-numbers\n  (is (= 2 (divide 4 2))))\n\n(deftest dividing-numbers-by-zero\n  (is (thrown? ArithmeticException (divide 1 0))))\n```\nNow we need to run them to make sure they pass. We have to add an alias (a command we will run), and a test runner,\nas an extra dependency. I picked [kaocha](https://github.com/lambdaisland/kaocha). Also, we need to tell the runner\nwhere the tests are located:\n```clojure\n;; deps.edn\n{:paths   [\"src/main/clojure\"]\n :deps    {org.clojure/clojure {:mvn/version \"1.10.1\"}}\n :aliases {:test {:extra-paths [\"test/main/clojure\"]\n                  :extra-deps  {lambdaisland/kaocha {:mvn/version \"0.0-529\"}}\n                  :main-opts   [\"-m\" \"kaocha.runner\"]}}}\n```\nHere is the test report:\n```bash\n$ clj -Atest\n[(...)]\n3 tests, 3 assertions, 0 failures.\n```\n\n## Building a self-contained JAT, a.k.a. uberjar\nPresume, we would like to print example calculations to the console. Let's add the code to do that:\n```clojure\n;; src/main/clojure/com/tomekw/cdeps/core.clj\n(ns com.tomekw.cdeps.core\n  (:gen-class)\n  (:require [com.tomekw.cdeps.calculator :refer :all]))\n\n(defn -main [\u0026 args]\n  (do (println (format \"2 + 2 is %s\" (plus 2 2)))\n      (println (format \"4 / 2 is %s\" (divide 4 2)))))\n```\nTo run the main function we can invoke the following command:\n```bash\n$ clj -m com.tomekw.cdeps.core\n2 + 2 is 4\n4 / 2 is 2\n```\nIt could be burdensome for the users of our calculator to install Clojure. To avoid this, we can package our project\nas a standalone Java JAR. There is number of tools to do that, like [cambada](https://github.com/luchiniatwork/cambada),\nbut I've decided to try out [uberdeps](https://github.com/tonsky/uberdeps). Let's add a proper configuration first:\n```clojure\n;; deps.edn\n{:paths   [\"src/main/clojure\"]\n :deps    {org.clojure/clojure {:mvn/version \"1.10.1\"}}\n :aliases {:test    {:extra-paths [\"test/main/clojure\"]\n                     :extra-deps  {lambdaisland/kaocha {:mvn/version \"0.0-529\"}}\n                     :main-opts   [\"-m\" \"kaocha.runner\"]}\n           :uberjar {:extra-deps {uberdeps {:mvn/version \"0.1.4\"}}\n                     :main-opts  [\"-m\" \"uberdeps.uberjar\" \"--target\" \"target/cdeps-0.1.0.jar\"]}}}\n```\nTo package the project we simply run:\n```bash\n$ clj -Auberjar\n[uberdeps] Packaging target/cdeps-0.1.0.jar...\n+ src/main/clojure/**\n+ org.clojure/clojure 1.10.1\n.   org.clojure/core.specs.alpha 0.2.44\n.   org.clojure/spec.alpha 0.2.176\n[uberdeps] Packaged target/cdeps-0.1.0.jar in 567 ms\n```\nAnd now we can run the project with Java:\n```bash\n$ java -cp target/cdeps-0.1.0.jar clojure.main -m com.tomekw.cdeps.core\n2 + 2 is 4\n4 / 2 is 2\n```\n\n## Managing outdated dependencies\nIt's often needed to manage the versions of all dependencies we put into our `deps.edn` file. There is a tool named\n[depot](https://github.com/Olical/depot):\n```clojure\n;; deps.edn\n{:paths   [\"src/main/clojure\"]\n :deps    {org.clojure/clojure {:mvn/version \"1.10.1\"}}\n :aliases {:test     {:extra-paths [\"test/main/clojure\"]\n                      :extra-deps  {lambdaisland/kaocha {:mvn/version \"0.0-529\"}}\n                      :main-opts   [\"-m\" \"kaocha.runner\"]}\n           :outdated {:extra-deps {olical/depot {:mvn/version \"1.8.4\"}}\n                      :main-opts  [\"-m\" \"depot.outdated.main\" \"-a\" \"outdated\"]}\n           :uberjar  {:extra-deps {uberdeps {:mvn/version \"0.1.4\"}}\n                      :main-opts  [\"-m\" \"uberdeps.uberjar\" \"--target\" \"target/cdeps-0.1.0.jar\"]}}}\n```\nEverything should be up to date:\n```bash\n$ clj -Aoutdated\nAll up to date!\n```\n\n## Summary\nThis guide covers basic use-cases in the daily workflow with Clojure. Of course there is alwats more than I presented\nhere, like deploying the project to [Clojars](https://clojars.org). The process is still not fully automated and I will\ntry to cover it with the next post.\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Ftomekw%2Fcdeps","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Ftomekw%2Fcdeps","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Ftomekw%2Fcdeps/lists"}