Skip to content

DevOps

Automator|Client Services · .NET 10

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/JOIN references)
  • 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