ASP.NET Core - Replace Tokens in Azure Pipelines

Replace Tokens is an extension that can be used in Azure DevOps to replace tokens in the code files with variable values (which can be configured in the Pipelines Library) during the execution of the CI/CD process. In this article, the focus will be on the configuration for the Replace Tokens.

Step 1 - Define tokens.

Define the tokens in appsettings.json file as ‘#{token_name}#’. You can refer below code,

{
  "Logging": {
    "LogLevel": {
      "Default": "Information",
      "Microsoft": "Warning",
      "Microsoft.Hosting.Lifetime": "Information"
    }
  },
  "AllowedHosts": "*",
  "ConnectionStrings": {
    "connection": "#{conString}#",
    "DataSource": "#{DataSourceValue}#",
    "InitialCataloge": "#{InitialCatalogeValue}#",
    "UserId": "#{UserIdValue}#",
    "Password": "#{PasswordValue}#"

  }
}

Step 2 - Set Variables in Azure DevOps

Go to the Azure DevOps portal and define the sets of variables in variable groups. You can give the variable group as per environments.

Navigation : Azure DevOps => Organization Page => Your Project => Pipelines => Library

Keep the Variable's name the same as the name of the tokens defined in appsettings.json. Specify the values in the following input box and save the changes. You can refer below image.

Step 3 - Installing Replace token extension

Go to the marketplace and search for Replace Tokens, or access it by clicking here. Then click on “Get it free,”

Select your organization and click on “Install,”

Then you should see this page,

Now Replace Tokens extension is installed in your Azure DevOps environment. You can check the extensions you have by clicking on “Organization Settings” > “Extensions”:

Step 4 - Replace tokens in Azure Pipelines

The task is driven through the YAML for replacing tokens in Azure pipelines. For that, you can refer to the below YAML code. The given YAML works as follows:

  1. The application will be build
  2. The application will be zipped and published to the pipeline artifacts
  3. The files will be extracted to a folder
  4. The replace tokens task will replace the tokens
  5. The old files will be deleted
  6. The new files (with the new values in the tokens) will be zipped
  7. The new files will be deployed with the new values in the tokens
  8. The application will be deployed to an App Service
trigger:
- master

pool:
  vmImage: ubuntu-latest

variables:
  buildConfiguration: 'Release'
  azureSubscription: 'Put your azure subscrition here'

stages:
  
- stage: Build

  jobs:
  - job: build

    steps:

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

    # Publish
    - task: DotNetCoreCLI@2
      inputs:
        command: publish
        publishWebProjects: True
        arguments: '--configuration $(buildConfiguration) --output $(Build.ArtifactStagingDirectory)'
        zipAfterPublish: True

    # Pack the files and uploads them as an artifact of the build
    - task: PublishPipelineArtifact@1
      inputs:
        targetPath: '$(Build.ArtifactStagingDirectory)'
        artifact: 'replacetokensbackend'
        publishLocation: 'pipeline'

- stage: Development
  displayName: 'Deploy to Development'
  dependsOn: Build
  condition: succeeded()
  variables:
    - group: development

  jobs:
  - deployment: DeploymentDevelopment
    pool:
      vmImage: 'ubuntu-latest'
    environment: Development
    strategy:
      runOnce:
        deploy:
          steps:

          # Replace tokens
          - task: ExtractFiles@1
            inputs:
              archiveFilePatterns: '$(Pipeline.Workspace)/**/*.zip'
              destinationFolder: '$(Pipeline.Workspace)/application'
              cleanDestinationFolder: true
              overwriteExistingFiles: false

          - task: replacetokens@5
            inputs:
              targetFiles: '$(Pipeline.Workspace)/application/appsettings*.json'
              encoding: 'auto'
              tokenPattern: 'default'
              writeBOM: true
              actionOnMissing: 'warn'
              keepToken: false
              actionOnNoFiles: 'continue'
              enableTransforms: false
              enableRecursion: false
              useLegacyPattern: false
              enableTelemetry: true

          - task: DeleteFiles@1
            inputs:
              SourceFolder: '$(Pipeline.Workspace)/drop/'
              Contents: '*.zip'

          - task: ArchiveFiles@2
            inputs:
              rootFolderOrFile: '$(Pipeline.Workspace)/application/'
              includeRootFolder: false
              archiveType: 'zip'
              archiveFile: '$(Pipeline.Workspace)/drop/$(Build.BuildId).zip'
              replaceExistingArchive: true
          - task: AzureWebApp@1
            displayName: 'Deploy App Service'
            inputs:
              azureSubscription: $(azureSubscription)
              appType: 'webApp'
              appName: 'resource_name_here'
              package: '$(Pipeline.Workspace)/drop/*.zip'

After the pipeline triggers, it will sequentially execute the task and the specified tokens will be replaced in the dedicated task.

Conclusion

This way, we can replace the values in appsettings.json with variables defined and stored in Azure DevOps. As a result, we can easily automate the process according to the environment.

Thanks for reading!