Zongsoft.Tools.Deployer
7.16.0
dotnet tool install --global Zongsoft.Tools.Deployer --version 7.16.0
dotnet new tool-manifest
dotnet tool install --local Zongsoft.Tools.Deployer --version 7.16.0
#tool dotnet:?package=Zongsoft.Tools.Deployer&version=7.16.0
nuke :add-package Zongsoft.Tools.Deployer --version 7.16.0
The Zongsoft Deployment Tool
Terminal colors distinguish warnings, errors and success messages. Redirected output remains plain text on its original stream.
Run dotnet deploy --help or dotnet deploy -h for common options: the command name is bold cyan, option names are cyan, and placeholders and candidate values are green. Help returns 0 without reading .env or processing input files. Once deployment starts, it ends with one elapsed-time line, with the command name and seconds in bold cyan. Failed operations also report elapsed time; timing alone does not indicate success.
Abstraction
This is an application deployment tool that instructs the deployment tool to copy specific files to the destination location by specifying the deployment file.
It is recommended to define a default deployment file named .deploy in the deployment project directory, and the deployment file is a plain text file in .ini format.
Format Specification
The deployment file is a plain text file in .ini format, and its content consists of Section(Paragraph) and Entry(Entry) enclosed in square brackets, the Section part represents the destination directory of deployment.
Sections specify structural directory levels. Entry source and output paths support Core ${...} template expressions; variables come from command options, environment variables, the source directory's .env and its explicit imports and output appsettings.
Each entry consists of KEY and VALUE parts separated by an equal sign (=), and the VALUE part is optional.
The KEY part consists of Parser-Name and Parser-Argument, separated by a colon (
:);- Parser-Name: Omit it, leave it empty, or specify
pathto use the default path parser. Other parsers aretemplate,nuget, anddelete/remove. Parser names are case-insensitive. - Parser-Argument: Parsed by the specified parser, please refer to Parser Argument below for details.
- Parser-Name: Omit it, leave it empty, or specify
The VALUE part consists of Output and Filtering.
- Output: Indicates the destination path for deployment. If missing, the destination directory is specified by the Section, and the destination file name is the same as the source file.
- Filtering: Indicates the preconditions for parsing, please refer to Filtering below for details.
Parser Argument
Path Parser
The default parser is named path, and its name can be omitted. It copies the source file indicated by the Parser-Argument to the destination location.
The Parser-Argument represents the path of the source file to be deployed, the source file path supports *, ? and ** wildcards, the ** means multi-level directory matching.
For an absolute Windows source path containing a drive-letter colon, use the path: prefix, for example path:D:/dir/files.ext or path:D:/dir/files.ext. Otherwise, D in D:/... is interpreted as a resolver name. Alternatively, use a path relative to the deployment file or expand the absolute path from a variable.
[plugins zongsoft data]
path:D:/Zongsoft/framework/Zongsoft.Data/src/Zongsoft.Data.plugin
[plugins zongsoft data mysql]
drivers/mysql/src/Zongsoft.Data.MySql.plugin
The path: prefix selects the default path resolver; the source path starts after its colon. Relative paths can also use this prefix, such as path:drivers/mysql/src/Zongsoft.Data.MySql.plugin. This example references existing plugin files in framework and assumes the deployment file is located in D:/Zongsoft/framework/Zongsoft.Data. Adjust the checkout path for your environment.
💡 Tip: You should generally avoid absolute paths in
.deployfiles. Source paths are resolved relative to the directory containing the deployment file, while destination paths are resolved relative to the host directory or the target directory specified by the deployment options. See the deployment files in framework, such as Zongsoft.Data.deploy, for examples.
Template Parser
template: reads text and evaluates it with this deployment's Core TemplateEvaluator. It uses the same relative paths, glob search, section destinations, and filters as path:. An explicit destination name wins; otherwise the final .template suffix is removed. Ordinary path copies do not evaluate file content.
# hosting/daemon/.deploy
template:../.deploy/.shared/app.option.template = Zongsoft.Hosting.Daemon.option
[plugins zongsoft externals aliyun]
template:../.deploy/.shared/Zongsoft.Externals.Aliyun.option.template
Templates use Core syntax, with no separate variable or conditional language. ${mysql:server} inserts raw text; ${mysql:server#xml} escapes XML text and attributes. ${title#json} produces a complete JSON value, including quotes for strings; do not add surrounding quotes. .env values are strings and #json does not infer numeric or Boolean types. There is no general INI/YAML escaping: structure content for the target format. \${runtime} emits literal ${runtime} and \\ emits one backslash.
<connection value="${mysql:connection#xml}" />
Templates are read as UTF-8 with UTF BOM detection and written as UTF-8 without BOM, preserving line endings. All templates are evaluated before any write or deletion. A missing explicit template, undefined variable, cycle, invalid expression, or changed source prevents execution. A glob with no matches produces no operation.
For templates, default newest compares generated content: different content is updated regardless of destination timestamps; identical content is Unchanged and keeps its timestamp. never preserves existing targets and alway writes every time. Ordinary copies still use modification time for newest.
.env supplies variables only and is excluded from file payloads, including directory searches. Use *.template as the template suffix.
Delete Parser
The parser name is delete or remove, which means delete the specified destination file.
The Parser-Argument represents the destination file to be deleted, and the full path of the destination file is a combination of the directory specified in the Section and the Parser-Argument.
🚨 Note: This parser does not support the Output part, so this part cannot be defined.
Examples
Delete the Zongsoft.Messaging.Mqtt.option file from the ~/plugins/zongsoft/messaging/mqtt directory in the target location.
[plugins zongsoft messaging mqtt]
nuget:Zongsoft.Messaging.Mqtt
delete:Zongsoft.Messaging.Mqtt.option
💡 Tip: The deployment file in the
nuget:Zongsoft.Messaging.Mqttpackage in the example contains a default configuration file(i.e.Zongsoft.Messaging.Mqtt.option), but it is not needed in the real project, so the configuration file is removed later.
NuGet Parser
The parser name is: nuget, which means download the NuGet package and perform the deployment, and that the dependencies of the specified package are also downloaded.
The format of Parser-Argument: package@version/path, where @version and /{path} parts are optional.
- An unspecified version or
latestselects the latest stable release. Use--prerelease:trueto include preview releases. An explicitly requested prerelease version is still accepted. - If the path part is unspecified:
- If the root directory contains a
.deployfile, execute that manifest without additionally selecting default assets or downloading unused dependencies; - Otherwise resolve the dependency closure and select the nearest assets: use a compatible RID managed runtime group in preference to
lib/{framework}, plus native and eligible content assets.The
{framework}indicates the version of the target framework nearest to the one declared by the${Framework}variable.
- If the root directory contains a
💡 Tip: Zongsoft's NuGet package usually has a deployment file named
.deployin it's root directory, and theartifactsdirectory in the package includes its plugin files(*.plugin)(required, one or more), configuration files(*.option), the mapping files(*.mapping) for Zongsoft.Data ORM, and other ancillary files.
💡 Note: The variable named
NuGet_Serverdefines the NuGet package source for this parser. If undefined thenhttps://api.nuget.org/v3/index.jsonis used as its default value.
Dependency Packages
Nuget by default ignores dependency packages whose names begin with System., Microsoft.Extensions., or Zongsoft.;
You can also specify the prefixes of dependency packages to ignore using the --ignoreDependentPrefix command-line option, multiple prefixes are separated by a comma(,), a semicolon(;), or a pipe(|). Matching is case insensitive and affects dependency edges, not explicitly requested root packages.
Examples
Get the latest version of the
Zongsoft.PluginsNuGet package and deploy theMain.pluginplugin file in it's/pluginsdirectory to the destination~/pluginsdirectory.[plugins] nuget:Zongsoft.Plugins/plugins/Main.pluginGet the
6.2.0version of theZongsoft.DataNuGet package and execute the.deploydeployment file in the package.[plugins zongsoft data] nuget:Zongsoft.Data@6.2.0 nuget:Zongsoft.Data@6.2.0/.deployNote: Since the root directory of the
Zongsoft.Datapackage contains the.deployfile, the above two writing styles have the same effect.Deploy version 8.3.0 of the MySql. (Assuming the value of the
Frameworkvariable isnet8.0)nuget:MySql.Data@8.3.0- First download the
MySql.Data@8.3.0package and its dependencies (ignore dependencies starting withSystem.andMicrosoft.Extensions.):
BouncyCastle.Cryptography 2.2.1 Google.Protobuf 3.25.1 K4os.Compression.LZ4.Streams 1.3.5 ZstdSharp.Port 0.7.1- Get the library files in the above dependency packages that are nearest to the
net8.0Target Framework version specified by theFrameworkvariable. - Copy the library files from the downloaded NuGet package to the destination directory.
- First download the
Filtering
The part enclosed by < and > at the end of the entry is the filter condition, and entries that do not meet the filter criteria will be ignored.
Multiple conditions are supported. Each condition consists of a variable name and the comparison values, If the variable name starts with !, it means that the matching result of the condition is negated; If you are comparing multiple values, separate them with commas. As follows:
../.deploy/${scheme}/options/app.${environment}.option = web.option <application>
../.deploy/${scheme}/options/app.${environment}.option = web.option <!application>
../.deploy/${scheme}/options/app.${environment}-debug.option = web.option <preview:A,B,C>
../.deploy/${scheme}/options/app.${environment}-debug.option = web.option <!preview:X,Y,Z>
../.deploy/${scheme}/options/app.${environment}-debug.option = web.option <application | debug:on>
../.deploy/${scheme}/options/app.${environment}-debug.option = web.option <!application & !debug:on>
<application>means that there is a variable namedapplication(Regardless of its content), then the result is true.<!application>means that there is no variable namedapplication(Regardless of its content), then the result is true.<preview:A,B,C>means that the value of the variable namedpreviewis any one of "A,B,C" (Ignoring case), then The result is true.<!preview:X,Y,Z>means that the value of the variable namedpreviewis not any one of "X,Y,Z" (Ignoring case), then the result is true.<application | debug:on>indicates that there is a variable namedapplication(Regardless of its content) OR a variable nameddebugison(Ignoring case), the result is true.<!application & !debug:on>means that there is no variable namedapplication(Regardless of its content) AND the variable nameddebugis noton(Ignoring case), the result is true.
Supports matching and version comparison of TargetFramework. If TargetFramework ends with ^, it means that the version of the current deployment TargetFramework must be greater than or equal to this version, as follows:
${NUGET_PACKAGES}/mysql.data/8.1.0/lib/netstandard2.1/*.dll <framework:net7.0^>
${NUGET_PACKAGES}/mysql.data/6.10.9/lib/netstandard2.0/*.dll <framework:net5.0,net6.0>
Variables
The tool explicitly enables Core variable fallback: named references search their namespace, its parents and global, querying every source in priority order at each level. A missing variable is reported after all levels miss. Unqualified references remain ${name}, and a found null or empty value stops fallback.
At each namespace, query command options, the destination application's appsettings.json, source .env (including explicit imports), then environment variables. The first match wins; an explicit null in appsettings.json also stops fallback to lower-priority sources. Configuration and command-option names ignore case. Core Variables.Environments() reads system values live in the default namespace without rewriting names or values; names are case-insensitive on Windows and case-sensitive on Unix/Linux.
All variables, including framework, use the first successful lookup: null, empty strings, false and zero never trigger fallback to a lower source. Only a missing value continues lookup. Operations requiring a valid value validate it and report an error when they cannot proceed.
Only source's direct .env is loaded automatically; parent, child and individual manifest directories are not searched. Use #@import ../.env to include a parent file explicitly. All manifests in one invocation share the resulting variables. Core Profile.Load reads these INI files, including #@import. Root entries use the default namespace; section levels form dot-separated namespaces and entry dots/hyphens become underscores: [io rustfs] with access_key=example creates io.rustfs:access_key=example. A root environment=Development creates environment. Missing .env files are skipped; read or parse failures stop initialization. Values expand only when used, and process environment variables are not modified.
Variable values may reference other values recursively, regardless of command-option order. Values expand when used; missing references, cycles, and chains longer than 64 levels fail. output may reference command options, environment variables and loaded .env values; its appsettings.json is loaded afterward.
- If a property named
ApplicationNameis defined inappsettings.json, you can useapplicationas a variable alias for that property. - The variable named
Frameworkrepresents the .NET TargetFramework identity, which is defined in https://learn.microsoft.com/en-us/dotnet/standard/frameworks
NuGet-related parameters can be specified via command options, environment variables or .env files:
NuGet_Serverindicates the NuGet server information, the default value is:https://api.nuget.org/v3/index.json.NuGet_Packagesindicates the directory of NuGet packages, the default value is:%USERPROFILE%/.nuget/packages.
Source paths, imports, and hosting
--source itself is relative to the invocation directory and cannot depend on .env files that have not yet been loaded. Once source is fixed, the source directory's .env and its explicit imports are loaded and --output is evaluated. Relative local .deploy arguments, output, report, lockFile, previous, NuGet_Packages, and local NuGet_Server paths resolve against source, including ./ and ../; absolute paths keep their meaning. Source paths inside .deploy and #@import paths remain relative to their declaring file.
Deployment APIs name the output-directory argument outputDirectory; DeploymentContext.OutputDirectory carries the current .deploy output directory. Entries and operations expose Output; report and lock JSON use Operations[].Output for the output path.
The tool gives scheme, environment, and network no special meaning. For example, hosting/daemon/.env explicitly selects a scheme:
#@import ../.env
#@import ../.deploy/${scheme}/.env
name=Zongsoft.Hosting.Daemon
title=Zongsoft Daemon
hosting/.deploy/default/.env may import ../.env to reuse hosting/.deploy/.env. Other files load only through explicit #@import directives, with paths relative to their declaring file. Later declarations of the same key in one Profile override earlier ones, so .env declarations control project/scheme precedence. Import arguments may use command options, already-read entries in the current file (including completed imports), and system variables, but not later declarations. All .deploy files and templates share the invocation's variables; template directories do not reload variables.
From the hosting root, deploy daemon configuration and plugins:
dotnet deploy --source:daemon --output:'bin/${edition}/${framework}' --scheme:default --environment:production --network:internal --edition:Release --platform:linux --architecture:x64 --prerelease:true
Root deploy.cmd/pack.cmd prompt for the host source directory. With no framework override, deployment and packaging use .env, while Cake uses its build.cake default; keep them aligned. deploy.cmd only builds and deploys; pack.cmd packages independently. Use the same explicit framework override in both scripts. Deployment edition selects the compilation directory; installation-package Edition is a separate identity. See hosting README.
Setup
- List tools
dotnet tool list
dotnet tool list -g
- Install tool
dotnet tool install -g zongsoft.tools.deployer
- Upgrade tool
dotnet tool update -g zongsoft.tools.deployer
- Uninstall tool
dotnet tool uninstall -g zongsoft.tools.deployer
Installing a local source build for testing
Run dotnet cake --edition Release to build Release, run the .NET 8/9/10 regression suites, and generate the local tool package without pushing to NuGet. Restore, build, and tests use the same configuration; Debug references the local Core DLL and Release uses the declared Core NuGet package.
Install the generated .nupkg directly without publishing it to NuGet.org. The following commands use the .NET 10 SDK and run from D:/Zongsoft/tools/deployer; use the corresponding directory for another checkout location.
The deployer enables GeneratePackageOnBuild, so a Release build also creates the tool package:
dotnet build src/Zongsoft.Tools.Deployer.csproj -c Release
After the build succeeds and src/bin/Release/Zongsoft.Tools.Deployer.<version>.nupkg exists, install it for the first time:
$toolVersion = dotnet msbuild src/Zongsoft.Tools.Deployer.csproj -getProperty:Version -nologo
dotnet tool install -g Zongsoft.Tools.Deployer --version "$toolVersion" --source ./src/bin/Release --no-http-cache
If the tool is already installed, especially when rebuilding the same version, uninstall it first, then repeat the local installation command above:
dotnet tool uninstall -g Zongsoft.Tools.Deployer
The installation command reads the version from the project file; <version> in the package filename denotes that value. --source restricts installation to the local directory, avoiding a same-named package from NuGet.org; --no-http-cache disables the download cache. See the .NET tool installation reference. Check the installed version with dotnet tool list -g. Here, “local” describes the package source; -g still replaces the current user’s global tool. Do not run the Cake pack task for local testing: it pushes packages to NuGet.org.
Deploy
- Execute the default deployment in the host(target) directory:
dotnet deploy --edition:Debug --framework:net10.0 --platform:win --architecture:x64
- If the host(target) directory does not have a default deployment file (
.deploy), you must manually specify the deployment file name (multiple deployment files are supported). The following example assumesZongsoft.Data@6.2.0has been downloaded and extracted into the NuGet package directory:
dotnet deploy --edition:Debug --framework:net10.0 --platform:win --architecture:x64 "${NUGET_PACKAGES}/zongsoft.data/6.2.0/.deploy"
- For the convenience of deployment, you can create a corresponding edition of the deployment script files in the host(target) project, for example:
- deploy-debug.cmd
dotnet deploy --edition:Debug --framework:net10.0 --platform:linux --architecture:x64 - deploy-release.cmd
dotnet deploy --edition:Release --framework:net10.0 --platform:linux --architecture:x64
- deploy-debug.cmd
Command options
The command supports redirected or piped output. Exit codes are 0 for success, 1 for validation/dependency/I/O failure, and 130 for cancellation. The complete plan is validated before target writes; skipped copies and deletions have separate counts.
Missing ordinary source files (including optional files referenced by package .deploy files) and missing deployment manifests are warnings: each is counted as skipped, and remaining inputs continue. This also applies to the default .deploy, explicit manifest arguments, and a directory without .deploy, so scripts can pass the same optional inputs across environments. Warnings are printed even with --verbosity:quiet and retained in report diagnostics; they do not cause a nonzero exit code. Missing NuGet packages, invalid variables or syntax, broken source links, access errors, and files lost after planning remain failures.
dotnet deploy [--option:value ...] [manifest-or-directory ...]
dotnet-deploy [--option:value ...] [manifest-or-directory ...]
The two entry points are equivalent and have no subcommands. With no positional arguments, the tool reads .deploy in source. Multiple manifests are processed in order; a directory selects its immediate .deploy. Relative .deploy arguments use source, sources inside a manifest use that manifest's directory, and destinations use output. --key=value also works; quote values with spaces according to the shell. Any other --name:value becomes a user variable for manifests and configuration. The table lists only options interpreted by the tool. Manifest path, template, nuget, and delete/remove entries are resolvers, not subcommands.
| Option | Default | Purpose |
|---|---|---|
--source:<directory> |
Invocation directory | Existing working source; resolved against the invocation directory using command options and system variables only. |
--output:<directory> |
source | Target root; resolve using command options, environment variables and .env values before loading its appsettings.json. |
--verbosity:<level> |
normal |
quiet, normal, or detail; unconvertible values fail. |
--overwrite:<policy> |
newest |
alway (the existing enum spelling), never, or newest. This is not a Boolean switch. |
--expansion[:boolean] |
false |
Preserve matched relative directory levels in target paths for directory wildcards; false keeps only wildcard captures. |
--ignoreDeploymentFile[:boolean] |
false |
Copy a source .deploy as a regular file instead of recursively executing it. |
--ignoreDependentPrefix:<prefixes> |
Built-in prefixes | Skip dependency edges with matching prefixes; separate with ,, ;, or |. |
--offline[:boolean] |
false |
Use only the local NuGet cache. |
--prerelease[:boolean] |
false |
Include prereleases when selecting latest. |
--dry-run[:boolean] |
false |
Build and validate the plan without modifying the target. |
--explain[:boolean] |
false |
Print per-item plan and execution results. |
--report:<file> |
None | Atomically write the JSON plan and result. |
--lockFile:<file> |
None | Save a lock plan after successful deployment; read it with locked. |
--locked[:boolean] |
false |
Require an existing lock plan to match this run. |
--previous:<file> |
None | Read the previous report to identify no-longer-selected files. |
--prune[:boolean] |
false |
With previous, remove unchanged stale files; preserve modified files. |
Boolean options accept a bare switch, true/false, 1/0, yes/no, on/off, or enable(d)/disable(d), case-insensitively; other values are false under Core's Switch convention. ${name} support Core identifiers, namespaces, and member/index access. Values expand lazily and recursively; missing, cyclic, or over-64-level references fail when used, before type conversion. Enum options follow Core conversion rules without an additional check that the enum member is defined; callers must supply a valid member. Unselected deployment branches are not expanded.
NuGet_Server and NuGet_Packages may be supplied as command options, environment variables or .env entries. Framework, Platform, Architecture, and edition are ordinary variables used by resolvers and manifests. Example:
dotnet deploy --output:'bin/${edition}/${framework}' --edition:Release --framework:net10.0 --dry-run --report:deploy-plan.json .deploy extra.deploy
NuGet Packages
Ordinary NuGet roots in one command share a dependency graph. Explicit root versions stay fixed; dependencies use the lowest available version satisfying all constraints. Unsatisfiable ranges, cycles, downgrade constraints, and conflicting package assets at the same target fail before writes. This strict deployment resolver does not execute MSBuild/buildTransitive and is not a full substitute for dotnet restore. Separate directories do not imply separate assembly load contexts; use separate calls only for genuinely isolated hosts. Package manifests and explicit package paths expand as file requests.
Identical package assets at the same destination are copied once; duplicate origins remain in the plan and are counted as skipped. An explicit delete ends the prior deduplication interval. DLLs are not moved or merged across plugin directories.
Explicit library paths inside the NuGet_Packages cache select the nearest applicable framework directory; nuget:package@version/lib/framework/file follows the same rule. A framework specified in the path takes precedence, such as lib/net9.0/*.dll; lib/*.dll uses the Framework variable. Matching preserves subsequent subpaths and the directory structure produced by wildcard expansion. Paths outside the cache root are not adjusted.
Nearest Matching
Assuming the Framework variable is net9.0, when a deployment file has the following deployment items:
${NUGET_PACKAGES}/mysql.data/8.3.0/lib/net9.0/*.dll
However, the above package library directory does not contains the net9.0 framework version, so the tool will use the library file that is most applicable(nearest) to that framework version. The path will be redirected to:
${NUGET_PACKAGES}/mysql.data/8.3.0/lib/net8.0/*.dll
Others
Reference examples
The NuGet Packages
The hosting projects
Plans, locks, and cleanup
The default overwrite policy is newest. Unconvertible overwrite values, invalid filters, and undefined variables in active paths cause errors. Writes must stay within output, and linked write paths are rejected. Both nested manifests and #@import detect cycles. Combined filters use left-to-right evaluation. ** matches zero or more directory levels; directory copies preserve their internal relative structure.
| Option | Behavior |
|---|---|
--dry-run:true |
Builds a plan without target writes or directory creation. Explicit reports still write; online resolution can populate the NuGet cache. |
--offline:true |
Uses only unpacked local packages with valid nuspec metadata; missing packages fail without network requests. |
--explain:true |
Prints operation results and package/file origins, preserving original messages and paths. |
--report:./deployment.json |
Saves success or failure, manifest origins, package versions/parents, hashes, duplicate/skipped operations and diagnostics. |
--lockFile:./deployment.lock.json |
Writes selected versions, package content and manifest/source hashes after a successful non-preview deployment. |
--locked:true |
Uses package versions from lockFile and validates the plan/content without updating the lock. Locks retain source manifest paths. |
--prerelease:true |
Includes prereleases for unpinned requests; dependencies explicitly requiring a preview lower bound can also select previews. |
--previous:./previous.json |
Compares a successful prior report for the same target root and lists obsolete files as Stale; keeps them by default. |
--prune:true |
Requires previous. Deletes only files whose last effective prior operation copied them, whose hashes are unchanged, and which are no longer selected. Modified, unowned and outside-root files are not automatically removed. |
Boolean options accept a bare name or true/false. A lock file is useful when reproducing the same deployment plan, especially with floating NuGet versions or dependencies. --locked checks versions and content; it is not an interprocess lock. Ordinary deployments need no lock file. Locks, reports, and cleanup are opt-in. Give reports/locks independent paths: they cannot overwrite known source manifests, source files, or planned targets. An execution-time I/O error stops subsequent operations; completed writes are not rolled back.
dotnet deploy --framework:net10.0 --platform:win --architecture:x64 --offline:true --dry-run:true --report:./preview.json .deploy
dotnet deploy --framework:net10.0 --platform:win --architecture:x64 --lockFile:./deployment.lock.json --report:./completed.json .deploy
dotnet deploy --framework:net10.0 --platform:win --architecture:x64 --lockFile:./deployment.lock.json --locked:true .deploy
RID fallback uses the repository-pinned dotnet/runtime v10.0.0 graph through NuGet.RuntimeModel (see implementation details), with aliases windows→win, mac/macos→osx, and x32→x86. contentFiles/any/{tfm} honors nuspec include/exclude, copyToOutput, and flatten; content without an output-copy rule is not deployed. The content directory is copied recursively. XML documentation in selected lib groups is included in deployment.
Package access, dependency resolution, asset selection, and RID fallback have separate implementations; framework and version models reuse NuGet/.NET types. See implementation details for responsibilities and behavior.
Variables load from the environment, the source directory's .env and its explicit imports, the destination application's appsettings.json, and finally command options. Nested JSON keys support ${Database_Name} and ${Items_0_Name}; substitution preserves URL slashes.
Run regression tests without publishing:
dotnet test test/Zongsoft.Tools.Deployer.Tests.csproj -f net10.0 -p:GeneratePackageOnBuild=false
Profile imports use Core: ImportDirective handles imports through a shared ProfileReader.Session; ProfileOptions.Loading records imported manifest hashes. See implementation details.
See implementation details for Core Profile source/override rules and read/write responsibilities. Deployment does not save its manifests.
Local source searches and links follow the implementation contract. See the repository instructions for editor configuration, resource generation and validation requirements.
| Product | Versions Compatible and additional computed target framework versions. |
|---|---|
| .NET | net8.0 is compatible. net8.0-android was computed. net8.0-browser was computed. net8.0-ios was computed. net8.0-maccatalyst was computed. net8.0-macos was computed. net8.0-tvos was computed. net8.0-windows was computed. net9.0 is compatible. net9.0-android was computed. net9.0-browser was computed. net9.0-ios was computed. net9.0-maccatalyst was computed. net9.0-macos was computed. net9.0-tvos was computed. net9.0-windows was computed. net10.0 is compatible. net10.0-android was computed. net10.0-browser was computed. net10.0-ios was computed. net10.0-maccatalyst was computed. net10.0-macos was computed. net10.0-tvos was computed. net10.0-windows was computed. |
This package has no dependencies.