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.
- Go to your GitHub repository
- Navigate to Settings > Secrets and variables > Actions
- Add these secrets:
CLOUDREPO_USERNAME: Your CloudRepo usernameCLOUDREPO_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:
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.xmlMaven Settings File
Create .github/settings.xml in your repository:
<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:
<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:
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 publishGradle Build Configuration
Add publishing configuration to your 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):
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:
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 cloudrepoInstalling 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:
[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 installInfo
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 GBMonthly transfer: 50 GB x 30 days = 1,500 GBWith 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 cachingUse Separate Repositories for Snapshots and Releases
Keep development artifacts separate from production releases:
maven-snapshotsfor-SNAPSHOTversionsmaven-releasesfor stable versionspython-releasesfor 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 deployTroubleshooting 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.