# This Yaml Document has been converted by ESAI Yaml Pipeline Conversion Tool.
parameters:

- name: jobName
  type: string

- name: displayName
  type: string

- name: pool
  type: object

- name: container
  type: string

- name: timeoutInMinutes
  type: number

- name: branch
  type: string

- name: os
  type: string
  values:
  - win
  - linux
  - linux-musl
  - osx

- name: arch
  type: string
  values:
  - arm
  - arm64
  - x64
  - x86

- name: unitTests
  type: boolean

- name: functionalTests
  type: boolean

- name: codeCoverage
  type: boolean

- name: sign
  type: boolean

- name: verifySigning
  type: boolean

- name: publishArtifact
  type: boolean

- name: enableADOLogIssue
  type: boolean
  default: false

- name: packageType
  type: string
  default: agent
  values:
  - agent
  - pipelines-agent

jobs:

- job: ${{ parameters.jobName }}
  displayName: ${{ parameters.displayName }}
  pool: ${{ parameters.pool }}
  timeoutInMinutes: ${{ parameters.timeoutInMinutes }}

  ${{ if ne(parameters.container, '') }}:
    container: ${{ parameters.container }}

  variables:
    PACKAGE_TYPE: ${{ parameters.packageType }}
    ${{ if eq(parameters.os, 'win') }}:
      devCommand: dev.cmd
    ${{ if ne(parameters.os, 'win') }}:
      devCommand: ./dev.sh
    layoutRoot: '_layout/${{ parameters.os }}-${{ parameters.arch }}'
    DisableCFSDetector: true
    DisableDockerDetector: true
    nugetMultiFeedWarnLevel: none
    CheckoutBranch: ${{ parameters.branch }}
  templateContext:
    outputs:
    - ${{ if or(parameters.unitTests, parameters.functionalTests) }}:
      - output: buildArtifacts
        displayName: 'Publish Test logs'
        condition: always()
        PathtoPublish: src/Test/TestLogs
        ArtifactName: ${{ parameters.os }}-${{ parameters.arch }}-$(System.JobId)
    - ${{ if eq(parameters.publishArtifact, true) }}:
      - output: buildArtifacts
        displayName: 'Publish Hash Artifact'
        PathtoPublish: _package
        ArtifactName: agent
    - ${{ if eq(parameters.publishArtifact, true) }}:
      - output: buildArtifacts
        displayName: 'Publish Agent Artifact'
        PathtoPublish: _package_hash
        ArtifactName: hash
  steps:

  - checkout: self
    clean: true

  - task: Bash@3
    displayName: Switch to target branch
    inputs:
      filePath: .azure-pipelines/scripts/switch-branch.sh
    env:
      TARGET_BRANCH: $(CheckoutBranch)
    condition: |
      and(
        eq(variables['Build.SourceBranch'], 'refs/heads/master'),
        ne(variables.CheckoutBranch, '')
      )

  # 1ES images used on the ARM pool doesn't contain unzip tool, so we need to install it before starting the build
  - ${{ if and(eq(parameters.arch, 'arm64'), ne(parameters.os, 'osx')) }}:
    - script: sudo dnf -y update && sudo dnf -y install unzip
      displayName: Install unzip
      retryCountOnTaskFailure: 5

  # Install nuget
  - ${{ if eq(parameters.os, 'win') }}:
    - task: NuGetToolInstaller@1
      displayName: Install NuGet for signing tests

  # Set up auth for nuget for when new packages need to be consumed
  - task: NuGetAuthenticate@1

  # Build agent layout
  - script: ${{ variables.devCommand }} layout Release ${{ parameters.os }}-${{ parameters.arch }}
    workingDirectory: src
    displayName: Build & Layout Release
    retryCountOnTaskFailure: 5
    ${{ if parameters.enableADOLogIssue }}:
      env:
        ADO_ENABLE_LOGISSUE: true

  # Check if broken symlinks exist in the agent build
  - task: Bash@3
    inputs:
      filePath: src/Misc/check-symlinks.sh
    displayName: Check symlinks

  # Run l0 tests
  - ${{ if parameters.unitTests }}:
    - ${{ if and(eq(parameters.os, 'win'), eq(parameters.arch, 'x86')) }}:
      - task: UseDotNet@2
        displayName: Install .NET Core 6 Runtime
        inputs:
          version: '6.0.x'
          packageType: 'runtime'
          installationPath: 'C:\Program Files (x86)\dotnet'
        env:
          PROCESSOR_ARCHITECTURE: x86
    - script: ${{ variables.devCommand }} testl0 Debug ${{ parameters.os }}-${{ parameters.arch }}
      workingDirectory: src
      displayName: Unit tests
      timeoutInMinutes: 5

  # Run l1 tests
  - ${{ if parameters.functionalTests }}:
    - ${{ if and(eq(parameters.os, 'win'), eq(parameters.arch, 'x86')) }}:
      - task: UseDotNet@2
        displayName: Install .NET Core 6 SDK
        inputs:
          version: '6.0.421'
          packageType: sdk
          performMultiLevelLookup: true
    - script: ${{ variables.devCommand }} testl1 Debug ${{ parameters.os }}-${{ parameters.arch }}
      workingDirectory: src
      displayName: Functional tests

  - ${{ if or(parameters.unitTests, parameters.functionalTests) }}:
    # Publish test results
    - task: PublishTestResults@2
      displayName: Publish Test Results **/*.trx
      inputs:
        testRunner: VSTest
        testResultsFiles: '**/*.trx'
        testRunTitle: 'Agent Tests - ${{ parameters.os }}-${{ parameters.arch }}'
      condition: always()

  # Code coverage
  - ${{ if and(parameters.codeCoverage, parameters.unitTests, parameters.functionalTests) }}:
    - script: dotnet tool install --global dotnet-reportgenerator-globaltool
      displayName: Install Report Generator

    - script: ${{ variables.devCommand }} report
      displayName: Generate Code Coverage report
      workingDirectory: src

    - task: PublishCodeCoverageResults@1
      inputs:
        codeCoverageTool: 'cobertura'
        summaryFileLocation: _reports/**/Cobertura.xml
        pathToSources: src

  - ${{ if eq(parameters.os, 'osx') }}:
    - task: UseDotNet@2
      inputs:
        packageType: 'sdk'
        version: '6.0.x'

  - ${{ if parameters.sign }}:
    # Signing steps
    - template: /.azure-pipelines/signing.yml@self
      parameters:
        layoutRoot: ${{ variables.layoutRoot }}
        isWindows: ${{ eq(parameters.os, 'win') }}

  # Publish artifacts
  - ${{ if parameters.publishArtifact }}:

    # Package .NET Core Windows dependency (VC++ Redistributable)
    - ${{ if eq(parameters.os, 'win') }}:
      - template: /.azure-pipelines/package-vcredist.yml@self
        parameters:
          layoutRoot: ${{ variables.layoutRoot }}
          flavor: ${{ parameters.arch }}

    # Create agent package zip
    - script: "${{ variables.devCommand }} package Release ${{ parameters.os }}-${{ parameters.arch }}"
      workingDirectory: src
      displayName: Package Release

    - script: "${{ variables.devCommand }} hash Release ${{ parameters.os }}-${{ parameters.arch }}"
      workingDirectory: src
      displayName: Hash Package

  - ${{ if parameters.verifySigning }}:

    # Verify all binaries are signed (generate report)
    - task: securedevelopmentteam.vss-secure-development-tools.build-task-codesignvalidation.CodesignValidation@0
      displayName: 'Generate Codesign Report'
      inputs:
        path: ${{ variables.layoutRoot }}

    # Verify all binaries are signed (check report)
    - task: securedevelopmentteam.vss-secure-development-tools.build-task-postanalysis.PostAnalysis@1
      displayName: 'Verify Codesign Report'
      inputs:
        CodesignValidation: true
        CodesignValidationBreakOn: WarningAbove
        ToolLogsNotFoundAction: Error