Search code examples
azure-devopsazure-deploymentazure-devops-pipelines

How to create a deployment to an IIS server out of sight from DevOps Release pipeline


I have searched around for a while, but not been able to find a good way to create a "installation bundle" for web service to run on IIS.

My problem is that we need to manually copy files to the on premises servers due to security, and thus not allowed to automate this job. But as far as I can see all the IIS Deployment templates uses Deployment group to distribute the releases to registered servers.

Is there a way to create a Release pipeline for IIS that produce a zip file/artifact that can be downloaded manually from DevOps or from a drop folder instead?

I have made one Release pipeline using tasks CopyFiles@2, FileTransform@1 and UniversalPackages@0 to copy the build artifact, transform the appsettings.json file and publish the package, but this does not add the nesessary files for IIS, such as the web.config file.

Thanx for any responses :-)

This is the build pipeline yml file:

trigger:
- release*

pool:
  vmImage: 'windows-latest'

variables:
  solution: '**/*.sln'
  buildPlatform: 'Any CPU'
  buildConfiguration: 'Release'

steps:
- task: DotNetCoreCLI@2
  displayName: 'dotnet build'
  inputs:
    command: build
    projects: '**/*.sln'
    configuration: '$(buildConfiguration)'

- task: DotNetCoreCLI@2
  displayName: 'dotnet test'
  inputs:
    command: test
    projects: '**/*Tests.csproj'
    arguments: '--configuration $(buildConfiguration) --no-restore --collect "Code coverage"'
    testRunTitle: 'Unit and Integrtion Tests'

- task: DotNetCoreCLI@2
  displayName: 'dotnet publish'
  inputs:
    command: publish
    publishWebProjects: true
    arguments: '--configuration $(buildConfiguration) --output $(build.artifactStagingDirectory)'
    zipAfterPublish: true

- task: PublishPipelineArtifact@1
  displayName: 'publish pipeline artifact'
  inputs:
    targetPath: '$(build.artifactStagingDirectory)'
    artifactName: 'WebAPI'

And the Release pipeline: Release pipeline


Solution

  • After som twists and turns I ended up with this solution, using a template yml file for Dev and Release.

    If anyone have any suggestions for improvments, please comment below. Hope this can be of help :-)

    Pipelines:

    azure-pipelines-build-template.yml:

    variables:
      buildPlatform: 'Any CPU'
      buildConfiguration: 'Release'
      artifactPath: '$(build.artifactStagingDirectory)'
    
    steps:
    - task: DotNetCoreCLI@2
      displayName: 'dotnet build solution'
      inputs:
        command: build
        projects: '**/*.sln'
        configuration: '$(buildConfiguration)'
    
    - task: DotNetCoreCLI@2
      displayName: 'dotnet test solution'
      inputs:
        command: test
        projects: '**/*Tests.csproj'
        arguments: '--configuration $(buildConfiguration) --no-restore'
        testRunTitle: 'Unit and Integrtion Tests'
    
    - task: DotNetCoreCLI@2
      displayName: 'dotnet publish to pipeline'
      inputs:
        command: publish
        publishWebProjects: true
        arguments: '--configuration $(buildConfiguration) --output $(artifactPath)'
        zipAfterPublish: true
    
    - task: PublishPipelineArtifact@1
      displayName: 'publish pipeline artifact Flyttavle'
      inputs:
        targetPath: '$(artifactPath)'
        artifactName: 'WebAPI'
    

    azure-pipelines-dev-build.yml:

    trigger:
    - dev
    
    pool:
      vmImage: 'windows-latest'
    
    extends:
      template: azure-pipelines-build-template.yml
    

    azure-pipelines-release-build.yml:

    trigger:
    - release*
    
    pool:
      vmImage: 'windows-latest'
    
    extends:
      template: azure-pipelines-build-template.yml
    

    Releases:

    I have created 4 releases, Azure_Dev_Deploy and Azure_Release_Deploy which deploys to Azure, and On_Prem_Prod_Deploy and On_Prem_Test_Deploy that creates packages to download for on premise deployment.

    Dev_Deploy and Release_Deploy:

    Difference here are:

    • Trigger is set up for changes respectively on dev and release branches
    • Deployment points to the app service in Azure for respectively dev and release app services
    • Variables points to Variable groups respectively for dev and release variable substitutions (defined in Library)

    Release Pipeline and Tasks for Dev_Deploy and Release_Deploy (same setup for both, but picture shows the Dev deployment)

    And the yaml view of the task:

    Deploy Azure App Service:

    steps:
    - task: AzureRmWebAppDeployment@4
      displayName: 'Deploy Azure App Service'
      inputs:
        azureSubscription: '$(Parameters.ConnectedServiceName)'
        appType: '$(Parameters.WebAppKind)'
        WebAppName: '$(Parameters.WebAppName)'
        packageForLinux: '$(System.DefaultWorkingDirectory)/_BEDevBuild/WebAPI.zip'
        JSONFiles: '**/appsettings*.json'
    

    On_Prem_Test_Deploy and On_Prem_Prod_Deploy:

    Difference here are:

    • Creates Artifacts respectively for on-prem-test and on-prem-prod
    • Variables points to Variable groups respectively for on-prem-test and on-prem-prod variable substitutions (defined in Library)

    Release Pipeline and Tasks for On_Prem_Test_Deploy and On_Prem_Prod_Deploy (same setup for both, but picture shows the Test deployment)

    And the yaml view of the tasks:

    File Transform:

    steps:
    - task: FileTransform@1
      displayName: 'File Transform: on-prem/prod'
      inputs:
        folderPath: '$(System.ArtifactsDirectory)/_BEReleaseBuild/*.zip'
        fileType: json
        targetFiles: '**/appsettings*.json'
    

    Universal publish:

    steps:
    - task: UniversalPackages@0
      displayName: 'Universal publish'
      inputs:
        command: publish
        publishDirectory: '$(System.ArtifactsDirectory)/_BEReleaseBuild'
        vstsFeedPublish: '********-****-****-****-************/********-****-****-****-************'
        vstsFeedPackagePublish: 'on-prem-prod'
        packagePublishDescription: 'Package for on premise production'
    

    Download Artifacts:

    Then to download the artifacts in the Artifacts feed, I use the following statement from Powershell locally.

    PS! As for today it is not possible to download from a REST call for the universal package which ruined my grand plan of creating a download link in the Wiki, but hopefully this will be supported in the future.

    on-prem-test:

    az artifacts universal download --organization "https://dev.azure.com/[my org name]/" --project "[DevOps project id]" --scope project --feed "on-premise" --name "on-prem-test" --version "*" --path .
    

    on-prem-prod:

    az artifacts universal download --organization "https://dev.azure.com/[my org name]/" --project "[DevOps project id]" --scope project --feed "on-premise" --name "on-prem-prod" --version "*" --path .
    

    Tip on parameters:

    • --version "*" will allways get latest version in the feed for the given package name
    • --path . downloads the package to where you execute the command in Powershell