parameters:
  - name: DependsOn
    type: object
  - name: ServiceDirectory
    type: string
  - name: SDKType
    type: string
  - name: Artifacts
    type: object
    default: []
  - name: TestPipeline
    type: boolean
    default: false
  - name: ArtifactName
    type: string
    default: 'not-specified'
  - name: TargetDocRepoName
    type: string
    default: ''
  - name: EnableIntegrationStage
    type: boolean
    default: true
  - name: UseEsrpRelease
    type: boolean

stages:
  # The signing stage is responsible for submitting binaries to ESRP for our official signing
  # where appropriate and also meeting any other signing requirements for particular artifacts,
  # in this case we do GPG signing in order to publish to Maven Central. At the moment signing
  # is protected by an approval check but this may be removed in the future.
  - stage: Signing
    dependsOn: ${{parameters.DependsOn}}
    jobs:
      - deployment: SignPackage
        environment: esrp
        timeoutInMinutes: 20
        variables:
          - template: /eng/pipelines/templates/variables/globals.yml
        pool:
          name: azsdk-pool-mms-ubuntu-2004-general
          vmImage: MMSUbuntu20.04
        strategy:
          runOnce:
            deploy:
              steps:
                - checkout: none

                - download: current
                  displayName: 'Download Artifact: ${{parameters.ArtifactName}}'
                  artifact: ${{parameters.ArtifactName}}

                - template: tools/java-esrp-signing/java-esrp-signing.yml@azure-sdk-build-tools
                  parameters:
                    Artifacts: ${{parameters.Artifacts}}
                    ArtifactDirectory: $(Pipeline.Workspace)/${{parameters.ArtifactName}}

                - publish: $(Pipeline.Workspace)/${{parameters.ArtifactName}}
                  artifact: ${{parameters.ArtifactName}}-signed
                  displayName: 'Store signed packages in ${{parameters.ArtifactName}}-signed artifact'

  # We generate two interdependent stages for each artifact listed in the ci.yml file, creates the release
  # in GitHub. The Release stage publishes to Maven Central. Both stages require approval since they
  # effectively burn the version number. For testing of packages prior to burning the version number -
  # the Validation step below publishes a package to a "burner" feed which is cleaned up after the
  # pipeline completes.
  - ${{if and(in(variables['Build.Reason'], 'Manual', ''), eq(variables['System.TeamProject'], 'internal'))}}:
    - ${{ each artifact in parameters.Artifacts }}:
      - stage:
        displayName: 'Release: ${{artifact.name}}'
        dependsOn: Signing
        condition: and(succeeded(), ne(variables['SetDevVersion'], 'true'), ne(variables['Skip.Release'], 'true'), ne(variables['Build.Repository.Name'], 'Azure/azure-sdk-for-java-pr'))
        jobs:
          - job: VerifyReleaseVersion
            displayName: "Verify release version"
            condition: ne(variables['Skip.VersionVerification'], 'true')
            variables:
              - template: /eng/pipelines/templates/variables/globals.yml
            pool:
              name: azsdk-pool-mms-ubuntu-2004-general
              vmImage: MMSUbuntu20.04

            steps:
              - template: /eng/common/pipelines/templates/steps/sparse-checkout.yml
                parameters:
                  Paths:
                    - '${{ parameters.ServiceDirectory }}'
                    - '**/*.xml'
                    - '!sdk/**/test-recordings'
                    - '!sdk/**/session-records'

              - task: UsePythonVersion@0
                displayName: 'Use Python $(PythonVersion)'
                inputs:
                  versionSpec: $(PythonVersion)

              - template: /eng/common/pipelines/templates/steps/set-test-pipeline-version.yml
                parameters:
                  PackageNames: "azure-sdk-template,azure-sdk-template-two,azure-sdk-template-three"
                  ServiceDirectory: "template"
                  TestPipeline: ${{ parameters.TestPipeline }}

              - script: |
                  python --version
                  python eng/versioning/set_versions.py --build-type ${{parameters.SDKType}} --vv --ai ${{artifact.name}} --gi ${{artifact.groupId}}
                displayName: 'Verify version for release'

              - pwsh: |
                  $(Build.SourcesDirectory)/eng/versioning/scan_for_unreleased_dependencies.ps1 ${{artifact.groupId}} ${{artifact.name}} $(Build.SourcesDirectory)/sdk/${{parameters.ServiceDirectory}}
                displayName: "Verify no unreleased dependencies"
                # Uber JARs release a flattened POM, as dependencies are incorporated into the JAR circumnavigating the
                # need to list dependencies in the POM. The flattened POM is generated and won't comply with our
                # versioning validation, so skip it.
                condition: and(succeeded(), ne('${{ artifact.uberJar }}', 'true'))

              - ${{if and(ne(parameters.SDKType, 'data'), ne(artifact.skipVerifyChangelog, 'true'))}}:
                - template: /eng/common/pipelines/templates/steps/verify-changelog.yml
                  parameters:
                    PackageName: ${{artifact.name}}
                    ServiceName: ${{parameters.ServiceDirectory}}
                    ForRelease: true

              # Only check compilation if this isn't an uber JAR release.
              # Uber JARs are self-contained and a compilation failure during creating it would have prevented its creation.
              - ${{ if ne(artifact.uberJar, 'true') }}:
                - template: /eng/pipelines/templates/steps/compilation.check.yml
                  parameters:
                    Artifact: ${{ artifact }}
                    ArtifactName: ${{ parameters.ArtifactName }}
                    ArtifactDirectory: "$(Pipeline.Workspace)/${{parameters.ArtifactName}}-signed/${{artifact.groupId}}/${{artifact.name}}"

          - deployment: TagRepository
            displayName: "Create release tag"
            condition: and(succeeded(), ne(variables['Skip.TagRepository'], 'true'))
            environment: maven
            dependsOn: VerifyReleaseVersion
            variables:
              - template: /eng/pipelines/templates/variables/globals.yml
            pool:
              name: azsdk-pool-mms-win-2022-general
              vmImage: windows-2022
            strategy:
              runOnce:
                deploy:
                  steps:
                    - download: current
                      displayName: 'Download Artifact: ${{parameters.ArtifactName}}-signed'
                      artifact: ${{parameters.ArtifactName}}-signed
                      patterns: ${{artifact.groupId}}/${{artifact.name}}/**
                    - template: /eng/common/pipelines/templates/steps/sparse-checkout.yml
                    - template: /eng/common/pipelines/templates/steps/retain-run.yml
                    - template: /eng/common/pipelines/templates/steps/create-tags-and-git-release.yml
                      parameters:
                        ArtifactLocation: $(Pipeline.Workspace)/${{parameters.ArtifactName}}-signed/${{artifact.groupId}}/${{artifact.name}}
                        PackageRepository: Maven
                        ReleaseSha: $(Build.SourceVersion)

          - ${{if ne(artifact.skipPublishPackage, 'true')}}:
            - deployment: PublishPackage
              displayName: "Publish to Maven Central"
              condition: and(succeeded(), ne(variables['Skip.PublishPackage'], 'true'))
              environment: maven
              dependsOn: TagRepository
              variables:
                - template: /eng/pipelines/templates/variables/globals.yml
              pool:
                name: azsdk-pool-mms-win-2022-general
                vmImage: windows-2022
              strategy:
                runOnce:
                  deploy:
                    steps:
                      - download: current
                        displayName: Download Artifacts
                        artifact: ${{parameters.ArtifactName}}-signed
                        patterns: ${{artifact.groupId}}/${{artifact.name}}/**
                      - checkout: azure-sdk-build-tools
                        path: azure-sdk-build-tools
                      - template: /eng/common/pipelines/templates/steps/sparse-checkout.yml
                        parameters:
                          SkipCheckoutNone: true
                          Repositories:
                            - Name: Azure/azure-sdk-for-java
                              Commitish: $(Build.SourceVersion)
                              WorkingDirectory: $(Pipeline.Workspace)/azure-sdk-for-java
                      - template: tools/gpg/gpg.yml@azure-sdk-build-tools
                      - ${{ if eq(parameters.UseEsrpRelease, 'true') }}:
                        - template: /eng/pipelines/templates/steps/java-publishing.yml
                          parameters:
                            ArtifactID: ${{artifact.name}}
                            GroupID: ${{artifact.groupId}}
                            ArtifactDirectory: $(Pipeline.Workspace)/${{parameters.ArtifactName}}-signed
                            OutputDirectory: $(Pipeline.Workspace)/EsrpPackages
                            Target: EsrpRelease
                            BuildToolsPath: $(Pipeline.Workspace)/azure-sdk-build-tools
                            JavaRepoRoot: $(Pipeline.Workspace)/azure-sdk-for-java
                        - template: /eng/common/pipelines/templates/steps/publish-artifact.yml
                          parameters:
                            ArtifactName: ${{parameters.ArtifactName}}-${{artifact.name}}-esrp-$(System.JobAttempt)
                            ArtifactPath: $(Pipeline.Workspace)/EsrpPackages
                      - ${{ else }}:
                        - template: /eng/pipelines/templates/steps/java-publishing.yml
                          parameters:
                            ArtifactID: ${{artifact.name}}
                            GroupID: ${{artifact.groupId}}
                            ArtifactDirectory: $(Pipeline.Workspace)/${{parameters.ArtifactName}}-signed
                            Target: MavenCentral
                            BuildToolsPath: $(Pipeline.Workspace)/azure-sdk-build-tools
                            JavaRepoRoot: $(Pipeline.Workspace)/azure-sdk-for-java
                        - template: /eng/common/pipelines/templates/steps/publish-artifact.yml
                          parameters:
                            ArtifactName: ${{parameters.ArtifactName}}-${{artifact.name}}-mavencentral-$(System.JobAttempt)
                            ArtifactPath: $(Pipeline.Workspace)/${{parameters.ArtifactName}}-signed
                      # After publishing to Maven, publish to the azure-sdk-for-java feed. The reason for
                      # this is that the azure-sdk-for-java feed will have the package available immediately
                      # whereas Maven can take several hours for the package to become available.
                      - template: /eng/pipelines/templates/steps/java-publishing.yml
                        parameters:
                          ArtifactID: ${{artifact.name}}
                          GroupID: ${{artifact.groupId}}
                          ArtifactDirectory: $(Pipeline.Workspace)/${{parameters.ArtifactName}}-signed
                          RepositoryUrl: https://pkgs.dev.azure.com/azure-sdk/public/_packaging/azure-sdk-for-java/maven/v1
                          Target: JavaDevFeed
                          BuildToolsPath: $(Pipeline.Workspace)/azure-sdk-build-tools
                          JavaRepoRoot: $(Pipeline.Workspace)/azure-sdk-for-java
                      - template: /eng/common/pipelines/templates/steps/publish-artifact.yml
                        parameters:
                          ArtifactName: ${{parameters.ArtifactName}}-${{artifact.name}}-javadevfeed-$(System.JobAttempt)
                          ArtifactPath: $(Pipeline.Workspace)/${{parameters.ArtifactName}}-signed

          - ${{if ne(artifact.skipPublishDocMs, 'true')}}:
            - deployment: PublishDocsMs
              displayName: Docs.MS Release
              condition: and(succeeded(), ne(variables['Skip.PublishDocs'], 'true'))
              environment: maven
              dependsOn: PublishPackage

              pool:
                name: azsdk-pool-mms-ubuntu-2004-general
                vmImage: MMSUbuntu20.04

              variables:
                - template: /eng/pipelines/templates/variables/globals.yml
                - name: DocValidationImageId
                  value: azuresdkimages.azurecr.io/javarefautocr:latest

              strategy:
                runOnce:
                  deploy:
                    steps:
                      - template: /eng/common/pipelines/templates/steps/sparse-checkout.yml
                        parameters:
                          Paths:
                            - sdk
                            - common/perf-test-core
                            - .github/CODEOWNERS
                            - '!sdk/**/test-recordings'
                            - '!sdk/**/session-records'
                      - download: current
                        displayName: 'Download Artifact: ${{parameters.ArtifactName}}'
                        artifact: ${{parameters.ArtifactName}}
                      # Pull and build the docker image.
                      - template: /eng/common/pipelines/templates/steps/update-docsms-metadata.yml
                        parameters:
                          PackageInfoLocations:
                            - $(Pipeline.Workspace)/${{parameters.ArtifactName}}/PackageInfo/${{artifact.name}}.json
                          WorkingDirectory: $(System.DefaultWorkingDirectory)
                          TargetDocRepoOwner: 'Azure'
                          TargetDocRepoName: ${{parameters.TargetDocRepoName}}
                          Language: 'java'
                          SparseCheckoutPaths:
                            - docs-ref-services/
                            - metadata/
                          DocValidationImageId: "$(DocValidationImageId)"
                      - template: /eng/pipelines/templates/steps/fetch-package-list.yml
                        parameters:
                          JavaDocJarLocation: "$(Pipeline.Workspace)/${{parameters.ArtifactName}}/${{artifact.groupId}}/${{artifact.name}}"
                          ArtifactName: ${{artifact.name}}
                          TargetBranch: $(TargetBranchName)
                          DocRepoLocation: $(DocRepoLocation)
                          TargetDocRepoName: ${{parameters.TargetDocRepoName}}
                          TargetDocRepoOwner: "Azure"

          - ${{if ne(artifact.skipPublishDocGithubIo, 'true')}}:
            - deployment: PublishDocs
              displayName: Publish Docs to GitHubIO Blob Storage
              condition: and(succeeded(), ne(variables['Skip.PublishDocs'], 'true'))
              environment: maven
              dependsOn: PublishPackage
              variables:
                - template: /eng/pipelines/templates/variables/globals.yml
              pool:
                name: azsdk-pool-mms-win-2022-general
                vmImage: windows-2022
              strategy:
                runOnce:
                  deploy:
                    steps:
                      - template: /eng/common/pipelines/templates/steps/sparse-checkout.yml
                      - download: current
                        displayName: 'Download Artifact: ${{parameters.ArtifactName}}-signed'
                        artifact: ${{parameters.ArtifactName}}-signed
                        patterns: ${{artifact.groupId}}/${{artifact.name}}/**
                      - pwsh: |
                          Get-ChildItem -Recurse $(Pipeline.Workspace)/${{parameters.ArtifactName}}-signed/${{artifact.groupId}}/${{artifact.name}}
                        workingDirectory: $(Pipeline.Workspace)
                        displayName: Output Visible Artifacts
                      - template: /eng/common/pipelines/templates/steps/publish-blobs.yml
                        parameters:
                          FolderForUpload: '$(Pipeline.Workspace)/${{parameters.ArtifactName}}-signed/${{artifact.groupId}}/${{artifact.name}}'
                          BlobSASKey: '$(azure-sdk-docs-prod-sas)'
                          BlobName: '$(azure-sdk-docs-prod-blob-name)'
                          TargetLanguage: 'java'
                          ArtifactLocation: $(Pipeline.Workspace)/${{parameters.ArtifactName}}-signed/${{artifact.groupId}}/${{artifact.name}}
                          # we override the regular script path because we have cloned the build tools repo as a separate artifact.
                          ScriptPath: 'eng/common/scripts/copy-docs-to-blobstorage.ps1'

          - ${{if ne(artifact.skipUpdatePackageVersion, 'true')}}:
            - deployment: UpdatePackageVersion
              displayName: "Update Package Version"
              condition: and(succeeded(), ne(variables['Skip.UpdatePackageVersion'], 'true'))
              environment: maven
              dependsOn: PublishPackage
              variables:
                - template: /eng/pipelines/templates/variables/globals.yml
              pool:
                name: azsdk-pool-mms-win-2022-general
                vmImage: windows-2022
              strategy:
                runOnce:
                  deploy:
                    steps:
                      - download: none

                      - template: /eng/common/pipelines/templates/steps/sparse-checkout.yml
                        parameters:
                          Paths:
                            - '${{ parameters.ServiceDirectory }}'
                            - '**/*.xml'
                            - '!sdk/**/test-recordings'
                            - '!sdk/**/session-records'

                      - task: UsePythonVersion@0
                        displayName: 'Use Python $(PythonVersion)'
                        inputs:
                          versionSpec: $(PythonVersion)

                      - script: |
                          python --version
                          python eng/versioning/set_versions.py --build-type ${{ parameters.SDKType }} --increment-version --ai ${{ artifact.name }} --gi ${{ artifact.groupId }}
                        displayName: Increment package version for ${{ artifact.groupId }} ${{ artifact.name }}

                      - script: |
                          python --version
                          python eng/versioning/update_versions.py --update-type library --build-type ${{ parameters.SDKType }} --avi --sr
                        displayName: Update pom files for new version of ${{ artifact.groupId }} ${{ artifact.name }}

                      - template: /eng/common/pipelines/templates/steps/create-pull-request.yml
                        parameters:
                          PRBranchName: increment-package-version-${{ parameters.ServiceDirectory }}-$(Build.BuildId)
                          CommitMsg: "Increment package version after release of ${{ artifact.groupId }} ${{ artifact.name }}"
                          PRTitle: "Increment version for ${{ parameters.ServiceDirectory }} releases"
                          CloseAfterOpenForTesting: '${{ parameters.TestPipeline }}'

  - ${{if ne(parameters.EnableIntegrationStage, false)}}:
    - stage: Integration
      dependsOn: Signing
      jobs:
      - job: PublishPackages
        condition: or(eq(variables['SetDevVersion'], 'true'), and(eq(variables['Build.Reason'],'Schedule'), eq(variables['System.TeamProject'], 'internal')))
        displayName: Publish package to daily feed
        variables:
          - template: /eng/pipelines/templates/variables/globals.yml
          - name: RepositoryUrl
            value: https://pkgs.dev.azure.com/azure-sdk/internal/_packaging/azure-sdk-for-java-pr/maven/v1

        pool:
          name: azsdk-pool-mms-win-2022-general
          vmImage: windows-2022
        steps:
        - checkout: azure-sdk-build-tools
          path: azure-sdk-build-tools
        - template: /eng/common/pipelines/templates/steps/sparse-checkout.yml
          parameters:
            SkipCheckoutNone: true
            Repositories:
              - Name: Azure/azure-sdk-for-java
                Commitish: $(Build.SourceVersion)
                WorkingDirectory: $(Pipeline.Workspace)/azure-sdk-for-java

        - download: current
          displayName: 'Download Artifact: ${{parameters.ArtifactName}}-signed'
          artifact: ${{parameters.ArtifactName}}-signed
        - pwsh: |
            # For safety default to publishing to the private feed.
            # Publish to https://pkgs.dev.azure.com/azure-sdk/internal/_packaging/azure-sdk-for-java-pr/maven/v1
            if ('$(Build.Repository.Name)' -eq 'Azure/azure-sdk-for-java') {
              # Publish to the public feed
              # Publish to https://pkgs.dev.azure.com/azure-sdk/public/_packaging/azure-sdk-for-java/maven/v1
              echo "##vso[task.setvariable variable=RepositoryUrl]https://pkgs.dev.azure.com/azure-sdk/public/_packaging/azure-sdk-for-java/maven/v1"
              echo "Using Java Public Dev Feed"
            } else {
              echo "Using Java Private Dev Feed"
            }
          displayName: Setup TargetFeed

        - template: tools/gpg/gpg.yml@azure-sdk-build-tools

        - ${{ each artifact in parameters.Artifacts }}:
          - ${{if ne(artifact.skipPublishDevFeed, 'true')}}:
            - template: /eng/pipelines/templates/steps/java-publishing.yml
              parameters:
                ArtifactID: ${{artifact.name}}
                GroupID: ${{artifact.groupId}}
                ArtifactDirectory: $(Pipeline.Workspace)/${{parameters.ArtifactName}}-signed
                RepositoryUrl: $(RepositoryUrl)
                Target: JavaDevFeed
                JavaRepoRoot: $(Pipeline.Workspace)/azure-sdk-for-java
            - template: /eng/common/pipelines/templates/steps/publish-artifact.yml
              parameters:
                ArtifactName: integration-${{parameters.ArtifactName}}-${{artifact.name}}-javadevfeed-$(System.JobAttempt)
                ArtifactPath: $(Pipeline.Workspace)/${{parameters.ArtifactName}}-signed

      - job: PublishDocsToNightlyBranch
        dependsOn: PublishPackages
        condition: or(eq(variables['SetDevVersion'], 'true'), and(eq(variables['Build.Reason'],'Schedule'), eq(variables['System.TeamProject'], 'internal')))
        pool:
          name: azsdk-pool-mms-ubuntu-2004-general
          vmImage: MMSUbuntu20.04
        variables:
          - template: /eng/pipelines/templates/variables/globals.yml
          - name: DocValidationImageId
            value: azuresdkimages.azurecr.io/javarefautocr:latest
        steps:
          - template: /eng/common/pipelines/templates/steps/sparse-checkout.yml
            parameters:
              Paths:
                - sdk/**/*.md
                - .github/CODEOWNERS
          - download: current
            displayName: 'Download Artifacts'
            artifact: ${{parameters.ArtifactName}}
          - pwsh: |
              Get-ChildItem -Recurse $(Pipeline.Workspace)/${{parameters.ArtifactName}}/
            displayName: Show visible artifacts
          # Docs daily updates is supposed to download packages from public feed repository, so we have to specify additional repositories in a POM or the profile.
          # Here is maven documentation: https://maven.apache.org/guides/mini/guide-multiple-repositories.html
          - powershell: |
              # Linux mvn `setting.xml` is sitting under path `~/.m2/setting.xml`
              Get-Command mvn
              if (!(Test-Path '~/.m2/')) {
                mkdir ~/.m2/
              }
              if (Test-Path '~/.m2/setting.xml') {
                Write-Host "'setting.xml' exists. Overwriting the file to support multiple repositories."
              }
              Copy-Item "./eng/repo-docs/docms/daily.update.setting.xml" -Destination "~/.m2/settings.xml"
            displayName: 'Configure mvn'
            workingDirectory: $(Build.SourcesDirectory)

          - template: /eng/common/pipelines/templates/steps/update-docsms-metadata.yml
            parameters:
              PackageInfoLocations:
                - ${{ each artifact in parameters.Artifacts }}:
                  - ${{if ne(artifact.skipPublishDocMs, 'true')}}:
                    - $(Pipeline.Workspace)/${{parameters.ArtifactName}}/PackageInfo/${{artifact.name}}.json
              WorkingDirectory: $(System.DefaultWorkingDirectory)
              TargetDocRepoOwner: "azure-sdk"
              TargetDocRepoName: ${{parameters.TargetDocRepoName}}
              Language: 'java'
              DailyDocsBuild: true
              SparseCheckoutPaths:
                - docs-ref-services/
                - metadata/
              DocValidationImageId: "$(DocValidationImageId)"

          - ${{ each artifact in parameters.Artifacts }}:
            - ${{if ne(artifact.skipPublishDocMs, 'true')}}:
              - template: /eng/pipelines/templates/steps/fetch-package-list.yml
                parameters:
                  JavaDocJarLocation: "$(Pipeline.Workspace)/${{parameters.ArtifactName}}/${{artifact.groupId}}/${{artifact.name}}"
                  ArtifactName: ${{artifact.name}}
                  TargetBranch: $(TargetBranchName)
                  DocRepoLocation: $(DocRepoLocation)
                  TargetDocRepoName: ${{parameters.TargetDocRepoName}}
                  TargetDocRepoOwner: "azure-sdk"
