clean
All checks were successful
Build Quartz Notes / build (push) Successful in 33s

This commit is contained in:
2026-06-02 14:26:45 +01:00
parent cfa8867ca1
commit 6e65fa187c
73 changed files with 1331 additions and 190 deletions

View File

@@ -0,0 +1,90 @@
# What is ESP?
ESP is a software suite built by ESS and sold to customers. It is deployed on a **per-customer basis** — similar to TMC (another internal product) but with fewer applications in the suite.
Key traits:
- Customers only have the apps **they use** — not every customer gets everything
- Customers may have multiple environments (e.g. TEST and PROD)
- Test and PROD instances may live on the **same server** — this is a risk to be mindful of during deployment
# Application Categories
ESP applications fall into three categories:
## 1\. Databases
| Application | Type | Notes |
| ----------- | ---------- | ------------------------------------------- |
| EspBroker | SQL Server | The core ESP database. Deployed via dacpac. |
See [[ESP Database]] for Dacpac detail.
## 2\. Windows Services
[[Windows Services]] are background processes that run on a Windows server. They have no UI — they start, run, and are managed via the Windows Service Manager (or PowerShell commands like `Stop-Service`, `Start-Service`).
| Service Name | Notes |
| --------------- | --------------------------------- |
| DLService | Unknown specific function (TBC) |
| EmailService | Likely handles outbound emails |
| ExPlService | Unknown specific function (TBC) |
| MISService | Unknown specific function (TBC) |
| OutboundService | Likely handles outbound messaging |
| ULService | Unknown specific function (TBC) |
### Working with Windows Services in PowerShell
``` powershell
# Stop a service
Stop-Service -Name "DLService" -Force
# Start a service
Start-Service -Name "DLService"
# Check service status
Get-Service -Name "DLService"
# Wait for a service to stop
(Get-Service -Name "DLService").WaitForStatus('Stopped', '00:01:00')
```
### Why Services Must Be Stopped Before Deployment
When deploying a new version, the old service process holds file locks on its [[DLL's]]. You cannot overwrite a locked file on Windows. Therefore the sequence is:
1. Stop the service
2. Swap the files (old → new)
3. Start the service
## 3\. Citrix Applications
Citrix is a technology that **streams desktop applications** to users remotely - the app runs on a server but the user sees it on their machine, similar to a remote desktop but on a per-app basis.
| Application | Notes |
| ------------- | ---------------------------- |
| VPlanner | Main planning application |
| VPlannerAdmin | Admin interface for VPlanner |
| ImportApp | Data import application |
### Citrix Deployment Considerations
Citrix apps are more complex to deploy than Windows Services because:
- **Active user sessions** may be running — you can't just swap files
- You must **notify users** of the upcoming upgrade and give a grace period
- After the grace period, **kill any remaining sessions**
- The actual upgrade mechanism is **still TBC** — believed to be a file copy with handling for locked executables built in
- Post-deploy **cycle checks** require navigating Citrix UI — hard to automate
# Per-Customer App Lists
Unlike TMC (where presumably all customers get everything), ESP is a subset deployment. This means:
- The manifest (see [[ESP Manifest]]) must define **which apps each customer has**
- The deployment scripts must skip apps not applicable to a given customer
- There is no universal "deploy everything" - each customer's list must be explicitly defined and maintained
# Completeness of This List
The handover document states this list is believed complete but **has not been confirmed**. Treat it as a working assumption, not a guarantee. Validate against actual customer environments when possible.

View File

@@ -0,0 +1,126 @@
# The ESP Database
ESP uses a single SQL Server database called **EspBroker**. This is deployed and upgraded as part of the overall ESP deployment process.
# What Is a Dacpac?
A **dacpac** (Data-tier Application Package) is a packaged representation of a SQL Server database **schema**. It is a file with the extension `.dacpac`.
Rather than writing migration scripts that say "ALTER TABLE, ADD COLUMN…" manually, you instead describe the **desired end state** of the database, and the dacpac deployment tool (`sqlpackage`) calculates the delta and applies it automatically.
## How Dacpac Deployment Works
Your dacpac file (desired schema)
sqlpackage.exe
├── Connects to target database
├── Compares desired schema to actual schema
├── Generates a diff
└── Applies the diff (ALTER TABLE, CREATE INDEX, etc.)
## Advantages Over Raw SQL Scripts
| Dacpac | Raw SQL Scripts |
| --------------------------------------- | ----------------------------------------- |
| Declarative — describe what you want | Imperative — describe each change step |
| Tool calculates the diff automatically | You must track and apply changes manually |
| Idempotent — safe to run multiple times | Can fail if run twice without care |
| Schema is versioned as code | Scripts can get out of sync |
## Relevant PowerShell / CLI
``` powershell
# Deploy a dacpac using sqlpackage
& "C:\Program Files\Microsoft SQL Server\160\DAC\bin\sqlpackage.exe" `
/Action:Publish `
/SourceFile:"EspBroker.dacpac" `
/TargetServerName:"ROMAC-DEV-DB01" `
/TargetDatabaseName:"EspBroker"
```
# Team Ludo's Dacpac
Team Ludo built a dacpac solution for EspBroker. This is already in the repo and represents the **target schema** that all customer databases should eventually conform to.
# The Critical Problem — Schema Inconsistency
## What the Problem Is
Existing customer databases have drifted from the official schema over time. This drift likely happened due to:
- Manual hotfixes applied directly to production databases
- Different versions of ESP deployed to different customers at different times
- No enforced schema management historically
This means the dacpac's expected schema does not match what is actually in customer databases.
## Consequence
If you attempt to deploy the dacpac against an inconsistent database, `sqlpackage` will either:
- Fail with errors (best case — nothing is changed)
- Apply incorrect changes that corrupt data (worst case)
## What Needs to Happen
Before the dacpac can be used for a customer:
1. A database expert must **manually inspect** the customer's database
2. Identify all schema differences between actual and expected state
3. Write and apply **manual SQL scripts** to bring the DB into alignment
4. Verify the dacpac can then deploy cleanly (ideally against a copy)
5. Only then mark the customer as `dacpacReady: true` in the manifest
## Pipeline Safeguard
The deployment pipeline **must** check the `dacpacReady` flag before attempting database deployment, and fail clearly if it is `false`:
``` powershell
function Invoke-DatabaseDeployment {
param($Manifest)
if (-not $Manifest.Database.DacpacReady) {
Write-Error "Database for $($Manifest.Customer) $($Manifest.Environment) is not dacpac-ready. " +
"Manual schema alignment is required before deployment."
throw "Database not ready for dacpac deployment."
}
# Proceed with dacpac deployment...
Deploy-Dacpac -DacpacPath $artifactPath -Server $Manifest.Servers.DbServer -Database "EspBroker"
}
```
# Database Deployment in the Deployment Stage
Database deployment sits inside the **DEPLOY stage**. See [[ESP Deploy Stages]] for full stage detail. The database is typically deployed before services are started up to ensure the schema is ready for the new application code.
Suggested order within the DEPLOY stage:
1. Stop Windows Services
2. Deploy database dacpac (if dacpacReady)
3. Handle Citrix sessions
4. Swap application files
5. Start Windows Services back up
# Rollback Considerations
If the dacpac deploys successfully but a subsequent step fails, rolling back the database is non-trivial. Dacpac does not natively support rollback — options are:
- Restore from backup (requires a backup to have been taken immediately before)
- Write a counter-dacpac that reverts the schema (complex, error-prone)
This is one of the reasons the **rollback plan is still TBC**. See [[ESP OQ]].
A **database backup must be taken before any deployment** — this should be a mandatory step in the PREDEPLOY stage.
# SQL Server Concepts Relevant Here
| Concept | Relevance |
| -------------- | ------------------------------------------------------------ |
| Schema | The structure of tables, columns, indexes, constraints, etc. |
| `sqlpackage` | Microsoft CLI tool that applies dacpac files |
| `BACPAC` | Like dacpac but includes data — useful for backup/restore |
| SQL Agent Jobs | Scheduled SQL jobs that may need to be handled during deploy |
| Linked Servers | DB connections to other servers — may be part of ESP's setup |

View File

@@ -0,0 +1,161 @@
# Overview
The deployment is broken into **discrete stages** that can be run in any combination. This allows you to, for example, only run validation, or only run post-deploy checks, without triggering a full deployment.
Entry point call:
``` powershell
Invoke-Deployment.ps1 -Customer ROMAC -Environment DEV -Stages VALIDATE,PREDEPLOY,DEPLOY,POSTDEPLOY
```
# Stage Summary
| Stage | Script (Tier 2) | Safe to Run Alone? | Notes |
| ------------- | --------------------- | ------------------ | ------------------------- |
| VALIDATE | `Validation.psm1` | Yes — read only | No changes made |
| PREREQUISITES | `Prerequisites.psm1` | Yes — read only | No changes made |
| PREDEPLOY | `PreDeployment.psm1` | Yes (with care) | Stages files, no swap yet |
| DEPLOY | `Deployment.psm1` | No — destructive | Requires PREDEPLOY first |
| POSTDEPLOY | `PostDeployment.psm1` | Yes (after DEPLOY) | Checks only, no changes |
# Stage 1 — VALIDATE
## Purpose
Load the manifest and verify it is well-formed and consistent before anything else happens.
## What It Does
- Reads the manifest file for the given customer/environment
- Checks all required fields are present
- Validates server names, version references, and flags
- Checks that the referenced build artifact version exists
- Fails fast with a clear error if anything is wrong
## What It Does NOT Do
- Makes no changes to any server
- Does not connect to target servers (it may ping/resolve names only)
## Why It Exists Separately
You might want to validate a new manifest you've written without triggering a full deployment. Running VALIDATE alone takes seconds and gives you confidence before committing to the rest.
# Stage 2 — PREREQUISITES
## Purpose
Verify that the target environment meets all requirements before deployment begins.
## What It Checks (Not Exhaustive — Full List TBC)
- Required software is installed on target servers (e.g. .NET runtime, SQL client)
- Correct environment labels/flags are set up
- Services exist (so the deployment can stop/start them)
- Network connectivity between agent and target servers
- Sufficient disk space on target servers
- Database is accessible
- If DEPLOY will include DB: check `dacpacReady` flag (see [[ESP Database]])
## Outcome
- Pass: continue to next stage
- Fail: abort with a clear list of what's missing — **no changes made**
# Stage 3 — PREDEPLOY
## Purpose
Prepare the new version's files on the target servers **without** switching anything live. Think of it as laying everything out ready before the actual switch.
## What It Does
- Copies build artifacts from the AzDO artifact store to a **staging location** on each target server (not the live installation path)
- Applies environment-specific configuration to the staged files (e.g. replaces connection strings, config values from the manifest)
- Takes a **backup of the current live installation** and the database
- Verifies the staged files look correct
## Why Stage Before Deploying?
Pre-staging minimises the time during which the application is down. When DEPLOY runs, it can simply swap directories (fast) rather than copying large amounts of data (slow) while services are stopped.
## Artifact Staging Note
The ESP build artifact is currently a **flat folder of DLLs** — not separated per application. Predeploy will need to handle the mapping of DLLs to their correct applications. See [[ESP Known Issues and Risks]].
# Stage 4 — DEPLOY
## Purpose
The actual upgrade — swap the old version for the new version.
## Sequence (High Level)
### 4a. Database
1. Check `dacpacReady` flag — fail if false
2. Deploy the dacpac to EspBroker (see [[ESP Database]])
### 4b. Windows Services
1. Stop all enabled Windows Services (one by one or in parallel — TBC)
2. For each service:
a. Move/delete old installation directory
b. Move staged new files into the installation directory
3. Apply any final configuration adjustments
### 4c. Citrix Applications
1. Send notification to active Citrix users (e.g. "System upgrade in 15 mins")
2. Wait for grace period to expire
3. Kill any remaining Citrix sessions
4. Perform Citrix application upgrade (mechanism TBC — believed to be file copy)
### 4d. Start Up
1. Start all enabled Windows Services
2. Wait for each to reach Running state before moving on
## Order Matters
The database schema must be deployed **before** starting the new application code, because the new application version expects the new schema. Starting services before the dacpac is deployed would likely cause errors.
## Risk
This is the most **destructive** stage. If something goes wrong mid-deploy, the system may be in a partially upgraded state. This is why rollback planning (currently TBC) is critical. See [[ESP Known Issues and Risks]].
# Stage 5 — POSTDEPLOY
## Purpose
Verify the deployment succeeded and the system is healthy.
## What It Does
### Basic Service Checks
- Verify all enabled Windows Services are in `Running` state
- Verify no services crashed immediately after start
### Cycle Checks
- Extensive checks that exercise the application's functionality
- Currently heavily reliant on **Citrix UI navigation** — very difficult to automate
- May initially be a manual prompt ("Please run the cycle checks and confirm pass/fail")
- Long term: UI automation or API-based checks
## What It Does NOT Do
- Makes no changes to the system
- Should be safe to re-run at any time
# Running Subsets of Stages
| Goal | Stages to Run |
| --------------------------------- | ---------------------------------- |
| Check config before deploying | `VALIDATE` |
| Full pre-flight check | `VALIDATE,PREREQUISITES` |
| Stage files only (no deploy yet) | `VALIDATE,PREREQUISITES,PREDEPLOY` |
| Full deployment | All stages |
| Re-run health checks after deploy | `POSTDEPLOY` |
| Everything except DB | Custom flags TBC |

View File

@@ -0,0 +1,197 @@
# Overview
Reference glossary for all technical and project-specific terms used across the ESP deployment pipeline project. Alphabetically ordered.
# A
## Agent (AzDO)
The machine that executes an AzDO pipeline. Can be **Microsoft-hosted** (a fresh Azure VM for each run) or **self-hosted** (a persistent machine you manage).
For deploying to customer servers, a self-hosted agent is required to have network access to those servers.
## Artifact (Build)
The output of a build pipeline — typically compiled binaries, DLLs, config files, etc. packaged and stored so a deployment pipeline can consume them.
The ESP build artifact is currently a flat folder of DLLs. See [[ESP Known Issues and Risks]]
## AzDO / Azure DevOps
Microsoft's DevOps platform. Provides Repos (Git), Pipelines (CI/CD), Boards (work tracking), and Artifacts (package storage). The ESP pipeline lives here.
# B
## BACPAC
A SQL Server package format that includes both schema **and** data. Useful for backup/restore. Contrast with Dacpac (schema only).
## Build Pipeline
An AzDO pipeline that compiles source code and produces a build artifact. The ESP build pipeline is `ESS.esp Main Build`.
# C
## CI/CD
**Continuous Integration / Continuous Delivery (or Deployment)**. The practice of automatically building, testing, and deploying software whenever changes are made. AzDO pipelines implement this.
## Citrix
A technology platform that delivers desktop applications to users remotely. The application runs on a Citrix server; users see and interact with it via the Citrix Workspace client. Three ESP applications (VPlanner, VPlannerAdmin, ImportApp) are delivered this way.
## Cycle Checks
Post-deployment validation checks for ESP that involve navigating through the Citrix application UI to verify the system is functioning correctly. These are extensive and difficult to automate. See [[ESP Deploy Stages]].
# D
## Dacpac
**Data-tier Application Package**. A `.dacpac` file that represents the desired schema of a SQL Server database. Deployed using `sqlpackage.exe`, which calculates the difference between desired and actual schema and applies it. See [[ESP Database]].
## `dacpacReady`
A flag in the manifest (see [[ESP Manifest]]) that indicates whether a customer's database has been manually aligned to be compatible with the dacpac. Must be `true` before the pipeline will attempt database deployment.
## Deploy Pipeline
The AzDO pipeline responsible for deploying ESP to customer environments. Currently: `ESS.esp Deploy`. This is the primary pipeline your team owns.
## DLL
**Dynamic Link Library**. A compiled Windows binary file (`.dll`) containing reusable code. Windows Services and other Windows applications are composed of DLLs. Deploying a new version means replacing old DLLs with new ones.
# E
## Environment
In the context of ESP, an environment is a specific deployment target for a customer (e.g. DEV, TEST, PROD). A customer may have multiple environments. Each environment has its own manifest.
## ESP
The application suite built by ESS. Delivered to customers on a per-customer basis. Contains databases, Windows Services, and Citrix applications. See [[ESP Applications]].
## ESS
The company that built ESP. Formerly had a larger engineering team; now reduced. Has a data centre of their own where some customer instances are hosted.
## EspBroker
The SQL Server database used by ESP. The only database in the suite currently. Deployed via dacpac.
# G
## Grace Period
In the context of Citrix deployment: the time given to active Citrix users to save their work and quit before their session is forcibly terminated to allow the upgrade to proceed.
# J
## Job (AzDO)
A unit of work within an AzDO pipeline stage. Each job runs on a single agent. A stage can have multiple parallel jobs.
# L
## Layer / Tier
The architectural layers in the PowerShell script design. Tier 1 = entry point; Tier 2 = orchestration; Tier 3 = isolated worker functions. See [[ESP Scripts]].
# M
## Manifest
A configuration file defining a specific customer environment. Used by the deployment scripts to know what to deploy, where, and how.
See [[ESP Manifest]].
## Microlise
The company the team works for. The ESP pipeline project is being done by Microlise engineers to assist ESS.
## Module (PowerShell)
A packaged collection of PowerShell functions, stored in a `.psm1` file. Modules are loaded with `Import-Module`. The Tier 2 and Tier 3 scripts are structured as modules.
# P
## Pester
The standard PowerShell testing framework. Used for writing unit tests for PowerShell functions. Particularly useful for testing Tier 3 functions in isolation.
## Pipeline (AzDO)
An automated workflow defined in YAML that can build, test, and deploy software. Triggered by events (code pushes, schedules, manual runs).
## PowerShell
Microsoft's scripting language and shell, built on .NET. Used for all deployment scripting in this project.
## Prerequisites
The PREREQUISITES deployment stage — checks that the target environment has all required software, configuration, and connectivity before deployment begins.
## `.psm1`
The file extension for a PowerShell module file.
# R
## Remote Session (PowerShell)
A PowerShell remoting session to another machine, created with `New-PSSession`. Allows you to run PowerShell commands on a remote server. Required for managing Windows Services and files on customer servers.
``` powershell
$session = New-PSSession -ComputerName "ROMAC-DEV-APP01"
Invoke-Command -Session $session -ScriptBlock { Get-Service }
```
## ROMAC DEV
The initial target customer environment for the pipeline. ROMAC is the customer name; DEV is the environment tier.
# S
## Schema (Database)
The structure of a SQL Server database — its tables, columns, indexes, constraints, stored procedures, etc. The dacpac encodes the desired schema.
## Self-Hosted Agent
An AzDO agent running on a machine you manage (rather than a Microsoft-managed Azure VM). Required for this project to have network access to customer servers.
## `sqlpackage.exe`
Microsoft's command-line tool for deploying dacpac files to SQL Server.
## Stage (Deployment)
One of the five phases of the ESP deployment: VALIDATE, PREREQUISITES, PREDEPLOY, DEPLOY, POSTDEPLOY. Each can be run independently. See [[ESP Deploy Stages]].
## Stage (AzDO Pipeline)
A high-level grouping within an AzDO YAML pipeline, containing jobs. Not the same as a deployment stage — naming coincidence.
# T
## Team Ludo
The Microlise team that preceded your team on this project. They built the ESP suite in AzDO, started deployment work, and built the dacpac. Now reassigned to paid customer work.
## Tier 1 / 2 / 3
See **Layer / Tier** above and [[ESP Scripts]].
## TMC
Another Microlise product, referenced in the handover as a comparison point for how ESP works (per-customer deployment, multiple environments, etc.).
# W
## Windows Service
A background process that runs on a Windows server, managed by the Windows Service Control Manager. Can be started, stopped, and queried via PowerShell. Six ESP services exist: DLService, EmailService, ExPlService, MISService, OutboundService, ULService.
# Y
## YAML
**YAML Ain't Markup Language**. A human-readable data format used for AzDO pipeline definitions. Stored in the repo as a `.yml` file.

View File

@@ -0,0 +1,161 @@
# Overview
This file documents all known issues, risks, and blockers identified in the handover material. Understanding these early will help you avoid surprises.
# Issue 1 — Database Schema Inconsistency
## What the Problem Is
Existing customer databases have drifted from the official ESP schema. The dacpac built by Team Ludo reflects what the schema **should** be, but what's actually in customer databases doesn't match.
## Impact
- The dacpac **cannot be used** against any customer database until that database is manually aligned
- Deploying a dacpac against a mismatched DB risks data corruption or failures
## What Needs to Happen
For each customer database:
1. A DBA or developer inspects the actual DB schema
2. Identifies differences from the dacpac's expected schema
3. Writes and applies manual scripts to bring the DB into line
4. Verifies a trial dacpac deployment succeeds against a copy
5. Marks the manifest `dacpacReady: true`
## Mitigations in the Pipeline
- The pipeline **must** check the `dacpacReady` flag before touching the database
- If `false`, fail immediately with a clear error message
- See [[ESP Database]] for implementation detail
# Issue 2 — Build Artifact Is a Flat DLL Dump
## What the Problem Is
The ESP Main Build pipeline produces a single large flat folder containing all DLLs for all applications mixed together. There is no clear separation like:
/artifacts/DLService/DLService.dll
/artifacts/EmailService/EmailService.dll
Instead it's more like:
/artifacts/DLService.dll
/artifacts/SomeSharedLibrary.dll
/artifacts/EmailService.dll
/artifacts/AnotherThing.dll
... (hundreds of files)
## Impact
- The PREDEPLOY stage can't simply copy a folder to a service's install path
- Scripts will need to know **which DLLs belong to which application**
- This mapping does not yet exist
## What Needs to Happen
- Investigate the build artifact structure in detail
- Create a mapping: application → list of DLLs/files it needs
- This mapping may need to be stored in the scripts, the manifest, or a separate config file
- Ideally, feed back to the build team to separate the artifacts properly
# Issue 3 — No Test Environment
## What the Problem Is
There is no dedicated sandbox environment to run test deployments against.
Any deployment the team runs is against a **real customer environment**.
## Impact
- Mistakes affect real customers
- You cannot safely iterate and test the pipeline without risk
- Developing and debugging deployment logic is much harder
## What Needs to Happen
- Set up a dedicated ESP test environment (raised as TBC in handover)
- This may require ESS to provision a server, or Microlise to build one
- Until then, exercise **extreme caution** with any deployment run
# Issue 4 — Licensing Prevents Local Execution
## What the Problem Is
ESP cannot be run on developer machines due to licensing restrictions.
## Impact
- You cannot test your deployment scripts against a local ESP instance
- Debugging requires deploying to a real (or test) server
- Makes the development feedback loop longer
## Mitigation
- The three-tier architecture helps here: Tier 3 functions can be unit tested in isolation without a real ESP environment
- Use Pester (PowerShell testing framework) for unit tests
- End-to-end testing requires access to a real environment
# Issue 5 — Cycle Checks Require Citrix UI Navigation
## What the Problem Is
Post-deployment validation ("cycle checks") involves navigating through the Citrix application UI to verify functionality. This is:
- Extensive and time-consuming
- Very hard to automate (requires UI automation tooling like Selenium or Tosca)
- Dependent on Citrix being accessible from the test runner
## Short-Term Mitigation
Implement cycle checks as a manual prompt in the POSTDEPLOY stage — the pipeline pauses and waits for a human to confirm the checks passed.
## Long-Term Options
- Investigate API-level checks if ESP exposes any (bypasses UI entirely)
- UI automation tools (e.g. Ranorex, Tosca, Selenium with Citrix plugin)
- Simplified smoke tests that don't require full UI navigation
# Issue 6 — Citrix Upgrade Mechanism Unknown
## What the Problem Is
The exact technical mechanism for upgrading a Citrix-delivered application is not yet confirmed. The working assumption is that it involves:
- Copying files to the Citrix server
- Handling any locked executable (the running app may lock its own `.exe`)
## What Needs to Happen
- Confirm with ESS or Citrix documentation how Citrix app upgrades work
- Determine if there's a Citrix-native method (e.g. App Layering, PVS updates) vs. a simple file swap
- Understand how to handle sessions that lock the executable
# Issue 7 — Test/Prod on Same Server
## What the Problem Is
Some customers may have their TEST and PROD instances on the same physical server, differentiated only by install path or port.
## Impact
A misconfigured manifest or script bug could cause a PROD deployment when a TEST deployment was intended.
## Mitigations
- The manifest must clearly separate TEST and PROD config even if they share a server
- Consider an explicit confirmation prompt when deploying to PROD
- AzDO approval gates for PROD stages (not yet designed)
- The VALIDATE stage should catch obvious misconfigurations
# Risk Register Summary
| \# | Issue | Severity | Status | Mitigation |
| -- | -------------------------------- | -------- | ----------------- | ------------------------------------- |
| 1 | DB schema inconsistency | High | Unresolved | dacpacReady flag, manual DB fix first |
| 2 | Flat DLL artifact | Medium | Unresolved | Needs DLL-to-app mapping |
| 3 | No test environment | High | TBC | Treat all runs as live |
| 4 | No local execution | Medium | Inherent | Unit test Tier 3 with Pester |
| 5 | Cycle checks need UI | Medium | Manual short-term | Automate later; manual prompt now |
| 6 | Citrix upgrade mechanism unknown | Medium | TBC | Investigate with ESS |
| 7 | Test/Prod on same server | Medium | Design needed | Manifest separation, approval gates |

View File

@@ -0,0 +1,118 @@
# What Is the Manifest?
The manifest is a **configuration file** that describes a specific customer environment. The deployment scripts read the manifest to understand **what** to deploy, **where**, and **how**.
There will be one manifest per customer/environment combination, for example:
- `ROMAC_DEV.json` (or `.yaml`, `.psd1` — format TBC)
- `ROMAC_PROD.json`
- `ACMECORP_DEV.json`
# Why the Manifest Matters
Without a manifest, the scripts would have no way of knowing:
- Which server(s) to connect to
- Which apps this customer actually uses
- What credentials to use
- What version is being deployed
- What environment-specific configuration to apply
It is the **single source of truth** for a deployment. Tier 1 loads it, validates it, and passes it to Tier 2. Tier 2 extracts values from it and passes those to Tier 3.
# Design Status
The manifest **structure has not yet been fully designed**. This is an open work item. See [[ESP OQ]] for a list of design questions to resolve.
What follows is a **proposed structure** based on what the scripts will need.
# Proposed Manifest Structure
``` json
{
"customer": "ROMAC",
"environment": "DEV",
"version": "3.2.1",
"servers": {
"appServer": "ROMAC-DEV-APP01",
"dbServer": "ROMAC-DEV-DB01",
"citrixServer": "ROMAC-DEV-CTX01"
},
"database": {
"name": "EspBroker",
"dacpacReady": false
},
"windowsServices": {
"DLService": { "enabled": true, "installPath": "C:\\ESP\\DLService" },
"EmailService": { "enabled": true, "installPath": "C:\\ESP\\EmailService" },
"ExPlService": { "enabled": false },
"MISService": { "enabled": true, "installPath": "C:\\ESP\\MISService" },
"OutboundService": { "enabled": true, "installPath": "C:\\ESP\\OutboundService" },
"ULService": { "enabled": false }
},
"citrixApps": {
"VPlanner": { "enabled": true, "installPath": "C:\\ESP\\VPlanner" },
"VPlannerAdmin": { "enabled": true, "installPath": "C:\\ESP\\VPlannerAdmin" },
"ImportApp": { "enabled": false }
},
"citrix": {
"notificationMinutes": 15,
"sessionKillGracePeriodMinutes": 5
}
}
```
# Key Fields to Define
| Field | Purpose |
| --------------------------- | ----------------------------------------------------------- |
| `customer` | Identifies the customer |
| `environment` | Identifies the environment (DEV/TEST/PROD) |
| `version` | Version of ESP being deployed |
| `servers.*` | Hostnames/IPs of servers to connect to |
| `database.dacpacReady` | Flag to indicate if DB is in a state for dacpac deployment |
| `windowsServices.*.enabled` | Whether this customer uses this service |
| `citrixApps.*.enabled` | Whether this customer uses this Citrix app |
| `citrix.*` | Citrix-specific config (notification timing, grace periods) |
# Manifest Validation (VALIDATE Stage)
The VALIDATE stage (see [[ESP Deploy Stages]]) loads the manifest and checks it is well-formed before any deployment activity. Things to validate:
- All required fields are present
- Server names are resolvable/pingable
- `version` matches available build artifacts
- `dacpacReady` flag prevents DB deployment if false
- No conflicting settings (e.g. test and prod on same server without flag)
# Manifest Location and Storage
Where manifests should live is TBC, but candidates include:
- A dedicated folder in the AzDO repo (versioned with the scripts)
- A separate config repo
- An external config store (Azure App Configuration, Key Vault, etc.)
Sensitive values (passwords, connection strings) should **never** be in the manifest file in plaintext — they should reference a secret store.
# Per-Customer App Lists
Because not all customers use all apps, the manifest is the mechanism that drives per-customer deployment. Tier 2 scripts iterate over enabled apps:
``` powershell
foreach ($service in $manifest.WindowsServices.GetEnumerator()) {
if ($service.Value.Enabled) {
Stop-WindowsService -ServiceName $service.Key `
-ServerName $manifest.Servers.AppServer
}
}
```
# Environments on the Same Server
The handover document flags that some customers may have TEST and PROD on the same physical server. The manifest must account for this — likely via distinct install paths per environment and explicit environment tagging to prevent accidental cross-environment deployment.

View File

@@ -0,0 +1,171 @@
# Overview
These are items explicitly marked as TBC or not yet designed in the handover material. They represent real blockers or gaps that need to be resolved before the pipeline is complete. Use this file to track answers as they are determined.
# Q1 — What Is the Rollback Plan?
## The Question
If a deployment fails partway through (e.g. the dacpac succeeds but a service won't start), how do we restore the system to its pre-deployment state?
## Why It's Hard
- The database cannot be easily rolled back without a restore from backup
- Files may have been partially swapped
- Citrix sessions may have been killed already
## Things to Consider
- Mandatory pre-deployment backup of database AND application files
- Snapshot-based restore if the server supports it (e.g. VM snapshots)
- A dedicated "rollback" stage that the pipeline can call
- Whether rollback is always manual or can be automated
## Answer (Fill In When Known)
<span class="underline">Not yet determined.</span>
# Q2 — What Is the Test Plan?
## The Question
How will the pipeline and scripts themselves be tested before being used against customer environments?
## Things to Consider
- Unit tests for Tier 3 functions using Pester
- Integration tests against a test environment (once available — see Issue 3)
- Dry-run mode where the pipeline goes through all steps but prompts instead of acting
- Staged rollout: run full pipeline against ROMAC DEV first before any other environment
## Answer (Fill In When Known)
<span class="underline">Not yet determined.</span>
# Q3 — What Is the Final Scope?
## The Question
Will the pipeline eventually cover:
- All customer environments (not just ROMAC DEV)?
- Production environments?
- Environments hosted in ESS's own data centre (not Microlise's)?
## Current Scope
ROMAC DEV only, as an initial target.
## Answer (Fill In When Known)
<span class="underline">Not yet determined — pending business decision.</span>
# Q4 — How Exactly Are Citrix Apps Deployed/Upgraded?
## The Question
What is the technical mechanism for upgrading a Citrix-delivered application?
## Working Assumption
A file copy to the Citrix server, with handling for the running executable being locked by active sessions.
## Things to Investigate
- Does Citrix use App Layering or Provisioning Services (PVS)? If so, the upgrade process is very different from a file copy
- Are there Citrix-native PowerShell cmdlets for managing published apps?
- How are locked executables handled — do sessions need to be fully terminated first, or is there a staging mechanism?
- Who at ESS has this knowledge?
## Answer (Fill In When Known)
<span class="underline">Not yet determined.</span>
# Q5 — What Is the Manifest Structure?
## The Question
What does the manifest config file look like? What format, what fields, where is it stored?
## See Also
[[ESP Manifest]] contains a proposed structure. This needs to be validated against actual deployment requirements and agreed by the team.
## Answer (Fill In When Known)
<span class="underline">Proposed in [ESP — The Manifest](id:9bf19a8b-5581-4be8-9892-913c51df0128) - not yet confirmed.</span>
# Q6 — How Are Build Artifacts Mapped to Applications?
## The Question
Given that the ESP build produces a flat folder of DLLs, how do we determine which DLLs belong to which application?
## Things to Investigate
- Does the build process have any metadata or manifest about what it produced?
- Can the build pipeline be modified to output per-application folders?
- Is there existing documentation from ESS about which files belong where?
- Can we infer the mapping from the existing install directories on ROMAC DEV?
## Answer (Fill In When Known)
<span class="underline">Not yet determined.</span>
# Q7 — Full Detail of Tier 2 & Tier 3 Functions Needed
## The Question
The handover defines the architecture but not the complete list of all Tier 2 logic and Tier 3 functions needed for a full deployment. What is the complete list?
## Approach to Resolve
- Work through each deployment stage manually with a human operator
- Document every step they perform
- Each manual step maps to at least one Tier 3 function
- Aggregate these into a complete function inventory
## Answer (Fill In When Known)
<span class="underline">Ongoing — to be determined through walkthroughs with ESS/ops.</span>
# Q8 — What Are All the Prerequisites?
## The Question
The PREREQUISITES stage is described as checking "an extensive list" of prerequisites, but the full list has not been documented.
## Things to Investigate
- What software must be installed on each server type (app server, DB server, Citrix server)?
- What Windows configuration must be in place?
- What network connectivity is required?
- What service accounts / permissions must exist?
- What environment labels/flags are needed?
## Answer (Fill In When Known)
<span class="underline">Not yet documented.</span>
# Q9 — How Should Secrets Be Managed?
## The Question
The manifest and scripts will need credentials (DB passwords, server credentials, service account passwords). Where do these live and how are they accessed securely?
## Options
- AzDO secret pipeline variables
- Azure Key Vault (referenced by name in manifest, retrieved at runtime)
- Windows Credential Manager on a self-hosted agent
- Encrypted secrets in the repo (not recommended)
## Answer (Fill In When Known)
<span class="underline">Not yet determined.</span>
# Resolved Questions
| \# | Question | Resolved Date | Answer |
| -- | -------------------------------------------------- | ------------- | ------ |
| | <span class="underline">(none resolved yet)</span> | | |

View File

@@ -0,0 +1,150 @@
# What is Azure DevOps (AzDO)?
Azure DevOps is Microsoft's platform for DevOps workflows. It covers:
- **Repos** — Git source code repositories
- **Pipelines** — automated build and deployment (CI/CD)
- **Boards** — work items, epics, features, tasks
- **Artifacts** — storing build outputs (packages, DLLs, etc.)
For this project, the relevant parts are **Pipelines** and **Repos**.
# What is a YAML Pipeline?
AzDO pipelines can be defined in two ways: through a GUI (classic) or via a YAML file stored in the repo. We use **YAML pipelines** — this means the pipeline definition lives in source control alongside the code, making it versioned and auditable.
## Basic YAML Pipeline Structure
``` yaml
trigger:
branches:
include:
- main
pool:
vmImage: 'windows-latest' # or a self-hosted agent
stages:
- stage: Build
jobs:
- job: BuildJob
steps:
- task: PowerShell@2
inputs:
filePath: 'scripts/Invoke-Deployment.ps1'
arguments: '-Customer ROMAC -Environment DEV -Stages PREDEPLOY,DEPLOY'
```
## Key YAML Concepts
| Term | Meaning |
| ---------- | ------------------------------------------------------------------- |
| `trigger` | What causes the pipeline to run (e.g. a push to main) |
| `pool` | The agent (machine) that runs the pipeline |
| `stage` | A high-level grouping of jobs (e.g. Build, Deploy) |
| `job` | A unit of work that runs on one agent |
| `step` | An individual action within a job (run a script, call a task, etc.) |
| `task` | A pre-built step from the AzDO marketplace (e.g. PowerShell@2) |
| `artifact` | Output from one stage/job that can be consumed by another |
# The ESP Pipelines
There are two existing pipelines to be aware of:
## ESS.esp Main Build
- **Purpose:** Builds the ESP applications from source code
- **Output:** Build artifacts (DLLs, binaries)
- **Known Issue:** The artifact does not separate applications cleanly - it produces a large flat folder of DLLs. See [[ESP Known Issues and Risks]]
- **Location:** AzDO → Pipelines → Runs for `ESS.esp Main Build`
## ESS.esp Deploy
- **Purpose:** Deploys ESP to a customer environment
- **Status:** Started by Team Ludo, incomplete
- **Location:** AzDO → Pipelines → Runs for `ESS.esp Deploy`
- This is the primary pipeline your team is responsible for completing
# How the Pipeline Calls Our Scripts
The pipeline's job is relatively thin - it is an **orchestrator** that calls our PowerShell entry point with the correct parameters.
Pipeline (YAML)
└── Calls: Invoke-Deployment.ps1 -Customer ROMAC -Environment DEV -Stages PREDEPLOY,DEPLOY,POSTDEPLOY
└── Tier 1 script (loads manifest, loads modules)
└── Calls Tier 2 scripts (PreDeployment.ps1, Deployment.ps1, etc.)
└── Calls Tier 3 functions (Stop-WindowsService, Invoke-Sql, etc.)
See [[ESP Scripts]] for full detail on the script architecture.
# Pipeline Agents
An **agent** is the machine that actually runs the pipeline. There are two types:
| Type | Description |
| ---------------- | ----------------------------------------------------------- |
| Microsoft-hosted | Azure spins up a fresh VM for each run; ephemeral |
| Self-hosted | A persistent machine you manage; has access to your network |
For deploying to customer VMs (ROMAC DEV), we will almost certainly need a **self-hosted agent** — a Microsoft-hosted agent running in Azure would not have network access to the customer's internal servers.
# Pipeline Variables and Secrets
Pipelines can use variables for configuration. Sensitive values (passwords, connection strings) should be stored as **secret variables** or in **Azure Key Vault**, never hardcoded in the YAML.
``` yaml
variables:
- name: CustomerName
value: ROMAC
- name: DbPassword
value: $(DB_PASSWORD) # references a secret variable set in AzDO UI
```
# Approvals and Gates
For higher environments (PROD), AzDO supports **manual approval gates** between stages — a human must approve before the pipeline continues. This is important when the scope expands beyond DEV.
# Pipeline Run History
Each pipeline run is logged in AzDO with full step-by-step output. This is your primary debugging tool when a deployment fails.
# Relationship to Our PowerShell Scripts
A key design goal is that the PowerShell scripts should be able to run **independently of AzDO** — i.e. you could call `Invoke-Deployment.ps1` directly from a terminal if needed. AzDO is just a convenient trigger and logging wrapper. This means the logic must not be baked into the YAML itself.
# One other note on agents:
Almost certainly ****Virtual Machines (VMs)****. Physical ("bare metal") servers are rarely used in modern infrastructure for this kind of thing. A data centre typically runs a small number of powerful physical machines, and on top of those you run many VMs — each VM behaves like its own independent server but they're all sharing the underlying physical hardware.
So the full picture is probably:
```
Physical machine(s) in ESS Altrincham DC
└── VM: AzDO Self-Hosted Agent
└── VM: App Server (runs the Windows Services, Citrix apps)
└── VM: SQL Server (runs EspBroker database)
... possibly more VMs
```
And the flow when you kick off a deployment in AzDO:
```
You click "Run Pipeline" in AzDO (cloud)
AzDO talks to the self-hosted agent VM in Altrincham
The agent picks up the job and runs the PowerShell scripts
The scripts connect (via PowerShell remoting) to the App Server VM
The scripts connect to the SQL Server VM
Deployment happens
```
The agent itself isn't the thing being deployed **to** — it's just the middleman that has network access to the other VMs in the same DC. Which also ties back to why each customer needs unique credentials — even though they share that infrastructure in DEV, each customer's VMs are in their own domain, so the agent needs the right credentials to authenticate into each one.

View File

@@ -0,0 +1,270 @@
# Overview
The deployment scripts are structured in **three tiers**, loosely analogous to a presentation/domain/data layered architecture in software. This separation exists to:
- Keep ESP-specific knowledge isolated to higher tiers
- Allow Tier 3 functions to be tested in isolation
- Allow the scripts to run independently of AzDO
- Make incremental automation easier (replace manual prompts one function at a time)
# Entry Point — How to Call the Scripts
``` powershell
Invoke-Deployment.ps1 -Customer ROMAC -Environment DEV -Stages PREDEPLOY,DEPLOY,POSTDEPLOY
```
You can pass any combination of stages. For example, to only validate:
``` powershell
Invoke-Deployment.ps1 -Customer ROMAC -Environment DEV -Stages VALIDATE
```
# Tier 1 — Entry Point (Presentation Layer)
## Responsibility
- The **single entry point** to the whole deployment system
- Loads and validates the manifest (see [[ESP Manifest]])
- Loads all required PowerShell modules (Tier 2, Tier 3, helpers)
- Calls the appropriate Tier 2 functions for the requested stages
- Passes the manifest object through to Tier 2
## Key Characteristics
- One script: `Invoke-Deployment.ps1`
- Does NOT contain deployment logic itself
- Acts as a wiring layer only
## Pseudocode
``` powershell
param(
[string]$Customer,
[string]$Environment,
[string[]]$Stages
)
$manifest = Load-Manifest -Customer $Customer -Environment $Environment
Assert-ManifestValid -Manifest $manifest
Import-Module ./Tier2/PreDeployment.psm1
Import-Module ./Tier2/Deployment.psm1
Import-Module ./Tier2/PostDeployment.psm1
Import-Module ./Helpers/Logging.psm1
foreach ($stage in $Stages) {
switch ($stage) {
"PREDEPLOY" { Invoke-PreDeployment -Manifest $manifest }
"DEPLOY" { Invoke-Deployment -Manifest $manifest }
"POSTDEPLOY" { Invoke-PostDeployment -Manifest $manifest }
}
}
```
# Tier 2 — Orchestration Layer (Domain Layer)
## Responsibility
- One script per deployment stage (e.g. `PreDeployment.psm1`, `Deployment.psm1`)
- Contains the **logic and sequencing** of what needs to happen
- Decides **which** Tier 3 functions to call and in what order
- Reacts to return values from Tier 3 (e.g. if a function fails, abort or retry)
## Key Constraints
- **Does NOT** pass the manifest to Tier 3 — all required data is extracted and passed as explicit parameters
- **Does NOT** directly perform any action itself — delegates entirely to Tier 3
- **Does** have knowledge of ESP and what a deployment involves
## Why "Does Not Pass Manifest to Tier 3"?
Tier 3 functions are designed to be generic and reusable. If they accepted a manifest object, they'd need to know about its structure — breaking isolation. Instead, Tier 2 extracts what Tier 3 needs:
``` powershell
# BAD — passes the whole manifest (couples Tier 3 to manifest structure)
Stop-WindowsService -Manifest $manifest
# GOOD — extracts what's needed and passes explicitly
Stop-WindowsService -ServiceName $manifest.Services.DLService.Name `
-ServerName $manifest.Servers.AppServer
```
## Scripts in This Tier
| Script | Stage it covers |
| --------------------- | ------------------- |
| `Validation.psm1` | VALIDATE stage |
| `Prerequisites.psm1` | PREREQUISITES stage |
| `PreDeployment.psm1` | PREDEPLOY stage |
| `Deployment.psm1` | DEPLOY stage |
| `PostDeployment.psm1` | POSTDEPLOY stage |
# Tier 3 — Functional Layer (Workers)
## Responsibility
- Small, **single-purpose** functions
- No knowledge of ESP, the manifest, or deployment context
- Accept all required data as **explicit parameters**
- Can be tested in isolation with mock data
## Key Characteristics
- Examples: `Stop-WindowsService`, `Invoke-SqlScript`, `Copy-Files`, `Get-RemoteSession`, `Send-CitrixNotification`
- Initially implemented as **manual prompt wrappers** — the function prints instructions to a human and waits for confirmation
- Will be replaced with real automation incrementally
## The Manual Prompt Pattern (Current State)
``` powershell
function Stop-WindowsService {
param([string]$ServiceName, [string]$ServerName)
# Current implementation — prompts a human
$response = Invoke-ManualPrompt -Message "Please stop service '$ServiceName' on '$ServerName', then press Enter."
return $response
}
```
## Target Implementation (Automated)
``` powershell
function Stop-WindowsService {
param([string]$ServiceName, [string]$ServerName)
$session = Get-RemoteSession -ServerName $ServerName
Invoke-Command -Session $session -ScriptBlock {
Stop-Service -Name $using:ServiceName -Force
(Get-Service -Name $using:ServiceName).WaitForStatus('Stopped', '00:01:00')
}
}
```
## Exceptions — Functions That Cannot Be Manual Prompts
A small number of Tier 3 functions **must** be implemented for real from the start because they return data the scripts need to function:
| Function | Why it can't be a manual prompt |
| ------------------- | ----------------------------------------------------- |
| `Load-Manifest` | Returns the manifest object — must actually read file |
| `Get-RemoteSession` | Returns a PS session — must actually connect |
| `Read-File` | Returns file contents — must actually read |
# Helper Modules
In addition to the three tiers, **general-purpose helper modules** exist that can be called from anywhere (Tier 1, 2, or 3):
| Module | Purpose |
| -------------- | ------------------------------------------ |
| `Logging.psm1` | Write structured log output |
| `Prompt.psm1` | The manual prompt mechanism used by Tier 3 |
| | |
Helpers follow the same rule as Tier 3: **the manifest is never passed to them**.
# Testing Strategy
Because Tier 3 functions are isolated, they can be unit tested without any connection to a real ESP environment:
``` powershell
# Example Pester test for Stop-WindowsService
Describe "Stop-WindowsService" {
It "calls Invoke-Command with correct service name" {
Mock Invoke-Command {}
Mock Get-RemoteSession { return [PSCustomObject]@{ Session = "MockSession" } }
Stop-WindowsService -ServiceName "DLService" -ServerName "SERVER01"
Assert-MockCalled Invoke-Command -Times 1
}
}
```
# Incremental Automation Plan
The architecture is designed so that automation can be added **one function at a time**, without restructuring anything:
1. Deploy with all Tier 3 functions as manual prompts (guided checklist)
2. Identify the lowest-risk, simplest functions to automate first
3. Replace manual prompts with real implementations one by one
4. Each replacement can be independently tested before deployment
Suggested automation order (rough):
1. `Stop-WindowsService` / `Start-WindowsService` — well-understood, low risk
2. `Copy-Files` — straightforward file operations
3. `Invoke-SqlScript` — once databases are in dacpac-ready state
4. Citrix-related functions — last, most complex
# Architecture Diagram (Text)
AzDO Pipeline (YAML)
└─► Invoke-Deployment.ps1 [TIER 1]
│ Loads manifest
│ Loads all modules
├─► PreDeployment.psm1 [TIER 2]
│ ├─► Copy-Files [TIER 3]
│ └─► ...
├─► Deployment.psm1 [TIER 2]
│ ├─► Stop-WindowsService [TIER 3]
│ ├─► Invoke-SqlScript [TIER 3]
│ ├─► Start-WindowsService [TIER 3]
│ └─► ...
└─► PostDeployment.psm1 [TIER 2]
├─► Get-ServiceStatus [TIER 3]
└─► ...
[Helpers: Logging, Prompt — available at any tier]
## Mermaid Diagram (Text)
``` mermaid
graph TD
%% Tier 1
subgraph "Tier 1 - Entry Point"
A[Invoke-Deployment.ps1]
end
%% Tier 2
subgraph "Tier 2 - Deployment Phases"
B[PreDeployment.psm1]
C[Deployment.psm1]
D[PostDeployment.psm1]
end
%% Tier 3
subgraph "Tier 3 - Actions"
E[Copy-Files]
F[Stop-WindowsService]
G[Invoke-SqlScript]
H[Start-WindowsService]
I[Get-ServiceStatus]
end
%% Helpers
subgraph "Helpers (All Tiers)"
J[Logging Helper]
K[Prompt Helper]
end
%% Relationships
A --> B
A --> C
A --> D
B --> E
C --> F
C --> G
C --> H
D --> I
A --> J
A --> K
```

View File

@@ -0,0 +1,58 @@
# Overview
The ESP Deployment Pipeline project is an effort to automate the deployment of the ESP application suite (built by ESS) into customer environments using Azure DevOps (AzDO) YAML pipelines and PowerShell scripts.
We are the third team to inherit this work. Team Ludo started it, got the build working in AzDO, and began deployment work before being reassigned. We pick up from there.
# Quick Reference - Key Concepts
| Concept | What it is | Notes File |
| --------------- | ---------------------------------------------------- | ------------------------------ |
| ESP | Suite of apps deployed per-customer | [[ESP Applications]] |
| AzDO Pipeline | YAML-based CI/CD pipeline in Azure DevOps | [[ESP Pipeline]] |
| PowerShell Arch | Three-tier script architecture (T1/T2/T3) | [[ESP Scripts]] |
| Manifest | Config file defining a customer environment | [[ESP Manifest]] |
| Dacpac | Packaged SQL Server DB schema deployment | [[ESP Database]] |
| Stages | Validate / Prerequisites / Predeploy / Deploy / Post | [[ESP Deploy Stages]] |
| Known Issues | Pain points, risks, and gaps | [[ESP Known Issues and Risks]] |
| Open Questions | Things still TBC or not yet designed | [[ESP OQ]] |
| Glossary | Terminology reference | [[ESP Glossary]] |
# Context — Why This Project Exists
- Few original ESS engineers remain; those left are on paid customer work
- Manual deployments are slow, risky, and rely on tribal knowledge
- Business goal: *all deployments are consistently repeatable with no manual VM work*
- Initial scope: ROMAC DEV environment only
- Future scope: all environments including PROD and ESS's own data centre
# Team History
| Team | Contribution | Current Status |
| --------- | ------------------------------------------------------- | --------------------------- |
| ESS | Built ESP; wrote original deployment docs | Mostly departed |
| Team Ludo | Full ESP build in AzDO; started deploy pipeline; dacpac | Reassigned to customer work |
| Our Team | Inheriting deploy pipeline work | Active |
# Existing Resources to Review
- Handover from Team Ludo: `ESP_Pipeline_Handover.docx`
- Ludo deployment docs: `DEPLOY.md` (in Repos)
- Ludo deploy scripts: `deploy` folder (in Repos)
- ESP Main Build pipeline: AzDO → Pipelines → `ESS.esp Main Build`
- ESP Deploy Pipeline: AzDO → Pipelines → `ESS.esp Deploy`
# File Index
| File | Contents |
| ------------------------------ | --------------------------------------- |
| [[ESS ESP Index]] | This file — master index |
| [[ESP Applications]] | ESP app suite breakdown |
| [[ESP Pipeline]] | AzDO pipeline structure and concepts |
| [[ESP Scripts]] | Three-tier PowerShell architecture |
| [[ESP Manifest]] | Manifest design and purpose |
| [[ESP Database]] | Database, dacpac, and SQL concerns |
| [[ESP Deploy Stages]] | Stages of deployment — detail per stage |
| [[ESP Known Issues and Risks]] | Known issues and risks |
| [[ESP OQ]] | TBC items and open design questions |
| [[ESP Glossary]] | Glossary of all technical terms |

View File

@@ -0,0 +1,102 @@
Joined team Shackleton on \<2026-04-07 Tue\>, who are now overseeing the deployment process for ESS applications.
[[ESS ESP Index]]
# AI generated overview of ESP
## What's the Big Picture?
Your team is building an **automated deployment pipeline** for a software suite called **ESP** (made by a company called ESS). Right now, deploying ESP to customer environments is done **manually** - someone has to go through a checklist and do things by hand. That's slow, error-prone, and relies on people who are leaving the company. The goal is to automate all of that.
The pipeline will live in **Azure DevOps (AzDO)** - Microsoft's platform for CI/CD (building and deploying software automatically).
## Why Is This Happening Now?
The engineers who originally built and understood ESP have mostly left ESS. The ones who remain are tied up on paid customer work. So this task was handed off to a Microlise team (**Team Ludo**) who got the ball rolling - they got ESP *building* in AzDO and started on deployment. Now Ludo have been pulled onto other work too, and **your team** has inherited it.
So you're the third team to touch this. Expect some rough edges and gaps in knowledge.
## What Is ESP, Exactly?
ESP is a **suite of applications** sold to customers. Think of it like a product bundle - each customer gets the apps they actually need (not every customer gets everything). It's delivered and runs on the customer's environment, which means:
- You're deploying to **their servers**, not yours
- Different customers have different sets of apps installed
- Some customers might have **test and production on the same server** - which is a headache, because you have to be careful not to accidentally deploy to prod when you meant test
The apps in the suite are:
- **One database** - `EspBroker` (SQL Server database)
- **Six Windows Services** - background processes that run on a server (DLService, EmailService, etc.)
- **Three Citrix Applications** - desktop apps delivered via Citrix (VPlanner, VPlannerAdmin, ImportApp). Citrix is a technology that streams apps to users remotely, like a remote desktop but per-app.
## What Is the Pipeline Actually Going to Do?
The pipeline will run **PowerShell scripts** that walk through a deployment in stages. Think of it like a structured checklist that will eventually become fully automated. The stages are:
| Stage | What it does |
| ----------------- | ---------------------------------------------------------------------------- |
| **Validate** | Loads and checks the manifest (config file describing the environment) |
| **Prerequisites** | Checks the target server has everything it needs before you touch it |
| **Predeploy** | Copies the new version's files to the server and configures them |
| **Deploy** | The actual upgrade - stops services, swaps old files for new, starts back up |
| **Postdeploy** | Checks everything came back up healthy |
You can run any combination of these stages, so for example you might just run Validate to check your config is right, without actually deploying anything.
## The Script Architecture (This Is Important)
The scripts are designed in **three tiers**, like a layered cake:
**Tier 1 - The Entry Point** You call one script (e.g. `Invoke-Deployment.ps1`) and tell it the customer, environment, and which stages to run. It loads the manifest, loads all the modules, then hands off to Tier 2.
**Tier 2 - The Orchestrator** One script per stage (PreDeployment, Deployment, etc.). This is the "brain" - it decides *what* needs to happen and in what order, then calls Tier 3 to actually do it. It never does anything directly itself.
**Tier 3 - The Workers** Small, self-contained functions that each do *one thing* - stop a Windows service, run a SQL query, copy a file, etc. They know nothing about ESP specifically. They just take parameters and do the job. This is useful because you can test them in isolation.
**Why this structure matters for you:** Right now, many Tier 3 functions are essentially **placeholders** - instead of actually doing something, they prompt a human to do it manually. The plan is to replace those manual prompts with real automation over time. So initially the pipeline is more of a guided checklist than true automation.
## The Manifest - What Is That?
A manifest is a **config file** that describes a specific customer's environment - which apps they have, what servers they're on, credentials, etc. The idea is that you have one manifest per customer/environment combo (e.g.ROMAC DEV), and the scripts read that to know what to do. The manifest design isn't fully defined yet, which is one of the open items.
## The Dacpac - What's That?
A **dacpac** is a packaged SQL Server database schema. Instead of writing raw SQL migration scripts, you describe what the database *should look like*, and the dacpac tool works out what changes to make to get there. Team Ludo built one for the ESP database.
**The big problem:** The existing customer databases are in an inconsistent state - they've drifted from the official schema over time (probably from manual fixes and patches). Before you can deploy via dacpac, someone will need to manually clean up each database to get it into a consistent state. Until that's done, the database deployment step can't be automated.
## The Known Pain Points You Should Be Aware Of
These are the things most likely to cause your team grief:
1. **Inconsistent databases** - Can't use the dacpac until each customer's DB is manually fixed first. The pipeline needs to detect this and fail gracefully rather than making things worse.
2. **The build artifact is a mess** - The ESP build produces a huge folder of DLLs all jumbled together, rather than neatly separated per application. Your scripts will need to figure out which files belong to which app.
3. **No test environment** - You don't have a safe sandbox to practice deployments on. Any deployment you run is against a real customer environment. This is a significant risk.
4. **Can't run locally** - Licensing restrictions mean you can't run ESP on your own machine to test things. Everything has to happen on the actual servers.
5. **Citrix is complicated** - Deploying the Citrix apps requires notifying users, waiting for them to quit, killing sessions if they don't, and then doing the upgrade. The exact mechanism for the upgrade itself (how do you actually swap the Citrix app?) is still TBC.
6. **Cycle checks** - Post-deployment checks involve navigating through the Citrix UI to verify things work. That's very hard to automate.
## What's Still Not Decided
Several important things are still open:
- **Rollback plan** - If a deployment goes wrong, how do you undo it? Not defined yet.
- **Test plan** - How will you test the pipeline itself?
- **Citrix deployment method** - Believed to be a file copy but not confirmed
- **Manifest structure** - What does the config file actually look like?
- **Full scope** - Will this eventually cover production and ESS's own data centre too?
## What Should You Focus On First?
To provide real value quickly, I'd suggest getting comfortable with:
1. **Azure DevOps YAML pipelines** - understand how they're structured and how they trigger scripts
2. **PowerShell scripting** - the whole deployment mechanism is PowerShell
3. **The existing Ludo work** - look at the existing pipeline runs and deploy scripts linked in the document before writing anything new
4. **The manifest concept** - helping define what that config file looks like is impactful foundational work
5. **The dacpac situation** - understanding which customer databases need manual cleanup before automation can work