Na podstawie FiscalPrinterApi-pipeline.yml utwórz FiscalPrinterApi-stage.yml oraz FiscalPrinterApi-production.yml. Zrób to analogicznie jak w przypadku build-production.yml oraz build-stage.yml, gdzie base.yml jest użyte jako base template.

/// FiscalPrinterApi-pipeline.yml

trigger:
  paths:
    include:
      - src-others/PosnetAPI/**
      - src-others/PosnetAPI.Test/**
      - azure/docker/fiscal-printer-api/**

pr:
  paths:
    include:
      - src-others/PosnetAPI/**
      - src-others/PosnetAPI.Test/**
      - azure/docker/fiscal-printer-api/**

variables:
  buildConfiguration: 'Release'
  shouldPublishBuild: 'true'
  shouldPublishDocker: 'true'

stages:
  - stage: Build
    displayName: Build Stage
    jobs:
      - job: Build
        displayName: Build FiscalPrinterApi
        steps:
          - checkout: self
            lfs: false
            fetchDepth: 1
            fetchTags: false

          - task: UseDotNet@2
            inputs:
              packageType: 'sdk'
              version: '6.x'
              installationPath: $(Agent.ToolsDirectory)/dotnet

          - task: DotNetCoreCLI@2
            displayName: 'Restore Dependencies'
            inputs:
              command: 'restore'
              projects: |
                src-others/PosnetAPI/FiscalPrinterApi.csproj
                src-others/PosnetAPI.Test/PosnetAPI.Test.csproj

          - task: DotNetCoreCLI@2
            displayName: 'Build FiscalPrinterApi'
            inputs:
              command: 'build'
              projects: 'src-others/PosnetAPI/FiscalPrinterApi.csproj'
              arguments: '--configuration $(buildConfiguration) /clp:ErrorsOnly'

          - task: DotNetCoreCLI@2
            displayName: 'Publish FiscalPrinterApi'
            inputs:
              command: 'publish'
              projects: 'src-others/PosnetAPI/FiscalPrinterApi.csproj'
              arguments: '--configuration $(buildConfiguration) --output $(Build.ArtifactStagingDirectory)/FiscalPrinterApi --property WarningLevel=1 /clp:ErrorsOnly'

          - publish: $(Build.ArtifactStagingDirectory)/FiscalPrinterApi
            artifact: FiscalPrinterApi

  - stage: Test
    displayName: Test Stage
    dependsOn: Build
    jobs:
      - job: Test
        displayName: Test PosnetAPI.Test
        steps:
          - checkout: self

          - task: UseDotNet@2
            inputs:
              packageType: 'sdk'
              version: '6.x'
              installationPath: $(Agent.ToolsDirectory)/dotnet

          - task: DotNetCoreCLI@2
            displayName: 'Restore Test Dependencies'
            inputs:
              command: 'restore'
              projects: 'src-others/PosnetAPI.Test/PosnetAPI.Test.csproj'

          - task: DotNetCoreCLI@2
            displayName: 'Run Tests'
            inputs:
              command: 'test'
              projects: 'src-others/PosnetAPI.Test/PosnetAPI.Test.csproj'
              arguments: '--configuration $(buildConfiguration) --logger "console;verbosity=detailed" /clp:ErrorsOnly'

          - task: PublishTestResults@2
            displayName: 'Publish Test Results'
            inputs:
              testResultsFormat: 'JUnit'
              testResultsFiles: '**/TEST-*.xml'
              failTaskOnFailedTests: true

  - stage: Publish
    displayName: Publish Stage
    dependsOn: Test
    jobs:
      - job: PublishDocker
        displayName: Build and Push Docker Image
        steps:
          - checkout: self

          - task: Docker@2
            displayName: 'Build and push an image to container registry'
            inputs:
              command: buildAndPush
              containerRegistry: "d9c165d7-11b1-48eb-892b-9704cc3af295"
              repository: "fiscal-printer-api"
              Dockerfile: "azure/docker/fiscal-printer-api/dockerfile"
              buildContext: "$(Build.SourcesDirectory)"
              tags: |
                $(Build.BuildId)
                latest
            condition: and(succeeded(), eq(variables['shouldPublishBuild'], 'true'), eq(variables['shouldPublishDocker'], 'true'))

          - script: |
              echo "##vso[build.addbuildtag]$(Build.BuildId)"
              echo "##vso[build.addbuildtag]latest"
            displayName: 'Add Build Tags'
            condition: succeeded()
			
/// base.yml

arameters:
  - name: shouldPublishBuild
    displayName: Should publish build
    type: boolean
    default: false

  - name: shouldRunTests
    displayName: Should run tests
    type: boolean
    default: false

  - name: shouldGenerateCoverage
    displayName: Should generate coverage
    type: boolean
    default: false

  - name: shouldGenerateMigrationBundle
    displayName: Should generate migration bundle
    type: boolean
    default: false

  - name: shouldPublishArtifacts
    displayName: Should publish artifacts
    type: boolean
    default: false

  - name: shouldPublishDocker
    displayName: Should publish docker
    type: boolean
    default: false

steps:
  - checkout: self
    lfs: false
    fetchDepth: 1
    fetchTags: false

  - task: UseDotNet@2
    inputs:
      version: "6.x"

  - task: DotNetCoreCLI@2
    displayName: dotnet build
    inputs:
      command: build
      projects: "src/Medica.Web.Host/Medica.Web.Host.csproj"
      arguments: "--configuration $(BuildConfiguration) /clp:ErrorsOnly"

  - task: DotNetCoreCLI@2
    displayName: dotnet publish
    inputs:
      command: publish
      projects: "src/Medica.Web.Host/Medica.Web.Host.csproj"
      arguments: "--configuration $(BuildConfiguration) --output $(Build.ArtifactStagingDirectory)/backend --property WarningLevel=1 /clp:ErrorsOnly"
      zipAfterPublish: true
      modifyOutputPath: false
      publishWebProjects: false
    condition: and(succeeded(), or(eq(${{ parameters.shouldPublishBuild }}, true), eq(${{ parameters.shouldPublishDocker }}, true)))

  - task: PublishBuildArtifacts@1
    displayName: publish artifact
    inputs:
      PathtoPublish: "$(Build.ArtifactStagingDirectory)/backend"
      ArtifactName: "backend"
    condition: and(succeeded(), eq(${{ parameters.shouldPublishBuild }}, true), eq(${{ parameters.shouldPublishArtifacts }}, true))

  - task: DotNetCoreCLI@2
    displayName: "dotnet test"
    inputs:
      command: "test"
      projects: "Medica.Unit.Tests/Medica.Unit.Tests.csproj"
      arguments: '--configuration $(buildConfiguration) --logger "console;verbosity=detailed" --filter "TestCategory!=IgnoreAzure" --settings:"code-coverage.runsettings" /clp:ErrorsOnly'
      publishTestResults: true
    condition: and(succeeded(), eq(${{ parameters.shouldRunTests }}, true))

  - task: reportgenerator@5
    displayName: reportgenerator
    inputs:
      reports: "$(Agent.TempDirectory)/**/*.cobertura.xml"
      targetdir: "coveragereport"
      reporttypes: "HtmlInline_AzurePipelines_Dark;Cobertura"
      publishCodeCoverageResults: true
    condition: and(succeeded(), eq(${{ parameters.shouldRunTests }}, true), eq(${{ parameters.shouldGenerateCoverage }}, true))

  - task: DotNetCoreCLI@2
    displayName: install dotnet-ef
    inputs:
      command: "custom"
      custom: "tool"
      arguments: "install --global dotnet-ef --version 6.*"
    condition: and(succeeded(), eq(${{ parameters.shouldGenerateMigrationBundle }}, true))

  - task: DotNetCoreCLI@2
    displayName: dotnet tool restore
    inputs:
      command: "custom"
      custom: "tool"
      arguments: "restore"
    condition: and(succeeded(), eq(${{ parameters.shouldGenerateMigrationBundle }}, true))

  - task: DotNetCoreCLI@2
    displayName: dotnet-ef version
    inputs:
      command: "custom"
      custom: "ef"
      arguments: "--version"
    condition: and(succeeded(), eq(${{ parameters.shouldGenerateMigrationBundle }}, true))

  - task: DotNetCoreCLI@2
    displayName: migrations bundle
    inputs:
      command: custom
      custom: "ef "
      arguments: 'migrations bundle --configuration $(buildConfiguration) --target-runtime linux-x64 --context $(dbContext) --force --project "src/Medica.EntityFrameworkCore/Medica.EntityFrameworkCore.csproj" -o $(Build.ArtifactStagingDirectory)/efbundle'
    condition: and(succeeded(), eq(${{ parameters.shouldGenerateMigrationBundle }}, true))

  - task: PublishBuildArtifacts@1
    displayName: publish artifact
    inputs:
      PathtoPublish: "$(Build.ArtifactStagingDirectory)/efbundle"
      ArtifactName: "migration"
    condition: and(succeeded(), eq(${{ parameters.shouldGenerateMigrationBundle }}, true), eq(${{ parameters.shouldPublishArtifacts }}, true))

  - task: CopyFiles@2
    inputs:
      SourceFolder: azure/docker/portal-backend
      Contents: "portal-backend.sh"
      TargetFolder: $(Build.ArtifactStagingDirectory)
    condition: and(succeeded(), eq(${{ parameters.shouldPublishBuild }}, true), eq(${{ parameters.shouldPublishDocker }}, true))

  - script: |
      unzip $(Build.ArtifactStagingDirectory)/backend/backend.zip -d $(Build.ArtifactStagingDirectory)/backend
      rm -f $(Build.ArtifactStagingDirectory)/backend/appsetting*.json
      rm -f $(Build.ArtifactStagingDirectory)/backend/backend.zip
      echo "`ls -la $(Build.ArtifactStagingDirectory)/backend`"
    displayName: "Prepare backend files for docker"
    condition: and(succeeded(), eq(${{ parameters.shouldPublishBuild }}, true), eq(${{ parameters.shouldPublishDocker }}, true))

  - task: Docker@2
    displayName: Build and push an image to container registry
    inputs:
      command: buildAndPush
      containerRegistry: "d9c165d7-11b1-48eb-892b-9704cc3af295"
      repository: "portal-backend"
      Dockerfile: "azure/docker/portal-backend/portal-backend.dockerfile"
      buildContext: $(Build.ArtifactStagingDirectory)
      tags: |
        $(Build.BuildId)
        $(Build.SourceBranchName)
    condition: and(succeeded(), eq(${{ parameters.shouldPublishBuild }}, true), eq(${{ parameters.shouldPublishDocker }}, true))

  - script: |
      echo "##vso[build.addbuildtag]$(Build.BuildId)"
      echo "##vso[build.addbuildtag]$(Build.SourceBranchName)"
    condition: succeeded()
	
/// build-production.yml

trigger:
  branches:
    include:
      - master

variables:
  buildConfiguration: "Release"
  dbContext: "MedicaDbContext"

stages:
  - stage: BuildProduction
    displayName: "Build Production"
    jobs:
      - job: BuildProduction
        displayName: "Build Production"
        pool:
          vmImage: "ubuntu-latest"
        steps:
          - template: base.yml
            parameters:
              shouldPublishBuild: true
              shouldRunTests: false
              shouldGenerateCoverage: false
              shouldGenerateMigrationBundle: true
              shouldPublishArtifacts: true # TODO change when using new production server
              shouldPublishDocker: false # TODO change when using new production server
  # - stage: DeployProduction
  #   displayName: "Deploy Production"
  #   dependsOn: BuildProduction
  #   # TODO remove when using new production server
  #   condition: and(succeeded(), ne(variables['Build.SourceBranch'], 'refs/heads/master'))
  #   jobs:
  #     - deployment: Production
  #       displayName: "Deploy Production"
  #       environment:
  #         name: Production
  #         resourceName: Production
  #       strategy:
  #         runOnce:
  #           deploy:
  #             steps:
  #               - script: |
  #                   pipe_input="/azp/portal-named-pipes/update-input"
  #                   pipe_output="/azp/portal-named-pipes/update-output"
  #                   new_version="$(Build.BuildId)"

  #                   echo "Starting portal updater"
  #                   echo "/PORTAL_START_UPDATE $new_version" >$pipe_input

  #                   while true; do
  #                       if read -u 3 cmd; then
  #                           echo "$cmd"

  #                           if [ "$cmd" == "/PORTAL_DEPLOY_SUCCEDED" ]; then
  #                               echo "Deployment succeeded"
  #                               exit 0
  #                           elif [ "$cmd" == "/PORTAL_DEPLOY_FAILED" ]; then
  #                               echo "Deployment failed"
  #                               exit 1
  #                           else
  #                               sleep 0.05
  #                           fi
  #                       fi
  #                   done 3<"$pipe_output" 4>"$pipe_output" # 4 is just to keep the pipe opened so any real client does not end up causing read to return EOF
  #                 displayName: "Portal backend deploy"
  #                 condition: succeeded()
  
  /// build-stage.yml
  
  trigger:
  branches:
    include:
      - develop

variables:
  buildConfiguration: "Release"
  dbContext: "MedicaDbContext"

stages:
  - stage: BuildStage
    displayName: "Build Stage"
    jobs:
      - job: BuildStage
        displayName: "Build Stage"
        pool:
          vmImage: "ubuntu-latest"
        steps:
          - template: base.yml
            parameters:
              shouldPublishBuild: true
              shouldRunTests: false
              shouldGenerateCoverage: false
              shouldGenerateMigrationBundle: true
              shouldPublishArtifacts: false
              shouldPublishDocker: true
  - stage: DeployStage
    displayName: "Deploy Stage"
    dependsOn: BuildStage
    condition: succeeded()
    jobs:
      - deployment: Stage
        displayName: "Deploy Stage"
        environment:
          name: Stage
          resourceName: Stage
        strategy:
          runOnce:
            deploy:
              steps:
                - script: |
                    pipe_input="/azp/portal-named-pipes/update-input"
                    pipe_output="/azp/portal-named-pipes/update-output"
                    new_version="$(Build.BuildId)"

                    echo "Starting portal updater"
                    echo "/PORTAL_START_UPDATE $new_version" >$pipe_input

                    while true; do
                        if read -u 3 cmd; then
                            echo "$cmd"

                            if [ "$cmd" == "/PORTAL_DEPLOY_SUCCEDED" ]; then
                                echo "Deployment succeeded"
                                exit 0
                            elif [ "$cmd" == "/PORTAL_DEPLOY_FAILED" ]; then
                                echo "Deployment failed"
                                exit 1
                            else
                                sleep 0.05
                            fi
                        fi
                    done 3<"$pipe_output" 4>"$pipe_output" # 4 is just to keep the pipe opened so any real client does not end up causing read to return EOF
                  displayName: "Portal backend deploy"
                  condition: succeeded()