diff --git a/devops-pipelines/api-postman-test.yml b/devops-pipelines/api-postman-test.yml index 9ba4f5b40..837c6fc3c 100644 --- a/devops-pipelines/api-postman-test.yml +++ b/devops-pipelines/api-postman-test.yml @@ -1,6 +1,6 @@ schedules: - - cron: "0 5 * * Tue-Sat" - displayName: "Weekday 5am UTC Api Test" + - cron: "0 3 * * Tue-Sat" + displayName: "Weekday 3am UTC Api Test" branches: include: - main diff --git a/devops-pipelines/backend/backend-build-and-deploy.yml b/devops-pipelines/backend/backend-build-and-deploy.yml index 0ba2ccf87..102b22b8c 100644 --- a/devops-pipelines/backend/backend-build-and-deploy.yml +++ b/devops-pipelines/backend/backend-build-and-deploy.yml @@ -25,9 +25,9 @@ variables: - name: buildConfiguration value: "Release" - name: dotNetVersion - value: '10.x' + value: "10.x" - name: efVersion - value: '10.0.*' + value: "10.0.*" - name: asposeLicenceFileName value: "Aspose.Total.NET.lic" @@ -43,7 +43,6 @@ stages: parameters: projectPath: "backend/CPS.ComplexCases.API.HttpTelemetry/CPS.ComplexCases.API.HttpTelemetry.csproj" projectName: "HttpTelemetry" - buildConfiguration: $(buildConfiguration) dotNetVersion: $(dotNetVersion) useLocalNuGet: false publishOutput: false @@ -68,7 +67,7 @@ stages: jobs: - ${{ if or(eq(parameters.deployMainApi, true), eq(parameters.deployDB, true)) }}: - job: Build_Main_API_And_DB - displayName: "Build Main API & DB Migration Scripts" + displayName: "Build Main API / DB Migration Scripts" steps: - ${{ if eq(parameters.deployMainApi, true) }}: - task: DownloadSecureFile@1 @@ -90,11 +89,12 @@ stages: parameters: projectPath: "backend/CPS.ComplexCases.API/CPS.ComplexCases.API.csproj" projectName: "lacc-main-api" - buildConfiguration: $(buildConfiguration) dotNetVersion: $(dotNetVersion) useLocalNuGet: true ${{ if eq(parameters.deployMainApi, true) }}: publishOutput: true + releaseVersionArg: "/p:Version=$(releaseVersion)" + releaseSourceVersionArg: "/p:SourceRevisionId=$(Build.SourceVersion)" ${{ else }}: publishOutput: false runTests: false @@ -130,27 +130,18 @@ stages: parameters: projectPath: "backend/CPS.ComplexCases.FileTransfer.API/CPS.ComplexCases.FileTransfer.API.csproj" projectName: "lacc-filetransfer-api" - buildConfiguration: $(buildConfiguration) dotNetVersion: $(dotNetVersion) useLocalNuGet: true publishOutput: true runTests: false + releaseVersionArg: "/p:Version=$(releaseVersion)" + releaseSourceVersionArg: "/p:SourceRevisionId=$(Build.SourceVersion)" # Deployment stages: - - template: ../templates/backend-deploy-stages.yml - parameters: - environment: dev - requireValidation: false - deployMainApi: ${{ parameters.deployMainApi }} - deployFiletransfer: ${{ parameters.deployFiletransfer }} - deployDB: ${{ parameters.deployDB }} - - template: ../templates/backend-deploy-stages.yml parameters: environment: staging - requireValidation: true - notifyUsers: $(preprodNotifyUsers) - approvers: $(preprodApprovers) + dependsOn: Build_Backend deployToSlot: true slotName: "stg" runPostmanSmokeTest: true @@ -158,19 +149,27 @@ stages: deployFiletransfer: ${{ parameters.deployFiletransfer }} deployDB: ${{ parameters.deployDB }} - - stage: Run_E2E_Tests - displayName: "Run E2E tests" + - stage: Release_Gate + displayName: "Release Gate" jobs: - - template: ../templates/e2e-playwright-test-job.yml - parameters: - environment: staging + - job: Manual_Validation + pool: server + timeoutInMinutes: 6500 + steps: + - task: ManualValidation@1 + displayName: Request Validation + timeoutInMinutes: 6480 + inputs: + notifyUsers: $(prodNotifyUsers) + approvers: $(prodApprovers) + allowApproversToApproveTheirOwnRuns: true + instructions: "Approval is required to deploy to production." + onTimeout: "reject" - template: ../templates/backend-deploy-stages.yml parameters: environment: prod - requireValidation: true - notifyUsers: $(prodNotifyUsers) - approvers: $(prodApprovers) + dependsOn: Release_Gate agentPool: "LACC Prod Pool" azureSubscription: "Azure Pipeline: Large and Complex Cases - Prod" deployToSlot: true diff --git a/devops-pipelines/backend/backend-dev-build-and-deploy.yml b/devops-pipelines/backend/backend-dev-build-and-deploy.yml new file mode 100644 index 000000000..851f1972e --- /dev/null +++ b/devops-pipelines/backend/backend-dev-build-and-deploy.yml @@ -0,0 +1,142 @@ +trigger: + batch: true + branches: + include: + - development + paths: + include: + - backend/* + +parameters: + - name: deployDB + type: boolean + default: true + - name: deployMainApi + type: boolean + default: true + - name: deployFiletransfer + type: boolean + default: true + +pr: none + +variables: + - name: buildConfiguration + value: "Release" + - name: dotNetVersion + value: "10.x" + - name: efVersion + value: "10.0.*" + - name: asposeLicenceFileName + value: "Aspose.Total.NET.lic" + +stages: + - stage: Build_Local_NuGet + displayName: "Pack and Publish NuGet Package" + pool: "LACC PreProd Pool" + jobs: + - job: Package_NuGet + displayName: "Pack and Publish NuGet Package" + steps: + - template: ../templates/dotnet-build-steps.yml + parameters: + projectPath: "backend/CPS.ComplexCases.API.HttpTelemetry/CPS.ComplexCases.API.HttpTelemetry.csproj" + projectName: "HttpTelemetry" + dotNetVersion: $(dotNetVersion) + useLocalNuGet: false + publishOutput: false + runTests: false + + - task: DotNetCoreCLI@2 + displayName: "Pack HttpTelemetry" + inputs: + command: "pack" + packagesToPack: "backend/CPS.ComplexCases.API.HttpTelemetry/CPS.ComplexCases.API.HttpTelemetry.csproj" + outputDir: "$(Build.ArtifactStagingDirectory)" + arguments: "--configuration $(buildConfiguration) --no-build" + + - publish: "$(Build.ArtifactStagingDirectory)" + artifact: "localnuget" + displayName: "Publish HttpTelemetry Package" + + - stage: Build_Backend + displayName: "Generate Build Artifacts for Deployment" + dependsOn: Build_Local_NuGet + pool: "LACC PreProd Pool" + jobs: + - ${{ if or(eq(parameters.deployMainApi, true), eq(parameters.deployDB, true)) }}: + - job: Build_Main_API_And_DB + displayName: "Build Main API / DB Migration Scripts" + steps: + - ${{ if eq(parameters.deployMainApi, true) }}: + - task: DownloadSecureFile@1 + inputs: + secureFile: $(asposeLicenceFileName) + displayName: "Download Aspose Licence File" + + - task: CopyFiles@2 + inputs: + sourceFolder: $(Agent.TempDirectory) + contents: $(asposeLicenceFileName) + targetFolder: "backend/CPS.ComplexCases.API/Licences" + OverWrite: true + displayName: "Copy Aspose Licence File to Project Folder" + + # When buildMainApi=false, the project still needs building + # as the startup project for the database migration script + - template: ../templates/dotnet-build-steps.yml + parameters: + projectPath: "backend/CPS.ComplexCases.API/CPS.ComplexCases.API.csproj" + projectName: "lacc-main-api" + dotNetVersion: $(dotNetVersion) + useLocalNuGet: true + ${{ if eq(parameters.deployMainApi, true) }}: + publishOutput: true + ${{ else }}: + publishOutput: false + runTests: false + + - ${{ if eq(parameters.deployDB, true) }}: + - task: DotNetCoreCLI@2 + displayName: "Build Database Project" + inputs: + command: "build" + projects: "backend/CPS.ComplexCases.Data/CPS.ComplexCases.Data.csproj" + arguments: "--configuration $(buildConfiguration)" + + - task: Bash@3 + displayName: "Generate Migration Scripts" + inputs: + filePath: "$(System.DefaultWorkingDirectory)/devops-pipelines/scripts/generateDBMigrationScripts.sh" + env: + EF_VERSION: $(efVersion) + DATA_PROJECT_PATH: "backend/CPS.ComplexCases.Data/CPS.ComplexCases.Data.csproj" + STARTUP_PROJECT_PATH: "backend/CPS.ComplexCases.API/CPS.ComplexCases.API.csproj" + MIGRATION_SCRIPT_OUT: "database-artifact/migration-script.sql" + ROLLBACK_SCRIPT_OUT: "database-artifact/rollback-migration-script.sql" + + - publish: "database-artifact" + artifact: "database-scripts-drop" + displayName: "Publish Database Scripts" + + - ${{ if eq(parameters.deployFiletransfer, true) }}: + - job: Build_FileTransfer_API + displayName: "Build FileTransfer API" + steps: + - template: ../templates/dotnet-build-steps.yml + parameters: + projectPath: "backend/CPS.ComplexCases.FileTransfer.API/CPS.ComplexCases.FileTransfer.API.csproj" + projectName: "lacc-filetransfer-api" + dotNetVersion: $(dotNetVersion) + useLocalNuGet: true + publishOutput: true + runTests: false + + # Deploy to the dev environment + - template: ../templates/backend-deploy-stages.yml + parameters: + environment: dev + dependsOn: Build_Backend + deployMainApi: ${{ parameters.deployMainApi }} + deployFiletransfer: ${{ parameters.deployFiletransfer }} + deployDB: ${{ parameters.deployDB }} diff --git a/devops-pipelines/backend/backend-pr-build-and-test.yml b/devops-pipelines/backend/backend-pr-build-and-test.yml index 1cbb3fdaa..7a31b6ad5 100644 --- a/devops-pipelines/backend/backend-pr-build-and-test.yml +++ b/devops-pipelines/backend/backend-pr-build-and-test.yml @@ -4,21 +4,11 @@ pr: branches: include: - main + - development paths: include: - backend/* -parameters: - - name: buildDB - type: boolean - default: true - - name: buildMainApi - type: boolean - default: true - - name: buildFiletransfer - type: boolean - default: true - variables: - name: buildConfiguration value: "Release" @@ -42,7 +32,6 @@ stages: parameters: projectPath: "backend/CPS.ComplexCases.API.HttpTelemetry/CPS.ComplexCases.API.HttpTelemetry.csproj" projectName: "HttpTelemetry" - buildConfiguration: $(buildConfiguration) dotNetVersion: $(dotNetVersion) useLocalNuGet: false publishOutput: false @@ -68,7 +57,6 @@ stages: parameters: projectPath: "backend/CPS.ComplexCases.sln" projectName: "Backend Solution" - buildConfiguration: "$(buildConfiguration)" dotNetVersion: $(dotNetVersion) useLocalNuGet: true publishOutput: false diff --git a/devops-pipelines/backend/backend-pr-integration-tests.yml b/devops-pipelines/backend/backend-pr-integration-tests.yml index e23bd5e10..6efbf8b40 100644 --- a/devops-pipelines/backend/backend-pr-integration-tests.yml +++ b/devops-pipelines/backend/backend-pr-integration-tests.yml @@ -3,7 +3,7 @@ trigger: none pr: branches: include: - - main + - development paths: include: - backend/* diff --git a/devops-pipelines/backend/db-rollback.yml b/devops-pipelines/backend/db-rollback.yml index 90f35fd72..f234eed93 100644 --- a/devops-pipelines/backend/db-rollback.yml +++ b/devops-pipelines/backend/db-rollback.yml @@ -7,20 +7,17 @@ parameters: - name: environment displayName: 'Target Environment' type: string - default: 'dev' values: - dev - staging - prod - name: agentPool type: string - default: 'LACC PreProd Pool' values: - 'LACC PreProd Pool' - 'LACC Prod Pool' - name: azureSubscription type: string - default: 'Azure Pipeline: Large and Complex Cases - Pre-Prod' values: - 'Azure Pipeline: Large and Complex Cases - Pre-Prod' - 'Azure Pipeline: Large and Complex Cases - Prod' diff --git a/devops-pipelines/cleanup-testfiles.yml b/devops-pipelines/cleanup-testfiles.yml index 6e25ba228..0aa4cc955 100644 --- a/devops-pipelines/cleanup-testfiles.yml +++ b/devops-pipelines/cleanup-testfiles.yml @@ -1,6 +1,6 @@ schedules: - - cron: "0 3 * * Tue-Sat" - displayName: "Weekday 3am UTC cleanup" + - cron: "0 5 * * Tue-Sat" + displayName: "Weekday 5am UTC cleanup" branches: include: - main diff --git a/devops-pipelines/templates/backend-deploy-stages.yml b/devops-pipelines/templates/backend-deploy-stages.yml index 986072de3..ee5514401 100644 --- a/devops-pipelines/templates/backend-deploy-stages.yml +++ b/devops-pipelines/templates/backend-deploy-stages.yml @@ -13,15 +13,6 @@ parameters: values: - "LACC PreProd Pool" - "LACC Prod Pool" - - name: requireValidation - type: boolean - default: false - - name: notifyUsers - type: string - default: "" - - name: approvers - type: string - default: "" - name: azureSubscription type: string default: "Azure Pipeline: Large and Complex Cases - Pre-Prod" @@ -34,9 +25,9 @@ parameters: - name: runPostmanSmokeTest type: boolean default: false - - name: buildStageName + - name: dependsOn type: string - default: "Build_Backend" + default: "" - name: deployDB type: boolean - name: deployMainApi @@ -45,26 +36,9 @@ parameters: type: boolean stages: - - ${{ if eq(parameters.requireValidation, true) }}: - - stage: Approve_Deployment_${{ parameters.environment }} - displayName: "${{ parameters.environment }} - Approve Deployment" - jobs: - - template: ./manual-validation-jobs.yml - parameters: - instructions: "Please verify the deployment to the lower environment worked as expected before approving deployment to ${{parameters.environment}}." - notifyUsers: ${{ parameters.notifyUsers }} - approvers: ${{ parameters.approvers }} - agentPool: ${{ parameters.agentPool }} - - stage: Deploy_Backend_${{ parameters.environment }} - ${{ if eq(parameters.requireValidation, true) }}: - dependsOn: - - Approve_Deployment_${{ parameters.environment }} - - ${{ parameters.buildStageName }} - ${{ else }}: - dependsOn: - - ${{ parameters.buildStageName }} displayName: "${{ parameters.environment }} - Deploy Backend Services" + dependsOn: ${{ parameters.dependsOn }} variables: - template: ./variables/backend-deploy-vars.yml parameters: diff --git a/devops-pipelines/templates/dotnet-build-steps.yml b/devops-pipelines/templates/dotnet-build-steps.yml index 2ddd92203..306b3507e 100644 --- a/devops-pipelines/templates/dotnet-build-steps.yml +++ b/devops-pipelines/templates/dotnet-build-steps.yml @@ -1,15 +1,46 @@ parameters: - projectPath: "" - projectName: "" - buildConfiguration: "Release" - dotNetVersion: "10.x" - useLocalNuGet: false - nugetArtifact: "localnuget" - nugetArtifactDownloadPath: "$(Build.SourcesDirectory)/localnuget" - publishOutput: false - runTests: false - checkFormatting: false - testResultsDirectory: "" + - name: projectPath + type: string + default: "" + - name: projectName + type: string + default: "" + - name: dotNetVersion + type: string + default: "10.x" + - name: useLocalNuGet + type: boolean + default: false + - name: nugetArtifact + type: string + default: "localnuget" + - name: nugetArtifactDownloadPath + type: string + default: "$(Build.SourcesDirectory)/localnuget" + - name: publishOutput + type: boolean + default: false + - name: runTests + type: boolean + default: false + - name: checkFormatting + type: boolean + default: false + - name: testResultsDirectory + type: string + default: "" + - name: releaseVersionArg + type: string + default: " " + values: + - " " + - "/p:Version=$(releaseVersion)" + - name: releaseSourceVersionArg + type: string + default: " " + values: + - " " + - "/p:SourceRevisionId=$(Build.SourceVersion)" steps: - task: UseDotNet@2 @@ -98,7 +129,11 @@ steps: inputs: command: "build" projects: "${{ parameters.projectPath }}" - arguments: "--configuration ${{ parameters.buildConfiguration }} --no-restore" + arguments: > + --configuration $(buildConfiguration) + --no-restore + ${{ parameters.releaseSourceVersionArg }} + ${{ parameters.releaseVersionArg }} # Run tests if enabled - ${{ if eq(parameters.runTests, true) }}: @@ -108,7 +143,7 @@ steps: command: "test" projects: "${{ parameters.projectPath }}" arguments: > - --configuration ${{ parameters.buildConfiguration }} + --configuration $(buildConfiguration) --no-build --collect "XPlat Code Coverage;Format=cobertura" --settings "$(Build.SourcesDirectory)/backend/CodeCoverage.runsettings" @@ -126,7 +161,7 @@ steps: failIfCoverageEmpty: true condition: succeededOrFailed() - # Publish if enabled + # Publish if enabled, no build or restore as these are already done in previous steps - ${{ if eq(parameters.publishOutput, true) }}: - task: DotNetCoreCLI@2 displayName: "Dotnet Publish ${{ parameters.projectName }}" @@ -135,12 +170,12 @@ steps: projects: "${{ parameters.projectPath }}" publishWebProjects: false arguments: > - --configuration ${{ parameters.buildConfiguration }} + --configuration $(buildConfiguration) --output $(Build.ArtifactStagingDirectory)/${{ parameters.projectName }} --no-restore + --no-build --self-contained false /p:PublishReadyToRun=false - /p:SourceRevisionId=$(Build.SourceVersion) - publish: "$(Build.ArtifactStagingDirectory)/${{ parameters.projectName }}" artifact: "${{ parameters.projectName }}-drop" diff --git a/devops-pipelines/templates/e2e-playwright-test-job.yml b/devops-pipelines/templates/e2e-playwright-test-job.yml index b61cc5d01..d8c4fc0ab 100644 --- a/devops-pipelines/templates/e2e-playwright-test-job.yml +++ b/devops-pipelines/templates/e2e-playwright-test-job.yml @@ -27,8 +27,6 @@ jobs: value: "22.x" - name: workingDir value: "$(System.DefaultWorkingDirectory)/e2e/pw" - - name: transferMaterialsV1 # Staging renders the v1 ("Shared Drive") transfer screen for the E2E user. - value: ${{ ne(parameters.environment, 'dev') }} steps: - task: UseNode@1 @@ -51,7 +49,7 @@ jobs: displayName: "Run E2E Tests" env: CI: true - TRANSFER_MATERIALS_V1: $(transferMaterialsV1) + TRANSFER_MATERIALS_V1: true BASE_URL: $(RedirectUrlLccUi) CMS_LOGIN_PAGE: "$(LccApiBaseUrl)/api/tactical/login" EGRESS_BASE_URL: $(EgressOptionsUrl) diff --git a/devops-pipelines/templates/ui-build-and-deploy-stages.yml b/devops-pipelines/templates/ui-build-and-deploy-stages.yml index b86603805..9ec245367 100644 --- a/devops-pipelines/templates/ui-build-and-deploy-stages.yml +++ b/devops-pipelines/templates/ui-build-and-deploy-stages.yml @@ -13,15 +13,6 @@ parameters: - name: azureSubscription type: string default: "Azure Pipeline: Large and Complex Cases - Pre-Prod" - - name: requireValidation - type: boolean - default: false - - name: notifyUsers - type: string - default: "" - - name: approvers - type: string - default: "" - name: deployToSlot type: boolean default: false @@ -30,21 +21,8 @@ parameters: default: "" stages: - - ${{ if eq(parameters.requireValidation, true) }}: - - stage: Approve_Deployment_${{ parameters.environment }} - displayName: "LACC ${{ parameters.environment }} - Approve Deployment" - jobs: - - template: ./manual-validation-jobs.yml - parameters: - instructions: "Please verify the deployment to the lower environment worked as expected before approving deployment to ${{parameters.environment}}." - notifyUsers: ${{ parameters.notifyUsers }} - approvers: ${{ parameters.approvers }} - agentPool: ${{ parameters.agentPool }} - - stage: Build_Deploy_${{ parameters.environment }} displayName: "${{ parameters.environment }} - Build & Deploy Web App" - ${{ if eq(parameters.requireValidation, true) }}: - dependsOn: Approve_Deployment_${{ parameters.environment }} variables: buildArtifact: "lacc-ui-${{ parameters.environment }}-drop" jobs: diff --git a/devops-pipelines/ui/ui-build-and-deploy.yml b/devops-pipelines/ui/ui-build-and-deploy.yml index 915d4a844..4472fc707 100644 --- a/devops-pipelines/ui/ui-build-and-deploy.yml +++ b/devops-pipelines/ui/ui-build-and-deploy.yml @@ -12,33 +12,32 @@ variables: - group: lacc-deployment-global stages: - - template: ../templates/ui-build-and-deploy-stages.yml - parameters: - environment: dev - requireValidation: false - - template: ../templates/ui-build-and-deploy-stages.yml parameters: environment: staging - requireValidation: true - notifyUsers: $(preprodNotifyUsers) - approvers: $(preprodApprovers) deployToSlot: true slotName: "stg" - - stage: Run_E2E_Tests - displayName: "Run E2E tests" + - stage: Release_Gate + displayName: "Release Gate" jobs: - - template: ../templates/e2e-playwright-test-job.yml - parameters: - environment: staging + - job: Manual_Validation + pool: server + timeoutInMinutes: 6500 + steps: + - task: ManualValidation@1 + displayName: Request Validation + timeoutInMinutes: 6480 + inputs: + notifyUsers: $(prodNotifyUsers) + approvers: $(prodApprovers) + allowApproversToApproveTheirOwnRuns: true + instructions: "Approval is required to deploy to production." + onTimeout: "reject" - template: ../templates/ui-build-and-deploy-stages.yml parameters: environment: prod - requireValidation: true - notifyUsers: $(prodNotifyUsers) - approvers: $(prodApprovers) agentPool: "LACC Prod Pool" azureSubscription: "Azure Pipeline: Large and Complex Cases - Prod" deployToSlot: true diff --git a/devops-pipelines/ui/ui-dev-build-and-deploy.yml b/devops-pipelines/ui/ui-dev-build-and-deploy.yml new file mode 100644 index 000000000..b81645374 --- /dev/null +++ b/devops-pipelines/ui/ui-dev-build-and-deploy.yml @@ -0,0 +1,14 @@ +trigger: + branches: + include: + - development + paths: + include: + - ui-spa/* + +pr: none + +stages: + - template: ../templates/ui-build-and-deploy-stages.yml + parameters: + environment: dev diff --git a/devops-pipelines/ui/ui-pr-build-and-test.yml b/devops-pipelines/ui/ui-pr-build-and-test.yml index fb1f81ab9..fca90c3cc 100644 --- a/devops-pipelines/ui/ui-pr-build-and-test.yml +++ b/devops-pipelines/ui/ui-pr-build-and-test.yml @@ -4,6 +4,7 @@ pr: branches: include: - main + - development paths: include: - ui-spa/*