Skip to content

Working with NuGet

CodeScoring.Save implements NuGet v3 API with the /nuget/<project>/<repository>/ prefix. It is compatible with standard dotnet, nuget.exe, Visual Studio, and Rider clients.

Proxy Repository

curl -X POST https://save.example.com/api/v1/repos \
  -H "Content-Type: application/json" \
  -u "<username>:<password>" \
  -d '{
    "project": "dotnet",
    "name": "nuget-proxy",
    "format": "nuget",
    "repository_type": "proxy",
    "remote_url": "https://api.nuget.org/v3/index.json"
  }'

URL for remote_url

Specify the full service index URL. For official nuget.org, it is https://api.nuget.org/v3/index.json. Save resolves nested resources (flatcontainer, registration, search) using this index.

Hosted Repository

curl -X POST https://save.example.com/api/v1/repos \
  -H "Content-Type: application/json" \
  -u "<username>:<password>" \
  -d '{
    "project": "dotnet",
    "name": "nuget-hosted",
    "format": "nuget",
    "repository_type": "hosted"
  }'

After creation, the service index is available at https://save.example.com/nuget/<project>/<repository>/v3/index.json.

Client Configuration

dotnet CLI

In nuget.config or NuGet.Config (file name depends on the OS):

<?xml version="1.0" encoding="utf-8"?>
<configuration>
  <packageSources>
    <clear />
    <add key="codescoring"
         value="https://save.example.com/nuget/<project>/nuget-proxy/v3/index.json"
         protocolVersion="3" />
  </packageSources>
  <packageSourceCredentials>
    <codescoring>
      <add key="Username" value="<username>" />
      <add key="ClearTextPassword" value="<password>" />
    </codescoring>
  </packageSourceCredentials>
</configuration>

Usage:

dotnet restore
dotnet add package Newtonsoft.Json

nuget.exe

nuget sources add \
  -Name codescoring \
  -Source https://save.example.com/nuget/<project>/nuget-proxy/v3/index.json \
  -UserName <username> \
  -Password <password>

nuget install Newtonsoft.Json -Source codescoring

Publishing (hosted)

Push packages to a hosted repository through standard clients:

# dotnet CLI
dotnet pack -c Release
dotnet nuget push bin/Release/MyPackage.1.0.0.nupkg \
  --source https://save.example.com/nuget/<project>/nuget-hosted/v3/index.json \
  --api-key <api-key-or-password>

# nuget.exe
nuget push MyPackage.1.0.0.nupkg \
  -Source https://save.example.com/nuget/<project>/nuget-hosted/v3/index.json \
  -ApiKey <api-key-or-password>

X-NuGet-ApiKey vs Basic Auth for CI

dotnet nuget push supports either an API key (X-NuGet-ApiKey header) or Basic Auth. CodeScoring.Save supports both methods: X-NuGet-ApiKey is classified as nuget_key. Still, Basic Auth with a robot account is recommended for CI/CD. It is consistent with other formats and explicitly records the robot identity in the audit log.

Repository URL Migration

Use case: migrating a NuGet repository from Nexus / Artifactory to CodeScoring.Save.

Source URL in NuGet.Config before migration URL in NuGet.Config after migration
Nexus https://nexus.host.ru/repository/nuget.org-proxy/index.json https://save.example.com/nuget/<project>/nuget-proxy/v3/index.json
Artifactory https://jfrog.host.ru/artifactory/api/nuget/v3/nuget-remote https://save.example.com/nuget/<project>/nuget-proxy/v3/index.json
Official repository https://api.nuget.org/v3/index.json https://save.example.com/nuget/<project>/nuget-proxy/v3/index.json

During migration, <packageSourceCredentials> remains unchanged.

Troubleshooting

Checking the Service Index

curl -u "<username>:<password>" \
  https://save.example.com/nuget/<project>/nuget-proxy/v3/index.json | jq .

The response must contain a resources array with PackageBaseAddress, RegistrationsBaseUrl, SearchQueryService, and other resources.

Package Version List

curl -u "<username>:<password>" \
  https://save.example.com/nuget/<project>/nuget-proxy/v3-flatcontainer/newtonsoft.json/index.json

Service Status

curl https://save.example.com/health

Repository Audit

curl -u "<username>:<password>" \
  "https://save.example.com/api/v1/admin/audit?resource_type=repository&q=nuget-proxy&limit=50"
Страница была полезна?