DataStar.Tools
DataStar.Tools is the CLI that deploys DataStar packages against a target database. It's a self-contained .NET application that runs on Windows, Linux or macOS, so any build agent that can run .NET can run it.
What it does:
- Deploys scripts from a manifest against Oracle or SQL Server.
- Builds a deployable package straight from source control, with nothing checked out.
- Optionally writes an audit trail (summary, history, and reversal tables) to the target database.
- Optionally generates reversal (rollback) scripts, either into the audit tables or as a NuGet package.
- Optionally publishes reversal packages to a NuGet repository.
- Inflates data documents to SQL, manages shared definitions, and merges documents for git.
- Checks a workspace's data documents against a database by checksum, and re-extracts the components that changed.
Deployment artefacts
A typical release uses two or three artefacts:
- DataStar.Tools package. The CLI itself. Published on the releases page as a zip or a NuGet package, and as a .NET tool. Install it once on the agent, or (recommended) deploy it as a release artefact so the deployment pulls in the right version.
- Component templates. Required if reversal is enabled. Package the templates as a NuGet package (under a
contentsfolder is fine) so the CLI can regenerate reversal scripts. - Deployment package. Produced by the build. Contains the scripts to run, a manifest listing the run order, and a
metadata.jsonwith build information (typically a work-item reference and version).
Running the CLI
On Windows, run DataStar.Tools.exe. On Linux, run dotnet DataStar.Tools.dll. Every flag can also be set as a property in appsettings.json, where the key is the PascalCase form of the long flag (so --log-level becomes LogLevel).
DataStar.Tools.exe [options]
Flags are case-sensitive. Multiple manifests can be processed in one run: see --work-item for the regular-expression form that extracts a work-item reference from each manifest filename. Each work item is processed in its own transaction, so a failure rolls back only the current work item, not earlier ones in the batch.
Install it as a dotnet tool
As well as the zip and the tarball, DataStar.Tools publishes as a .NET tool called datastar, so an agent with the .NET SDK can install it without unpacking anything:
dotnet tool install --global DataStar.Tools --version 3.1.6
datastar --help
The packages are per platform, so the install downloads only the one for the agent it runs on. The examples below use datastar; if you are running the zip or the tarball, substitute DataStar.Tools.exe or dotnet DataStar.Tools.dll and everything else is the same.
The tool needs the .NET 10 runtime, which any agent with the .NET SDK already has. For an agent with no .NET at all, use the zip or the tarball, which carry their own runtime.
Install it from your own NuGet feed
The tool is several packages: DataStar.Tools, which is what you install, and one package per platform, DataStar.Tools.win-x64, DataStar.Tools.linux-x64, DataStar.Tools.linux-arm64, DataStar.Tools.osx-x64 and DataStar.Tools.osx-arm64. DataStar.Tools holds no program. It names the platform package to fetch, and the install downloads that one. So to install from your own feed (Azure Artifacts, Artifactory, Nexus, ProGet, or a folder), the feed needs DataStar.Tools and the platform package for every kind of agent you run.
-
Download the packages from the download page, or from nuget.org, and check their SHA-256 checksums.
-
Push them to your feed:
dotnet nuget push "DataStar.Tools*.nupkg" --source https://your-feed/v3/index.json --api-key <key> -
Install from it, either by naming the feed:
dotnet tool install --global DataStar.Tools --version 3.1.6 --add-source https://your-feed/v3/index.jsonor by adding the feed to the agent's
nuget.configand running the plaindotnet tool install --global DataStar.Tools.
If an install fails saying it cannot find a package such as DataStar.Tools.linux-x64, the platform package for that agent is missing from the feed.
Commands
--command-name (-cn) picks what to do. It defaults to release, so existing pipelines need no change.
| Command | What it does | Needs |
|---|---|---|
release | Deploys a package against a target database. The default. | A connection; a licence key when reversal is enabled |
reversal | Generates a reversal package from existing audit data. | A connection |
build | Reads a deployment file and source control, and produces a deployable package. | A git repository; no database, no workspace, no licence |
inflate | Turns data documents into the SQL they stand for. | Nothing: no database, no licence |
definitions | Lists, prunes, shares or inlines the definitions a workspace's documents point at. | The workspace, for share |
merge | git's merge driver for data documents and changesets. | The workspace's templates |
changes | Checks a workspace's tracked data documents against a database by checksum, and can re-extract the ones that changed. | The workspace and a connection; a licence key with --extract |
build, inflate, definitions and merge never open a database connection and never ask for --license-key.
build: source control in, a package out
A deployment file already names every item and the revision it is pinned at, so there is nothing to check out. build reads each item as a blob at its own revision, inflates any data document or changeset to SQL, and writes the scripts and a manifest.mf into an output folder. Give it a package file name and it packs that folder too.
datastar --command-name build \
--git-directory . \
--build-file releases/TASK-123/TASK-123.xml \
--database Microsoft \
--work-branch "$BUILD_SOURCEBRANCHNAME" \
--output-directory artifacts/scripts \
--package-directory artifacts/package \
--package-file 'TASK-123.zip'
| Flag | Purpose |
|---|---|
--git-directory (-gd) | The repository to read blobs from. Defaults to the current directory. |
--build-file (-bf) | Required. The deployment file, read from disk. Fetch it first if it lives on a work item; build does not read it out of a commit or a tag. |
--database (-db) | Required. Which vendor to inflate for: Microsoft or Oracle. A document inflates only for the vendor it was captured from. |
--at (-at) | Optional. Read every item, and every shared definition, at this one revision (a commit, tag or branch) instead of each item's pinned one. A deployment file in Branch mode is always read at one revision: --at when given, otherwise the repository's HEAD, which in a pipeline is the commit the build was started for. |
--work-item (-wi) | Optional. The work item outright. Wins over --work-branch. |
--work-branch (-wb) | Optional. A branch name to take the work item from when --work-item is not given, using the built-in patterns or --task-pattern. |
--task-pattern (-tp) | Optional. A regular expression that finds the work item in the branch name, tried before the built-in patterns. |
--output-directory (-od) | Where the scripts and manifest.mf are written. Defaults to build under the repository. It must be empty, because everything in it is packaged: a build refuses a folder that already holds files. |
--clean | Optional. Empty the output directory before writing to it, rather than refusing it. Use it on an agent that reuses its workspace between builds. |
--include | Optional, repeatable. A file or folder to add to the package root as it is, such as a variables file for the deployment step. |
--package-file (-pf) | Optional. Pack the output folder into this file, written to --package-directory. ${TaskId} (or ${WorkItem}) is replaced with the work item. A .nupkg name produces a NuGet package; anything else a zip. |
--package-directory (-pd) | Where the package is written. Required with --package-file. Also accepted as --artifacts-directory, which is what GitSources.Tools called it. The long name only: -ad means --audit-database here. |
--package-id, --package-version, --package-author, --package-summary | For a .nupkg: the package's id and version (otherwise both are parsed out of the file name), and its metadata. ${Manifest} in the summary is replaced with the deployment file's name. |
--package-uri, --package-api-key, --package-header | Push the package to a NuGet feed once it is written. |
What the output holds, per item in the deployment file:
- a
.sqlscript (or any file that is not a data document) is copied as it is, to<category>/<file>; - a data document or a changeset is inflated to
<category>/<name>.sql, reading its shared definition out of the repository at the item's own revision, so nodefinitionsfolder travels with the package; manifest.mflists them in deployment order.
Beside the scripts, at the root:
- the deployment file the build read, copied byte for byte, as
deployment.xmlordeployment.jsonaccording to its format; metadata.json, holding the work item and the package version, for example{"WorkItem": "CTAM-2586", "Version": "26.9.191917"}. The Octopus DataStar release step reads these as its variables file. The version is left out when no package is being made.
A Branch-mode deployment.json saved by DataStar 3.1.4 or later names no commit on its items, and build reads them at --at or HEAD. DataStar.Tools 3.1.0 to 3.1.2 refuse such a file with '<path>' in the deployment file has no version., so a pipeline that builds one must install DataStar.Tools 3.1.4 or later. Branch-mode deployment.xml files, and Pinned-mode files in either format, build with any 3.1 version.
Anything else the deployment stage needs goes in with --include, given once per file or folder: a file lands at the package root under its own name, and a folder brings its contents, laid out as they are. An include that would replace a file the build wrote is refused, naming it. Write such files anywhere but the output directory, which must be empty.
A release that bundles several work items can hold a changeset each for one component, and a package holds one file per component. build combines them into one changeset before anything is inflated, the same way the client does when a deployment runs: rows on different keys are taken as they are, and a row both work items changed is taken as a chain, the first one's before and the last one's after. The combined changeset records them both, as TASK-123+TASK-124, so the script says where its rows came from.
build is all or nothing. Any item that cannot be read at its revision, cannot be inflated, or would write over another item's file fails the build with Built nothing: N of M item(s) could not be built and exit code 1, and each reason is logged above it. Three things to expect:
- an item in a Pinned-mode file that pins no
Versionneeds--at(a Branch-mode file is always read at--atorHEAD), otherwise'<path>' pins no version, and the build was given no revision to read at; - changesets that cannot be chained, because the second does not start where the first left the row, are refused with both work items named. Deploy them separately, or rebase one on the other;
- a changeset in the deployment beside its component's own document or script is refused (
is in this deployment both as its component and as changeset TASK-123; deploy one or the other), because the two contradict each other: one applies a work item's rows, the other the whole component.
A NuGet package built this way records the repository it came from, read from the repository being built, so a package found months later says where its scripts came from. Any user name, token or password the clone URL carries (a CI job token, a personal access token) is left out. A clone with no remote simply records none.
Each item is read out of git as the client reads the same file from disk: a leading UTF-8 byte order mark is dropped, so a script an editor saved with one packages the same way the client would export it.
Because the documents are inflated here, the package holds scripts and a manifest and needs no templates, no workspace and no database when it lands. That is what lets the deploy stage run on a plain agent, and lets you decide after the build which environment to send it to.
Nothing about build needs a task tracker. The work item comes from the branch name, so fetching a deployment file from Jira or Azure Boards belongs in the pipeline, not in the tool.
An end-to-end pipeline
The build stage reads the repository and publishes a package; the release stage, on any agent, deploys it. Nothing in between needs templates or a workspace.
# Build stage: repository in, package out.
dotnet tool install --global DataStar.Tools --version 3.1.6
datastar --command-name build \
--git-directory . \
--build-file releases/TASK-123/TASK-123.xml \
--database Microsoft \
--work-branch "$BUILD_SOURCEBRANCHNAME" \
--output-directory artifacts/scripts \
--package-directory artifacts/package \
--package-file 'MyProduct.${TaskId}.${Version}.nupkg' \
--package-id MyProduct.TASK-123 \
--package-version "1.0.$BUILD_BUILDID"
# Writes artifacts/package/MyProduct.TASK-123.1.0.42.nupkg (for build 42).
# Publish artifacts/package with your pipeline's own step.
# Release stage: deploy the package. The scripts are plain SQL by now.
datastar --command-name release \
--deploy-package MyProduct.TASK-123.1.0.42.nupkg \
--working-directory artifacts/package \
--database Microsoft \
--connection-string "$UAT_CONNECTION_STRING" \
--environment-name UAT \
--work-item TASK-123 \
--version-number 42
To deploy from the unpacked folder instead, point --working-directory at artifacts/scripts and leave out --deploy-package. Add the audit and reversal flags below as you would for any release; reversal still needs --template-directory.
This replaces GitSources.Tools for a repository that holds data documents. GitSources copies the .json as it is and cannot include the definitions folder a shared-definition document needs, so release would fail to read it; build inflates at build time and the question does not arise.
inflate: documents to SQL, offline
Turns every data document under a directory into the SQL script it stands for, with no database and no licence. Use it to review what a document deploys as, or to get scripts out of a checkout without a workspace.
datastar --command-name inflate --working-directory ./components
datastar --command-name inflate --working-directory . --output-directory ./inflated --database Microsoft
| Flag | Purpose |
|---|---|
--working-directory (-wd) | The folder to search. Every .json below it that is a data document is inflated; folders whose name starts with . are skipped. Defaults to the current directory. |
--database (-db) | Optional. Defaults to the vendor each document was captured from, which is the only vendor it can inflate for offline. |
--output-directory (-od) | Optional. Scripts are written beside their documents unless this is given, in which case the folder tree is mirrored under it. |
--template-directory (-td) | Optional. Only needed for a document that carries no script surface (an early 3.1 preview extract). When the directory is inside a workspace, the workspace's template folders are used. |
Each document is inflated as it was extracted. A template that has changed shape since is reported (Template '<file>' has changed since the document was captured) as a warning for a document that carries its surface, and as a failure for one that does not. A shared definition is found in the definitions folder above the document, so run it from a checkout that has one. The command exits 1 if any document failed and says which.
definitions: manage shared definitions
For workspaces whose data templates share their definition, which is the default.
datastar --command-name definitions --operation list --working-directory .
datastar --command-name definitions --operation prune --working-directory .
datastar --command-name definitions --operation share --working-directory . --category reference-data
datastar --command-name definitions --operation inline --working-directory .
| Operation | What it does |
|---|---|
list | Every definition under definitions, how many documents point at it, and which are unused. A document pointing at a definition that is not there is reported as an error. The default. |
prune | Removes definitions no document in this working tree points at. Refuses to remove anything while a document cannot be read, since it might point at one. |
share | Rewrites documents that carry their definition inline as documents that point at a shared one, writing the definition. Only documents whose template says (or defaults to) Definition="shared" are converted; others are left as they are and said so. |
inline | The reverse: rewrites documents that point at a definition as documents that carry it. |
| Flag | Purpose |
|---|---|
--working-directory (-wd) | A folder in the workspace. The workspace root is found by walking up to .ds/workspace.json; without one, the folder itself is the root. |
--operation (-op) | One of the four above. Defaults to list. |
--category (-cy) | Optional. Limits share and inline to one component category. |
--template-directory (-td) | Optional. share reads each document's template to know whether it shares; the workspace supplies the templates when this is not given. |
A converted document is read back and compared with what it was before the file is replaced, so a conversion never changes what a document says; one that would is left untouched and reported.
prune reads only the working tree in front of it. A definition nothing here points at may still be the one another branch's documents point at, and removing it merges into everyone. The command says so when it removes anything. Prune on main once the branches that used a definition have merged.
merge: the git merge driver for documents
You never run this command yourself. Once it is set up, git runs it for you whenever a merge, rebase, cherry-pick or pull has to combine two versions of a data document or a changeset.
Why it exists. Git merges text line by line. Two people who change different rows of the same component can still get a conflict. For example, both branches add a row in the same place, or both touch a table's last row. The rows don't clash, but the lines of JSON do. The merge driver merges these files by row instead, so only a real clash, the same row changed differently on both sides, is a conflict.
Do you need it? Set it up if more than one person changes components or changesets on parallel branches. If only one person edits them, or branches never overlap, git's normal merge is enough.
Setting it up
Three things are needed. The first is committed once for the whole team; the other two are done on each developer's machine.
-
Declare it in
.gitattributes(once, committed to the repository). This tells git which files use the driver:components/**/*.json merge=datastarchangesets/**/*.json merge=datastarUse your workspace's Component Location and Changeset Location if they are not the defaults. Definitions never need merging: two branches that captured the same schema wrote the same file.
-
Install DataStar.Tools as a .NET tool (each machine), so the
datastarcommand is on the path:dotnet tool install --global DataStar.Tools -
Register the driver in git (each clone, or once per machine with
--global). DataStar does not do this for you, and git never takes this setting from the repository:git config merge.datastar.name "DataStar data documents and changesets"git config merge.datastar.driver "datastar --command-name merge --merge-base %O --merge-ours %A --merge-theirs %B --merge-path %P"
- On a machine that skipped step 3. Git does not warn you. It falls back to its normal line-by-line merge, and you get ordinary text conflicts.
- When a pull request is completed in Azure DevOps or GitHub. The server merges without your driver. If the hosted merge reports a conflict in a document, merge the target branch into yours locally, where the driver runs, push, and then complete the pull request.
What happens when you merge
The driver compares the two versions table by table and row by row:
- a row changed on only one side is taken from that side;
- a row changed the same way on both sides is taken once;
- a row changed differently on both sides is a conflict.
The merged file is written in the standard layout. Rows keep your branch's order, and each new row from the other branch goes after the row that comes before it on that branch. Then one of three things happens:
| Outcome | What you see | What to do |
|---|---|---|
| Every row merged | Nothing. The driver exits 0 and git carries on. | Nothing. |
| Some rows conflict | Each conflict is logged by table and key, for example both sides changed table COUNTRY row COUNTRY_CODE = GB differently; ours was kept. Base ..., ours ..., theirs .... Git marks the file as conflicted. Your branch's version of each conflicting row is kept, so the file is still a valid document. | There are no conflict markers to look for. Open the file, settle the rows the log lists, and git add it. |
| No row-level merge possible | Git marks the file as conflicted and the driver leaves it as it was. This happens when both sides changed the header (template, variables or changeset details) differently, or a table's columns differently, or when the file is not a document. | Resolve it by hand, usually by extracting the component again on the merged branch. |
A changeset merges the same way, by the row each change is for, so two people's changesets for one work item combine.
The driver needs each document's template, which it looks up by name in the workspace. Could not merge <file>: template '<name>' was not found means the clone has no workspace, or the workspace's template folders do not contain that template. In that case, add --template-directory to the driver command in step 3.
Flags
Git fills these in from the % placeholders in the driver command, so you only set them when you register the driver.
| Flag | Purpose |
|---|---|
--merge-ours (-mo) | Required. Git's %A: the current branch's version. The result is written over it. |
--merge-theirs (-mt) | Required. Git's %B: the other branch's version. |
--merge-base (-mb) | Git's %O: the common ancestor. It is empty when the file is new on both sides, which the driver handles. |
--merge-path (-mp) | Git's %P: the file's path in the working tree. Git runs the driver on temporary files at the top of the working tree, so this path is how the driver finds the file's workspace, and through it the templates and the definitions folder. |
--template-directory (-td) | Optional. Where to find templates when the clone has no .ds/workspace.json. |
changes: check a workspace against a database
Checks the workspace's tracked data documents against a database without extracting anything, the way DataStar's Changes tab does: each document's recorded checksum against the one the database computes now. Only templates with TrackChanges="true" take part.
datastar --command-name changes \
--working-directory . \
--database Microsoft \
--connection-string "$UAT_CONNECTION_STRING" \
--environment-name UAT \
--report-file artifacts/changes-uat.json
The command finds the workspace by walking up from --working-directory to .ds/workspace.json, and takes its templates, its line endings and its file naming rules from there, so it knows each component by the name DataStar gives its file. It logs a summary, then a line for each component that is not up to date, with the reason:
Checked 1,284 components of 42 templates against UAT: 3 changed, 1,281 up to date
Changed currency-lists/MIFID2_CURRLST: Rows differ
| Status | Meaning |
|---|---|
UpToDate | The database holds the document's rows. |
Changed | The database's rows differ from the document's. |
ReExtract | Not compared: the document has no checksum, has changed in the workspace since it was extracted, or its template has changed since. |
NotCheckable | The database could not compute the checksum, is of another vendor, or the template's query failed there. |
NotInDatabase | The database has no component of that name. |
--report-file also writes the report as JSON, for a later step to read:
{
"connection": "UAT",
"templates": ["currency-lists/${filename}", "exchange-lists/${filename}"],
"checked": 1284,
"upToDate": 1281,
"changed": 3,
"reExtract": 0,
"notCheckable": 0,
"notInDatabase": 0,
"items": [
{ "category": "currency-lists", "name": "MIFID2_CURRLST", "status": "Changed", "partial": false, "reason": "Rows differ" }
],
"notes": []
}
items lists every component that is not up to date, worst first. notes says what could not be checked: templates that do not track changes, a document under another file name than its component's (a copy, or a file from before the file naming rules changed), a template whose query failed, and a --name no document has.
With --extract, the file is written once the re-extract is done, and an extract section lists the components re-extracted, skipped and failed, each with its category, name and reason.
Fail a build when an environment has drifted
--fail-on-changes exits with code 2 when any component is not up to date, so a pipeline can stop a release to an environment someone has changed by hand. A check that compared nothing is no answer, so it exits with code 1 when nothing was checked (a wrong --category, say) or a component could not be:
datastar --command-name changes --working-directory . --database Microsoft \
--connection-string "$PRD_CONNECTION_STRING" --environment-name PRD --fail-on-changes
Bring a workspace up to date with an environment
--extract re-extracts the components found changed, writing their documents as DataStar would, so a scheduled job can keep a branch in step with an environment. It needs --license-key, because a document names the licensee it was extracted under. It takes the checked database's rows into the workspace, so run it against the environment the workspace follows, such as DEV, not one it deploys to.
datastar --command-name changes --working-directory . --database Microsoft \
--connection-string "$DEV_CONNECTION_STRING" --environment-name DEV \
--extract --license-key "$DATASTAR_LICENSE_KEY"
git add components definitions
git commit -m "Components changed in DEV"
An unattended job should not overwrite work, so by default --extract is careful about what it touches:
- Only
Changedcomponents are re-extracted. AReExtractdocument has changed in the workspace since it was extracted, by a pull, a merge or an edit, and re-extracting it would discard that. Add--extract-status ReExtractto re-extract those too. - Components of templates that deploy changesets are left as they are, each with a line saying so. Their changes travel in work items' changesets, and a whole extract would take every row. Add
--include-changeset-templatesto re-extract them whole. - A document under another file name than its component's is never written; the report notes it. It is a copy, or a file from before the file naming rules changed: rename it, or delete it. DataStar offers to when it recorded the rules changing.
With --fail-on-changes as well, only what is still not up to date after the re-extract counts towards exit code 2.
Keeping merged rows: --update-checksums
A ReExtract document whose rows a merge or an edit changed may hold exactly the rows you want, with only its checksum out of date. --update-checksums records the checksum of the rows each such document holds, computed by the checked database, and checks again before reporting, so those components read UpToDate or Changed instead. Their rows are kept, and each file is written the way its template writes documents now, so commit them afterwards. A document whose template changed since it was extracted, or whose file cannot be written, is left as ReExtract with a line saying why, and the run goes on. It needs no licence, and runs before --extract when both are given. See Update Checksum.
| Flag | Purpose |
|---|---|
--working-directory (-wd) | A folder in the workspace. Defaults to the current directory. |
--database (-db) | Required. Microsoft or Oracle. |
--connection-string (-cs) | Required. The database to check against. Oracle can also use --tns-admin and --wallet-location. |
--environment-name (-en) | Optional. How the report names the database. |
--category (-cy) | Optional. Only this category. |
--name (-nm) | Optional, repeatable. Only this component, by name within --category; give it once per component. Needs --category. A name no document has fails the run. |
--report-file (-rf) | Optional. Also write the report as JSON. A relative path is taken from the current directory. |
--fail-on-changes (-fc) | Optional. Exit with code 2 when a component is not up to date, and with 1 when nothing was checked or a component could not be. |
--extract (-ex) | Optional. Re-extract the components found changed. Needs --license-key. |
--extract-status (-es) | Optional, repeatable, with --extract. The statuses to re-extract: Changed (the default) and ReExtract. |
--include-changeset-templates (-ic) | Optional, with --extract. Also re-extract, whole, the components of templates that deploy changesets. |
--update-checksums (-uc) | Optional. Give each ReExtract document the checksum of the rows it holds, keeping them, then check again. |
--template-directory (-td) | Optional. Read templates from this folder instead of the workspace's template folders. A relative path is taken from the current directory; a folder that does not exist, or holds no data template, fails the run. |
--license-key (-lk) | Needed with --extract. |
| Exit code | Meaning |
|---|---|
0 | The check ran. Without --fail-on-changes, whatever it found. |
1 | The check could not run (no workspace, a bad option, no data template, no connection), a --name matched no document, or a re-extract failed. With --fail-on-changes, also when nothing was checked or a component was NotCheckable. The log says which. |
2 | With --fail-on-changes: a component is Changed, ReExtract or NotInDatabase. |
The check sends 25 components to a statement and runs up to MaxDegreeOfParallelism statements at once, 10 unless the tool's appsettings.json says otherwise; re-extracting uses the same limit. Only the checksums cross the network, so a check of thousands of components takes seconds.
Flag reference
Target database
| Switch | Long name | Type | Description |
|---|---|---|---|
-db | --database | String | Required for every command but inflate, where it defaults to the vendor each document was captured from. Target database vendor: Oracle or Microsoft. |
-cs | --connection-string | String | The database connection string. Oracle uses the ODP.NET format; SQL Server uses the SqlClient format. Oracle users should also consider --tns-admin and --wallet-location. |
-en | --environment-name | String | Name of the target environment. Used in logging and as a default when a package description is not supplied. |
-ds | --default-schema | String | Default schema for the deployment. Ignored if the templates specify a schema. |
-ta | --tns-admin | String | Directory containing the Oracle TNS admin files. Lets the connection string use a TNS alias instead of host / port / service. |
-wl | --wallet-location | String | Path to an Oracle Wallet. Used for shared credentials, so passwords don't appear in connection strings. |
SQL Server connection encryption
DataStar v3 ships with Microsoft.Data.SqlClient 6.x, which changed the
default for two connection-string keys compared to the older driver bundled
with v2.x:
| Key | v2.x default | New driver default |
|---|---|---|
Encrypt | False | Mandatory |
TrustServerCertificate | False | False |
Connection strings that worked under v2.x can therefore fail the TLS handshake under v3, typically against SQL Server instances that present self-signed or otherwise untrusted certificates. To smooth the upgrade, DataStar.Tools applies the v2.x defaults when the connection string sets neither key:
- If your connection string contains neither
Encrypt=norTrustServerCertificate=, DataStar.Tools appendsEncrypt=False;TrustServerCertificate=True;so the connection behaves the same as under v2.x. A single Information-level log line records exactly which defaults were added. - If you set either key explicitly, your value is used unchanged.
To force the new strict-TLS behaviour explicitly:
Server=...;Database=...;Encrypt=Mandatory;TrustServerCertificate=False;
To trust a self-signed certificate while still encrypting the connection:
Server=...;Database=...;Encrypt=Mandatory;TrustServerCertificate=True;
To match v2.x exactly (no encryption), either let the defaults apply or set both explicitly:
Server=...;Database=...;Encrypt=False;TrustServerCertificate=True;
Both Encrypt and TrustServerCertificate flow through --connection-string;
no separate flags are exposed for them. In the Octopus action template, set
the values in the dsr-connectionString parameter and the helper passes them
through unchanged.
When a connection fails, the underlying SqlClient exception (certificate
trust, authentication, name resolution, etc.) is now logged directly so the
cause is visible in the deployment output, rather than a generic
"Failed to connect to the Microsoft database" line as in earlier 3.0.x
releases.
Deployment mode and manifest
| Switch | Long name | Type | Description |
|---|---|---|---|
-cn | --command-name | String | The command to execute: release (the default), reversal, build, inflate, definitions, merge or changes. See Commands. |
-wd | --working-directory | String | Directory containing the deployment packages or manifests; for inflate, definitions and changes, the folder to work in. Defaults to the current directory. |
-wi | --work-item | String | Work item or user-story reference. Required for all releases. For a batch of manifests, set this to a regex (prefixed with @) that extracts the work item from the filename. For example, "@[A-Z]{2,}\\d+" extracts US123456 from 001-US123456.mf. For build, optional: the branch name supplies it otherwise. |
-vn | --version-number | String | Version number being released. Required for all releases. |
-mr | --manifest.regexp | String | Regex for matching manifest files. Defaults to any file with a .mf suffix. |
-dp | --deploy-package | String | Name of a NuGet package to deploy, if you want to deploy directly from the package rather than from unpacked files. |
Build
| Switch | Long name | Type | Description |
|---|---|---|---|
-gd | --git-directory | String | The repository the items are read out of. Defaults to the current directory. |
-bf | --build-file | String | The deployment file to build, read from disk. |
-at | --at | String | Read every item and definition at this revision instead of the version each item was pinned at. |
-wb | --work-branch | String | A branch name to take the work item from when --work-item is not given. |
-tp | --task-pattern | String | The pattern that finds the work item in a branch name. Defaults to the built-in patterns. |
Definitions and merge
| Switch | Long name | Type | Description |
|---|---|---|---|
-op | --operation | String | The definitions operation: list (default), prune, share or inline. |
-cy | --category | String | Limits definitions and changes to one component category. |
-mb | --merge-base | String | For merge: the common base version (git's %O). |
-mo | --merge-ours | String | For merge: the current version, which the merge is written over (git's %A). |
-mt | --merge-theirs | String | For merge: the other branch's version (git's %B). |
-mp | --merge-path | String | For merge: the file's path in the working tree (git's %P). |
Changes
| Switch | Long name | Type | Description |
|---|---|---|---|
-nm | --name | String, repeatable | For changes: a component to check, by name within --category. |
-rf | --report-file | String | For changes: also write the report to this file, as JSON. |
-fc | --fail-on-changes | Flag | For changes: exit with code 2 when a component is not up to date, and 1 when nothing was checked or a component could not be. |
-ex | --extract | Flag | For changes: re-extract the components found changed. Needs --license-key. |
-es | --extract-status | String, repeatable | For changes --extract: the statuses to re-extract, Changed (the default) or ReExtract. |
-ic | --include-changeset-templates | Flag | For changes --extract: also re-extract, whole, the components of templates that deploy changesets. |
Audit tables
| Switch | Long name | Type | Description |
|---|---|---|---|
-ae | --audit-enabled | Flag | Write deployment details to the audit tables (summary, history, reversal). |
-ah | --audit-history | String | Name of the audit history table. Required when auditing is enabled. |
-ar | --audit-reversal | String | Name of the audit reversal table. Required when auditing is enabled. |
-as | --audit-summary | String | Name of the audit summary table. Required when auditing is enabled. |
-ao | --audit-schema | String | Schema where the audit tables live. |
-ad | --audit-database | String | Database holding the audit tables. SQL Server only, for when audit tables are in a different database from the target. |
-ai | --audit-initialize | Flag | Create the audit tables automatically if they don't already exist. |
Reversal and packaging
| Switch | Long name | Type | Description |
|---|---|---|---|
-re | --reversal-enabled | Flag | Generate reversal scripts alongside the deployment. Requires --template-directory. |
-td | --template-directory | String | Directory containing the DataStar component templates. Required when --reversal-enabled is set; optional for inflate, definitions, merge and changes, which otherwise take the workspace's. |
-ir | --inverse-reversal | Flag | Run reversal scripts in reverse order. Oracle's default; recommended for SQL Server when using v2 templates. |
-id | --audit-id | String | In reversal mode, identifies the audit history record to generate a package from. |
-ri | --reversal-id | String | In reversal mode, identifies the reversal record to generate a package from. |
--artifacts-directory | String | Another name for --package-directory, as GitSources.Tools called it. No short form: -ad is --audit-database. | |
-pd | --package-directory | String | Output directory for the generated package (a reversal package, or build's). |
-pf | --package-file | String | Output filename for the package. Supports ${TaskId} (or ${WorkItem}) and ${Version} substitutions. |
-pi | --package-invariant | Flag | Generate a reversal package even when no changes were applied. Off by default. |
--clean | Flag | For build: empty the output directory first. Without it, a build refuses an output directory that is not empty. | |
--include | String, repeatable | For build: a file or folder added to the package root as it is. Give it once per path. | |
-pk | --package-id | String | Package id for the generated NuGet package. |
-pv | --package-version | String | Package version for the generated NuGet package. |
-pa | --package-author | String | Package author for the generated NuGet package. |
-ps | --package-summary | String | Package summary for the generated NuGet package. |
-pu | --package-uri | String | URI to publish the package to. |
-px | --package-api-key | String | API key for the package repository. |
-ph | --package-header | String | Header name for the API key, if the repository expects something other than the default. |
Connection and runtime
| Switch | Long name | Type | Description |
|---|---|---|---|
-st | --statement-timeout | Integer | Per-statement timeout in seconds. 0 means no timeout on SQL Server. |
-rt | --rollback-transaction | Flag | Roll back the deployment after running it. Useful for dry-run verification before a real release. |
Logging and output
| Switch | Long name | Type | Description |
|---|---|---|---|
-lf | --log-file | String | Also write logs to this file, in addition to the console. |
-ll | --log-level | String | Log verbosity. For example, debug enables debug logging. |
-od | --output-directory | String | Output directory for artefacts: reversal packages, build's scripts and manifest, inflate's scripts. |
Licence
| Switch | Long name | Type | Description |
|---|---|---|---|
-lk | --license-key | String | The software licence key supplied by Absolute Technology. Required when --reversal-enabled is set, and for changes --extract. Not used by build, inflate, definitions or merge. Like every flag, it can also be set in appsettings.json, or as the LicenseKey environment variable, which keeps it off the command line. |
Flag value types
| Type | Meaning |
|---|---|
| Flag | No value expected after the switch. |
| String | A string argument follows the switch. |
| Integer | An integer argument follows the switch. |
| Boolean | true or false follows the switch. |