parameters:
  Artifacts: []
  ArtifactName: 'not-specified'
  ServiceDirectory: not-specified
  TestPipeline: false
  DependsOn:
    - Build
  IntegrationDependsOn:
    - PrePublishBuild

stages:
  - ${{if and(eq(variables['Build.Reason'], 'Manual'), eq(variables['System.TeamProject'], 'internal'))}}:
    - ${{ each artifact in parameters.Artifacts }}:
      - stage: Release_${{ replace(artifact.Name, '-', '_') }}
        displayName: 'Release ${{artifact.name}}'
        dependsOn: ${{ parameters.DependsOn }}
        condition:  and(succeeded(), not(endsWith(variables['Build.Repository.Name'], '-pr')), ne(variables['Skip.AllRelease'], 'true'))

        variables:
          - template: /eng/pipelines/templates/variables/image.yml

        jobs:
          - deployment: ReleaseGate
            displayName: "Release Gate"
            environment: package-publish

            pool:
              name: azsdk-pool
              image: windows-2022
              os: windows

            templateContext:
              type: releaseJob
              isProduction: true

            strategy:
              runOnce:
                deploy:
                  steps:
                    - pwsh: Write-Host 'Release gate succeeded. Dependent jobs will run.'

          - job: TagRepository
            displayName: "Create release tag"
            condition: ne(variables['Skip.TagRepository'], 'true')
            dependsOn:
              - ReleaseGate

            pool:
              name: $(WINDOWSPOOL)
              image: $(WINDOWSVMIMAGE)
              os: windows

            templateContext:
              inputs:
                - input: pipelineArtifact
                  artifactName: packages
                  targetPath: $(Pipeline.Workspace)/packages

            steps:
              - checkout: self
              - template: /eng/common/pipelines/templates/steps/retain-run.yml
              - template: /eng/common/pipelines/templates/steps/set-test-pipeline-version.yml
                parameters:
                  PackageName: ${{ artifact.Name }}
                  ServiceDirectory: ${{ parameters.ServiceDirectory }}
                  TestPipeline: ${{ parameters.TestPipeline }}
              - pwsh: Get-ChildItem -Recurse $(Pipeline.Workspace)/packages/${{artifact.Name}}
                displayName: Output Visible Artifacts
              - task: Powershell@2
                inputs:
                  filePath: $(Build.SourcesDirectory)/eng/common/scripts/Verify-ChangeLog.ps1
                  arguments: >
                    -ChangeLogLocation $(Pipeline.Workspace)/packages/${{artifact.Name}}/CHANGELOG.md
                    -VersionString (Get-Content $(Pipeline.Workspace)/packages/${{artifact.Name}}/package-info.json | ConvertFrom-Json).version
                    -ForRelease $true
                  pwsh: true
                displayName: Verify CHANGELOG.md contents
              - template: /eng/common/pipelines/templates/steps/create-tags-and-git-release.yml
                parameters:
                  ArtifactLocation: "$(Pipeline.Workspace)/packages/${{artifact.Name}}"
                  PackageRepository: CPP
                  ReleaseSha: $(Build.SourceVersion)
                  RepoId: Azure/azure-sdk-for-cpp

          - ${{if ne(artifact.skipPublishDocGithubIo, 'true')}}:
            - job: PublishDocs
              displayName: Publish Docs to GitHub pages
              condition: and(succeeded(), ne(variables['Skip.PublishDocs'], 'true'))
              # Release tag must exist for link substitution to work
              dependsOn:
                - TagRepository
                - ReleaseGate

              pool:
                name: $(WINDOWSPOOL)
                image: $(WINDOWSVMIMAGE)
                os: windows

              templateContext:
                inputs:
                  - input: pipelineArtifact
                    artifactName: docs
                    targetPath: $(Pipeline.Workspace)/docs
                  - input: pipelineArtifact
                    artifactName: packages
                    targetPath: $(Pipeline.Workspace)/packages

              steps:
                - checkout: self
                - pwsh: |
                    Get-ChildItem -Recurse $(Pipeline.Workspace)/docs/${{ artifact.Name }}
                  displayName: Output Visible Artifacts
                - template: ../../../common/pipelines/templates/steps/publish-blobs.yml
                  parameters:
                    FolderForUpload: '$(Pipeline.Workspace)/docs/${{ artifact.Name }}'
                    TargetLanguage: 'cpp'
                    ArtifactLocation: '$(Pipeline.Workspace)/packages/${{artifact.Name}}'

          - ${{ if ne(artifact.skipPublishVcpkg, 'true') }}:
            - job: PublishVcpkg
              displayName: Publish to vcpkg
              condition: and(succeeded(), ne(variables['Skip.PublishVcpkg'], 'true'))
              # This step requires the tag step
              dependsOn:
                - TagRepository
                - ReleaseGate
              pool:
                name: $(WINDOWSPOOL)
                image: $(WINDOWSVMIMAGE)
                os: windows

              variables:
                VcpkgPrRepoOwner: Microsoft
                VcpkgPrRepoName: vcpkg

              templateContext:
                inputs:
                  - input: pipelineArtifact
                    artifactName: packages
                    targetPath: $(Pipeline.Workspace)/packages

              steps:
                - checkout: self
                - pwsh: |
                    $branchName = "azure-sdk-for-cpp-${{ artifact.Name }}-$(Build.BuildId)"
                    if ('$(VcpkgForkBranchName)') {
                      Write-Host "Using queue time branch name"
                      $branchName = '$(VcpkgForkBranchName)'
                    }
                    Write-Host "##vso[task.setvariable variable=PrBranchName]$branchName"
                  displayName: Set fork branch name

                - pwsh: |
                    $packageSpec = Get-Content -Raw -Path "$(Pipeline.Workspace)/packages/${{artifact.Name}}/package-info.json" | ConvertFrom-Json
                    $version = $packageSpec.version
                    Write-Host "##vso[task.setvariable variable=PackageVersion]$version"
                  displayName: Set PackageVersion variable

                - pwsh: |
                    $title = "[${{ artifact.VcpkgPortName }}] publish version $(PackageVersion)"

                    if ('$(VcpkgPRTitle)') {
                      Write-Host "Using queue time PR title"
                      $title = '$(VcpkgPRTitle)'
                    }
                    Write-Host "##vso[task.setvariable variable=PrTitle]$title"
                  displayName: Set PR title

                # There are potential race conditions if this script runs
                # in parallel against the same branch name. Release only
                # one package at a time.
                # Clone main vcpkg repo
                - template: /eng/pipelines/templates/steps/vcpkg-clone.yml
                  parameters:
                    RepoOwner: azure-sdk
                    PRBranchName: $(PrBranchName)

                # Clone Vcpkg Betas
                - template: /eng/pipelines/templates/steps/vcpkg-clone.yml
                  parameters:
                    RepoOwner: Azure
                    RepoName: azure-sdk-vcpkg-betas
                    SetVcpkgRoot: false

                - template: /eng/pipelines/templates/steps/vcpkg-publish.yml
                  parameters:
                    ArtifactName: ${{ artifact.Name }}
                    VcpkgPortName: ${{ artifact.VcpkgPortName }}


                - template: /eng/common/pipelines/templates/steps/set-default-branch.yml
                  parameters:
                    WorkingDirectory: $(Pipeline.Workspace)/azure-sdk-vcpkg-betas

                # Push changes to vcpkg betas
                - template: /eng/common/pipelines/templates/steps/git-push-changes.yml
                  parameters:
                    WorkingDirectory: $(Pipeline.Workspace)/azure-sdk-vcpkg-betas
                    TargetRepoName: azure-sdk-vcpkg-betas
                    BaseRepoOwner: Azure
                    CommitMsg: Update vcpkg-configuration.json
                    BaseRepoBranch: $(DefaultBranch)

                # Set $(HasChanges) to $(PublishToVcpkg) so that
                # create-pull-request.yml creates or does not create a PR
                # based on the deicision of the step that determines
                # whether to publish to vcpkg.
                - pwsh: Write-Host "##vso[task.setvariable variable=HasChanges]$(PublishToVcpkg)"
                  displayName: Set $(HasChanges) to $(PublishToVcpkg) for create-pull-request.yml

                - template: /eng/common/pipelines/templates/steps/set-default-branch.yml
                  parameters:
                    WorkingDirectory: $(Pipeline.Workspace)/vcpkg

                # SkipCheckingForChanges is true to skip the commit step
                # (which is already done by Update-VcpkgPort.ps1)
                - template: /eng/common/pipelines/templates/steps/create-pull-request.yml
                  parameters:
                    RepoOwner: $(VcpkgPrRepoOwner)
                    RepoName: $(VcpkgPrRepoName)
                    WorkingDirectory: $(Pipeline.Workspace)/vcpkg
                    PrBranchName: $(PrBranchName)
                    PRTitle: $(PrTitle)
                    PRBody: Update vcpkg ports for Azure SDK release. This release may contain multiple ports.
                    SkipCheckingForChanges: true
                    BaseBranchName: $(DefaultBranch)
                    OpenAsDraft: ${{ parameters.TestPipeline }}
                    CloseAfterOpenForTesting: '${{ parameters.TestPipeline }}'

                - task: AzureCLI@2
                  displayName: Authenticate to OpenSource API
                  condition: and(succeeded(), eq(variables['PublishToVcpkg'], 'true'))
                  inputs:
                    azureSubscription: opensource-api-connection
                    scriptType: pscore
                    scriptLocation: inlineScript
                    inlineScript: |
                      $jwt_accessToken = az account get-access-token --resource "api://2789159d-8d8b-4d13-b90b-ca29c1707afd" --query "accessToken" --output tsv
                      Write-Host "##vso[task.setvariable variable=opensource-api-token;isSecret=true]$jwt_accessToken"

                # Workaround: -Fallback uses names from CODEOWNERS who
                # should be notified about the release in the event of a
                # failure to resolve the appropriate aliases.
                - pwsh: |
                    $notifyUsers = ./eng/scripts/Get-TriggeringUserGitHubAlias.ps1 `
                      -EmailAddress "$($env:BUILD_REQUESTEDFOREMAIL)" `
                      -OpenApiToken "$(opensource-api-token)" `
                      -Fallback '@rickwinter @antkmsft @LarryOsterman'

                    $prComment = "Adding ${{ artifact.Name }} to release"
                    if ($notifyUsers) {
                      $prComment += "`n`ncc: $notifyUsers"
                    }

                    ./eng/common/scripts/Add-IssueComment.ps1 `
                      -AuthToken "$(azuresdk-github-pat)" `
                      -RepoOwner $(VcpkgPrRepoOwner) `
                      -RepoName $(VcpkgPrRepoName) `
                      -IssueNumber "$(Submitted.PullRequest.Number)" `
                      -Comment $prComment
                  condition: and(succeeded(), eq(variables['PublishToVcpkg'], 'true'))
                  displayName: Comment notification to PR

          - ${{if ne(artifact.skipUpdatePackageVersion, 'true')}}:
            - job: UpdatePackageVersion
              displayName: "Update Package Version"
              condition: and(succeeded(), ne(variables['Skip.UpdatePackageVersion'], 'true'))
              dependsOn: ReleaseGate

              pool:
                name: $(WINDOWSPOOL)
                image: $(WINDOWSVMIMAGE)
                os: windows

              steps:
                - checkout: self
                - pwsh: |
                    eng/scripts/Update-PkgVersion.ps1 -ServiceDirectory '${{parameters.ServiceDirectory}}' -PackageName '${{artifact.name}}'
                  displayName: Increment package version
                - template: ../../../common/pipelines/templates/steps/create-pull-request.yml
                  parameters:
                    RepoName: azure-sdk-for-cpp
                    PRBranchName: increment-package-version-${{ parameters.ServiceDirectory }}-$(Build.BuildId)
                    CommitMsg: "Increment package version after release of ${{ artifact.name }}"
                    PRTitle: "Increment version for ${{ parameters.ServiceDirectory }} releases"
                    CloseAfterOpenForTesting: '${{ parameters.TestPipeline }}'

  - ${{if eq(variables['System.TeamProject'], 'internal') }}:
    - stage: Integration
      dependsOn: ${{ parameters.IntegrationDependsOn }}
      condition: >-
        and(
          succeededOrFailed(),
          or(
            eq(variables['PublishDailyVcpkg'], 'true'),
            eq(variables['Build.Reason'],'Schedule')
          )
        )
      variables:
        - template: /eng/pipelines/templates/variables/globals.yml
        - template: /eng/pipelines/templates/variables/image.yml

      jobs:
        - job: PublishDailyVcpkg
          displayName: Publish to vcpkg daily branch

          pool:
            name: $(WINDOWSPOOL)
            image: $(WINDOWSVMIMAGE)
            os: windows

          steps:
            - checkout: self

            - download: current
              artifact: packages

            - template: /eng/pipelines/templates/steps/generate-daily-branch-name.yml

            - template: /eng/pipelines/templates/steps/vcpkg-clone.yml
              parameters:
                RepoOwner: azure-sdk
                PRBranchName: $(DailyBranchName)

            # Placing artifacts in the same branch in sequence reduces the
            # potential for race conditions. If this job does fail to push
            # because another job has already pushed to the same branch it
            # can be re-run.
            - ${{ each artifact in parameters.Artifacts }}:
              # Only run vcpkg publish if the artifact has a "VcpkgPortName"
              # property. Absence of VcpkgPortName implies that the artifact
              # does not ship to vcpkg.
              - ${{ if ne(artifact.VcpkgPortName, '') }}:
                - template: /eng/pipelines/templates/steps/vcpkg-publish.yml
                  parameters:
                    ArtifactName: ${{ artifact.Name }}
                    VcpkgPortName: ${{ artifact.VcpkgPortName }}
                    DisplayNameExtension: ${{ artifact.Name }}
                    DailyRelease: true
                    DailyReleaseRef: $(Build.SourceVersion)
                    UpdateVcpkgBeta: false

            - template: /eng/common/pipelines/templates/steps/git-push-changes.yml
              parameters:
                BaseRepoBranch: $(DailyBranchName)
                CommitMsg: Daily vcpkg ports for ${{ parameters.ServiceDirectory }}
                TargetRepoOwner: azure-sdk
                TargetRepoName: vcpkg
                WorkingDirectory: $(Pipeline.Workspace)/vcpkg
                ScriptDirectory: $(System.DefaultWorkingDirectory)/eng/common/scripts
