Set Up a Build Tool with JFrog CLI
Set up a build tool with JFrog Artifactory using JFrog CLI. This tutorial walks through the full workflow with npm, then shows how to adapt for any supported build tool.
This topic covers the following tasks:
- Configure npm for Artifactory
- Install dependencies through Artifactory
- Publish a package to Artifactory
- Enrich and publish build information
Prerequisites
- JFrog CLI installed — Installation guide
- JFrog CLI authenticated — Run
jf config addto configure a server connection (Configuring the CLI) - npm installed — Or your build tool of choice
- An npm project with
package.json(or create one for testing)
What You Will Do
- Configure npm to use Artifactory
- Install npm dependencies via Artifactory
- Publish an npm package
- Collect and publish build information
How do I configure npm for Artifactory?
Generate npm configuration that points your project to Artifactory for resolving and deploying packages. Run this in your project directory.
To configure npm for Artifactory:
Interactive configuration:
cd <your-project-dir>
jf npm-configNon-interactive example:
jf npm-config --server-id-resolve=<server-id> --repo-resolve=<repo-name> --server-id-deploy=<server-id> --repo-deploy=<repo-name>Replace <server-id> and <repo-name> with your Artifactory server ID and repository names. This creates or updates .jfrog/projects/npm.yaml in your project.
To see all available options:
jf npm-config --helpHow do I install dependencies through Artifactory?
Install dependencies through Artifactory. The CLI records build information when you pass --build-name and --build-number.
To install dependencies through Artifactory:
jf npm install --build-name=<build-name> --build-number=<build-number>Or without build information:
jf npm installExample for CI:
jf npm ci --build-name=my-app --build-number=$BUILD_NUMBERHow do I publish a package to Artifactory?
Publish your package to the configured Artifactory repository. Include build information for traceability.
To publish the package to Artifactory:
jf npm publish --build-name=<build-name> --build-number=<build-number>How do I enrich and publish build information?
After running npm commands with --build-name and --build-number, enrich the build-info with environment and Git context, then publish.
To enrich and publish build information:
# Capture environment variables (CI build URL, job name, etc.)
jf rt build-collect-env <build-name> <build-number>
# Attach Git commit info (hash, branch, message)
jf rt build-add-git <build-name> <build-number>
# Publish the enriched build-info to Artifactory
jf rt build-publish <build-name> <build-number>Example:
jf rt build-collect-env my-app 1
jf rt build-add-git my-app 1
jf rt bp my-app 1The
build-collect-envandbuild-add-gitsteps are optional but recommended in CI/CD pipelines. They add traceability to your builds — linking each build to its source commit and build environment.
Complete Workflow Example
# 1. Configure npm (run once per project)
jf npm-config --server-id-resolve=my-server --repo-resolve=npm-virtual --server-id-deploy=my-server --repo-deploy=npm-local
# 2. Install dependencies
jf npm install --build-name=my-app --build-number=1
# 3. Publish the package
jf npm publish --build-name=my-app --build-number=1
# 4. Enrich and publish build information
jf rt build-collect-env my-app 1
jf rt build-add-git my-app 1
jf rt build-publish my-app 1Verifying Success
After completing the workflow, verify that everything worked:
Check that artifacts were uploaded:
jf rt search npm-local/my-package/Check that build-info was published:
jf rt curl -XGET "/api/build/my-app/1"Or visit Artifactory UI > Builds > my-app > 1 to see the build-info with its dependencies, artifacts, environment variables, and Git context.
CI/CD Integration
Bash (Jenkins / GitLab CI)
jf config add ci-server --url=$JFROG_URL --access-token=$JFROG_ACCESS_TOKEN --interactive=false
jf npm-config --server-id-resolve=ci-server --repo-resolve=npm-virtual --server-id-deploy=ci-server --repo-deploy=npm-local
jf npm ci --build-name=$BUILD_NAME --build-number=$BUILD_NUMBER
jf npm publish --build-name=$BUILD_NAME --build-number=$BUILD_NUMBER
jf rt build-collect-env $BUILD_NAME $BUILD_NUMBER
jf rt build-add-git $BUILD_NAME $BUILD_NUMBER
jf rt build-publish $BUILD_NAME $BUILD_NUMBERGitHub Actions
# .github/workflows/build.yml
steps:
- uses: actions/checkout@v4
- name: Setup JFrog CLI
uses: jfrog/setup-jfrog-cli@v4
env:
JF_URL: ${{ vars.JF_URL }}
JF_ACCESS_TOKEN: ${{ secrets.JF_ACCESS_TOKEN }}
- name: Configure npm
run: jf npm-config --server-id-resolve=setup-jfrog-cli-server --repo-resolve=npm-virtual --server-id-deploy=setup-jfrog-cli-server --repo-deploy=npm-local
- name: Install dependencies
run: jf npm ci --build-name=my-app --build-number=${{ github.run_number }}
- name: Enrich and publish build info
run: |
jf rt build-collect-env my-app ${{ github.run_number }}
jf rt build-add-git my-app ${{ github.run_number }}
jf rt build-publish my-app ${{ github.run_number }}Coming from the UI? If you have been configuring build tool integrations through the Artifactory UI under Administration > Repositories, the
*-configcommands create the same association between your project and Artifactory repositories — but locally, so your builds resolve dependencies through Artifactory automatically.
Adapting for Other Build Tools
This tutorial uses npm, but the pattern is the same for all build tools:
| Build Tool | Config Command | Build Command | Publish Command |
|---|---|---|---|
| npm | jf npm-config | jf npm install | jf npm publish |
| Maven | jf mvn-config | jf mvn clean install | Via deploy goal |
| Gradle | jf gradle-config | jf gradle build | Via publish tasks |
| pip | jf pip-config | jf pip install | jf twine upload |
| Go | jf go-config | jf go build | jf go-publish |
| Docker | — | jf docker pull / build | jf docker push |
| Yarn | jf yarn-config | jf yarn install | — |
| NuGet | jf nuget-config | jf nuget restore | — |
| Poetry | jf poetry-config | jf poetry install | jf poetry publish |
Always finish with jf rt build-publish <name> <number> to send build information to Artifactory.
End-to-End: Python (pip + twine)
# Configure
jf pip-config --server-id-resolve=my-server --repo-resolve=pypi-virtual \
--server-id-deploy=my-server --repo-deploy=pypi-local
# Install dependencies
jf pip install -r requirements.txt --build-name=my-python-app --build-number=1
# Build and publish the package
python -m build
jf twine upload dist/* --build-name=my-python-app --build-number=1
# Enrich and publish build-info
jf rt build-collect-env my-python-app 1
jf rt build-add-git my-python-app 1
jf rt build-publish my-python-app 1End-to-End: Java (Maven)
# Configure
jf mvn-config --server-id-resolve=my-server \
--repo-resolve-releases=libs-release --repo-resolve-snapshots=libs-snapshot \
--server-id-deploy=my-server \
--repo-deploy-releases=libs-release-local --repo-deploy-snapshots=libs-snapshot-local
# Build (artifacts deploy automatically at install phase)
jf mvn clean install -DskipTests --build-name=my-java-app --build-number=1
# Enrich and publish build-info
jf rt build-collect-env my-java-app 1
jf rt build-add-git my-java-app 1
jf rt build-publish my-java-app 1End-to-End: Go
# Configure
jf go-config --server-id-resolve=my-server --repo-resolve=go-virtual \
--server-id-deploy=my-server --repo-deploy=go-local
# Build
jf go build --build-name=my-go-app --build-number=1
# Publish the module
jf go-publish v1.0.0 --build-name=my-go-app --build-number=1
# Enrich and publish build-info
jf rt build-collect-env my-go-app 1
jf rt build-add-git my-go-app 1
jf rt build-publish my-go-app 1End-to-End: Docker
# Login to the Docker registry
jf docker login acme.jfrog.io
# Build and push
jf docker build -t acme.jfrog.io/docker-local/my-app:1.0.0 .
jf docker push acme.jfrog.io/docker-local/my-app:1.0.0 \
--build-name=my-docker-app --build-number=1
# Enrich and publish build-info
jf rt build-collect-env my-docker-app 1
jf rt build-add-git my-docker-app 1
jf rt build-publish my-docker-app 1Common Issues and Fixes
| Problem | Fix |
|---|---|
| "no config file was found" | Run jf <tool>-config in the project directory first |
| Resolution fails with 404 | Check that the repo name in config matches an existing Artifactory repository |
| Build info shows 0 dependencies | Ensure you passed --build-name and --build-number to the build command |
jf rt build-publish fails | Verify your server configuration has a valid access token with deploy permissions |
Build Succeeded but Nothing Was Deployed
JFrog CLI invokes your package manager and passes native flags through unchanged. If your build finishes successfully but no artifacts appear in Artifactory (or only build-info is recorded), check whether your native tool requires you to select a target to publish:
- Gradle (Artifactory Gradle plugin): You must tell the plugin which publication(s) to deploy.
- Maven: Make sure you run a phase/goal that actually deploys (e.g.,
deploy, orinstallif your setup deploys during install). The CLI accepts Maven args as-is. - npm / Yarn: Install only resolves. Use
jf npm publish(orjf rt upload) to push a package.
Frequently Asked Questions
What is the difference between jf npm install and jf npm ci?
jf npm install and jf npm ci?jf npm install resolves dependencies from package.json and may update package-lock.json. jf npm ci installs strictly from package-lock.json without modifying it — preferred in CI/CD for reproducible builds. Both collect build-info when --build-name and --build-number are provided.
Do I need to run jf rt build-publish after every build?
jf rt build-publish after every build?Only if you want build-info stored in Artifactory. The --build-name and --build-number flags collect build-info locally. Running jf rt build-publish uploads that record to Artifactory, enabling traceability, promotion, and Xray scanning.
Can I adapt this tutorial for Maven, Gradle, or other tools?
Yes. The three-step pattern (configure, build, publish build-info) is identical for all tools.
What if my build succeeds but no artifacts appear in Artifactory?
Check whether your build tool requires an explicit publish step. For npm, run jf npm publish. For Gradle, configure the Artifactory plugin's publication target.
Related Topics
- Native Mode — Wrapped vs Native execution modes
Updated 8 days ago
