Leiningen Repositories
This section provides comprehensive documentation for configuring and using Leiningen with CloudRepo Maven repositories.
Overview
Leiningen is the traditional and most widely-adopted build automation tool for Clojure projects. Created in 2009, it remains the preferred choice for many Clojure developers and teams, offering a comprehensive solution for project management, dependency resolution, and build automation.
What is Leiningen?
Leiningen is a build automation and dependency management tool that:
Manages Dependencies: Fetches and manages JVM libraries from Maven repositories
Builds Projects: Compiles Clojure code and creates JAR artifacts
Runs Tasks: Executes tests, starts REPLs, and runs custom tasks
Generates Projects: Provides templates for creating new projects
Handles Deployment: Publishes libraries to Maven repositories
Leiningen uses a project.clj file written in Clojure syntax to define project configuration, making it familiar and intuitive for Clojure developers.
Leiningen vs deps.edn
Aspect |
Leiningen |
deps.edn / tools.deps |
---|---|---|
Use Case |
Full-featured builds, traditional projects |
Minimal tooling, modern CLI approach |
Configuration |
project.clj (Clojure syntax) |
deps.edn (EDN data) |
Build Features |
Comprehensive built-in tasks |
Requires additional tools |
Plugin Ecosystem |
Extensive plugin system |
Tool-based extensions |
Learning Curve |
Steeper but more features |
Minimal, focused on dependencies |
JAR Creation |
Built-in uberjar support |
Requires tools.build |
Templates |
Rich template system |
Limited templates |
Note
Many teams use both tools: Leiningen for established projects and complex builds, deps.edn for new projects and library development. CloudRepo supports both approaches seamlessly.
Why Private Maven Repositories?
Teams using Leiningen need private Maven repositories to:
Share Internal Libraries: Distribute proprietary Clojure libraries within the organization
Control Dependencies: Ensure consistent, reliable access to third-party libraries
Maintain Privacy: Keep sensitive code and algorithms secure
Version Management: Control library versions across teams and projects
Reduce External Dependencies: Cache external libraries for reliability
Comply with Regulations: Meet data residency and security requirements
Prerequisites
Before configuring Leiningen with CloudRepo, ensure you have:
A CloudRepo Maven Repository
Create a Maven repository in the CloudRepo Admin Portal:
Navigate to Repositories → Create Repository
Select Maven as the repository type
Note your repository URL:
https://[organization-id].mycloudrepo.io/repositories/[repository-id]
See Creating a Repository for detailed instructions.
A Repository User
Create a dedicated user for repository access:
Navigate to Users → Create User
Assign appropriate permissions (read/write)
Save the credentials securely
See Creating Users for detailed instructions.
Warning
For security reasons, the admin user cannot access repositories directly. Always create dedicated repository users.
Leiningen Installed
Install Leiningen following the official instructions:
Verify Leiningen Installationlein --version # Output: Leiningen 2.11.2 on Java 17.0.8 OpenJDK 64-Bit Server VM
Configuring project.clj
Repository Configuration
Configure CloudRepo repositories in your project.clj file for both fetching and deploying artifacts.
Basic Repository Setup
1(defproject com.example/my-library "0.1.0-SNAPSHOT"
2 :description "A private Clojure library"
3 :url "https://github.com/example/my-library"
4 :license {:name "Proprietary"
5 :url ""}
6
7 :dependencies [[org.clojure/clojure "1.11.1"]
8 [com.example/internal-lib "1.2.3"]]
9
10 ;; Repository for fetching dependencies
11 :repositories [["cloudrepo" {:url "https://mycompany.mycloudrepo.io/repositories/maven-releases"
12 :username :env/cloudrepo_username
13 :password :env/cloudrepo_password}]
14 ["central" {:url "https://repo1.maven.org/maven2/"
15 :snapshots false}]
16 ["clojars" {:url "https://clojars.org/repo/"}]]
17
18 ;; Repository for deploying artifacts
19 :deploy-repositories [["releases" {:url "https://mycompany.mycloudrepo.io/repositories/maven-releases"
20 :username :env/cloudrepo_username
21 :password :env/cloudrepo_password
22 :sign-releases false}]
23 ["snapshots" {:url "https://mycompany.mycloudrepo.io/repositories/maven-snapshots"
24 :username :env/cloudrepo_username
25 :password :env/cloudrepo_password
26 :sign-releases false}]])
Advanced Repository Configuration
1(defproject com.example/advanced-library "2.0.0"
2 :description "Advanced Leiningen configuration example"
3
4 ;; Repository configuration with mirrors and policies
5 :repositories [["cloudrepo" {:url "https://mycompany.mycloudrepo.io/repositories/maven-releases"
6 :username :env/cloudrepo_username
7 :password :env/cloudrepo_password
8 :update :always ; :daily, :always, or :never
9 :checksum :fail ; :fail, :warn, or :ignore
10 :releases {:enabled true
11 :update :daily}
12 :snapshots {:enabled false}}]
13
14 ;; Mirror configuration for Maven Central
15 ["cloudrepo-central" {:url "https://mycompany.mycloudrepo.io/repositories/maven-central-proxy"
16 :username :env/cloudrepo_username
17 :password :env/cloudrepo_password
18 :mirror-of "central"
19 :mirror-exclude "clojars"}]]
20
21 ;; Separate repositories for different artifact types
22 :deploy-repositories [["releases" {:url "https://mycompany.mycloudrepo.io/repositories/maven-releases"
23 :username :env/cloudrepo_username
24 :password :env/cloudrepo_password}]
25 ["snapshots" {:url "https://mycompany.mycloudrepo.io/repositories/maven-snapshots"
26 :username :env/cloudrepo_username
27 :password :env/cloudrepo_password}]]
28
29 ;; Repository authentication via GPG
30 :signing {:gpg-key "your-gpg-key@example.com"})
Authentication Setup
Leiningen supports multiple authentication methods. Choose the most appropriate for your security requirements.
Environment Variables (Recommended)
The most secure approach uses environment variables to store credentials:
1# Add to ~/.bashrc, ~/.zshrc, or equivalent
2export CLOUDREPO_USERNAME="your-repository-user@example.com"
3export CLOUDREPO_PASSWORD="your-secure-password"
4
5# For temporary use
6CLOUDREPO_USERNAME="user@example.com" CLOUDREPO_PASSWORD="pass" lein deploy
1# Set permanently (requires admin privileges)
2[Environment]::SetEnvironmentVariable("CLOUDREPO_USERNAME", "your-repository-user@example.com", "User")
3[Environment]::SetEnvironmentVariable("CLOUDREPO_PASSWORD", "your-secure-password", "User")
4
5# Set for current session
6$env:CLOUDREPO_USERNAME = "your-repository-user@example.com"
7$env:CLOUDREPO_PASSWORD = "your-secure-password"
Profiles Configuration (~/.lein/profiles.clj)
Store credentials in your Leiningen profiles for user-specific configuration:
1{:auth {:repository-auth {#"https://mycompany\.mycloudrepo\.io/.*"
2 {:username "your-repository-user@example.com"
3 :password "your-secure-password"}}}}
4
5;; Alternative: Separate profiles for different environments
6{:dev {:repository-auth {#"https://mycompany\.mycloudrepo\.io/.*"
7 {:username "dev-user@example.com"
8 :password "dev-password"}}}
9
10 :prod {:repository-auth {#"https://mycompany\.mycloudrepo\.io/.*"
11 {:username "prod-user@example.com"
12 :password "prod-password"}}}}
Warning
The profiles.clj file contains plaintext passwords. Ensure proper file permissions: chmod 600 ~/.lein/profiles.clj
GPG Encrypted Credentials
For enhanced security, use GPG to encrypt credentials:
1{:auth {:repository-auth {#"https://mycompany\.mycloudrepo\.io/.*"
2 {:username "your-repository-user@example.com"
3 :password [:gpg :env/cloudrepo_password_gpg]}}}}
# Encrypt password
echo -n "your-password" | gpg --armor --encrypt -r your-gpg-key@example.com > password.gpg
# Set as environment variable
export CLOUDREPO_PASSWORD_GPG=$(cat password.gpg)
Publishing Clojure Libraries
Basic Deployment
Deploy your Clojure library to CloudRepo using Leiningen’s deploy command:
1# Deploy a release version
2lein deploy releases
3
4# Deploy a snapshot version
5lein deploy snapshots
6
7# Deploy to default repository (based on version)
8lein deploy
Version Management
Leiningen automatically determines the target repository based on version:
1;; SNAPSHOT version - deploys to snapshots repository
2(defproject com.example/my-lib "1.0.0-SNAPSHOT"
3 ;; ... configuration ...
4 )
5
6;; Release version - deploys to releases repository
7(defproject com.example/my-lib "1.0.0"
8 ;; ... configuration ...
9 )
Artifact Generation
Leiningen generates multiple artifacts during deployment:
1# Standard JAR with compiled Clojure code
2my-library-1.0.0.jar
3
4# POM file with project metadata
5my-library-1.0.0.pom
6
7# Sources JAR (optional)
8my-library-1.0.0-sources.jar
9
10# Javadoc JAR (optional)
11my-library-1.0.0-javadoc.jar
Configure additional artifacts in project.clj:
1(defproject com.example/my-library "1.0.0"
2 ;; Include source files
3 :source-paths ["src"]
4 :java-source-paths ["java-src"]
5
6 ;; Generate additional artifacts
7 :classifiers {:sources {:source-paths ["src"]
8 :resource-paths []}
9 :javadoc {:source-paths []
10 :resource-paths []
11 :javadoc-opts {:package-names ["com.example"]
12 :output-dir "target/javadoc"}}}
13
14 ;; Include resources
15 :resource-paths ["resources"]
16
17 ;; AOT compilation for better performance
18 :aot [com.example.my-library.core]
19
20 ;; Metadata for POM
21 :pom-addition [:developers [:developer
22 [:id "developer1"]
23 [:name "Jane Developer"]
24 [:email "jane@example.com"]]])
Deployment Workflow
Follow this workflow for reliable deployments:
1# 1. Clean previous builds
2lein clean
3
4# 2. Run tests
5lein test
6
7# 3. Check for reflection warnings (Clojure best practice)
8lein check
9
10# 4. Generate JAR locally for verification
11lein jar
12
13# 5. Deploy to CloudRepo
14lein deploy
15
16# Alternative: All-in-one command
17lein do clean, test, check, deploy
Consuming Dependencies
Adding Private Dependencies
Include CloudRepo-hosted libraries in your project:
1(defproject com.example/my-application "0.1.0"
2 :dependencies [[org.clojure/clojure "1.11.1"]
3 ;; Public dependencies from Clojars/Maven Central
4 [ring/ring-core "1.10.0"]
5 [compojure "1.7.0"]
6
7 ;; Private dependencies from CloudRepo
8 [com.mycompany/auth-library "2.3.1"]
9 [com.mycompany/data-processor "1.5.0-SNAPSHOT"]
10 [com.mycompany/utils "3.0.0" :classifier "sources"]]
11
12 :repositories [["cloudrepo" {:url "https://mycompany.mycloudrepo.io/repositories/maven-releases"
13 :username :env/cloudrepo_username
14 :password :env/cloudrepo_password}]
15 ["cloudrepo-snapshots" {:url "https://mycompany.mycloudrepo.io/repositories/maven-snapshots"
16 :username :env/cloudrepo_username
17 :password :env/cloudrepo_password}]])
Dependency Resolution Order
Control how Leiningen resolves dependencies:
1(defproject com.example/my-app "1.0.0"
2 ;; Repositories are checked in order
3 :repositories [;; 1. Check CloudRepo first for internal libraries
4 ["cloudrepo" {:url "https://mycompany.mycloudrepo.io/repositories/maven-releases"
5 :username :env/cloudrepo_username
6 :password :env/cloudrepo_password}]
7
8 ;; 2. Then check Clojars for Clojure libraries
9 ["clojars" {:url "https://clojars.org/repo/"}]
10
11 ;; 3. Finally check Maven Central
12 ["central" {:url "https://repo1.maven.org/maven2/"
13 :snapshots false}]]
14
15 ;; Disable automatic repository inclusion
16 :omit-default-repositories true)
Repository Mirrors
Use CloudRepo as a proxy/mirror for external repositories:
1(defproject com.example/my-app "1.0.0"
2 :repositories [;; CloudRepo proxy for Maven Central
3 ["cloudrepo-central" {:url "https://mycompany.mycloudrepo.io/repositories/maven-central-proxy"
4 :username :env/cloudrepo_username
5 :password :env/cloudrepo_password
6 :mirror-of "central"}]
7
8 ;; CloudRepo proxy for Clojars
9 ["cloudrepo-clojars" {:url "https://mycompany.mycloudrepo.io/repositories/clojars-proxy"
10 :username :env/cloudrepo_username
11 :password :env/cloudrepo_password
12 :mirror-of "clojars"}]
13
14 ;; Direct CloudRepo repository
15 ["cloudrepo" {:url "https://mycompany.mycloudrepo.io/repositories/maven-releases"
16 :username :env/cloudrepo_username
17 :password :env/cloudrepo_password}]])
Dependency Management
Advanced dependency management techniques:
1(defproject com.example/my-app "1.0.0"
2 :dependencies [[org.clojure/clojure "1.11.1"]
3
4 ;; Exclude transitive dependencies
5 [com.mycompany/lib-with-deps "1.0.0"
6 :exclusions [commons-logging
7 log4j]]
8
9 ;; Override transitive dependency versions
10 [com.mycompany/another-lib "2.0.0"]
11 [org.slf4j/slf4j-api "2.0.9"]] ; Override version
12
13 ;; Global exclusions
14 :exclusions [commons-logging
15 commons-codec]
16
17 ;; Dependency version management
18 :managed-dependencies [[org.slf4j/slf4j-api "2.0.9"]
19 [org.clojure/data.json "2.4.0"]]
20
21 ;; Pedantic mode for version conflicts
22 :pedantic? :abort) ; :abort, :warn, or false
Advanced Leiningen Features
Profiles for Different Environments
Use profiles to manage environment-specific configurations:
1(defproject com.example/my-app "1.0.0"
2 :description "Application with environment profiles"
3
4 ;; Base configuration
5 :dependencies [[org.clojure/clojure "1.11.1"]]
6
7 :profiles {:dev {:dependencies [[ring/ring-mock "0.4.0"]
8 [criterium "0.4.6"]]
9 :repositories [["cloudrepo-dev"
10 {:url "https://mycompany.mycloudrepo.io/repositories/maven-dev"
11 :username :env/cloudrepo_dev_username
12 :password :env/cloudrepo_dev_password}]]
13 :resource-paths ["dev-resources"]
14 :jvm-opts ["-Dconf=dev-config.edn"]}
15
16 :test {:dependencies [[test-runner "1.0.0"]]
17 :resource-paths ["test-resources"]}
18
19 :staging {:repositories [["cloudrepo-staging"
20 {:url "https://mycompany.mycloudrepo.io/repositories/maven-staging"
21 :username :env/cloudrepo_staging_username
22 :password :env/cloudrepo_staging_password}]]
23 :jvm-opts ["-Dconf=staging-config.edn"]}
24
25 :production {:repositories [["cloudrepo-prod"
26 {:url "https://mycompany.mycloudrepo.io/repositories/maven-prod"
27 :username :env/cloudrepo_prod_username
28 :password :env/cloudrepo_prod_password}]]
29 :jvm-opts ["-Dconf=prod-config.edn"
30 "-Xmx2g"]
31 :aot :all}
32
33 ;; Composite profile
34 :dev-all [:dev :test]})
# Activate dev profile
lein with-profile dev repl
# Run tests with test profile
lein with-profile test test
# Deploy with production profile
lein with-profile production deploy
# Combine profiles
lein with-profile dev,test deps
Plugins and Middleware
Extend Leiningen with plugins:
1(defproject com.example/my-app "1.0.0"
2 ;; Global plugins
3 :plugins [[lein-ancient "1.0.0-RC3"] ; Check for outdated dependencies
4 [lein-cloverage "1.2.4"] ; Code coverage
5 [lein-kibit "0.1.8"] ; Static code analysis
6 [lein-bikeshed "0.5.2"] ; Code style checking
7 [lein-release "1.0.9"]] ; Release automation
8
9 ;; Plugin repositories (if needed)
10 :plugin-repositories [["cloudrepo-plugins"
11 {:url "https://mycompany.mycloudrepo.io/repositories/maven-plugins"
12 :username :env/cloudrepo_username
13 :password :env/cloudrepo_password}]]
14
15 ;; Plugin-specific configuration
16 :cloverage {:output "target/coverage"
17 :codecov? true
18 :html? true}
19
20 :release-tasks [["vcs" "assert-committed"]
21 ["change" "version" "leiningen.release/bump-version" "release"]
22 ["vcs" "commit"]
23 ["vcs" "tag" "--no-sign"]
24 ["deploy"]
25 ["change" "version" "leiningen.release/bump-version"]
26 ["vcs" "commit"]
27 ["vcs" "push"]])
Multi-Module Projects
Manage multi-module projects with lein-modules:
1(defproject com.example/parent-project "1.0.0"
2 :description "Parent project for multi-module application"
3 :plugins [[lein-modules "0.3.11"]]
4
5 :modules {:versions {org.clojure/clojure "1.11.1"
6 com.example/shared-lib :version}
7
8 :dirs ["modules/core"
9 "modules/api"
10 "modules/web"
11 "modules/shared"]
12
13 :inherited {:repositories [["cloudrepo"
14 {:url "https://mycompany.mycloudrepo.io/repositories/maven-releases"
15 :username :env/cloudrepo_username
16 :password :env/cloudrepo_password}]]
17
18 :deploy-repositories [["releases"
19 {:url "https://mycompany.mycloudrepo.io/repositories/maven-releases"
20 :username :env/cloudrepo_username
21 :password :env/cloudrepo_password}]]
22
23 :license {:name "Proprietary"
24 :url ""}
25
26 :organization {:name "Example Corp"
27 :url "https://example.com"}}
28
29 :subprocess nil})
1(defproject com.example/core-module "1.0.0"
2 :description "Core module"
3 :dependencies [[org.clojure/clojure "_"] ; Version from parent
4 [com.example/shared-lib "_"]])
# Install all modules
lein modules install
# Deploy all modules
lein modules deploy
# Run tests in all modules
lein modules test
# Run command in specific module
lein modules :dirs "modules/core" test
Uberjar Deployment
Deploy standalone executable JARs:
1(defproject com.example/standalone-app "1.0.0"
2 :description "Standalone application"
3 :dependencies [[org.clojure/clojure "1.11.1"]
4 [com.mycompany/internal-lib "2.0.0"]]
5
6 :repositories [["cloudrepo" {:url "https://mycompany.mycloudrepo.io/repositories/maven-releases"
7 :username :env/cloudrepo_username
8 :password :env/cloudrepo_password}]]
9
10 :main com.example.standalone-app.core
11
12 ;; Uberjar configuration
13 :profiles {:uberjar {:aot :all
14 :jvm-opts ["-Dclojure.compiler.direct-linking=true"]
15 :uberjar-name "standalone-app.jar"
16 :omit-source true}}
17
18 ;; Deploy uberjar to CloudRepo
19 :deploy-repositories [["releases" {:url "https://mycompany.mycloudrepo.io/repositories/maven-releases"
20 :username :env/cloudrepo_username
21 :password :env/cloudrepo_password}]]
22
23 ;; Custom deployment for uberjar
24 :classifiers {:standalone {:jar-name "standalone-app.jar"
25 :uberjar true}})
# Build uberjar
lein uberjar
# Deploy regular JAR and uberjar
lein deploy releases
# Deploy only uberjar with classifier
lein deploy releases com.example/standalone-app "1.0.0" target/standalone-app.jar :classifier "standalone"
ClojureScript Projects
Configure Leiningen for ClojureScript projects:
1(defproject com.example/cljs-app "1.0.0"
2 :description "ClojureScript application"
3 :dependencies [[org.clojure/clojure "1.11.1"]
4 [org.clojure/clojurescript "1.11.132"]
5 ;; Private ClojureScript libraries from CloudRepo
6 [com.mycompany/cljs-components "1.2.0"]]
7
8 :repositories [["cloudrepo" {:url "https://mycompany.mycloudrepo.io/repositories/maven-releases"
9 :username :env/cloudrepo_username
10 :password :env/cloudrepo_password}]]
11
12 :plugins [[lein-cljsbuild "1.1.8"]
13 [lein-figwheel "0.5.20"]]
14
15 :cljsbuild {:builds [{:id "dev"
16 :source-paths ["src"]
17 :figwheel {:on-jsload "com.example.app/reload"}
18 :compiler {:main com.example.app
19 :asset-path "js/compiled/out"
20 :output-to "resources/public/js/compiled/app.js"
21 :output-dir "resources/public/js/compiled/out"
22 :source-map-timestamp true}}
23
24 {:id "prod"
25 :source-paths ["src"]
26 :compiler {:main com.example.app
27 :output-to "resources/public/js/compiled/app.js"
28 :optimizations :advanced
29 :pretty-print false}}]}
30
31 ;; Deploy compiled JavaScript to CloudRepo Raw repository
32 :deploy-repositories [["js-releases" {:url "https://mycompany.mycloudrepo.io/repositories/raw-releases"
33 :username :env/cloudrepo_username
34 :password :env/cloudrepo_password}]])
CI/CD Integration
GitHub Actions
Configure GitHub Actions for automated deployments:
1name: Deploy to CloudRepo
2
3on:
4 push:
5 branches: [ main ]
6 tags: [ 'v*' ]
7
8jobs:
9 test:
10 runs-on: ubuntu-latest
11 steps:
12 - uses: actions/checkout@v4
13
14 - name: Set up JDK
15 uses: actions/setup-java@v4
16 with:
17 java-version: '17'
18 distribution: 'temurin'
19
20 - name: Cache Leiningen dependencies
21 uses: actions/cache@v3
22 with:
23 path: ~/.m2
24 key: ${{ runner.os }}-m2-${{ hashFiles('**/project.clj') }}
25 restore-keys: |
26 ${{ runner.os }}-m2-
27
28 - name: Install Leiningen
29 run: |
30 curl -O https://raw.githubusercontent.com/technomancy/leiningen/stable/bin/lein
31 chmod +x lein
32 sudo mv lein /usr/local/bin/
33 lein version
34
35 - name: Run tests
36 run: lein test
37
38 - name: Check code quality
39 run: |
40 lein kibit
41 lein bikeshed
42
43 deploy:
44 needs: test
45 runs-on: ubuntu-latest
46 if: github.event_name == 'push' && startsWith(github.ref, 'refs/tags/v')
47
48 steps:
49 - uses: actions/checkout@v4
50
51 - name: Set up JDK
52 uses: actions/setup-java@v4
53 with:
54 java-version: '17'
55 distribution: 'temurin'
56
57 - name: Install Leiningen
58 run: |
59 curl -O https://raw.githubusercontent.com/technomancy/leiningen/stable/bin/lein
60 chmod +x lein
61 sudo mv lein /usr/local/bin/
62
63 - name: Deploy to CloudRepo
64 env:
65 CLOUDREPO_USERNAME: ${{ secrets.CLOUDREPO_USERNAME }}
66 CLOUDREPO_PASSWORD: ${{ secrets.CLOUDREPO_PASSWORD }}
67 run: |
68 lein deploy releases
GitLab CI
Configure GitLab CI for continuous deployment:
1image: clojure:temurin-17-lein-2.11.2
2
3variables:
4 MAVEN_OPTS: "-Dmaven.repo.local=.m2/repository"
5
6cache:
7 paths:
8 - .m2/repository/
9
10stages:
11 - test
12 - deploy
13
14test:
15 stage: test
16 script:
17 - lein test
18 - lein cloverage
19 artifacts:
20 reports:
21 coverage_report:
22 coverage_format: cobertura
23 path: target/coverage/cobertura.xml
24
25deploy-snapshot:
26 stage: deploy
27 script:
28 - lein deploy snapshots
29 environment:
30 name: development
31 only:
32 - develop
33 variables:
34 CLOUDREPO_USERNAME: ${CI_CLOUDREPO_USERNAME}
35 CLOUDREPO_PASSWORD: ${CI_CLOUDREPO_PASSWORD}
36
37deploy-release:
38 stage: deploy
39 script:
40 - lein deploy releases
41 environment:
42 name: production
43 only:
44 - tags
45 variables:
46 CLOUDREPO_USERNAME: ${CI_CLOUDREPO_PROD_USERNAME}
47 CLOUDREPO_PASSWORD: ${CI_CLOUDREPO_PROD_PASSWORD}
Jenkins Pipeline
Configure Jenkins for Leiningen deployments:
1pipeline {
2 agent any
3
4 tools {
5 jdk 'JDK-17'
6 }
7
8 environment {
9 CLOUDREPO_USERNAME = credentials('cloudrepo-username')
10 CLOUDREPO_PASSWORD = credentials('cloudrepo-password')
11 }
12
13 stages {
14 stage('Checkout') {
15 steps {
16 checkout scm
17 }
18 }
19
20 stage('Setup Leiningen') {
21 steps {
22 sh '''
23 if ! command -v lein &> /dev/null; then
24 curl -O https://raw.githubusercontent.com/technomancy/leiningen/stable/bin/lein
25 chmod +x lein
26 sudo mv lein /usr/local/bin/
27 fi
28 lein version
29 '''
30 }
31 }
32
33 stage('Test') {
34 steps {
35 sh 'lein test'
36 junit 'target/test-results/**/*.xml'
37 }
38 }
39
40 stage('Code Quality') {
41 parallel {
42 stage('Coverage') {
43 steps {
44 sh 'lein cloverage'
45 publishHTML(target: [
46 reportDir: 'target/coverage',
47 reportFiles: 'index.html',
48 reportName: 'Coverage Report'
49 ])
50 }
51 }
52 stage('Static Analysis') {
53 steps {
54 sh 'lein kibit'
55 sh 'lein bikeshed'
56 }
57 }
58 }
59 }
60
61 stage('Deploy') {
62 when {
63 anyOf {
64 branch 'main'
65 tag pattern: "v\\d+\\.\\d+\\.\\d+", comparator: "REGEXP"
66 }
67 }
68 steps {
69 script {
70 if (env.TAG_NAME) {
71 sh 'lein deploy releases'
72 } else {
73 sh 'lein deploy snapshots'
74 }
75 }
76 }
77 }
78 }
79
80 post {
81 always {
82 cleanWs()
83 }
84 }
85}
CircleCI
Configure CircleCI for automated deployments:
1version: 2.1
2
3executors:
4 clojure:
5 docker:
6 - image: cimg/clojure:1.11.1-openjdk-17.0
7 environment:
8 JVM_OPTS: -Xmx3200m
9
10jobs:
11 test:
12 executor: clojure
13 steps:
14 - checkout
15 - restore_cache:
16 keys:
17 - v1-dependencies-{{ checksum "project.clj" }}
18 - v1-dependencies-
19
20 - run:
21 name: Install dependencies
22 command: lein deps
23
24 - save_cache:
25 paths:
26 - ~/.m2
27 key: v1-dependencies-{{ checksum "project.clj" }}
28
29 - run:
30 name: Run tests
31 command: lein test
32
33 - store_test_results:
34 path: target/test-results
35
36 deploy:
37 executor: clojure
38 steps:
39 - checkout
40 - restore_cache:
41 keys:
42 - v1-dependencies-{{ checksum "project.clj" }}
43
44 - run:
45 name: Deploy to CloudRepo
46 command: |
47 if [ "${CIRCLE_TAG}" ]; then
48 lein deploy releases
49 else
50 lein deploy snapshots
51 fi
52
53workflows:
54 test-and-deploy:
55 jobs:
56 - test:
57 filters:
58 tags:
59 only: /.*/
60 - deploy:
61 requires:
62 - test
63 filters:
64 branches:
65 only: main
66 tags:
67 only: /^v.*/
68 context:
69 - cloudrepo-credentials
Secure Credential Management
Best practices for managing CloudRepo credentials in CI/CD:
Use Secret Management Services
AWS Secrets Manager Example# Retrieve credentials in CI/CD pipeline export CLOUDREPO_USERNAME=$(aws secretsmanager get-secret-value \ --secret-id cloudrepo/username \ --query SecretString --output text) export CLOUDREPO_PASSWORD=$(aws secretsmanager get-secret-value \ --secret-id cloudrepo/password \ --query SecretString --output text)
Rotate Credentials Regularly
project.clj - Multiple Credential Sets(defproject com.example/my-app "1.0.0" :deploy-repositories [["releases" {:url "https://mycompany.mycloudrepo.io/repositories/maven-releases" :username :env/cloudrepo_username_v2 :password :env/cloudrepo_password_v2}]])
Use Service Accounts
Create dedicated CI/CD users with minimal permissions in CloudRepo Admin Portal.
Audit Access
Regularly review CloudRepo access logs and repository user permissions.
Troubleshooting
Common Issues and Solutions
Authentication Failures
Problem: 401 Unauthorized
or 403 Forbidden
errors
# Verify environment variables
echo $CLOUDREPO_USERNAME
echo $CLOUDREPO_PASSWORD | wc -c # Check password is set (don't echo it)
# Test with explicit credentials
lein deploy releases com.example/test "0.0.1" \
target/test-0.0.1.jar \
pom.xml \
:repository [["test" {:url "https://mycompany.mycloudrepo.io/repositories/maven-releases"
:username "user@example.com"
:password "password"}]]
# Check profiles.clj
cat ~/.lein/profiles.clj
Solutions:
Verify credentials in CloudRepo Admin Portal
Ensure repository user has appropriate permissions
Check for typos in repository URLs
Confirm environment variables are exported correctly
Dependency Resolution Issues
Problem: Could not find artifact
errors
;; Add verbose output to project.clj
(defproject com.example/debug "1.0.0"
:dependencies [[com.mycompany/missing-lib "1.0.0"]]
:repositories [["cloudrepo" {:url "..."
:update :always}]] ; Force update
;; Enable debug output
:jvm-opts ["-Dclojure.debug=true"])
# Show dependency tree
lein deps :tree
# Force re-download
lein deps :force
# Check specific artifact
lein deps :why com.mycompany/missing-lib
# Clear local cache
rm -rf ~/.m2/repository/com/mycompany/missing-lib
SSL/TLS Certificate Issues
Problem: SSLHandshakeException
or certificate errors
# Test SSL connection
openssl s_client -connect mycompany.mycloudrepo.io:443 -showcerts
# Import CloudRepo certificate (if using self-signed)
keytool -import -trustcacerts \
-keystore $JAVA_HOME/lib/security/cacerts \
-storepass changeit \
-alias cloudrepo \
-file cloudrepo.crt
# Disable SSL verification (development only!)
export JVM_OPTS="-Dmaven.wagon.http.ssl.insecure=true -Dmaven.wagon.http.ssl.allowall=true"
Deployment Failures
Problem: Artifacts don’t appear in CloudRepo after deployment
# Enable verbose logging
DEBUG=1 lein deploy releases
# Check local artifact generation
lein jar
ls -la target/
# Verify POM generation
lein pom
cat pom.xml
# Manual deployment test
mvn deploy:deploy-file \
-DgroupId=com.example \
-DartifactId=test \
-Dversion=1.0.0 \
-Dpackaging=jar \
-Dfile=target/test-1.0.0.jar \
-DrepositoryId=cloudrepo \
-Durl=https://mycompany.mycloudrepo.io/repositories/maven-releases
Performance Optimization
Improve Leiningen performance with CloudRepo:
1(defproject com.example/optimized "1.0.0"
2 ;; Parallel dependency downloads
3 :jvm-opts ["-Dmaven.artifact.threads=10"]
4
5 ;; Local repository caching
6 :local-repo ".m2"
7
8 ;; Minimize repository checks
9 :repositories [["cloudrepo" {:url "..."
10 :update :daily ; Not :always
11 :checksum :warn}]] ; Not :fail
12
13 ;; Offline mode for CI builds
14 :offline? false ; Set to true when possible
15
16 ;; Repository caching proxy
17 :mirrors {#".*" {:name "cloudrepo-mirror"
18 :url "https://mycompany.mycloudrepo.io/repositories/all-proxy"}})
Best Practices
Version Management
Use semantic versioning (MAJOR.MINOR.PATCH)
Deploy SNAPSHOT versions during development
Tag releases in version control
Security
Never commit credentials to version control
Use environment variables or encrypted storage
Rotate credentials regularly
Use separate credentials for different environments
Repository Organization
Separate repositories for releases and snapshots
Use repository groups for simplified configuration
Implement retention policies for snapshots
Build Hygiene
Always run tests before deployment
Use lein clean to ensure fresh builds
Version control your project.clj carefully
Documentation
Document repository URLs and access requirements
Maintain README files with setup instructions
Include license and contributor information
Summary
This guide has covered comprehensive Leiningen integration with CloudRepo, including:
Basic Setup: Repository configuration and authentication
Publishing: Deploying Clojure libraries and applications
Consumption: Using private dependencies effectively
Advanced Features: Profiles, plugins, and multi-module projects
CI/CD: Automated deployments across major platforms
Troubleshooting: Common issues and solutions
Leiningen’s mature ecosystem and comprehensive feature set make it an excellent choice for teams building production Clojure applications. CloudRepo provides the secure, reliable Maven repository infrastructure needed to share and manage your Clojure artifacts effectively.
For teams also using the newer deps.edn tooling, see our Clojure deps.edn Repositories guide. Many organizations successfully use both tools, leveraging each for their respective strengths.
See Also
Clojure deps.edn Repositories - Modern Clojure dependency management with deps.edn
Maven Repositories - General Maven repository configuration
Gradle Repositories - Gradle configuration for JVM projects
Continuous Integration and Deployment - CI/CD best practices with CloudRepo
Leiningen Documentation - Official Leiningen documentation
Clojure Build Tools Guide - Clojure’s official build tools documentation