Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
84 changes: 84 additions & 0 deletions .github/workflows/nixTests.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,84 @@
name: Nix Tests
on:
workflow_dispatch:
inputs:
jfrog_url:
description: "External JFrog Platform URL. Leave empty for local Artifactory."
type: string
required: false
default: ""
jfrog_admin_token:
description: "Admin token for external JFrog Platform."
type: string
required: false
default: ""
push:
branches:
- "master"
pull_request_target:
types: [labeled]
branches:
- "master"

concurrency:
group: ${{ github.workflow }}-${{ github.event.pull_request.number || github.sha }}-${{ github.ref }}
cancel-in-progress: true
jobs:
Nix-Tests:
name: Nix tests (${{ matrix.os.name }})
if: github.event_name == 'workflow_dispatch' || github.event_name == 'push' || contains(github.event.pull_request.labels.*.name, 'safe to test')
strategy:
fail-fast: false
matrix:
os:
- name: ubuntu
version: 24.04
- name: macos
version: 14
# Windows omitted: Nix does not have first-class Windows support.
runs-on: ${{ matrix.os.name }}-${{ matrix.os.version }}
steps:
- name: Skip macOS - JGC-413
if: matrix.os.name == 'macos'
run: |
echo "::warning::JGC-413 - Skip until artifactory bootstrap in osx is fixed"
exit 0

- name: Checkout code
if: matrix.os.name != 'macos'
uses: actions/checkout@v6
with:
ref: ${{ github.event.pull_request.head.sha || github.ref }}

- name: Setup FastCI
if: matrix.os.name != 'macos'
uses: jfrog-fastci/fastci@v1
with:
github_token: ${{ secrets.GITHUB_TOKEN }}
fastci_otel_token: ${{ secrets.FASTCI_TOKEN }}

- name: Setup Go with cache
if: matrix.os.name != 'macos'
uses: jfrog/.github/actions/install-go-with-cache@main

- name: Install Nix
if: matrix.os.name != 'macos'
uses: cachix/install-nix-action@v31
with:
extra_nix_config: |
experimental-features = nix-command flakes

- name: Install local Artifactory
if: matrix.os.name != 'macos'
uses: jfrog/.github/actions/install-local-artifactory@main
with:
RTLIC: ${{ secrets.RTLIC }}
JFROG_URL: ${{ inputs.jfrog_url }}
JFROG_ADMIN_TOKEN: ${{ inputs.jfrog_admin_token }}
RT_CONNECTION_TIMEOUT_SECONDS: '1200'

- name: Run Nix tests
if: matrix.os.name != 'macos'
run: >-
go test -v github.com/jfrog/jfrog-cli --timeout 0 --test.nix
${{ env.JFROG_TESTS_IS_EXTERNAL == 'true' && format('--jfrog.url={0} --jfrog.adminToken={1}', env.JFROG_TESTS_URL, env.JFROG_TESTS_LOCAL_ACCESS_TOKEN) || '' }}
62 changes: 62 additions & 0 deletions buildtools/cli.go
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ import (
"errors"
"fmt"
conancommand "github.com/jfrog/jfrog-cli-artifactory/artifactory/commands/conan"
nixcommand "github.com/jfrog/jfrog-cli-artifactory/artifactory/commands/nix"
"io/fs"
"os"
"os/exec"
Expand Down Expand Up @@ -67,6 +68,7 @@ import (
huggingfaceuploaddocs "github.com/jfrog/jfrog-cli/docs/buildtools/huggingfaceupload"
mvndoc "github.com/jfrog/jfrog-cli/docs/buildtools/mvn"
"github.com/jfrog/jfrog-cli/docs/buildtools/mvnconfig"
"github.com/jfrog/jfrog-cli/docs/buildtools/nix"
"github.com/jfrog/jfrog-cli/docs/buildtools/npmcommand"
"github.com/jfrog/jfrog-cli/docs/buildtools/npmconfig"
nugetdocs "github.com/jfrog/jfrog-cli/docs/buildtools/nuget"
Expand Down Expand Up @@ -409,6 +411,19 @@ func GetCommands() []cli.Command {
Category: buildToolsCategory,
Action: ConanCmd,
},
{
Name: "nix",
Hidden: true,
Flags: cliutils.GetCommandFlags(cliutils.Nix),
Usage: nix.GetDescription(),
HelpName: corecommon.CreateUsage("nix", nix.GetDescription(), nix.Usage),
UsageText: nix.GetArguments(),
ArgsUsage: common.CreateEnvVars(),
SkipFlagParsing: true,
BashComplete: corecommon.CreateBashCompletionFunc(),
Category: buildToolsCategory,
Action: NixCmd,
},
{
Name: "ruby-config",
Flags: cliutils.GetCommandFlags(cliutils.RubyConfig),
Expand Down Expand Up @@ -2010,6 +2025,53 @@ func ConanCmd(c *cli.Context) error {
return commands.Exec(conanCommand)
}

func NixCmd(c *cli.Context) error {
if show, err := cliutils.ShowCmdHelpIfNeeded(c, c.Args()); show || err != nil {
return err
}
if c.NArg() < 1 {
return cliutils.WrongNumberOfArgumentsHandler(c)
}

args := cliutils.ExtractCommand(c)

// The first arg determines which native tool to run:
// jf nix nix-channel --add ... → nativeTool="nix-channel", args=["--add", ...]
// jf nix nix-env -iA ... → nativeTool="nix-env", args=["-iA", ...]
// jf nix nix-build '<nixpkgs>' → nativeTool="nix-build", args=["'<nixpkgs>'", ...]
// jf nix copy --to ... → nativeTool="copy" (runs as "nix copy"), args=["--to", ...]
nativeTool, remainingArgs := getCommandName(args)

// Extract --server-id flag before passing to native tool
var serverID string
var err error
remainingArgs, serverID, err = coreutils.ExtractServerIdFromCommand(remainingArgs)
if err != nil {
return fmt.Errorf("failed to extract server ID: %w", err)
}

// Extract build flags (--build-name, --build-number, --module, --project)
filteredArgs, buildConfiguration, err := build.ExtractBuildDetailsFromArgs(remainingArgs)
if err != nil {
return err
}

cmd := nixcommand.NewNixCommand().SetNativeTool(nativeTool).SetArgs(filteredArgs).SetBuildConfiguration(buildConfiguration)

// Pass server details — use --server-id if provided, otherwise default
var serverDetails *coreConfig.ServerDetails
if serverID != "" {
serverDetails, err = coreConfig.GetSpecificConfig(serverID, false, false)
} else {
serverDetails, err = coreConfig.GetDefaultServerConf()
}
if err == nil && serverDetails != nil {
cmd.SetServerDetails(serverDetails)
}

return commands.Exec(cmd)
}

func pythonCmd(c *cli.Context, projectType project.ProjectType) error {
if show, err := cliutils.ShowCmdHelpIfNeeded(c, c.Args()); show || err != nil {
return err
Expand Down
20 changes: 20 additions & 0 deletions docs/buildtools/nix/help.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
package nix

var Usage = []string{"nix <native-command> <args> [command options]"}

func GetDescription() string {
return "Run native nix commands with build-info support."
}

func GetArguments() string {
return ` nix native-command
Wraps native Nix commands (nix-channel, nix-env, nix-build, nix copy)
with build-info collection. All args are passed through to the native tool.

Examples:
- jf nix nix-channel --add https://server/artifactory/api/nix/repo/channels/nixos-25.11 nixpkgs
- jf nix nix-channel --update
- jf nix nix-env -iA nixpkgs.hello --build-name=my-build --build-number=1
- jf nix nix-build '<nixpkgs>' -A hello --build-name=my-build --build-number=1
- jf nix copy --to "http://user:pass@server/artifactory/api/nix/repo/" ./result --build-name=my-build --build-number=1`
}
6 changes: 3 additions & 3 deletions go.mod
Original file line number Diff line number Diff line change
Expand Up @@ -16,11 +16,11 @@ require (
github.com/docker/docker v28.5.2+incompatible
github.com/gocarina/gocsv v0.0.0-20240520201108-78e41c74b4b1
github.com/jfrog/archiver/v3 v3.6.3
github.com/jfrog/build-info-go v1.13.1-0.20260521104402-1e35b9b5b0c6
github.com/jfrog/build-info-go v1.13.1-0.20260526201157-3dd942bd9e1f
github.com/jfrog/gofrog v1.7.6
github.com/jfrog/jfrog-cli-application v1.0.2-0.20260511133105-55a0ab56fd64
github.com/jfrog/jfrog-cli-artifactory v0.8.1-0.20260520131142-ef80a14dd499
github.com/jfrog/jfrog-cli-core/v2 v2.60.1-0.20260520130103-75be6a23c54b
github.com/jfrog/jfrog-cli-artifactory v0.8.1-0.20260527043943-fdf755c4f4c2
github.com/jfrog/jfrog-cli-core/v2 v2.60.1-0.20260522091649-43f236276873
github.com/jfrog/jfrog-cli-evidence v0.9.4
github.com/jfrog/jfrog-cli-platform-services v1.10.1-0.20260430094150-ce7d9b371c6f
github.com/jfrog/jfrog-cli-security v1.29.0
Expand Down
14 changes: 6 additions & 8 deletions go.sum
Original file line number Diff line number Diff line change
Expand Up @@ -406,8 +406,8 @@ github.com/jellydator/ttlcache/v3 v3.4.0 h1:YS4P125qQS0tNhtL6aeYkheEaB/m8HCqdMMP
github.com/jellydator/ttlcache/v3 v3.4.0/go.mod h1:Hw9EgjymziQD3yGsQdf1FqFdpp7YjFMd4Srg5EJlgD4=
github.com/jfrog/archiver/v3 v3.6.3 h1:hkAmPjBw393tPmQ07JknLNWFNZjXdy2xFEnOW9wwOxI=
github.com/jfrog/archiver/v3 v3.6.3/go.mod h1:5V9l+Fte30Y4qe9dUOAd3yNTf8lmtVNuhKNrvI8PMhg=
github.com/jfrog/build-info-go v1.13.1-0.20260521104402-1e35b9b5b0c6 h1:x9UKlP7rEzCYS/Z8IP0I+Oy8PTPpOxFy8qpMeRMbrwo=
github.com/jfrog/build-info-go v1.13.1-0.20260521104402-1e35b9b5b0c6/go.mod h1:CYRUCvLKfyARjoJXLWAxce1qNUxTEtbRKAARkV42vpE=
github.com/jfrog/build-info-go v1.13.1-0.20260526201157-3dd942bd9e1f h1:2f9rUp14HdL8SD84/3Vu1UOmn71OIX7MxmHLW4VCjwM=
github.com/jfrog/build-info-go v1.13.1-0.20260526201157-3dd942bd9e1f/go.mod h1:CYRUCvLKfyARjoJXLWAxce1qNUxTEtbRKAARkV42vpE=
github.com/jfrog/froggit-go v1.22.0 h1:eeN5F8sOUo+h2cXkzArAu4nvSdjkDTAZtgqwrct70qg=
github.com/jfrog/froggit-go v1.22.0/go.mod h1:wRDryqyp3oe+eHgME2mpnEQmO8XBECIPagFwj0nHmdI=
github.com/jfrog/go-mockhttp v0.3.1 h1:/wac8v4GMZx62viZmv4wazB5GNKs+GxawuS1u3maJH8=
Expand All @@ -418,18 +418,16 @@ github.com/jfrog/jfrog-apps-config v1.0.1 h1:mtv6k7g8A8BVhlHGlSveapqf4mJfonwvXYL
github.com/jfrog/jfrog-apps-config v1.0.1/go.mod h1:8AIIr1oY9JuH5dylz2S6f8Ym2MaadPLR6noCBO4C22w=
github.com/jfrog/jfrog-cli-application v1.0.2-0.20260511133105-55a0ab56fd64 h1:bxcy1v1LXQV4T0kVU1duWQr3h7vKfHyMD1B+IuFLWUw=
github.com/jfrog/jfrog-cli-application v1.0.2-0.20260511133105-55a0ab56fd64/go.mod h1:cKqb/JgN+XuD4RhOxvSZnyGyXw3cJsTZfQT3rk9MCho=
github.com/jfrog/jfrog-cli-artifactory v0.8.1-0.20260520131142-ef80a14dd499 h1:wkhhrH5nIpCFM61z2mEGXnFuk44FQMPmGudDzmPZuV8=
github.com/jfrog/jfrog-cli-artifactory v0.8.1-0.20260520131142-ef80a14dd499/go.mod h1:g8hvUcVJs26a+3F6X4+Cthx5q4LeLrlPsekn0vxPYU0=
github.com/jfrog/jfrog-cli-core/v2 v2.60.1-0.20260520130103-75be6a23c54b h1:Bi0dfWKDANYjzV7xVH1eV2LdNdJAE259IXPjX6IDAO0=
github.com/jfrog/jfrog-cli-core/v2 v2.60.1-0.20260520130103-75be6a23c54b/go.mod h1:D9afcOJmauUYcQZ3WGDg7HejyoBmCQr2XrwXHeN1YY8=
github.com/jfrog/jfrog-cli-artifactory v0.8.1-0.20260527043943-fdf755c4f4c2 h1:acwlLYjjglecqjXXgj2JoM1bUhH/dDMpLpJXrBfvyqU=
github.com/jfrog/jfrog-cli-artifactory v0.8.1-0.20260527043943-fdf755c4f4c2/go.mod h1:T5HDtDxHlUZWF4LQnmF2kiyFyd8yLOf3K618BsG0CWk=
github.com/jfrog/jfrog-cli-core/v2 v2.60.1-0.20260522091649-43f236276873 h1:6X1Hwu0st7c9gbFoIj1fc8qjoQ3wAHWX2qo7K9IxWgU=
github.com/jfrog/jfrog-cli-core/v2 v2.60.1-0.20260522091649-43f236276873/go.mod h1:D9afcOJmauUYcQZ3WGDg7HejyoBmCQr2XrwXHeN1YY8=
github.com/jfrog/jfrog-cli-evidence v0.9.4 h1:RAqZYaH2RrzmhW+bGA7dx/yTqa4X1fZ4/5V7VVMSJtc=
github.com/jfrog/jfrog-cli-evidence v0.9.4/go.mod h1:nLSLqLIhQz1Hi2n+KjHZTyK1mcmPLevv41LjItLswmE=
github.com/jfrog/jfrog-cli-platform-services v1.10.1-0.20260430094150-ce7d9b371c6f h1:M1cesbKYSznwPA76dNctjCELxGx34TSSjwoYnJm9/6Y=
github.com/jfrog/jfrog-cli-platform-services v1.10.1-0.20260430094150-ce7d9b371c6f/go.mod h1:JUdq/dQoNscpta62FDCAcaSVbvcCOr5VkH8UeGTG1HQ=
github.com/jfrog/jfrog-cli-security v1.29.0 h1:TN2OCA5i/iPbikQWzSwVqGvySvIvw1P6rPga+DbVBOI=
github.com/jfrog/jfrog-cli-security v1.29.0/go.mod h1:q38TPlxortIJvbyD3u9P9UhHwyx007tEb9WbXlXw2E0=
github.com/jfrog/jfrog-client-go v1.55.1-0.20260518090239-a4f67e2bd8cb h1:ew1foDyxCyqKbSz06ybrrHruf4OIbhti/YLwaa0J8dI=
github.com/jfrog/jfrog-client-go v1.55.1-0.20260518090239-a4f67e2bd8cb/go.mod h1:sCE06+GngPoyrGO0c+vmhgMoVSP83UMNiZnIuNPzU8U=
github.com/jfrog/jfrog-client-go v1.55.1-0.20260522071027-8b60a715d6e4 h1:ujVu255rk51l9Uz1t75DdsVoa2MH+lYNV2cB2xDWjPM=
github.com/jfrog/jfrog-client-go v1.55.1-0.20260522071027-8b60a715d6e4/go.mod h1:k3PqoFpS6XDt9/4xg3pS8J8JUvxtaz1w2vdTdodknGk=
github.com/jhump/protoreflect v1.17.0 h1:qOEr613fac2lOuTgWN4tPAtLL7fUSbuJL5X5XumQh94=
Expand Down
4 changes: 2 additions & 2 deletions main_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -67,7 +67,7 @@ func setupIntegrationTests() {
InitArtifactoryTests()
}

if *tests.TestNpm || *tests.TestPnpm || *tests.TestGradle || *tests.TestMaven || *tests.TestGo || *tests.TestNuget || *tests.TestPip || *tests.TestPipenv || *tests.TestPoetry || *tests.TestConan || *tests.TestHelm || *tests.TestUv || (*tests.TestArtifactory && !*tests.TestArtifactoryProxy) || *tests.TestArtifactoryProject {
if *tests.TestNpm || *tests.TestPnpm || *tests.TestGradle || *tests.TestMaven || *tests.TestGo || *tests.TestNuget || *tests.TestPip || *tests.TestPipenv || *tests.TestPoetry || *tests.TestConan || *tests.TestHelm || *tests.TestUv || *tests.TestNix || (*tests.TestArtifactory && !*tests.TestArtifactoryProxy) || *tests.TestArtifactoryProject {
InitBuildToolsTests()
}
if *tests.TestDocker || *tests.TestPodman || *tests.TestDockerScan {
Expand Down Expand Up @@ -109,7 +109,7 @@ func tearDownIntegrationTests() {
if (*tests.TestArtifactory && !*tests.TestArtifactoryProxy) || *tests.TestArtifactoryProject {
CleanArtifactoryTests()
}
if *tests.TestNpm || *tests.TestPnpm || *tests.TestGradle || *tests.TestMaven || *tests.TestGo || *tests.TestNuget || *tests.TestPip || *tests.TestPipenv || *tests.TestPoetry || *tests.TestConan || *tests.TestHelm || *tests.TestDocker || *tests.TestPodman || *tests.TestDockerScan || (*tests.TestArtifactory && !*tests.TestArtifactoryProxy) || *tests.TestArtifactoryProject {
if *tests.TestNpm || *tests.TestPnpm || *tests.TestGradle || *tests.TestMaven || *tests.TestGo || *tests.TestNuget || *tests.TestPip || *tests.TestPipenv || *tests.TestPoetry || *tests.TestConan || *tests.TestHelm || *tests.TestNix || *tests.TestDocker || *tests.TestPodman || *tests.TestDockerScan || (*tests.TestArtifactory && !*tests.TestArtifactoryProxy) || *tests.TestArtifactoryProject {
CleanBuildToolsTests()
}
if *tests.TestDistribution {
Expand Down
Loading
Loading