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
66 changes: 66 additions & 0 deletions .github/workflows/uvTests.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,66 @@
name: UV Tests
on:
workflow_dispatch:
push:
branches:
- "master"
# Triggers the workflow on PRs to master branch only.
pull_request_target:
types: [labeled]
branches:
- "master"

# Ensures that only the latest commit is running for each PR at a time.
concurrency:
group: ${{ github.workflow }}-${{ github.event.pull_request.number || github.sha }}-${{ github.ref }}
cancel-in-progress: true

jobs:
UV-Tests:
name: uv ${{ matrix.os.name }} py${{ matrix.python-version }} uv${{ matrix.uv-version }}
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:
# TODO(JGC-413): re-add macos once Artifactory bootstrap is fixed
- name: ubuntu
version: 24.04
- name: windows
version: 2022
python-version: ["3.11.5", "3.x"]
uv-version: ["0.6.17", "latest"]
runs-on: ${{ matrix.os.name }}-${{ matrix.os.version }}
steps:
- name: Checkout code
uses: actions/checkout@v5
with:
ref: ${{ github.event.pull_request.head.sha || github.ref }}

- name: Setup FastCI
uses: jfrog-fastci/fastci@v1
with:
github_token: ${{ secrets.GITHUB_TOKEN }}
fastci_otel_token: ${{ secrets.FASTCI_TOKEN }}

- name: Setup Python3
uses: actions/setup-python@v6
with:
python-version: ${{ matrix.python-version }}

- name: Setup UV
uses: astral-sh/setup-uv@v5
Comment thread
agrasth marked this conversation as resolved.
Resolved
with:
version: ${{ matrix.uv-version }}

- name: Setup Go with cache
uses: jfrog/.github/actions/install-go-with-cache@main

- name: Install local Artifactory
uses: jfrog/.github/actions/install-local-artifactory@main
with:
RTLIC: ${{ secrets.RTLIC }}
RT_CONNECTION_TIMEOUT_SECONDS: ${{ env.RT_CONNECTION_TIMEOUT_SECONDS || '1200' }}

- name: Run UV tests
run: go test -v github.com/jfrog/jfrog-cli --timeout 0 --test.uv
5 changes: 1 addition & 4 deletions artifactory_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -1889,10 +1889,7 @@ func checkIfServerIsUp(port, proxyScheme string, useClientCerts bool) error {
if err != nil {
log.Error(fmt.Sprintf("Couldn't close response body. Error: %s", err.Error()))
}
if resp.StatusCode != http.StatusOK {
time.Sleep(time.Second)
continue
}
// Any HTTP response (including redirects) confirms the proxy is up and forwarding requests.
return nil
}
return fmt.Errorf("failed while waiting for the proxy server to be accessible")
Expand Down
61 changes: 61 additions & 0 deletions buildtools/cli.go
Comment thread
agrasth marked this conversation as resolved.
Resolved
Original file line number Diff line number Diff line change
Expand Up @@ -79,6 +79,7 @@ import (
"github.com/jfrog/jfrog-cli/docs/buildtools/pnpmconfig"
"github.com/jfrog/jfrog-cli/docs/buildtools/poetry"
"github.com/jfrog/jfrog-cli/docs/buildtools/poetryconfig"
uvcommand "github.com/jfrog/jfrog-cli/docs/buildtools/uvcommand"
yarndocs "github.com/jfrog/jfrog-cli/docs/buildtools/yarn"
"github.com/jfrog/jfrog-cli/docs/buildtools/yarnconfig"
"github.com/jfrog/jfrog-cli/docs/common"
Expand Down Expand Up @@ -357,6 +358,19 @@ func GetCommands() []cli.Command {
Category: buildToolsCategory,
Action: PoetryCmd,
},
{
Name: "uv",
Comment thread
agrasth marked this conversation as resolved.
Resolved
Flags: cliutils.GetCommandFlags(cliutils.Uv),
Usage: uvcommand.GetDescription(),
HelpName: corecommon.CreateUsage("uv", uvcommand.GetDescription(), uvcommand.Usage),
UsageText: uvcommand.GetArguments(),
ArgsUsage: common.CreateEnvVars(),
SkipFlagParsing: true,
BashComplete: corecommon.CreateBashCompletionFunc(),
Category: buildToolsCategory,
Action: UvCmd,
Hidden: true,
},
{
Name: "helm",
Flags: cliutils.GetCommandFlags(cliutils.Helm),
Expand Down Expand Up @@ -1809,6 +1823,53 @@ func PoetryCmd(c *cli.Context) error {
return pythonCmd(c, project.Poetry)
}

func UvCmd(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)
filteredArgs, buildConfiguration, err := build.ExtractBuildDetailsFromArgs(args)
if err != nil {
return err
}
var serverID string
filteredArgs, serverID, err = coreutils.ExtractServerIdFromCommand(filteredArgs)
if err != nil {
return fmt.Errorf("failed to extract server ID: %w", err)
}
cmdName, uvArgs := getCommandName(filteredArgs)
// Peek at --publish-url to populate DeployerRepo for build-info enrichment.
// The flag is NOT consumed here — it is forwarded to uv as-is.
deployerRepo := ""
for i, arg := range uvArgs {
if strings.HasPrefix(arg, "--publish-url=") {
deployerRepo = strings.TrimPrefix(arg, "--publish-url=")
} else if arg == "--publish-url" && i+1 < len(uvArgs) {
deployerRepo = uvArgs[i+1]
}
}
uvCommand := python.NewNativeUVCommand().
SetCommandName(cmdName).
SetArgs(uvArgs).
SetServerID(serverID).
SetDeployerRepo(deployerRepo).
SetBuildConfiguration(buildConfiguration)
// For help requests, bypass commands.Exec() to skip the concurrent usage-reporting
// goroutine that would otherwise make Artifactory version calls unnecessarily.
for _, a := range uvArgs {
if a == "-h" || a == "--help" {
return uvCommand.Run()
}
}
if cmdName == "help" || cmdName == "" {
return uvCommand.Run()
}
return commands.Exec(uvCommand)
}

// HelmCmd executes Helm commands with build info collection support
func HelmCmd(c *cli.Context) error {
if show, err := cliutils.ShowCmdHelpIfNeeded(c, c.Args()); show || err != nil {
Expand Down
12 changes: 12 additions & 0 deletions docs/buildtools/uvcommand/help.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
package uvcommand

var Usage = []string{"uv <args> [command options]"}

func GetDescription() string {
return "Run uv command"
}

func GetArguments() string {
return ` sub-command
Arguments and options for the uv command.`
}
14 changes: 6 additions & 8 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.20260331040230-c3b53d1a24ac
github.com/jfrog/build-info-go v1.13.1-0.20260429070557-93b98034d295
github.com/jfrog/gofrog v1.7.6
github.com/jfrog/jfrog-cli-application v1.0.2-0.20260405065840-c930d515ef34
github.com/jfrog/jfrog-cli-artifactory v0.8.1-0.20260421101844-c42ed5f491fa
github.com/jfrog/jfrog-cli-core/v2 v2.60.1-0.20260420010255-65b7a8d432af
github.com/jfrog/jfrog-cli-artifactory v0.8.1-0.20260429074430-a5871f2898b5
github.com/jfrog/jfrog-cli-core/v2 v2.60.1-0.20260429073430-5723b4f21705
github.com/jfrog/jfrog-cli-evidence v0.9.2
github.com/jfrog/jfrog-cli-platform-services v1.10.1-0.20260421062714-60f8615a2c6c
github.com/jfrog/jfrog-cli-security v1.27.0
Expand Down Expand Up @@ -248,13 +248,11 @@ require (

//replace github.com/ktrysmt/go-bitbucket => github.com/ktrysmt/go-bitbucket v0.9.80

// replace github.com/jfrog/jfrog-cli-artifactory => github.com/jfrog/jfrog-cli-artifactory v0.8.1-0.20260421082647-2c85c5bbdaab
// replace github.com/jfrog/jfrog-cli-artifactory => github.com/agrasth/jfrog-cli-artifactory v0.2.2-0.20260428100316-aa702370ec20

//replace github.com/jfrog/build-info-go => github.com/fluxxBot/build-info-go v1.10.10-0.20260105070825-d3f36f619ba5
// replace github.com/jfrog/build-info-go => github.com/jfrog/build-info-go v1.13.1-0.20260428071432-1e9d9a1991ad

// replace github.com/jfrog/build-info-go => github.com/reshmifrog/build-info-go v1.10.11-0.20260303032831-71878c7210bf

//replace github.com/jfrog/jfrog-cli-core/v2 => github.com/fluxxBot/jfrog-cli-core/v2 v2.58.1-0.20260105065921-c6488910f44c
// replace github.com/jfrog/jfrog-cli-core/v2 => github.com/agrasth/jfrog-cli-core/v2 v2.0.0-20260428093456-2bc01db3b153

//replace github.com/jfrog/jfrog-client-go => github.com/jfrog/jfrog-client-go v1.54.2-0.20251007084958-5eeaa42c31a6

Expand Down
12 changes: 6 additions & 6 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.20260331040230-c3b53d1a24ac h1:VKZar+MKKcCoEnT3f1Nq0DkHV07PuI18NEPjlnJCh7M=
github.com/jfrog/build-info-go v1.13.1-0.20260331040230-c3b53d1a24ac/go.mod h1:+OCtMb22/D+u7Wne5lzkjJjaWr0LRZcHlDwTH86Mpwo=
github.com/jfrog/build-info-go v1.13.1-0.20260429070557-93b98034d295 h1:EH0h86KwGvNHWyEBQoHoU9WfMMKy1GJ6jJQNmfy6E0U=
github.com/jfrog/build-info-go v1.13.1-0.20260429070557-93b98034d295/go.mod h1:+OCtMb22/D+u7Wne5lzkjJjaWr0LRZcHlDwTH86Mpwo=
github.com/jfrog/froggit-go v1.21.1 h1:I/XUOO6GQ1d/rmBlM361F8T654C3ohIWrpw23xNL9JY=
github.com/jfrog/froggit-go v1.21.1/go.mod h1:umBiakJB0CSPFfe0AHVaC3n9xsmUT7NGkDCny3bRchI=
github.com/jfrog/go-mockhttp v0.3.1 h1:/wac8v4GMZx62viZmv4wazB5GNKs+GxawuS1u3maJH8=
Expand All @@ -418,10 +418,10 @@ 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.20260405065840-c930d515ef34 h1:qD53oDmaw7+5HjaU7FupqbB55saabNzMoMtu3kJfmg4=
github.com/jfrog/jfrog-cli-application v1.0.2-0.20260405065840-c930d515ef34/go.mod h1:xum2HquWO5uExa/A7MQs3TgJJVEeoqTR+6Z4mfBr1Xw=
github.com/jfrog/jfrog-cli-artifactory v0.8.1-0.20260421101844-c42ed5f491fa h1:TYcV+5qmFF1x8+jNpklseXQnKc4K5xh6XminwFhZbTo=
github.com/jfrog/jfrog-cli-artifactory v0.8.1-0.20260421101844-c42ed5f491fa/go.mod h1:6QJFQvde/CLnFeIIFOvm/6QuQr8OT1QWiTJAkQ+1Mnc=
github.com/jfrog/jfrog-cli-core/v2 v2.60.1-0.20260420010255-65b7a8d432af h1:TGYTFW5egYMD1MhLtuLbYwB2vn+KRlVZLk+9uLVjKyM=
github.com/jfrog/jfrog-cli-core/v2 v2.60.1-0.20260420010255-65b7a8d432af/go.mod h1:qpD7einonjqskDTEyqeG3NzAbZO6se0s0Pet0ObBQ3I=
github.com/jfrog/jfrog-cli-artifactory v0.8.1-0.20260429074430-a5871f2898b5 h1:+52DDmdSZFP1dxgeu0pkB1sQuoHa0PWbW7HVdFOqK3A=
github.com/jfrog/jfrog-cli-artifactory v0.8.1-0.20260429074430-a5871f2898b5/go.mod h1:BV+aCTQsaZeFec2WjgmQjqlxecju4CkkM9NqfiFyjo0=
github.com/jfrog/jfrog-cli-core/v2 v2.60.1-0.20260429073430-5723b4f21705 h1:J0VjEWHN6iXIWthphaKVakly7ONsN5GyoumMhP/m6yc=
github.com/jfrog/jfrog-cli-core/v2 v2.60.1-0.20260429073430-5723b4f21705/go.mod h1:bjAkVD8c2W+jg4whqy10bSXDC/c+Se8/ll/GPp5F/+0=
github.com/jfrog/jfrog-cli-evidence v0.9.2 h1:huiBzQSI9z3OF3l2RphthdXl1aH9zBsvAt+zLsApORI=
github.com/jfrog/jfrog-cli-evidence v0.9.2/go.mod h1:R9faPfyQESBmKrdZCmHvlpmYSHmffswjNnFeT3RMq8I=
github.com/jfrog/jfrog-cli-platform-services v1.10.1-0.20260421062714-60f8615a2c6c h1:FmKtkKwf9LPXwikjCmX5ofJ1qg4T7hfsg3v00QDvaUY=
Expand Down
2 changes: 1 addition & 1 deletion 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.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.TestArtifactory && !*tests.TestArtifactoryProxy) || *tests.TestArtifactoryProject {
InitBuildToolsTests()
}
if *tests.TestDocker || *tests.TestPodman || *tests.TestDockerScan {
Expand Down
18 changes: 18 additions & 0 deletions testdata/uv/uvproject-no-index/pyproject.toml
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
[project]
name = "uv-jfrog-test"
version = "0.1.0"
description = "Test package with no Artifactory index configured"
requires-python = ">=3.11"
dependencies = [
"certifi>=2024.0.0",
]

[build-system]
requires = ["flit_core>=3.2"]
build-backend = "flit_core.buildapi"

# No [[tool.uv.index]] — resolves from lock file URLs (PyPI)
# Tests the case where dependency enrichment is not possible

[tool.uv]
publish-url = "ARTIFACTORY_PUBLISH_URL"
2 changes: 2 additions & 0 deletions testdata/uv/uvproject-no-index/src/uv_jfrog_test/__init__.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
"""JFrog CLI UV integration test package."""
__version__ = "0.1.0"
23 changes: 23 additions & 0 deletions testdata/uv/uvproject/pyproject.toml
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
[project]
name = "uv-jfrog-test"
version = "0.1.0"
description = "Test package for JFrog CLI UV integration tests"
requires-python = ">=3.11"
dependencies = [
"certifi>=2024.0.0",
]

[build-system]
requires = ["flit_core>=3.2"]
build-backend = "flit_core.buildapi"

# ARTIFACTORY_INDEX_URL and ARTIFACTORY_PUBLISH_URL are replaced at test runtime
# by patchUvPyprojectToml() in uv_test.go

[[tool.uv.index]]
name = "jfrog-pypi-virtual"
url = "ARTIFACTORY_INDEX_URL"
default = true

[tool.uv]
publish-url = "ARTIFACTORY_PUBLISH_URL"
2 changes: 2 additions & 0 deletions testdata/uv/uvproject/src/uv_jfrog_test/__init__.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
"""JFrog CLI UV integration test package."""
__version__ = "0.1.0"
5 changes: 5 additions & 0 deletions testdata/uv_local_repository_config.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
{
"key": "${UV_LOCAL_REPO}",
"rclass": "local",
"packageType": "pypi"
}
6 changes: 6 additions & 0 deletions testdata/uv_remote_repository_config.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
{
"key": "${UV_REMOTE_REPO}",
"rclass": "remote",
"packageType": "pypi",
"url": "https://files.pythonhosted.org"
}
9 changes: 9 additions & 0 deletions testdata/uv_virtual_repository_config.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
{
"key": "${UV_VIRTUAL_REPO}",
"rclass": "virtual",
"packageType": "pypi",
"repositories": [
"${UV_LOCAL_REPO}",
"${UV_REMOTE_REPO}"
]
}
Loading
Loading