Production Blueprint · Real-world pipeline
From commit to production: .NET 8 + Angular 20 on Azure Windows VMs
A working dev-to-production setup, end to end: GitHub, Jenkins, SonarQube, Nexus and Jira on the delivery side, Ansible AWX deploying to IIS on Windows VMs across five environments.
The platform
Who talks to whom. Click any tool to open its guide.
Build once, deploy many
Only the dev job builds. Every higher environment deploys the exact package that dev already published to Nexus, after a Jira approval.
Dev
builds + deploys
SIT
deploys only
UAT
deploys only
Stage
deploys only
Prod
deploys only
Whether the jobs share one scalable template or each environment has its own branch and Jenkins job, the rule is the same: the dev job builds, and every higher job starts at deployment.
Inside the pipeline
Pick an environment to see which Jenkins stages actually run there, then a stage for the detail. Dev runs nine stages; every higher environment runs five.
Triggered by a commit to the dev branch. Builds, tests, scans, publishes to Nexus and deploys to dev.
Preload
Get the job ready before touching any code.
- Load the environment parameters and credentials from Jenkins.
- Confirm the .NET 8 SDK and the Node toolchain are available on the agent.
- Start from a clean workspace.
What AWX does on the VM
The API and the UI each have their own deployment playbook, in the order they run. The same playbooks serve every environment; only the target VM and its variables change.
Backs up the running release first, and only stops the app pool once the new package is downloaded and extracted, so the API is down for the shortest possible window.
Check connectivity
Confirm AWX can reach the Windows VM over WinRM before anything is changed.
- Fails when
- The VM is stopped or deallocated, a network rule blocks WinRM, or the credentials are wrong or expired.
- Check first
- VM state in the Azure portal, then network security rules and the WinRM connection from AWX.
Get root folder for backup
Work out where backups live for this application and environment.
- Fails when
- The backup path variable is missing or wrong for this environment.
- Check first
- The environment's variables in the AWX inventory.
Create backup folder if it does not exist
Create the backup folder on first use.
- Fails when
- The deploy account can't create folders at the backup path.
- Check first
- The backup path and its permissions.
Copy deployment folder to backup folder
Save the currently deployed release aside before anything is replaced.
- Fails when
- The disk is full, or files in the deployment folder are locked.
- Check first
- Free disk space on the backup drive.
Create deployment folder
Create the deployment folder if it doesn't exist yet, so a brand-new VM works on its first deploy.
- Fails when
- The deploy account can't create folders at that path.
- Check first
- The folder path variable for this environment, and the deploy account's permissions.
Create temp folder
Create a temporary working folder for this release's download and extraction.
- Fails when
- The disk is full or the deploy account lacks permission.
- Check first
- Free disk space and folder permissions.
Clean content from AWX folder
Empty the AWX working folder so leftovers from an earlier run can't be mistaken for this release.
- Fails when
- Files from a previous run are locked or the account lacks permission to delete them.
- Check first
- What is still in the folder and which process holds it.
Download from Nexus
Fetch the exact package version being deployed from the Nexus repository.
- Fails when
- The version doesn't exist, Nexus is unreachable, or the download credentials lack permission.
- Check first
- Is that exact version listed in Nexus? Can the VM reach Nexus?
Unzip
Extract the downloaded package.
- Fails when
- The download was incomplete or corrupt, or the disk is full.
- Check first
- Does the downloaded archive open by hand? Free disk space.
Stop app pool
Stop the API's app pool so IIS releases every file in the deployment folder. From here until the pool restarts, the API is down.
- Fails when
- The pool hangs while stopping, or the worker process won't exit.
- Check first
- IIS Manager and the w3wp process for that pool.
Clean content from deployment folder
Remove the previous release's files so old and new files never mix.
- Fails when
- A file is still locked, or the deploy account lacks permission.
- Check first
- What holds the file, and the folder permissions.
Copy to deployment folder
Put the new release's files into the deployment folder.
- Fails when
- The disk is full or permissions are wrong. The pool is already stopped, so restore from the backup if it can't be fixed quickly.
- Check first
- Free disk space, permissions, and the backup made at the start of the run.
Start app pool
Start the app pool so IIS loads the new build.
- Fails when
- The pool won't come back up, often a runtime, module or configuration problem in the new build.
- Check first
- Event Viewer's Application log for ASP.NET Core Module and .NET runtime errors.
Write success entry to application event log
Record in the Windows Application log that the deployment finished, leaving an audit trail in Event Viewer.
- Fails when
- The event source isn't registered, or the account can't write to the log.
- Check first
- That the event source exists on the VM and the deploy account's rights.
Why each tool sits where it does
GitHub
Source of truthEvery change starts as a commit. A webhook on the dev branch is what starts the pipeline, so no one has to remember to run a build.
Read the guide →Jenkins
OrchestratorRuns the full build job in dev and the lighter promotion jobs elsewhere, and hands every deployment to AWX. It coordinates; it doesn't hold the server credentials.
Read the guide →SonarQube
Quality gateTurns 'is this code good enough?' into a pass/fail that stops the pipeline, instead of a review comment that gets ignored.
Read the guide →Nexus
Artifact storeHolds every build as an immutable, versioned package. This is what makes 'build once, deploy many' possible.
Read the guide →Jira
Approval gateA recorded approval is what triggers promotion to the next environment, so every production change has an audit trail.
Ansible AWX
Deployment engineRuns the API and UI playbooks against the servers with centrally managed credentials, role-based access and a job history. The same playbooks serve all five environments.
Read the guide →Azure Windows VM
Runtime hostOne VM per environment running Windows and IIS. AWX reaches it over WinRM.
Read the guide →IIS
Web serverHosts the .NET 8 API in its own app pool and serves the Angular 20 build as a site. Event Viewer and the IIS logs are where you look when something breaks.
Read the guide →Where the pipeline itself can fail
The secret scan or quality gate fails
The build job stops before Nexus. Nothing was published and nothing was deployed. Remove the secret or fix the flagged issues, then push again.
The package can't be downloaded
The playbook fails at the download step, before the app pool is stopped or the deployment folder is touched. The running release is unharmed. Check the version in Nexus.
The API fails after the pool is stopped
This is the risky window: the API is down until the pool restarts. The backup taken at the start of the playbook is what you restore from, or you redeploy the previous Nexus version.
The interview talk track
"Walk me through how code gets from a commit to production." About two minutes, out loud.
Our code lives in GitHub. A merge to the dev branch fires a webhook and Jenkins runs the full build job: it preloads the environment, checks out the code, runs a secret scan, then builds and unit-tests the .NET 8 API or the Angular 20 UI and sends it through SonarQube. If the secret scan, a test or the quality gate fails, the pipeline stops there.
If it passes, Jenkins publishes one versioned package to Nexus and asks Ansible AWX to run the deployment playbook. For the API, that means checking connectivity, backing up the current release, downloading and unzipping the package, stopping the app pool, replacing the files, starting the pool again and writing a success entry to the Windows Application log. The UI playbook is the same idea without the app pool: download, unzip, clean, copy.
To move up we don't rebuild. Someone approves the promotion in Jira, which triggers the next environment's Jenkins job. It preloads, works out which application and which approved version it's deploying, runs the same playbook against that environment's VM, then runs the tests and the post tasks. The same package goes through SIT, UAT, Stage and Prod, so what we tested is what ships.
What I'd improve next
Knowing the gaps in a setup is what separates a senior answer from a description of the tools.
Automate the rollback
The API playbook already backs up the current release. A matching restore playbook (or 'run the job with the previous Nexus version') turns a manual scramble into one click.
A health check after the pool starts
The success entry in the event log proves the playbook finished, not that the API works. A call to a health endpoint proves the release is actually serving.
Give the UI playbook a backup step too
The API playbook saves the running release before replacing it; the UI playbook doesn't. The same three backup steps would make a bad UI release just as recoverable.
Prune old backups
Every deploy adds a copy of the previous release. Without a retention rule, backups quietly eat the disk until a deploy fails at the backup step.
Blue/green releases on IIS
Deploy to a second site or VM, verify it, then switch traffic, so the API is never down while the pool restarts.
Want to work through the tools behind this?
Create a free account to track the roadmap, practise the interview questions and read the tool guides.