DevOps
Development and release tooling for the Payroll Engine. The scripts are located in the
devops/scripts
directory of the main repository.
Scripts
| Script | Group | Purpose |
|---|---|---|
Update-BreakingChanges.ps1 |
Release | Detect breaking API changes and document them in RELEASE_NOTES.md |
Release-Changelog.ps1 |
Release | Consolidate Git changelogs across all repositories for a release |
Update-CommitMessage.ps1 |
Release | Populate the VS commit message from the latest RELEASE_NOTES.md section |
Export-DbScript.ps1 |
Database | Export the live database schema to a .sql file |
Format-DbScript.ps1 |
Database | Format a .sql file and resolve object dependency order |
Compare-DbScript.ps1 |
Database | Diff two formatted .sql files and generate an update script |
Global Usage
To run scripts from any directory without specifying the full path, add the scripts folder
to PATH in your PowerShell profile:
New-Item -ItemType File -Path $PROFILE -Force
Add-Content -Path $PROFILE -Value "`$env:PATH += `";C:\Shared\PayrollEngine\Repos\PayrollEngine\devops\scripts`""
After restarting the session, scripts are available from any directory without a path prefix:
Update-BreakingChanges.ps1
Format-DbScript.ps1 -SourceFile ModelCreate.sql -TargetFile ModelCreate.Formatted.sql
Do not use
.\— that forces PowerShell to look in the current directory only.
Directory Layout
All scripts expect the standard repository layout and resolve paths relative to the script
location (devops\scripts\ → repo root → parent). Override with -ReposRoot if your
layout differs.
<ReposRoot>\
PayrollEngine\ ← main repo (with devops\scripts\)
PayrollEngine.Backend\
PayrollEngine.Core\
PayrollEngine.Client.Core\
PayrollEngine.Client.Scripting\
PayrollEngine.Client.Services\
...
See Repositories for the full repository list.
Release Scripts
Scripts for release preparation, changelog consolidation and breaking change detection.
| Script | Purpose |
|---|---|
Update-BreakingChanges.ps1 |
Detect breaking API changes and document them in RELEASE_NOTES.md |
Release-Changelog.ps1 |
Consolidate Git changelogs across all repositories for a release |
Update-CommitMessage.ps1 |
Populate the VS commit message from the latest RELEASE_NOTES.md section |
Release Workflow
The release process follows a defined sequence. The devops scripts support steps 1–3:
| Step | Task | Tool |
|---|---|---|
| 1 | Detect breaking changes across all APIs | Update-BreakingChanges.ps1 |
| 2 | Update commit messages from release notes | Update-CommitMessage.ps1 |
| 3 | Collect and consolidate changelogs | Release-Changelog.ps1 |
| 4 | Execute CI/CD release pipeline | GitHub Actions |
See Releases for release artifacts and version history.
Update-BreakingChanges
Update-BreakingChanges.ps1 compares uncommitted code against the last Git commit (or a specific tag) and detects breaking changes across four API surfaces:
| API Surface | Method | Repository |
|---|---|---|
| REST API (Provider) | swagger.json diff |
PayrollEngine.Backend |
| Backend API Models | .NET assembly surface diff via MetadataLoadContext |
PayrollEngine.Backend |
| Scripting API (Regulator) | .NET assembly surface diff | PayrollEngine.Client.Scripting |
| Client Services (Automator) | .NET assembly surface diff | PayrollEngine.Client.Services |
Detected breaking changes are automatically appended to RELEASE_NOTES.md, mapped to the
correct section. Only new entries are added — existing content is never modified.
# detect against HEAD, auto-update RELEASE_NOTES.md
Update-BreakingChanges.ps1
# detect against a specific tag
Update-BreakingChanges.ps1 -BaselineRef "v0.9.0"
# with confirmation prompt before updating RELEASE_NOTES.md
Update-BreakingChanges.ps1 -ConfirmReleaseNotes
# skip RELEASE_NOTES.md update entirely
Update-BreakingChanges.ps1 -SkipReleaseNotes
# write a Markdown report
Update-BreakingChanges.ps1 -ReportPath ".\breaking-changes.md"
# use pre-generated swagger.json (CI integration)
Update-BreakingChanges.ps1 -SwaggerJsonPath "docs\swagger.json"
The -SwaggerJsonPath parameter skips Swashbuckle CLI generation and uses a pre-generated
file directly — useful in CI where swagger.json has already been generated by a prior
build step (e.g. Wave 5 in the release pipeline).
Prerequisites: .NET SDK, Swashbuckle CLI (dotnet tool install -g Swashbuckle.AspNetCore.Cli)
Release-Changelog
Release-Changelog.ps1 consolidates Git changelogs across all repositories for a release. Requires PowerShell 7+.
| Mode | Description |
|---|---|
PreCheck |
Verify all repos are clean (no uncommitted/unpushed changes) |
Collect |
Gather commit entries since last tag |
Consolidate |
Generate release notes with interactive entry selection |
Full |
All steps in sequence |
# full release changelog
Release-Changelog.ps1 -Version "1.0.0"
# pre-check only
Release-Changelog.ps1 -Mode PreCheck
# dry run against specific tag
Release-Changelog.ps1 -Version "1.0.0" -SinceTag "v0.9.0" -DryRun
Update-CommitMessage
Update-CommitMessage.ps1 reads the latest section from RELEASE_NOTES.md and writes
it to .git/MERGE_MSG. Visual Studio picks this up as the default commit message in
Git Changes. Only processes repositories with uncommitted changes.
Update-CommitMessage.ps1
Update-CommitMessage.ps1 -RepoPath "C:\path\to\PayrollEngine.Backend"
Update-CommitMessage.ps1 -RepoPath "C:\path\to\PayrollEngine.Backend" -Silent
Database Scripts
Scripts for SQL Server schema export, formatting and diff. All three handle large .sql
files (280 KB+) and operate on:
| File | Purpose |
|---|---|
ModelCreate.sql |
Full CREATE script for a fresh database |
ModelDrop.sql |
DROP script for all schema objects |
ModelUpdate.sql |
Incremental migration between versions |
Default location: PayrollEngine.Backend\Database\
| Script | Purpose |
|---|---|
Export-DbScript.ps1 |
Export the live database schema to a .sql file |
Format-DbScript.ps1 |
Format a .sql file and resolve object dependency order |
Compare-DbScript.ps1 |
Diff two formatted .sql files and generate an update script |
Export-DbScript
Export-DbScript.ps1 connects to SQL Server and exports the live database schema to a
.sql file. The connection string is read from the PayrollDatabaseConnection environment
variable.
| Mode | Output |
|---|---|
Create |
CREATE TABLE, indexes, foreign keys, stored procedures, functions, views |
Delete |
Safe DROP statements in dependency order (procedures first, then tables) |
The output is unordered — pipe it through Format-DbScript.ps1 to normalise style and
resolve dependency order before committing as a snapshot.
$env:PayrollDatabaseConnection = 'Server=.;Database=PayrollEngine;Integrated Security=True;'
Export-DbScript.ps1 -Mode Create -TargetFile Snapshot_Create.sql
Export-DbScript.ps1 -Mode Delete -TargetFile Snapshot_Delete.sql
Format-DbScript
Format-DbScript.ps1 formats a .sql file and resolves forward-reference dependency
warnings. SourceFile is never modified; the result is written to TargetFile.
What it does:
- Splits the file into GO-delimited blocks and groups them into named DDL objects
- Detects inter-object dependencies (
EXEC, UDF calls,FROM/JOINreferences) - Topologically sorts all objects so each is defined before its dependents
- Eliminates warnings such as: "The module 'X' depends on the missing object 'Y'..."
- Normalises GO delimiters, trailing whitespace and line endings (CRLF)
Format-DbScript.ps1 -SourceFile ModelCreate.sql -TargetFile ModelCreate.Formatted.sql
Compare-DbScript
Compare-DbScript.ps1 compares two formatted .sql files and generates a delta script
that migrates a database from the baseline state to the current state. Both input files
should be pre-processed by Format-DbScript.ps1.
| Category | Detection | Output |
|---|---|---|
| Added | Present in Current, missing in Baseline | CREATE |
| Removed | Present in Baseline, missing in Current | DROP |
| Modified | Present in both with different body | DROP + CREATE (tables: TODO comment — manual ALTER TABLE required) |
Compare-DbScript.ps1 `
-BaselineFile ModelCreate.Formatted.sql `
-CurrentFile ModelCreate.New.Formatted.sql `
-TargetFile ModelUpdate.sql
Typical Workflow
# 1. Export current database state
Export-DbScript.ps1 -Mode Create -TargetFile Snapshot.sql
# 2. Format both files for reliable comparison
Format-DbScript.ps1 -SourceFile Snapshot.sql -TargetFile Snapshot.Formatted.sql
Format-DbScript.ps1 -SourceFile ModelCreate.sql -TargetFile ModelCreate.Formatted.sql
# 3. Generate update script
Compare-DbScript.ps1 `
-BaselineFile Snapshot.Formatted.sql `
-CurrentFile ModelCreate.Formatted.sql `
-TargetFile ModelUpdate.sql