| name | ewl-azure-pipelines |
| description | Azure Pipelines CI/CD for EWL systems including build templates, deploy templates, and pipeline code generation |
Overview
EWL generates Azure Pipelines YAML for client systems. The build pipeline is
fully generated. The deploy pipeline uses a generated template with
per-installation pipeline files that have a custom region for hand-maintained
overrides.
File Locations
EWL Repository
Library/Files/Azure Pipeline Templates/Build.yml -- build pipeline template
(contains @@ placeholders replaced by the DU)
Library/Files/Azure Pipeline Templates/Deploy.yml -- deploy job template
(parameters + jobs only; no trigger or resources)
Development Utility/Operations/UpdateDependentLogic.cs -- C# code generator
for per-installation deploy pipeline files and the deploy job template copy
Client System (Generated)
src/Library/Configuration/Azure Build Pipeline.yml -- generated build
pipeline
src/Library/Configuration/Azure Deploy Job.yml -- generated deploy job
template (copy of Deploy.yml with placeholders resolved)
src/Library/Configuration/Installation/Installations/{Name}/Azure Deploy Pipeline.yml
-- per-installation deploy pipeline (generated region + custom region)
Deploy Pipeline Architecture
Each installation gets its own Azure Deploy Pipeline.yml with two regions:
trigger: none
resources:
pipelines:
- pipeline: build
source: Build
trigger:
enabled: true
branches:
include:
- Integration
extends:
template: ../../../Azure Deploy Job.yml
parameters:
installationName: 'Testing'
resourceGroup: 'rg-systemshortname-intermediate'
appService: 'app-systemshortname-testing'
resourceGroupOverride: 'ClientHosting'
appServiceOverride: 'asas-portals'
deploymentSlot: 'testing-new'
Everything above # END-EWL-REGION is regenerated. Everything below is
preserved across DU runs.
Override Pattern
Generated defaults can be overridden in the custom region. Override parameters
have a default of '' in the template. The resolve step in Deploy.yml picks
the override if non-empty, otherwise uses the generated value.
Exceptions:
deploymentSlot has no override -- it is specified directly in the custom
region when needed (default '' means no slot)
serviceConnection has no override -- simple parameter with hardcoded
default of 'Azure'
Critical Constraints
AzureWebApp@1 Deployment Method
The AzureWebApp@1 task's default deployment method (auto) resolves to
Run From Package for Windows web apps. This mounts the zip as a read-only
virtual filesystem and sets WEBSITE_RUN_FROM_PACKAGE=1, making the app's
wwwroot read-only.
Always use deploymentMethod: 'zipDeploy' to extract files to disk
instead. The zipDeploy method also auto-cleans WEBSITE_RUN_FROM_PACKAGE and
WEBSITE_RUN_FROM_ZIP app settings before deploying.
Template Expressions in Resources Blocks
Template expressions (${{ }}) are completely blocked inside the resources
block of an extends template. This means:
trigger on pipeline resources cannot be parameterized from within the
extends template
- The
enabled property under trigger does NOT accept template expressions
- Branch filtering in
trigger.branches.include does NOT accept template
expressions
Therefore, trigger:, resources:, and branch filtering must live in the
per-installation pipeline file (top-level), not in the shared deploy job
template.
Pipeline Resource Trigger Default Branch
Pipeline resource triggers are only evaluated from the default branch of
the deploy pipeline repository. The YAML with trigger config must exist on
that branch (typically master) for auto-triggering to work.
Artifact Download Across Pipelines
DownloadPipelineArtifact@2 with buildType: current only works within the
same pipeline. Since the deploy is a separate pipeline from the build, use:
- task: DownloadPipelineArtifact@2
inputs:
buildType: 'specific'
project: '$(System.TeamProjectId)'
definition: '$(resources.pipeline.build.pipelineID)'
specificBuildWithTriggering: true
Note: resources.pipeline.build.pipelineID is a runtime value -- use
$(...) syntax, not ${{ }} template expressions.
Naming Conventions
- App service names:
app-{systemShortNameSlug}-{installationShortNameSlug}
- Resource groups:
rg-{systemShortNameSlug}-{installationType} where
installationType is prod for Live, intermediate for others
- Slugs are generated using
ToUrlSlug() from Tewl's StringTools
Build Pipeline
The build template is fully generated and includes:
- .NET SDK install
- NuGet restore
- EWL DU dotnet-tool restore
update-data
sync
- Second restore (for generated Directory.Build.props)
export-logic
- Artifact publishing (per Logic Packages subfolder)
Deploy Job Template
The deploy job template (Deploy.yml) contains:
- Parameter resolution (override pattern)
- Download server-side logic artifact
- Download installation configuration artifact
- Stop app (
az webapp stop)
- Build and push the installation container image and update the Container App Job image
- Upload the ISU installation package to blob storage
- Upload logic (
AzureWebApp@1 with zipDeploy)
- Upload the IIS transform via Kudu VFS
- Run data migrator by starting the installation Container App Job and polling for completion
- Start app (
az webapp start)
Kudu VFS Notes
The deploy template still uses the Kudu VFS API to upload
site/applicationHost.xdt after deployment so IIS modules can be removed.