DevOps

How to Use CloudRepo with GitHub Actions

Every feature on every plan, with unlimited users

See how teams move to CloudRepo

Complete guide to integrating CloudRepo with GitHub Actions for Maven, Gradle, and Python builds. Includes working examples and CI/CD best practices.

CloudRepo Team
10 min read

GitHub Actions has become the default CI/CD platform for millions of developers. If your code lives on GitHub, running builds, tests, and deployments directly in Actions eliminates the need for external CI services.

But here’s the problem: your builds need to pull dependencies and push artifacts somewhere. Using public registries works for open source, but private projects need private artifact repositories. And if you’ve priced out JFrog Artifactory or Sonatype Nexus for this, you’ve seen how quickly costs escalate when CI/CD pipelines download artifacts hundreds of times per day.

This guide shows you how to integrate CloudRepo with GitHub Actions for Maven, Gradle, and Python builds. You’ll get working examples you can copy into your workflows today.

Why CloudRepo for GitHub Actions

Before diving into configuration, here’s why CloudRepo works well with GitHub Actions:

Every time your workflow runs mvn install or pip install, it downloads artifacts. With consumption-based pricing (like Artifactory), each download costs money. If you exceed your monthly transfer allowance, we reach out first. Nothing is throttled, no build ever stops, and there are no automatic charges. Occasional spikes are simply fine. Sustained overage is billed at $120 per additional TB, always rounded down in your favor (2.9 TB over = 2 TB billed = $240). Storage growth is a prorated one-click plan upgrade, not per-GB fees.

Simple authentication. CloudRepo uses standard HTTP basic auth. No special plugins, no complex token management. GitHub Actions secrets work perfectly.

Tip

Already have artifacts in Artifactory or Nexus? Our migration guides for Artifactory and Nexus walk you through moving everything over.

Prerequisites

Before configuring your workflows, you’ll need:

  • A GitHub repository with Actions enabled
  • A CloudRepo account with at least one repository created
  • Your CloudRepo credentials (username and API token or password)

Setting Up GitHub Secrets

Store your CloudRepo credentials as GitHub secrets. Never hardcode credentials in workflow files.

  1. Go to your GitHub repository
  2. Navigate to Settings > Secrets and variables > Actions
  3. Add these secrets:
    • CLOUDREPO_USERNAME: Your CloudRepo username
    • CLOUDREPO_API_TOKEN: Your CloudRepo password or API token

These secrets will be available as environment variables in your workflows.

Maven Builds with GitHub Actions

Maven is the most common use case. Here’s a complete workflow that builds a Java project, runs tests, and deploys artifacts to CloudRepo.

Workflow Configuration

Create .github/workflows/maven-build.yml:

.github/workflows/maven-build.yml
name: Maven Build and Deploy
on:
push:
branches: [main, develop]
pull_request:
branches: [main]
jobs:
build:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- name: Set up JDK 21
uses: actions/setup-java@v4
with:
java-version: '21'
distribution: 'temurin'
cache: maven
- name: Build and test
run: mvn -B verify
- name: Deploy to CloudRepo
if: github.ref == 'refs/heads/main'
env:
CLOUDREPO_USERNAME: ${{ secrets.CLOUDREPO_USERNAME }}
CLOUDREPO_API_TOKEN: ${{ secrets.CLOUDREPO_API_TOKEN }}
run: |
mvn -B deploy -s .github/settings.xml

Maven Settings File

Create .github/settings.xml in your repository:

.github/settings.xml
<settings xmlns="http://maven.apache.org/SETTINGS/1.0.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/SETTINGS/1.0.0
https://maven.apache.org/xsd/settings-1.0.0.xsd">
<servers>
<server>
<id>cloudrepo-releases</id>
<username>${env.CLOUDREPO_USERNAME}</username>
<password>${env.CLOUDREPO_API_TOKEN}</password>
</server>
<server>
<id>cloudrepo-snapshots</id>
<username>${env.CLOUDREPO_USERNAME}</username>
<password>${env.CLOUDREPO_API_TOKEN}</password>
</server>
</servers>
</settings>

POM Configuration

Add distribution management to your pom.xml:

pom.xml
<distributionManagement>
<repository>
<id>cloudrepo-releases</id>
<url>https://your-org.mycloudrepo.io/repositories/maven-releases</url>
</repository>
<snapshotRepository>
<id>cloudrepo-snapshots</id>
<url>https://your-org.mycloudrepo.io/repositories/maven-snapshots</url>
</snapshotRepository>
</distributionManagement>

Replace your-org with your CloudRepo organization name.

Important

The id elements in your POM must match the id elements in settings.xml. Maven uses these IDs to look up credentials.

Gradle Builds with GitHub Actions

Gradle configuration follows a similar pattern but uses Gradle’s publishing plugin.

Workflow Configuration

Create .github/workflows/gradle-build.yml:

.github/workflows/gradle-build.yml
name: Gradle Build and Deploy
on:
push:
branches: [main, develop]
pull_request:
branches: [main]
jobs:
build:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- name: Set up JDK 21
uses: actions/setup-java@v4
with:
java-version: '21'
distribution: 'temurin'
cache: gradle
- name: Grant execute permission for gradlew
run: chmod +x gradlew
- name: Build and test
run: ./gradlew build
- name: Publish to CloudRepo
if: github.ref == 'refs/heads/main'
env:
CLOUDREPO_USERNAME: ${{ secrets.CLOUDREPO_USERNAME }}
CLOUDREPO_API_TOKEN: ${{ secrets.CLOUDREPO_API_TOKEN }}
run: ./gradlew publish

Gradle Build Configuration

Add publishing configuration to your build.gradle.kts:

build.gradle.kts
plugins {
`maven-publish`
}
publishing {
publications {
create<MavenPublication>("mavenJava") {
from(components["java"])
}
}
repositories {
maven {
name = "cloudrepo"
url = uri(
if (version.toString().endsWith("SNAPSHOT"))
"https://your-org.mycloudrepo.io/repositories/maven-snapshots"
else
"https://your-org.mycloudrepo.io/repositories/maven-releases"
)
credentials {
username = System.getenv("CLOUDREPO_USERNAME")
password = System.getenv("CLOUDREPO_API_TOKEN")
}
}
}
}

Or if you’re using Groovy DSL (build.gradle):

build.gradle
plugins {
id 'maven-publish'
}
publishing {
publications {
mavenJava(MavenPublication) {
from components.java
}
}
repositories {
maven {
name = 'cloudrepo'
url = version.endsWith('SNAPSHOT')
? 'https://your-org.mycloudrepo.io/repositories/maven-snapshots'
: 'https://your-org.mycloudrepo.io/repositories/maven-releases'
credentials {
username = System.getenv('CLOUDREPO_USERNAME')
password = System.getenv('CLOUDREPO_API_TOKEN')
}
}
}
}

Python/Poetry Builds with GitHub Actions

CloudRepo also hosts Python packages. Here’s how to configure Poetry to publish to your private PyPI repository.

Workflow Configuration

Create .github/workflows/python-build.yml:

.github/workflows/python-build.yml
name: Python Build and Deploy
on:
push:
branches: [main]
tags:
- 'v*'
pull_request:
branches: [main]
jobs:
build:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- name: Set up Python
uses: actions/setup-python@v5
with:
python-version: '3.12'
- name: Install Poetry
uses: snok/install-poetry@v1
with:
version: 1.8.0
virtualenvs-create: true
virtualenvs-in-project: true
- name: Load cached venv
id: cached-poetry-dependencies
uses: actions/cache@v4
with:
path: .venv
key: venv-${{ runner.os }}-${{ hashFiles('**/poetry.lock') }}
- name: Install dependencies
if: steps.cached-poetry-dependencies.outputs.cache-hit != 'true'
run: poetry install --no-interaction --no-root
- name: Install project
run: poetry install --no-interaction
- name: Run tests
run: poetry run pytest
- name: Build package
run: poetry build
- name: Publish to CloudRepo
if: startsWith(github.ref, 'refs/tags/v')
env:
POETRY_HTTP_BASIC_CLOUDREPO_USERNAME: ${{ secrets.CLOUDREPO_USERNAME }}
POETRY_HTTP_BASIC_CLOUDREPO_PASSWORD: ${{ secrets.CLOUDREPO_API_TOKEN }}
run: |
poetry config repositories.cloudrepo https://your-org.mycloudrepo.io/repositories/python-releases/
poetry publish -r cloudrepo

Installing Private Packages

To install packages from your private CloudRepo repository in other projects, add it as an explicit source and name it on each private dependency. Poetry then looks up those packages on CloudRepo only:

pyproject.toml
[tool.poetry.dependencies]
acme-shared-lib = { version = "^1.2", source = "cloudrepo" }
[[tool.poetry.source]]
name = "cloudrepo"
url = "https://your-org.mycloudrepo.io/repositories/python-releases/simple/"
priority = "explicit"

Name the source on every private package, including the private packages your private packages depend on: Poetry looks up any dependency that names no source on PyPI.

Then in your workflow, give Poetry the credential for the source. It reads the credential for the cloudrepo source from two environment variables named for it:

- name: Install with the private repository
env:
POETRY_HTTP_BASIC_CLOUDREPO_USERNAME: ${{ secrets.CLOUDREPO_USERNAME }}
POETRY_HTTP_BASIC_CLOUDREPO_PASSWORD: ${{ secrets.CLOUDREPO_API_TOKEN }}
run: poetry install

Info

For more details on Poetry and private Python repositories, see our complete Poetry guide.

CloudRepo vs. Competitors for CI/CD

Here’s why teams choose CloudRepo over alternatives for their GitHub Actions workflows:

Feature CloudRepo JFrog Artifactory Sonatype Nexus GitHub Packages
Pricing Model Flat monthly Consumption-based Self-hosted or consumption-based Free tier + overages
Maven Support Full Full Full Full
Gradle Support Full Full Full Full
Python Support Full Full Full Limited
Setup Complexity Low High Medium-High Medium
Support Included Yes Community on Pro; 24/7 SLA on Enterprise X Community on Community Edition; enterprise support and SLA on Pro GitHub support

Info

GitHub Packages data transfer is free when downloading via GitHub Actions using GITHUB_TOKEN. However, storage limits apply (500MB free, then $0.25/GB), and external downloads outside Actions are billed.

Why Flat Pricing Matters for CI/CD

Consumption-based pricing creates unpredictable costs that scale with your success. The more you build, the more you pay.

Consider a team running 100 builds per day, each downloading 500 MB of dependencies:

Daily transfer: 100 builds x 500 MB = 50 GB
Monthly transfer: 50 GB x 30 days = 1,500 GB

With JFrog Artifactory Cloud:

  • Consumption charges add up quickly at scale
  • Plus a base subscription: $150/month for Cloud Pro at list, or $27,000 a year for self-managed Pro X
  • Gold and Platinum support are optional upgrades; JFrog publishes no price for them

With self-hosted Nexus:

  • You pay for your own infrastructure (servers, storage, bandwidth)
  • Maintenance and upgrade burden on your team
  • No direct egress fees to Sonatype, but infrastructure costs scale with usage

With CloudRepo:

  • Team plan: $499/month billed annually, flat
  • Support included

CloudRepo’s predictable pricing means you can scale your CI/CD pipelines without worrying about runaway costs.

Best Practices for CI/CD with CloudRepo

Cache Dependencies Aggressively

GitHub Actions caching reduces both build time and repository load:

- uses: actions/setup-java@v4
with:
java-version: '21'
distribution: 'temurin'
cache: maven # Built-in caching

Use Separate Repositories for Snapshots and Releases

Keep development artifacts separate from production releases:

  • maven-snapshots for -SNAPSHOT versions
  • maven-releases for stable versions
  • python-releases for published packages

This makes it easy to clean up old snapshots without affecting releases.

Rotate Credentials Regularly

Create dedicated CI/CD credentials in CloudRepo and rotate them periodically. Don’t use your personal account for automated builds.

Implement Branch-Based Deployment Logic

Only deploy from specific branches to prevent accidental releases:

- name: Deploy to CloudRepo
if: github.ref == 'refs/heads/main' && github.event_name == 'push'
run: mvn deploy

Troubleshooting Common Issues

401 Unauthorized Errors

  • Verify secrets are set correctly in GitHub
  • Check that secret names match exactly (they’re case-sensitive)
  • Ensure your CloudRepo credentials haven’t expired
  • Verify the repository URLs are correct

403 Forbidden Errors

  • Confirm your CloudRepo user has write access to the repository
  • Check if the repository exists (typos in URLs are common)
  • Verify you’re using HTTPS, not HTTP

Slow Builds

  • Enable dependency caching in your workflow
  • Consider using GitHub-hosted larger runners for complex builds
  • Check if your repository is in a region close to GitHub’s runners

Next Steps

You now have everything you need to integrate CloudRepo with GitHub Actions for Maven, Gradle, and Python projects.

Ready to simplify your CI/CD artifact management?

Start your free CloudRepo trial - no credit card required. Get your private repositories set up in minutes and connect them to your GitHub Actions workflows today.

Already using Artifactory or Nexus? Our team can help you migrate. Contact us or check out our migration guides:


Have questions about integrating CloudRepo with your CI/CD pipeline? Our support team is here to help - support is included with every CloudRepo plan, not sold as an expensive add-on.

Competitor figures in this guide were read on 2026-10-06 from JFrog’s pricing (archived), JFrog’s Pro checkout (archived), JFrog’s support page (archived), Sonatype’s pricing (archived), GitHub Packages billing (archived) and GitHub’s rate data (archived). Vendors change prices and plans, so check each page before you decide.

Related Articles

DevOps

JFrog Artifactory to CloudRepo Migration Guide

Step-by-step guide to migrate from JFrog Artifactory to CloudRepo. Escape complex licensing and move to simple, published pricing with our comprehensive migration playbook.

15 min read Read more →