Clojure deps.edn Repositories

This section provides comprehensive documentation for configuring and using Clojure deps.edn (tools.deps) repositories with CloudRepo.

Overview

Clojure CLI and deps.edn represent the modern approach to dependency management in Clojure. Introduced as part of the official Clojure toolchain, tools.deps provides a lightweight, declarative system for managing dependencies directly from Maven repositories, Git repositories, and local projects.

What is deps.edn?

deps.edn is a configuration file that declares:

  • Dependencies: Libraries your project needs

  • Paths: Source and resource directories

  • Aliases: Optional configurations for different contexts (dev, test, build)

  • Repositories: Maven repositories to fetch dependencies from

Unlike Leiningen, which is a full build tool, deps.edn focuses solely on dependency management and classpath construction, following the Unix philosophy of doing one thing well.

Key Differences from Leiningen

Clojure CLI vs Leiningen

Feature

deps.edn / tools.deps

Leiningen

Philosophy

Minimal, composable tools

Comprehensive build tool

Configuration

EDN format (deps.edn)

Clojure format (project.clj)

Build Tasks

Via tools (tools.build)

Built-in task system

Dependency Resolution

Maven + Git + Local

Primarily Maven

JAR Creation

Requires additional tools

Built-in uberjar support

Why Private Maven Repositories for Clojure?

Clojure teams need private repositories to:

  • Share Internal Libraries: Distribute proprietary Clojure/ClojureScript libraries across teams

  • Control Dependencies: Manage approved versions of both Clojure and Java libraries

  • Integrate with Java Ecosystem: Clojure runs on the JVM and seamlessly uses Java libraries

  • Cache Dependencies: Improve build performance and reliability

  • Ensure Reproducible Builds: Guarantee consistent dependency resolution

CloudRepo provides fully managed Maven repositories that work seamlessly with deps.edn, eliminating infrastructure overhead while providing enterprise-grade security.

Prerequisites

Before configuring deps.edn with CloudRepo, ensure you have:

  1. Clojure CLI Installed: Version 1.11.0 or later

  2. CloudRepo Repository: A Maven-type repository created in the CloudRepo Admin Portal

  3. Repository User: A dedicated user with appropriate permissions

If you haven’t completed these steps, please refer to:

Important

Admin users cannot directly access repositories. Always create dedicated repository users for artifact access.

Note

CloudRepo repositories use the following URL format: https://[organization-id].mycloudrepo.io/repositories/[repository-id]

deps.edn Configuration

Basic Repository Setup

Configure CloudRepo in your deps.edn file:

deps.edn - Basic CloudRepo Configuration
1{:deps {org.clojure/clojure {:mvn/version "1.11.1"}
2        ;; Your private library from CloudRepo
3        com.yourcompany/internal-lib {:mvn/version "1.0.0"}}
4
5 :paths ["src" "resources"]
6
7 :mvn/repos {"cloudrepo" {:url "https://your-org.mycloudrepo.io/repositories/your-repo"}
8             "central" {:url "https://repo1.maven.org/maven2/"}
9             "clojars" {:url "https://repo.clojars.org/"}}}

Authentication Configuration

Clojure CLI uses Maven’s settings.xml for repository authentication. Create or update ~/.m2/settings.xml:

~/.m2/settings.xml - CloudRepo Authentication
 1<?xml version="1.0" encoding="UTF-8"?>
 2<settings xmlns="http://maven.apache.org/SETTINGS/1.0.0"
 3          xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
 4          xsi:schemaLocation="http://maven.apache.org/SETTINGS/1.0.0
 5                              https://maven.apache.org/xsd/settings-1.0.0.xsd">
 6  <servers>
 7    <server>
 8      <id>cloudrepo</id>
 9      <username>your-username</username>
10      <password>your-password</password>
11    </server>
12  </servers>
13</settings>

Warning

Never commit credentials to version control. Use environment variables for CI/CD environments.

Environment Variable Configuration

For better security, use environment variables in settings.xml:

~/.m2/settings.xml - Environment Variables
 1<?xml version="1.0" encoding="UTF-8"?>
 2<settings xmlns="http://maven.apache.org/SETTINGS/1.0.0"
 3          xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
 4          xsi:schemaLocation="http://maven.apache.org/SETTINGS/1.0.0
 5                              https://maven.apache.org/xsd/settings-1.0.0.xsd">
 6  <servers>
 7    <server>
 8      <id>cloudrepo</id>
 9      <username>${env.CLOUDREPO_USERNAME}</username>
10      <password>${env.CLOUDREPO_PASSWORD}</password>
11    </server>
12  </servers>
13</settings>

Set environment variables:

Setting Environment Variables
1# Linux/macOS
2export CLOUDREPO_USERNAME="your-username"
3export CLOUDREPO_PASSWORD="your-password"
4
5# Windows
6set CLOUDREPO_USERNAME=your-username
7set CLOUDREPO_PASSWORD=your-password

Multiple Repository Configuration

Configure multiple CloudRepo repositories for different artifact types:

deps.edn - Multiple Repositories
 1{:deps {org.clojure/clojure {:mvn/version "1.11.1"}
 2        com.yourcompany/core-lib {:mvn/version "2.1.0"}
 3        com.yourcompany/utils {:mvn/version "1.3.0"}}
 4
 5 :paths ["src" "resources"]
 6
 7 :mvn/repos {"cloudrepo-releases" {:url "https://your-org.mycloudrepo.io/repositories/releases"}
 8             "cloudrepo-snapshots" {:url "https://your-org.mycloudrepo.io/repositories/snapshots"}
 9             "central" {:url "https://repo1.maven.org/maven2/"}
10             "clojars" {:url "https://repo.clojars.org/"}}}

Add corresponding entries in settings.xml:

~/.m2/settings.xml - Multiple Repositories
 1<servers>
 2  <server>
 3    <id>cloudrepo-releases</id>
 4    <username>${env.CLOUDREPO_USERNAME}</username>
 5    <password>${env.CLOUDREPO_PASSWORD}</password>
 6  </server>
 7  <server>
 8    <id>cloudrepo-snapshots</id>
 9    <username>${env.CLOUDREPO_USERNAME}</username>
10    <password>${env.CLOUDREPO_PASSWORD}</password>
11  </server>
12</servers>

Publishing Clojure Libraries

deps-deploy Setup

deps-deploy is the standard tool for deploying artifacts from deps.edn projects:

deps.edn - deps-deploy Alias
 1{:deps {org.clojure/clojure {:mvn/version "1.11.1"}}
 2
 3 :paths ["src" "resources"]
 4
 5 :aliases {:deploy {:extra-deps {slipset/deps-deploy {:mvn/version "0.2.2"}}
 6                    :exec-fn deps-deploy.deps-deploy/deploy
 7                    :exec-args {:installer :remote
 8                                :sign-releases? false
 9                                :repository {"cloudrepo"
10                                            {:url "https://your-org.mycloudrepo.io/repositories/your-repo"
11                                             :username :env/cloudrepo_username
12                                             :password :env/cloudrepo_password}}
13                                :artifact "target/your-library.jar"}}}}

Deploy your library:

Deploying with deps-deploy
1# Set credentials
2export CLOUDREPO_USERNAME="your-username"
3export CLOUDREPO_PASSWORD="your-password"
4
5# Deploy the artifact
6clojure -X:deploy

Using tools.build for JAR Creation

tools.build provides programmatic JAR creation:

build.clj - Complete Build Script
 1(ns build
 2  (:require [clojure.tools.build.api :as b]
 3            [deps-deploy.deps-deploy :as dd]))
 4
 5(def lib 'com.yourcompany/your-library)
 6(def version (format "1.0.%s" (b/git-count-revs nil)))
 7(def class-dir "target/classes")
 8(def jar-file (format "target/%s-%s.jar" (name lib) version))
 9
10;; Clean target directory
11(defn clean [_]
12  (b/delete {:path "target"}))
13
14;; Create JAR file
15(defn jar [_]
16  (clean nil)
17  (b/write-pom {:class-dir class-dir
18                :lib lib
19                :version version
20                :basis (b/create-basis {:project "deps.edn"})
21                :src-dirs ["src"]
22                :scm {:url "https://github.com/yourcompany/your-library"
23                      :connection "scm:git:git://github.com/yourcompany/your-library.git"
24                      :developerConnection "scm:git:ssh://git@github.com/yourcompany/your-library.git"
25                      :tag (str "v" version)}})
26  (b/copy-dir {:src-dirs ["src" "resources"]
27               :target-dir class-dir})
28  (b/jar {:class-dir class-dir
29          :jar-file jar-file}))
30
31;; Deploy to CloudRepo
32(defn deploy [_]
33  (jar nil)
34  (dd/deploy {:installer :remote
35              :artifact (b/resolve-path jar-file)
36              :repository {"cloudrepo"
37                          {:url "https://your-org.mycloudrepo.io/repositories/your-repo"
38                           :username (System/getenv "CLOUDREPO_USERNAME")
39                           :password (System/getenv "CLOUDREPO_PASSWORD")}}}))

Add the build alias to deps.edn:

deps.edn - tools.build Alias
1{:deps {org.clojure/clojure {:mvn/version "1.11.1"}}
2
3 :paths ["src" "resources"]
4
5 :aliases {:build {:deps {io.github.clojure/tools.build {:mvn/version "0.9.6"}
6                          slipset/deps-deploy {:mvn/version "0.2.2"}}
7                   :ns-default build}}}

Build and deploy:

Building and Deploying
1# Build JAR
2clojure -T:build jar
3
4# Deploy to CloudRepo
5clojure -T:build deploy

POM Generation and Customization

Customize your POM file for better metadata:

build.clj - Custom POM Configuration
 1(defn create-pom [_]
 2  (b/write-pom {:class-dir class-dir
 3                :lib lib
 4                :version version
 5                :basis (b/create-basis {:project "deps.edn"})
 6                :scm {:url "https://github.com/yourcompany/your-library"
 7                      :connection "scm:git:git://github.com/yourcompany/your-library.git"
 8                      :developerConnection "scm:git:ssh://git@github.com/yourcompany/your-library.git"
 9                      :tag (str "v" version)}
10                :pom-data [[:description "Your library description"]
11                           [:url "https://github.com/yourcompany/your-library"]
12                           [:licenses
13                            [:license
14                             [:name "Eclipse Public License"]
15                             [:url "http://www.eclipse.org/legal/epl-v10.html"]]]
16                           [:developers
17                            [:developer
18                             [:name "Your Name"]
19                             [:email "you@yourcompany.com"]]]
20                           [:organization
21                            [:name "Your Company"]
22                            [:url "https://yourcompany.com"]]]}))

Version Management

Implement flexible version management:

build.clj - Version Management Strategies
 1(ns build
 2  (:require [clojure.tools.build.api :as b]
 3            [clojure.string :as str]))
 4
 5;; Strategy 1: Read from file
 6(def version (str/trim (slurp "VERSION")))
 7
 8;; Strategy 2: Git-based versioning
 9(def version (format "1.0.%s" (b/git-count-revs nil)))
10
11;; Strategy 3: Timestamp-based for SNAPSHOTs
12(def version (format "1.0.0-%s-SNAPSHOT"
13                     (.format (java.time.LocalDateTime/now)
14                             (java.time.format.DateTimeFormatter/ofPattern "yyyyMMddHHmmss"))))
15
16;; Strategy 4: Environment variable
17(def version (or (System/getenv "VERSION") "1.0.0-SNAPSHOT"))

Publishing Sources and Documentation

Include source JARs and documentation:

build.clj - Sources and Docs
 1(defn jar-all [_]
 2  (clean nil)
 3  ;; Main JAR
 4  (b/write-pom {:class-dir class-dir
 5                :lib lib
 6                :version version
 7                :basis (b/create-basis {:project "deps.edn"})})
 8  (b/copy-dir {:src-dirs ["src" "resources"]
 9               :target-dir class-dir})
10  (b/jar {:class-dir class-dir
11          :jar-file jar-file})
12
13  ;; Sources JAR
14  (b/jar {:class-dir "src"
15          :jar-file (format "target/%s-%s-sources.jar" (name lib) version)})
16
17  ;; Javadoc JAR (for Clojure API docs)
18  (b/javadoc {:src-dirs ["src"]
19              :class-dir class-dir
20              :javadoc-dir "target/javadoc"
21              :lib lib
22              :version version})
23  (b/jar {:class-dir "target/javadoc"
24          :jar-file (format "target/%s-%s-javadoc.jar" (name lib) version)}))
25
26(defn deploy-all [_]
27  (jar-all nil)
28  ;; Deploy all artifacts
29  (doseq [artifact ["" "-sources" "-javadoc"]]
30    (dd/deploy {:installer :remote
31                :artifact (b/resolve-path
32                          (format "target/%s-%s%s.jar" (name lib) version artifact))
33                :repository {"cloudrepo"
34                            {:url "https://your-org.mycloudrepo.io/repositories/your-repo"
35                             :username (System/getenv "CLOUDREPO_USERNAME")
36                             :password (System/getenv "CLOUDREPO_PASSWORD")}}})))

Consuming Dependencies

Adding Private Dependencies

Reference your private libraries from CloudRepo:

deps.edn - Using Private Dependencies
 1{:deps {;; Public dependencies
 2        org.clojure/clojure {:mvn/version "1.11.1"}
 3        ring/ring-core {:mvn/version "1.10.0"}
 4
 5        ;; Private dependencies from CloudRepo
 6        com.yourcompany/auth-lib {:mvn/version "2.1.0"}
 7        com.yourcompany/data-processor {:mvn/version "3.0.0"}
 8        com.yourcompany/api-client {:mvn/version "1.5.2"}}
 9
10 :paths ["src" "resources"]
11
12 :mvn/repos {"cloudrepo" {:url "https://your-org.mycloudrepo.io/repositories/your-repo"}
13             "central" {:url "https://repo1.maven.org/maven2/"}
14             "clojars" {:url "https://repo.clojars.org/"}}}

Mixing Repository Sources

Combine CloudRepo with other repository sources:

deps.edn - Multiple Repository Sources
 1{:deps {;; From Maven Central
 2        org.clojure/clojure {:mvn/version "1.11.1"}
 3
 4        ;; From Clojars
 5        metosin/reitit {:mvn/version "0.6.0"}
 6
 7        ;; From CloudRepo
 8        com.yourcompany/core {:mvn/version "1.0.0"}
 9
10        ;; From Git
11        com.yourcompany/experimental {:git/url "https://github.com/yourcompany/experimental"
12                                      :git/sha "abc123"}
13
14        ;; Local development
15        com.yourcompany/local-lib {:local/root "../local-lib"}}
16
17 :paths ["src" "resources"]
18
19 :mvn/repos {"cloudrepo" {:url "https://your-org.mycloudrepo.io/repositories/your-repo"}
20             "central" {:url "https://repo1.maven.org/maven2/"}
21             "clojars" {:url "https://repo.clojars.org/"}}}

Dependency Aliases and Profiles

Use aliases for different dependency sets:

deps.edn - Aliases for Different Contexts
 1{:deps {org.clojure/clojure {:mvn/version "1.11.1"}
 2        com.yourcompany/core {:mvn/version "1.0.0"}}
 3
 4 :paths ["src" "resources"]
 5
 6 :aliases {:dev {:extra-deps {nrepl/nrepl {:mvn/version "1.0.0"}
 7                              cider/cider-nrepl {:mvn/version "0.30.0"}
 8                              com.yourcompany/dev-tools {:mvn/version "2.0.0"}}
 9                 :extra-paths ["dev" "test"]}
10
11           :test {:extra-deps {lambdaisland/kaocha {:mvn/version "1.87.1366"}
12                               com.yourcompany/test-fixtures {:mvn/version "1.0.0"}}
13                  :extra-paths ["test"]}
14
15           :prod {:override-deps {com.yourcompany/core {:mvn/version "1.0.0-RELEASE"}}
16                  :jvm-opts ["-Xmx2g" "-Xms2g"]}
17
18           :staging {:override-deps {com.yourcompany/core {:mvn/version "1.0.0-RC1"}}
19                     :mvn/repos {"cloudrepo-staging"
20                                {:url "https://your-org.mycloudrepo.io/repositories/staging"}}}}
21
22 :mvn/repos {"cloudrepo" {:url "https://your-org.mycloudrepo.io/repositories/your-repo"}
23             "central" {:url "https://repo1.maven.org/maven2/"}
24             "clojars" {:url "https://repo.clojars.org/"}}}

Run with specific aliases:

Using Aliases
1# Development REPL
2clojure -A:dev
3
4# Run tests
5clojure -A:test -m kaocha.runner
6
7# Production build
8clojure -A:prod -T:build jar

Advanced Topics

Monorepo Support

Structure for Clojure monorepos with CloudRepo:

monorepo/deps.edn - Root Configuration
 1{:deps {}
 2
 3 :paths []
 4
 5 :aliases {:lib-a {:extra-deps {com.yourcompany/lib-a {:local/root "libs/lib-a"}}}
 6           :lib-b {:extra-deps {com.yourcompany/lib-b {:local/root "libs/lib-b"}}}
 7           :app {:extra-deps {com.yourcompany/app {:local/root "apps/main-app"}}}
 8
 9           :deploy-all {:exec-fn monorepo.deploy/deploy-all
10                       :exec-args {:libs ["lib-a" "lib-b"]
11                                  :repository {:url "https://your-org.mycloudrepo.io/repositories/your-repo"
12                                              :username :env/cloudrepo_username
13                                              :password :env/cloudrepo_password}}}}
14
15 :mvn/repos {"cloudrepo" {:url "https://your-org.mycloudrepo.io/repositories/your-repo"}
16             "central" {:url "https://repo1.maven.org/maven2/"}}}
monorepo/libs/lib-a/deps.edn - Library Configuration
1{:deps {org.clojure/clojure {:mvn/version "1.11.1"}
2        ;; Internal dependency from CloudRepo
3        com.yourcompany/lib-core {:mvn/version "1.0.0"}}
4
5 :paths ["src" "resources"]}

Tools and Aliases Management

Centralize tool configurations:

~/.clojure/deps.edn - User-level Tool Configuration
 1{:aliases {:outdated {:extra-deps {com.github.liquidz/antq {:mvn/version "2.5.1144"}}
 2                     :main-opts ["-m" "antq.core"]}
 3
 4           :deps-ancient {:extra-deps {deps-ancient/deps-ancient {:mvn/version "0.1.0"}}
 5                         :main-opts ["-m" "deps-ancient.deps-ancient"]}
 6
 7           :deploy {:extra-deps {slipset/deps-deploy {:mvn/version "0.2.2"}}
 8                   :exec-fn deps-deploy.deps-deploy/deploy}
 9
10           :build {:deps {io.github.clojure/tools.build {:mvn/version "0.9.6"}}
11                  :ns-default build}
12
13           :cloudrepo {:mvn/repos {"cloudrepo-releases"
14                                  {:url "https://your-org.mycloudrepo.io/repositories/releases"}
15                                  "cloudrepo-snapshots"
16                                  {:url "https://your-org.mycloudrepo.io/repositories/snapshots"}}}}}

Caching Strategies

Optimize dependency caching:

CI/CD Caching Configuration
 1# GitHub Actions example
 2- name: Cache Clojure dependencies
 3  uses: actions/cache@v3
 4  with:
 5    path: |
 6      ~/.m2/repository
 7      ~/.gitlibs
 8      ~/.clojure/.cpcache
 9    key: ${{ runner.os }}-clojure-${{ hashFiles('**/deps.edn') }}
10    restore-keys: |
11      ${{ runner.os }}-clojure-
12
13# Pre-download dependencies
14- name: Download dependencies
15  run: |
16    clojure -P
17    clojure -P -A:dev:test:build

Multi-Module Projects

Configure multi-module projects with shared dependencies:

parent/deps.edn - Parent Module
 1{:deps {}
 2
 3 :aliases {:modules {:extra-paths ["module-a/src" "module-b/src" "module-c/src"]
 4                    :extra-deps {com.yourcompany/module-a {:local/root "module-a"}
 5                                com.yourcompany/module-b {:local/root "module-b"}
 6                                com.yourcompany/module-c {:local/root "module-c"}}}
 7
 8           :deploy-modules {:exec-fn deploy.multi/deploy-all
 9                          :exec-args {:modules ["module-a" "module-b" "module-c"]
10                                     :repository {:url "https://your-org.mycloudrepo.io/repositories/your-repo"
11                                                 :username :env/cloudrepo_username
12                                                 :password :env/cloudrepo_password}}}}
13
14 :mvn/repos {"cloudrepo" {:url "https://your-org.mycloudrepo.io/repositories/your-repo"}}}

ClojureScript Libraries

Publish and consume ClojureScript libraries:

deps.edn - ClojureScript Library
 1{:deps {org.clojure/clojure {:mvn/version "1.11.1"}
 2        org.clojure/clojurescript {:mvn/version "1.11.60"}
 3        thheller/shadow-cljs {:mvn/version "2.25.0"}}
 4
 5 :paths ["src/clj" "src/cljs" "resources"]
 6
 7 :aliases {:cljs {:extra-deps {com.yourcompany/cljs-utils {:mvn/version "1.0.0"
 8                                                           :exclusions [org.clojure/clojurescript]}}}
 9
10           :build-cljs {:exec-fn build/build-cljs
11                       :exec-args {:optimizations :advanced
12                                  :output-to "target/main.js"
13                                  :source-map true}}}
14
15 :mvn/repos {"cloudrepo" {:url "https://your-org.mycloudrepo.io/repositories/your-repo"}
16             "central" {:url "https://repo1.maven.org/maven2/"}
17             "clojars" {:url "https://repo.clojars.org/"}}}

CI/CD Integration

GitHub Actions

Complete GitHub Actions workflow:

.github/workflows/deploy.yml - GitHub Actions
 1name: Deploy to CloudRepo
 2
 3on:
 4  push:
 5    tags:
 6      - 'v*'
 7
 8jobs:
 9  deploy:
10    runs-on: ubuntu-latest
11
12    steps:
13      - uses: actions/checkout@v3
14
15      - name: Install Clojure
16        uses: DeLaGuardo/setup-clojure@12.1
17        with:
18          cli: 1.11.1.1435
19
20      - name: Cache dependencies
21        uses: actions/cache@v3
22        with:
23          path: |
24            ~/.m2/repository
25            ~/.gitlibs
26          key: ${{ runner.os }}-clojure-${{ hashFiles('**/deps.edn') }}
27
28      - name: Run tests
29        run: clojure -A:test -M:runner
30
31      - name: Build JAR
32        run: clojure -T:build jar
33
34      - name: Deploy to CloudRepo
35        env:
36          CLOUDREPO_USERNAME: ${{ secrets.CLOUDREPO_USERNAME }}
37          CLOUDREPO_PASSWORD: ${{ secrets.CLOUDREPO_PASSWORD }}
38        run: clojure -T:build deploy

GitLab CI

.gitlab-ci.yml - GitLab CI
 1stages:
 2  - test
 3  - build
 4  - deploy
 5
 6variables:
 7  MAVEN_OPTS: "-Dmaven.repo.local=$CI_PROJECT_DIR/.m2/repository"
 8
 9cache:
10  paths:
11    - .m2/repository/
12    - .cpcache/
13
14test:
15  stage: test
16  image: clojure:temurin-21-tools-deps
17  script:
18    - clojure -A:test -M:runner
19
20build:
21  stage: build
22  image: clojure:temurin-21-tools-deps
23  script:
24    - clojure -T:build jar
25  artifacts:
26    paths:
27      - target/
28
29deploy:
30  stage: deploy
31  image: clojure:temurin-21-tools-deps
32  script:
33    - clojure -T:build deploy
34  environment:
35    name: production
36  only:
37    - tags
38  variables:
39    CLOUDREPO_USERNAME: $CLOUDREPO_USERNAME
40    CLOUDREPO_PASSWORD: $CLOUDREPO_PASSWORD

Jenkins Pipeline

Jenkinsfile - Jenkins Pipeline
 1pipeline {
 2    agent any
 3
 4    environment {
 5        CLOUDREPO_USERNAME = credentials('cloudrepo-username')
 6        CLOUDREPO_PASSWORD = credentials('cloudrepo-password')
 7    }
 8
 9    stages {
10        stage('Checkout') {
11            steps {
12                checkout scm
13            }
14        }
15
16        stage('Test') {
17            steps {
18                sh 'clojure -A:test -M:runner'
19            }
20        }
21
22        stage('Build') {
23            steps {
24                sh 'clojure -T:build jar'
25            }
26        }
27
28        stage('Deploy') {
29            when {
30                tag pattern: "v\\d+\\.\\d+\\.\\d+", comparator: "REGEXP"
31            }
32            steps {
33                sh 'clojure -T:build deploy'
34            }
35        }
36    }
37
38    post {
39        always {
40            cleanWs()
41        }
42    }
43}

CircleCI

.circleci/config.yml - CircleCI
 1version: 2.1
 2
 3executors:
 4  clojure:
 5    docker:
 6      - image: cimg/clojure:1.11.1
 7
 8jobs:
 9  test:
10    executor: clojure
11    steps:
12      - checkout
13      - restore_cache:
14          keys:
15            - v1-deps-{{ checksum "deps.edn" }}
16            - v1-deps-
17      - run:
18          name: Download dependencies
19          command: clojure -P && clojure -P -A:test
20      - save_cache:
21          key: v1-deps-{{ checksum "deps.edn" }}
22          paths:
23            - ~/.m2
24            - ~/.gitlibs
25      - run:
26          name: Run tests
27          command: clojure -A:test -M:runner
28
29  deploy:
30    executor: clojure
31    steps:
32      - checkout
33      - restore_cache:
34          keys:
35            - v1-deps-{{ checksum "deps.edn" }}
36      - run:
37          name: Build and Deploy
38          command: |
39            clojure -T:build jar
40            clojure -T:build deploy
41
42workflows:
43  version: 2
44  test-and-deploy:
45    jobs:
46      - test
47      - deploy:
48          requires:
49            - test
50          filters:
51            tags:
52              only: /^v.*/
53            branches:
54              ignore: /.*/

Troubleshooting

Common Issues and Solutions

Authentication Failures

Problem: 401 Unauthorized errors when accessing CloudRepo

Solution:

  1. Verify credentials in ~/.m2/settings.xml:

    cat ~/.m2/settings.xml | grep -A 3 cloudrepo
    
  2. Ensure server ID matches repository ID in deps.edn

  3. Check environment variables are set:

    echo $CLOUDREPO_USERNAME
    echo $CLOUDREPO_PASSWORD
    
  4. Verify user has correct repository permissions in CloudRepo Admin Portal

Dependency Resolution Failures

Problem: Dependencies from CloudRepo not found

Solution:

  1. Check repository URL format:

    ;; Correct
    {:mvn/repos {"cloudrepo" {:url "https://your-org.mycloudrepo.io/repositories/your-repo"}}}
    
    ;; Incorrect - missing /repositories/
    {:mvn/repos {"cloudrepo" {:url "https://your-org.mycloudrepo.io/your-repo"}}}
    
  2. Verify artifact exists in repository:

    curl -u username:password https://your-org.mycloudrepo.io/repositories/your-repo/com/yourcompany/your-lib/maven-metadata.xml
    
  3. Clear local cache:

    rm -rf ~/.m2/repository/com/yourcompany/your-lib
    clojure -Sforce -Stree
    

SSL Certificate Issues

Problem: SSL handshake failures

Solution:

For self-signed certificates (not recommended for production):

# Add to JAVA_TOOL_OPTIONS
export JAVA_TOOL_OPTIONS="-Dmaven.wagon.http.ssl.insecure=true -Dmaven.wagon.http.ssl.allowall=true"

For proper certificate installation:

# Import certificate to Java truststore
keytool -import -trustcacerts -keystore $JAVA_HOME/lib/security/cacerts \
        -storepass changeit -alias cloudrepo \
        -file cloudrepo-certificate.crt

Deployment Failures

Problem: Artifacts fail to deploy

Solution:

  1. Check write permissions for user

  2. Verify artifact doesn’t already exist (for releases)

  3. Enable verbose logging:

    ;; In build.clj
    (require '[clojure.pprint :refer [pprint]])
    
    (defn deploy-verbose [_]
      (let [result (dd/deploy {:installer :remote
                              :artifact jar-file
                              :repository repo-config})]
        (pprint result)))
    
  4. Check file size limits in CloudRepo settings

Snapshot vs Release Confusion

Problem: SNAPSHOT versions treated as releases or vice versa

Solution:

Configure separate repositories:

{:mvn/repos {"cloudrepo-releases" {:url "https://your-org.mycloudrepo.io/repositories/releases"}
             "cloudrepo-snapshots" {:url "https://your-org.mycloudrepo.io/repositories/snapshots"}}}

Use version detection in build:

(defn deploy [_]
  (let [snapshot? (str/ends-with? version "SNAPSHOT")
        repo-url (if snapshot?
                  "https://your-org.mycloudrepo.io/repositories/snapshots"
                  "https://your-org.mycloudrepo.io/repositories/releases")]
    (dd/deploy {:installer :remote
                :artifact jar-file
                :repository {"cloudrepo" {:url repo-url
                                         :username (System/getenv "CLOUDREPO_USERNAME")
                                         :password (System/getenv "CLOUDREPO_PASSWORD")}}})))

Debugging Tips

Enable Verbose Output

# Show dependency tree
clojure -Stree

# Force re-resolution
clojure -Sforce -Stree

# Verbose Maven output
clojure -Sdeps '{:mvn/local-repo ".m2-debug"}' -Sverbose

Check Effective Configuration

# Show computed classpath
clojure -Spath

# Show basis (merged deps.edn)
clojure -X:deps tree

Test Repository Access

# Test authentication
curl -u username:password https://your-org.mycloudrepo.io/repositories/your-repo/

# Download specific artifact
curl -u username:password -O \
  https://your-org.mycloudrepo.io/repositories/your-repo/com/yourcompany/your-lib/1.0.0/your-lib-1.0.0.jar

Summary

This guide covered the complete integration of Clojure deps.edn projects with CloudRepo:

  • Configuration: Set up deps.edn and authentication via settings.xml

  • Publishing: Deploy libraries using deps-deploy and tools.build

  • Consuming: Use private dependencies alongside public repositories

  • Advanced Topics: Monorepos, ClojureScript, and multi-module projects

  • CI/CD: Automate builds and deployments across popular platforms

  • Troubleshooting: Resolve common issues with authentication, SSL, and deployments

CloudRepo provides a seamless, managed solution for hosting private Clojure artifacts, eliminating infrastructure overhead while providing enterprise-grade security and reliability. With proper configuration, your Clojure projects can leverage CloudRepo’s cost-effective repository management alongside the simplicity and power of deps.edn.

Additional Resources