Skip to content
bitzorcas
中EN

Recipe

Guide: Dual-Track NuGet Distribution & Release Management for Bitz CLI

Comprehensive operational guide for Bitz CLI packaging and distribution: public NuGet.org vs. enterprise Yunxiao private feeds, packageSourceMapping supply chain defense, local offline validation, and CI/CD automation.

Last updated

In distributed enterprise software engineering, developer tooling (bitz) is not merely a project generator; it acts as the primary gateway for cross-platform diagnostics, hardware licensing handshakes, OpenAPI-driven proxy synthesis, and CQRS vertical slice scaffolding.

Distributing CLI binaries via ad-hoc scripts or requiring engineers to compile from source inevitably causes severe version fragmentation and risks leaking commercial licensing private keys and proprietary business models.

Dual-Track Distribution Topology

BitzOrcas.Modern implements a .NET Global Tool dual-track topology: public open-source scaffolding is distributed via NuGet.org for the broader community, while commercial enterprise capabilities (including LegalTech domain generators, hardware licensing locks, and SSO integration) are securely hosted on Alibaba Cloud Yunxiao Private NuGet Feeds.

Workstations & CI Agents (Win / macOS / Linux)Dual-Track NuGet Registry TopologyCI/CD Automation PipelineBitzOrcas Core RepositoryOpen Source PipelineCommercial CompliancePipeline

BitzOrcas.Cli.csproj
(PackAsTool=true, ToolCommandName=bitz)

dotnet pack -c Release
(Outputs .nupkg & .snupkg symbols)

Enterprise Certificate & Code Signing

【Track A: Public Feed】
NuGet.org
(BitzOrcas.Cli Community Scaffolding)

【Track B: Enterprise Feed】
Yunxiao Private Packages
(BitzOrcas.Cli.Enterprise Commercial Suite)

nuget.config
(packageSourceMapping Namespace Isolation)

dotnet tool update -g BitzOrcas.Cli


Architectural Trade-offs

When designing tool distribution, software architects must evaluate three core trade-offs:

CriterionAd-hoc Shell Script / Local Source BuildSingle Public Feed OnlyBitzOrcas Dual-Track Strategy (Selected)
Version ConsistencyVery poor; divergent build configurationsHigh; driven uniformly by NuGet versionsStrict; enforced via CPM and semantic versions
IP ProtectionHigh risk; licensing keys exposed in sourceNon-existent; commercial modules forced openIsolated; commercial binaries restricted to private feed
Supply Chain SecurityFragile; prone to local workstation tamperingVulnerable to Dependency Confusion attacksZero-Trust; strictly governed by packageSourceMapping

Step 1: Tool Packaging Contract (BitzOrcas.Cli.csproj)

The CLI project must be configured as a standard .NET Global Tool:

src/tooling/BitzOrcas.Cli/BitzOrcas.Cli.csproj
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<!-- Output must be an executable binary -->
<OutputType>Exe</OutputType>
<TargetFramework>net10.0</TargetFramework>
<Nullable>enable</Nullable>
<ImplicitUsings>enable</ImplicitUsings>
<!-- Global tool packaging properties -->
<PackAsTool>true</PackAsTool>
<!-- Command registered in global system PATH -->
<ToolCommandName>bitz</ToolCommandName>
<PackageOutputPath>$(MSBuildThisFileDirectory)../../artifacts/packages</PackageOutputPath>
<!-- Semantic package identity -->
<PackageId>BitzOrcas.Cli</PackageId>
<Title>Bitz CLI Developer Toolchain</Title>
<Authors>BitzOrcas Core Architecture Team</Authors>
<Company>LinkedLaw BitzSoft</Company>
<Description>Developer toolchain, vertical slice scaffolding, and licensing manager for BitzOrcas.Modern.</Description>
<PackageTags>dotnet-tool;bitz;architecture;scaffolding;cqrs</PackageTags>
<PackageLicenseExpression>Apache-2.0</PackageLicenseExpression>
</PropertyGroup>
</Project>

Step 2: Local Packaging & Offline Validation

Before pushing packages to any remote registry, release managers must validate the package locally in an isolated test environment:

Local packaging and offline test suite
# 1. Clean previous build artifacts
dotnet clean src/tooling/BitzOrcas.Cli/BitzOrcas.Cli.csproj -c Release
# 2. Pack release package and symbol bundle
dotnet pack src/tooling/BitzOrcas.Cli/BitzOrcas.Cli.csproj \
-c Release \
-p:Version=2.5.0 \
-p:IncludeSymbols=true \
-p:SymbolPackageFormat=snupkg \
-o ./artifacts/packages
# 3. Uninstall existing global tool to prevent cache interference
dotnet tool uninstall -g BitzOrcas.Cli || true
# 4. Install directly from local staging directory
dotnet tool install -g BitzOrcas.Cli \
--add-source ./artifacts/packages \
--version 2.5.0
# 5. Verify runtime health and version report
bitz --version
bitz doctor --verbose

Step 3: Pushing to Enterprise Private Feed (Yunxiao)

Commercial editions (such as BitzOrcas.Cli.Enterprise) containing proprietary LegalTech generators and hardware licensing routines are pushed to Alibaba Cloud Yunxiao:

Push to enterprise private feed
# Export credentials (never hardcode in repository scripts)
export BITZORCAS_COMMERCIAL_FEED_URL="https://packages.aliyun.com/63a120000000000000/nuget/v3/index.json"
export BITZORCAS_COMMERCIAL_PUSH_TOKEN="sec_pat_xxxxxxxxxxxxxxxxxxxx"
# Push commercial package to private feed
dotnet nuget push ./artifacts/packages/BitzOrcas.Cli.Enterprise.2.5.0.nupkg \
--source "${BITZORCAS_COMMERCIAL_FEED_URL}" \
--api-key "${BITZORCAS_COMMERCIAL_PUSH_TOKEN}" \
--skip-duplicate

Security Rule: The private registry must enforce package immutability. If a bug is discovered after release, increment the patch version (2.5.1) instead of overwriting the package.


Step 4: Publishing to Public NuGet.org

Pushing public community tools to NuGet.org requires an enterprise API key managed securely via KMS:

Push to public NuGet.org
# Push community edition to official NuGet.org
dotnet nuget push ./artifacts/packages/BitzOrcas.Cli.2.5.0.nupkg \
--source https://api.nuget.org/v3/index.json \
--api-key "${NUGET_ORG_API_KEY}" \
--skip-duplicate

Step 5: Supply Chain Defense (packageSourceMapping)

To prevent Dependency Confusion attacks, every downstream business repository must configure packageSourceMapping in nuget.config:

nuget.config (Business Solution Root)
<?xml version="1.0" encoding="utf-8"?>
<configuration>
<packageSources>
<clear />
<!-- Public Official Source -->
<add key="nuget.org" value="https://api.nuget.org/v3/index.json" />
<!-- Enterprise Commercial Source -->
<add key="BitzOrcasCommercial" value="%BITZORCAS_COMMERCIAL_FEED_URL%" />
</packageSources>
<!-- Strict namespace isolation to prevent package spoofing -->
<packageSourceMapping>
<!-- Public packages can only be resolved from nuget.org -->
<packageSource key="nuget.org">
<package pattern="*" />
<package pattern="BitzOrcas.Cli" />
<package pattern="Microsoft.*" />
<package pattern="System.*" />
</packageSource>
<!-- Commercial proprietary packages are restricted to private feed -->
<packageSource key="BitzOrcasCommercial">
<package pattern="BitzOrcas.*" />
<package pattern="BitzOrcas.Cli.Enterprise" />
<package pattern="Bitzsoft.Licensing.*" />
</packageSource>
</packageSourceMapping>
</configuration>

Step 6: Automated CI/CD Workflow

Deploy dual-track releases automatically upon Git tag pushes:

.github/workflows/cli-publish.yml
name: Publish Bitz CLI Global Tool
on:
push:
tags:
- 'v*.*.*'
jobs:
build-and-publish:
runs-on: ubuntu-latest
steps:
- name: Checkout Code
uses: actions/checkout@v4
- name: Setup .NET 10 SDK
uses: actions/setup-dotnet@v4
with:
dotnet-version: '10.0.x'
- name: Pack CLI
run: |
VERSION=${GITHUB_REF_NAME#v}
dotnet pack src/tooling/BitzOrcas.Cli/BitzOrcas.Cli.csproj \
-c Release \
-p:Version=${VERSION} \
-o ./artifacts/packages
- name: Push to Enterprise Yunxiao Feed
env:
FEED_URL: ${{ secrets.BITZORCAS_COMMERCIAL_FEED_URL }}
FEED_TOKEN: ${{ secrets.BITZORCAS_COMMERCIAL_PUSH_TOKEN }}
run: |
dotnet nuget push ./artifacts/packages/*.nupkg \
--source "${FEED_URL}" \
--api-key "${FEED_TOKEN}" \
--skip-duplicate
- name: Push to NuGet.org (Public Track)
if: "!contains(github.ref, '-rc') && !contains(github.ref, '-beta')"
env:
NUGET_KEY: ${{ secrets.NUGET_ORG_API_KEY }}
run: |
dotnet nuget push ./artifacts/packages/BitzOrcas.Cli.*.nupkg \
--source https://api.nuget.org/v3/index.json \
--api-key "${NUGET_KEY}" \
--skip-duplicate

Troubleshooting Guide

SymptomRoot CauseRemediation
NU1100: Unable to resolve package 'Bitz.Cli'Missing pattern in packageSourceMappingRun bitz doctor --fix or verify nuget.config pattern mapping
HTTP 409 Conflict: Package already existsImmutability protection triggered on registryIncrement the patch version (2.5.1) and re-pack
HTTP 401 UnauthorizedExpired feed token or invalid API keyRegenerate access token in registry settings and update CI secrets
bitz: command not foundPATH variable missing .NET tools directoryAdd export PATH="$PATH:$HOME/.dotnet/tools" to shell profile

100%

Scroll or use controls to zoom · drag when enlarged · double-click for 100% / 200%