# default-build.yml
# Description: Defines a build phase for invoking build.sh/cmd
# Parameters:
#   jobName: string
#       The name of the job. Defaults to the name of the OS. No spaces allowed
#   jobDisplayName: string
#       The friendly job name to display in the UI. Defaults to the name of the OS.
#   poolName: string
#       The name of the Azure DevOps agent pool to use.
#   agentOs: string
#       Used in templates to define variables which are OS specific. Typically from the set { Windows, Linux, macOS }
#   buildArgs: string
#       Additional arguments to pass to the build.sh/cmd script.
#       Note: -ci is always passed
#   beforeBuild: [steps]
#       Additional steps to run before build.sh/cmd
#   afterBuild: [steps]
#       Additional steps to run after build.sh/cmd
#   artifacts:
#      publish: boolean
#           Should artifacts be published
#      path: string
#           The file path to artifacts output
#      name: string
#           The name of the artifact container
#   variables: { string: string }
#     A map of custom variables
#   matrix: { string: { string: string } }
#     A map of matrix configurations and variables. https://docs.microsoft.com/en-us/azure/devops/pipelines/yaml-schema?view=azure-devops&tabs=schema#job
#   demands: string | [ string ]
#     A list of agent demands. https://docs.microsoft.com/en-us/azure/devops/pipelines/yaml-schema?view=azure-devops&tabs=schema#demands
#   dependsOn: string | [ string ]
#     For fan-out/fan-in. https://docs.microsoft.com/en-us/azure/devops/pipelines/yaml-schema?view=azure-devops&tabs=schema#job
#   codeSign: boolean
#       This build definition is enabled for code signing. (Only applies to Windows)

#
# See https://docs.microsoft.com/en-us/azure/devops/pipelines/yaml-schema for details
#

parameters:
  agentOs: 'Windows'
  poolName: ''
  buildArgs: ''
  configuration: 'Release'
  demands: []
  beforeBuild: []
  afterBuild: []
  codeSign: false
  variables: {}
  dependsOn: ''
  # buildSteps: [] - don't define an empty object default because there is no way in template expression yet to check "if isEmpty(parameters.buildSteps)"
  # jobName: '' - use agentOs by default.
  # jobDisplayName: '' - use agentOs by default.
  # matrix: {} - don't define an empty object default because there is no way in template expression yet to check "if isEmpty(parameters.matrix)"
  artifacts:
    publish: true
    path: 'artifacts/'

jobs:
- job: ${{ coalesce(parameters.jobName, parameters.agentOs) }}
  displayName: ${{ coalesce(parameters.jobDisplayName, parameters.agentOs) }}
  dependsOn: ${{ parameters.dependsOn }}
  workspace:
    clean: all
  strategy:
    ${{ if ne(parameters.matrix, '') }}:
      maxParallel: 8
      matrix: ${{ parameters.matrix }}
  # Map friendly OS names to the right queue
  # See https://github.com/dotnet/arcade/blob/main/Documentation/ChoosingAMachinePool.md and
  # https://docs.microsoft.com/en-us/azure/devops/pipelines/agents/hosted?view=azure-devops&tabs=yaml#use-a-microsoft-hosted-agent
  pool:
    ${{ if ne(parameters.poolName, '') }}:
      name: ${{ parameters.poolName }}
    ${{ if and(eq(parameters.poolName, ''), eq(parameters.agentOs, 'macOS')) }}:
      vmImage: macOS-10.15
    ${{ if and(eq(parameters.poolName, ''), eq(parameters.agentOs, 'Linux')) }}:
      vmImage: ubuntu-18.04
    ${{ if and(eq(parameters.poolName, ''), eq(parameters.agentOs, 'Windows')) }}:
      vmImage: windows-latest
      ${{ if ne(variables['System.TeamProject'], 'public') }}:
        # This override makes the specified vmImage irrelevant.
        name: NetCore1ESPool-Internal
        demands: ImageOverride -equals Build.Server.Amd64.VS2019
  variables:
    AgentOsName: ${{ parameters.agentOs }}
    ASPNETCORE_TEST_LOG_MAXPATH: "200" # Keep test log file name length low enough for artifact zipping
    DOTNET_HOME: $(Agent.BuildDirectory)/.dotnet
    BuildScriptArgs: ${{ parameters.buildArgs }}
    BuildConfiguration: ${{ parameters.configuration }}
    DOTNET_CLI_TELEMETRY_OPTOUT: 1 # Skip signing telemetry to work around an error
    TeamName: AspNetCore
    ${{ if and(eq(parameters.codeSign, 'true'), eq(variables['System.TeamProject'], 'internal'), ne(variables['Build.Reason'], 'PullRequest')) }}:
      _SignType: real
    ${{ if or(ne(parameters.codeSign, 'true'), ne(variables['System.TeamProject'], 'internal'), eq(variables['Build.Reason'], 'PullRequest')) }}:
      _SignType: ''
    ${{ insert }}: ${{ parameters.variables }}
  steps:
  - checkout: self
    clean: true
  - ${{ if eq(parameters.agentOs, 'Windows') }}:
    - task: NuGetCommand@2
      displayName: 'Clear NuGet caches'
      condition: succeeded()
      inputs:
        command: custom
        arguments: 'locals all -clear'
  - ${{ if and(eq(variables['System.TeamProject'], 'internal'), eq(parameters.agentOs, 'Windows'), eq(parameters.codeSign, 'true')) }}:
    - task: MicroBuildSigningPlugin@2
      displayName: Install MicroBuild Signing plugin
      condition: and(succeeded(), in(variables['_SignType'], 'test', 'real'))
      inputs:
        signType: $(_SignType)
        zipSources: false
        feedSource: https://dnceng.pkgs.visualstudio.com/_packaging/MicroBuildToolset/nuget/v3/index.json
  - ${{ parameters.beforeBuild }}
  - ${{ if eq(parameters.buildSteps, '') }}:
    - ${{ if eq(parameters.agentOs, 'Windows') }}:
      - task: NuGetToolInstaller@1
        displayName: 'Install NuGet.exe'
      - task: NodeTool@0
        displayName: Install Node 16.x
        inputs:
          versionSpec: 16.x
      - script: .\build.cmd /p:SignType=$(_SignType) /p:Configuration=$(BuildConfiguration) $(BuildScriptArgs) /bl:artifacts/logs/build.binlog
        displayName: Run build.cmd
    - ${{ if ne(parameters.agentOs, 'Windows') }}:
      - script: ./build.sh -ci -p:Configuration=$(BuildConfiguration) $(BuildScriptArgs)
        displayName: Run build.sh
  - ${{ if ne(parameters.buildSteps, '') }}:
    - ${{ parameters.buildSteps }}
  - task: PublishTestResults@2
    displayName: Publish test results
    condition: always()
    continueOnError: true
    inputs:
      testRunTitle: $(AgentOsName)-$(BuildConfiguration)
      testRunner: vstest
      testResultsFiles: 'artifacts/logs/**/*.trx'
      mergeTestResults: true
  - ${{ if eq(parameters.artifacts.publish, 'true') }}:
    - task: PublishBuildArtifacts@1
      displayName: Upload artifacts
      condition: eq(variables['system.pullrequest.isfork'], false)
      continueOnError: true
      inputs:
        pathtoPublish: ${{ parameters.artifacts.path }}
        ${{ if eq(parameters.artifacts.name, '') }}:
          artifactName: artifacts-$(AgentOsName)-$(BuildConfiguration)
        ${{ if ne(parameters.artifacts.name, '') }}:
          artifactName: ${{ parameters.artifacts.name }}
        artifactType: Container
        parallel: true
  - ${{ parameters.afterBuild }}
  - ${{ if and(eq(variables['System.TeamProject'], 'internal'), eq(parameters.agentOs, 'Windows'), eq(parameters.codeSign, 'true')) }}:
    - task: MicroBuildCleanup@1
      displayName: Cleanup MicroBuild tasks
      condition: always()
