From 5528845db6d2036b899c166058bc98eaf11e97d6 Mon Sep 17 00:00:00 2001 From: OneBranch Resources Date: Fri, 15 Mar 2024 16:40:04 +0000 Subject: [PATCH 1/9] Adding OneBranch pipeline YAML config file for PSReadLine-Official --- .pipelines/PSReadLine-Official.yml | 170 +++++++++++++++++++++++++++++ 1 file changed, 170 insertions(+) create mode 100644 .pipelines/PSReadLine-Official.yml diff --git a/.pipelines/PSReadLine-Official.yml b/.pipelines/PSReadLine-Official.yml new file mode 100644 index 000000000..4fe744b91 --- /dev/null +++ b/.pipelines/PSReadLine-Official.yml @@ -0,0 +1,170 @@ +################################################################################# +# OneBranch Pipelines # +# This pipeline was created by EasyStart from a sample located at: # +# https://aka.ms/obpipelines/easystart/samples # +# Documentation: https://aka.ms/obpipelines # +# Yaml Schema: https://aka.ms/obpipelines/yaml/schema # +# Retail Tasks: https://aka.ms/obpipelines/tasks # +# Support: https://aka.ms/onebranchsup # +################################################################################# + +trigger: none # https://aka.ms/obpipelines/triggers + +parameters: # parameters are shown up in ADO UI in a build queue time +- name: 'debug' + displayName: 'Enable debug output' + type: boolean + default: false + +variables: + CDP_DEFINITION_BUILD_COUNT: $[counter('', 0)] # needed for onebranch.pipeline.version task https://aka.ms/obpipelines/versioning + system.debug: ${{ parameters.debug }} + + BuildSolution: $(Build.SourcesDirectory)\dirs.proj + BuildConfiguration: Release + + WindowsContainerImage: 'onebranch.azurecr.io/windows/ltsc2019/vse2022:latest' # Docker image which is used to build the project https://aka.ms/obpipelines/containers + +resources: + repositories: + - repository: templates + type: git + name: OneBranch.Pipelines/GovernedTemplates + ref: refs/heads/main + +extends: + template: v2/OneBranch.Official.CrossPlat.yml@templates # https://aka.ms/obpipelines/templates + parameters: + cloudvault: # https://aka.ms/obpipelines/cloudvault + enabled: false + globalSdl: # https://aka.ms/obpipelines/sdl + asyncSdl: + enabled: true + tsaOptionsFile: .config/tsaoptions.json + # tsa: + # enabled: false # onebranch publish all sdl results to TSA. If TSA is disabled all SDL tools will forced into 'break' build mode. + # credscan: + # suppressionsFile: $(Build.SourcesDirectory)\.config\CredScanSuppressions.json + policheck: + break: true # always break the build on policheck issues. You can disable it by setting to 'false' + # suppression: + # suppressionFile: $(Build.SourcesDirectory)\.gdn\global.gdnsuppress + + stages: + - stage: build + jobs: + - job: main + pool: + type: windows # read more about custom job pool types at https://aka.ms/obpipelines/yaml/jobs + + variables: # More settings at https://aka.ms/obpipelines/yaml/jobs + ob_outputDirectory: '$(Build.SourcesDirectory)\out' # this directory is uploaded to pipeline artifacts, reddog and cloudvault. More info at https://aka.ms/obpipelines/artifacts + # https://aka.ms/obpipelines/sdl + ob_sdl_binskim_break: true # always break the build on binskim issues, even if TSA enabled. You can disable it by setting to 'false' + ob_sdl_roslyn_break: true + ${{ if eq(variables['Build.SourceBranch'], 'refs/heads/main') }}: # conditionally enable symbolsPublishing for main branch only + ob_symbolsPublishing_enabled: true # https://aka.ms/obpipelines/symbols + # ob_sdl_suppression_suppressionFile: $(Build.SourcesDirectory)\.gdn\job.gdnsuppress + + steps: + - task: UseDotNet@2 + continueOnError: true + inputs: + packageType: 'sdk' + useGlobalJson: true + performMultiLevelLookup: true + + - task: onebranch.pipeline.version@1 # generates automatic version. For other versioning options check https://aka.ms/obpipelines/versioning + displayName: 'Setup BuildNumber' + inputs: + system: 'RevisionCounter' + major: '1' + minor: '0' + exclude_commit: true + + - task: DotNetCoreCLI@2 + displayName: 'DotNetCore restore' + inputs: + command: 'custom' + projects: $(BuildSolution) + custom: 'restore' + + # roslynanalyzers task wraps around dotnet build to enable static analysis + - task: RoslynAnalyzers@3 + displayName: 'DotNetCore build with RoslynAnalyzers' + inputs: + userProvideBuildInfo: 'msBuildInfo' + msBuildCommandline: 'dotnet.exe build $(BuildSolution) --no-restore --configuration $(BuildConfiguration)' + + - task: DotNetCoreCLI@2 + displayName: 'DotNetCore test' + inputs: + command: 'test' + projects: $(BuildSolution) + arguments: '--no-build --no-restore --configuration $(BuildConfiguration) --logger trx --blame --collect "Code coverage" --results-directory $(Build.SourcesDirectory)\TestResults\' + publishTestResults: false + + - task: PublishTestResults@2 + displayName: 'Publish test results' + inputs: + testResultsFormat: VSTest + testResultsFiles: '$(Build.SourcesDirectory)\TestResults\**\*.trx' + failTaskOnFailedTests: true + + - task: DotNetCoreCLI@2 + displayName: 'DotNetCore publish' + inputs: + command: 'publish' + publishWebProjects: false + projects: $(BuildSolution) + arguments: '--no-build --no-restore --configuration $(BuildConfiguration) --output $(Build.SourcesDirectory)\out' + zipAfterPublish: false + + - task: onebranch.pipeline.signing@1 + displayName: 'Sign output' + inputs: + command: 'sign' + signing_environment: 'azure-ado' + files_to_sign: '**/*.exe;**/*.dll;**/*.ps1;**/*.psm1' + search_root: '$(Build.SourcesDirectory)\out' +# uncomment this section and edit parameters to enable VSTest instead of dotnet tests. When you enable this you dont need publish test results and codecoverage steps + # - task: VSTest@3 + # inputs: + # testSelector: 'testAssemblies' + # testAssemblyVer2: | + # **\*test*.dll + # !**\*TestAdapter.dll + # !**\obj\** + # searchFolder: '$(Build.SourcesDirectory)\out' ## or use '$(Agent.BuildDirectory)' + ##testFiltercriteria: 'TestCategory=UnitTests' ## update + #resultsFolder: '$(Build.SourcesDirectory)\out\logs\TestResults' + #runInParallel: true ## this setting helps to speed up test case execution but if youhave depdencies between tests you change or remove this but having it enabled is always recommended + #codeCoverageEnabled: true + #testRunTitle: 'release_x64' ## Update this for a custom readable way of taggin your test run when you query in ADO test runs view + #platform: 'x64' ## you can modify this as needed + #configuration: 'release' + #publishRunAttachments: false + #failOnMinTestsNotRun: true + #rerunFailedTests: true + #rerunFailedThreshold: '70' +# https://aka.ms/obpipelines/cloudtest +# uncomment this section and edit parameters to enable CloudTest + # - stage: cloudtest + # dependsOn: build_stage + # jobs: + # - job: cloudtestjob + # pool: + # type: cloudtestagentless + # continueOnError: true + # steps: + # - task: CloudTestServerBuildTask@1 + # displayName: 'CloudTest' + # inputs: + # connectedServiceName: 'CloudTest-prod' + # cloudTestTenant: 'onebranchtest' + # testMapLocation: '[BuildRoot]\ClassLibrary.UnitTest\TestMapCdp.xml' + # pipelineArtifactName: 'drop_build_main' + # pipelineArtifactBuildUrl: '$(System.TaskDefinitionsUri)$(System.TeamProject)/_build/results?buildId=$(Build.BuildId)' + # parserProperties: 'worker:VsTestVersion=V150;CodeCoverageType=Dynamic;worker:TestVar=$(RUN_PIPELINE_VARIABLE)' + # cacheEnabled: false + # scheduleBuildRequesterAlias: 'azbldrun' \ No newline at end of file From e5cbd3bda53ae5814c0a2058e558603934a5963f Mon Sep 17 00:00:00 2001 From: Dongbo Wang Date: Tue, 19 Mar 2024 16:43:28 -0700 Subject: [PATCH 2/9] WIP --- .pipelines/PSReadLine-Official.yml | 350 ++++++++++++++++------------- 1 file changed, 193 insertions(+), 157 deletions(-) diff --git a/.pipelines/PSReadLine-Official.yml b/.pipelines/PSReadLine-Official.yml index 4fe744b91..3336d2109 100644 --- a/.pipelines/PSReadLine-Official.yml +++ b/.pipelines/PSReadLine-Official.yml @@ -1,170 +1,206 @@ -################################################################################# -# OneBranch Pipelines # -# This pipeline was created by EasyStart from a sample located at: # -# https://aka.ms/obpipelines/easystart/samples # -# Documentation: https://aka.ms/obpipelines # -# Yaml Schema: https://aka.ms/obpipelines/yaml/schema # -# Retail Tasks: https://aka.ms/obpipelines/tasks # -# Support: https://aka.ms/onebranchsup # -################################################################################# - -trigger: none # https://aka.ms/obpipelines/triggers - -parameters: # parameters are shown up in ADO UI in a build queue time -- name: 'debug' - displayName: 'Enable debug output' - type: boolean - default: false +# This Yaml Document has been converted by ESAI Yaml Pipeline Conversion Tool. +# Please make sure to check all the converted content, it is your team's responsibility to make sure that the pipeline is still valid and functions as expected. +# This pipeline will be extended to the OneBranch template +name: PSReadLine-ModuleBuild-$(Build.BuildId) +trigger: none +pr: none variables: - CDP_DEFINITION_BUILD_COUNT: $[counter('', 0)] # needed for onebranch.pipeline.version task https://aka.ms/obpipelines/versioning - system.debug: ${{ parameters.debug }} - - BuildSolution: $(Build.SourcesDirectory)\dirs.proj - BuildConfiguration: Release - - WindowsContainerImage: 'onebranch.azurecr.io/windows/ltsc2019/vse2022:latest' # Docker image which is used to build the project https://aka.ms/obpipelines/containers + DOTNET_CLI_TELEMETRY_OPTOUT: 1 + POWERSHELL_TELEMETRY_OPTOUT: 1 + DOTNET_SKIP_FIRST_TIME_EXPERIENCE: 1 + WindowsContainerImage: onebranch.azurecr.io/windows/ltsc2022/vse2022:latest resources: - repositories: - - repository: templates - type: git - name: OneBranch.Pipelines/GovernedTemplates - ref: refs/heads/main + repositories: + - repository: onebranchTemplates + type: git + name: OneBranch.Pipelines/GovernedTemplates + ref: refs/heads/main extends: - template: v2/OneBranch.Official.CrossPlat.yml@templates # https://aka.ms/obpipelines/templates + template: v2/OneBranch.Official.CrossPlat.yml@onebranchTemplates parameters: - cloudvault: # https://aka.ms/obpipelines/cloudvault - enabled: false - globalSdl: # https://aka.ms/obpipelines/sdl - asyncSdl: + featureFlags: + WindowsHostVersion: '1ESWindows2022' + globalSdl: + disableLegacyManifest: true + sbom: + enabled: true + packageName: PSReadLine + codeql: + compiled: + enabled: true + asyncSdl: # https://aka.ms/obpipelines/asyncsdl enabled: true - tsaOptionsFile: .config/tsaoptions.json - # tsa: - # enabled: false # onebranch publish all sdl results to TSA. If TSA is disabled all SDL tools will forced into 'break' build mode. - # credscan: - # suppressionsFile: $(Build.SourcesDirectory)\.config\CredScanSuppressions.json - policheck: - break: true # always break the build on policheck issues. You can disable it by setting to 'false' - # suppression: - # suppressionFile: $(Build.SourcesDirectory)\.gdn\global.gdnsuppress + forStages: [Build] + credscan: + enabled: true + scanFolder: $(Build.SourcesDirectory)\PSReadLine + binskim: + enabled: true + apiscan: + enabled: false stages: - - stage: build + - stage: Build + displayName: Build and Sign jobs: - - job: main - pool: - type: windows # read more about custom job pool types at https://aka.ms/obpipelines/yaml/jobs - - variables: # More settings at https://aka.ms/obpipelines/yaml/jobs - ob_outputDirectory: '$(Build.SourcesDirectory)\out' # this directory is uploaded to pipeline artifacts, reddog and cloudvault. More info at https://aka.ms/obpipelines/artifacts - # https://aka.ms/obpipelines/sdl - ob_sdl_binskim_break: true # always break the build on binskim issues, even if TSA enabled. You can disable it by setting to 'false' - ob_sdl_roslyn_break: true - ${{ if eq(variables['Build.SourceBranch'], 'refs/heads/main') }}: # conditionally enable symbolsPublishing for main branch only - ob_symbolsPublishing_enabled: true # https://aka.ms/obpipelines/symbols - # ob_sdl_suppression_suppressionFile: $(Build.SourcesDirectory)\.gdn\job.gdnsuppress + - job: build_windows + displayName: Build PSReadLine + variables: + - name: ob_outputDirectory + value: '$(Build.ArtifactStagingDirectory)/ONEBRANCH_ARTIFACT' + - name: repoRoot + value: $(Build.SourcesDirectory)\PSReadLine + - name: ob_sdl_tsa_configFile + value: $(repoRoot)\.config\tsaoptions.json + - name: signSrcPath + value: $(repoRoot)\bin\Release\PSReadLine + - name: ob_sdl_sbom_enabled + value: true + - name: ob_signing_setup_enabled + value: true + #CodeQL tasks added manually to workaround signing failures + - name: ob_sdl_codeql_compiled_enabled + value: false + pool: + type: windows steps: - - task: UseDotNet@2 - continueOnError: true - inputs: - packageType: 'sdk' - useGlobalJson: true - performMultiLevelLookup: true - - - task: onebranch.pipeline.version@1 # generates automatic version. For other versioning options check https://aka.ms/obpipelines/versioning - displayName: 'Setup BuildNumber' - inputs: - system: 'RevisionCounter' - major: '1' - minor: '0' - exclude_commit: true - - - task: DotNetCoreCLI@2 - displayName: 'DotNetCore restore' - inputs: - command: 'custom' - projects: $(BuildSolution) - custom: 'restore' - - # roslynanalyzers task wraps around dotnet build to enable static analysis - - task: RoslynAnalyzers@3 - displayName: 'DotNetCore build with RoslynAnalyzers' - inputs: - userProvideBuildInfo: 'msBuildInfo' - msBuildCommandline: 'dotnet.exe build $(BuildSolution) --no-restore --configuration $(BuildConfiguration)' - - - task: DotNetCoreCLI@2 - displayName: 'DotNetCore test' - inputs: - command: 'test' - projects: $(BuildSolution) - arguments: '--no-build --no-restore --configuration $(BuildConfiguration) --logger trx --blame --collect "Code coverage" --results-directory $(Build.SourcesDirectory)\TestResults\' - publishTestResults: false - - - task: PublishTestResults@2 - displayName: 'Publish test results' - inputs: - testResultsFormat: VSTest - testResultsFiles: '$(Build.SourcesDirectory)\TestResults\**\*.trx' - failTaskOnFailedTests: true - - - task: DotNetCoreCLI@2 - displayName: 'DotNetCore publish' - inputs: - command: 'publish' - publishWebProjects: false - projects: $(BuildSolution) - arguments: '--no-build --no-restore --configuration $(BuildConfiguration) --output $(Build.SourcesDirectory)\out' - zipAfterPublish: false - - - task: onebranch.pipeline.signing@1 - displayName: 'Sign output' - inputs: - command: 'sign' - signing_environment: 'azure-ado' - files_to_sign: '**/*.exe;**/*.dll;**/*.ps1;**/*.psm1' - search_root: '$(Build.SourcesDirectory)\out' -# uncomment this section and edit parameters to enable VSTest instead of dotnet tests. When you enable this you dont need publish test results and codecoverage steps - # - task: VSTest@3 - # inputs: - # testSelector: 'testAssemblies' - # testAssemblyVer2: | - # **\*test*.dll - # !**\*TestAdapter.dll - # !**\obj\** - # searchFolder: '$(Build.SourcesDirectory)\out' ## or use '$(Agent.BuildDirectory)' - ##testFiltercriteria: 'TestCategory=UnitTests' ## update - #resultsFolder: '$(Build.SourcesDirectory)\out\logs\TestResults' - #runInParallel: true ## this setting helps to speed up test case execution but if youhave depdencies between tests you change or remove this but having it enabled is always recommended - #codeCoverageEnabled: true - #testRunTitle: 'release_x64' ## Update this for a custom readable way of taggin your test run when you query in ADO test runs view - #platform: 'x64' ## you can modify this as needed - #configuration: 'release' - #publishRunAttachments: false - #failOnMinTestsNotRun: true - #rerunFailedTests: true - #rerunFailedThreshold: '70' -# https://aka.ms/obpipelines/cloudtest -# uncomment this section and edit parameters to enable CloudTest - # - stage: cloudtest - # dependsOn: build_stage - # jobs: - # - job: cloudtestjob - # pool: - # type: cloudtestagentless - # continueOnError: true - # steps: - # - task: CloudTestServerBuildTask@1 - # displayName: 'CloudTest' - # inputs: - # connectedServiceName: 'CloudTest-prod' - # cloudTestTenant: 'onebranchtest' - # testMapLocation: '[BuildRoot]\ClassLibrary.UnitTest\TestMapCdp.xml' - # pipelineArtifactName: 'drop_build_main' - # pipelineArtifactBuildUrl: '$(System.TaskDefinitionsUri)$(System.TeamProject)/_build/results?buildId=$(Build.BuildId)' - # parserProperties: 'worker:VsTestVersion=V150;CodeCoverageType=Dynamic;worker:TestVar=$(RUN_PIPELINE_VARIABLE)' - # cacheEnabled: false - # scheduleBuildRequesterAlias: 'azbldrun' \ No newline at end of file + - checkout: self + env: + # Set ob_restore_phase to run this step before '🔒 Setup Signing' step. + ob_restore_phase: true + + - pwsh: | + if (-not (Test-Path $(repoRoot)/.config/tsaoptions.json)) { + throw "tsaoptions.json does not exist under $(repoRoot)/.config" + } + displayName: Test if tsaoptions.json exists + env: + # Set ob_restore_phase to run this step before '🔒 Setup Signing' step. + ob_restore_phase: true + + - pwsh: | + Write-Host "PS Version: $($($PSVersionTable.PSVersion))" + Set-Location -Path '$(repoRoot)' + .\build.ps1 -Bootstrap + displayName: Bootstrap + env: + # Set ob_restore_phase to run this step before '🔒 Setup Signing' step. + ob_restore_phase: true + + # Add CodeQL Init task right before your 'Build' step. + - task: CodeQL3000Init@0 + env: + # Set ob_restore_phase to run this step before '🔒 Setup Signing' step. + ob_restore_phase: true + inputs: + Enabled: true + AnalyzeInPipeline: true + Language: csharp + + - pwsh: | + function Send-VstsCommand ($vstsCommandString) { + Write-Host ("sending: " + $vstsCommandString) + Write-Host "##$vstsCommandString" + } + + Write-Host "PS Version: $($($PSVersionTable.PSVersion))" + Set-Location -Path '$(repoRoot)' + .\build.ps1 -Configuration Release -Framework net461 + + # Set target folder paths + New-Item -Path .\bin\Release\NuGetPackage -ItemType Directory > $null + Send-VstsCommand "vso[task.setvariable variable=NuGetPackage]$(Build.SourcesDirectory)\PSReadLine\bin\Release\NuGetPackage" + Send-VstsCommand "vso[task.setvariable variable=PSReadLine]$(Build.SourcesDirectory)\PSReadLine\bin\Release\PSReadLine" + Send-VstsCommand "vso[task.setvariable variable=Signed]$(Build.SourcesDirectory)\PSReadLine\bin\Release\Signed" + displayName: Build + env: + # Set ob_restore_phase to run this step before '🔒 Setup Signing' step. + ob_restore_phase: true + + # Add CodeQL Finalize task right after your 'Build' step. + - task: CodeQL3000Finalize@0 + condition: always() + env: + # Set ob_restore_phase to run this step before '🔒 Setup Signing' step. + ob_restore_phase: true + + - task: onebranch.pipeline.signing@1 + displayName: Sign 1st party files + inputs: + command: 'sign' + signing_profile: external_distribution + files_to_sign: '*.psd1;*.psm1;*.ps1;*.ps1xml;**\Microsoft*.dll;!Microsoft.PowerShell.Pager.dll' + search_root: $(signSrcPath) + + - task: CopyFiles@2 + displayName: "Copy signed files to ob_outputDirectory - '$(ob_outputDirectory)'" + inputs: + SourceFolder: "$(signSrcPath)" + Contents: '**' + TargetFolder: $(ob_outputDirectory) + + - pwsh: | + try { + $RepoName = "PSRLLocal" + Register-PSRepository -Name $RepoName -SourceLocation $(NuGetPackage) -PublishLocation $(NuGetPackage) -InstallationPolicy Trusted + Publish-Module -Repository $RepoName -Path $(PSReadLine) + } finally { + Unregister-PSRepository -Name $RepoName -ErrorAction SilentlyContinue + } + Get-ChildItem -Path $(NuGetPackage) + displayName: 'Create the NuGet package' + - pwsh: | + Get-ChildItem -Path $(PSReadLine), $(NuGetPackage) + Write-Host "##vso[artifact.upload containerfolder=PSReadLine;artifactname=PSReadLine]$(PSReadLine)" + Write-Host "##vso[artifact.upload containerfolder=NuGetPackage;artifactname=NuGetPackage]$(NuGetPackage)" + displayName: 'Upload artifacts' + - stage: compliance + displayName: Compliance + dependsOn: Build + jobs: + - job: Compliance_Job + displayName: PSReadLine Compliance + variables: + - group: APIScan + - name: ob_outputDirectory + value: '$(Build.ArtifactStagingDirectory)/ONEBRANCH_ARTIFACT' + timeoutInMinutes: 240 + pool: + type: windows + steps: + - checkout: self + - checkout: ComplianceRepo + - download: current + artifact: PSReadLine + - pwsh: | + Get-ChildItem -Path "$(Pipeline.Workspace)\PSReadLine" -Recurse + displayName: Capture downloaded artifacts + - pwsh: | + function Send-VstsCommand ($vstsCommandString) { + Write-Host ("sending: " + $vstsCommandString) + Write-Host "##$vstsCommandString" + } + # Get module version + $psd1Data = Import-PowerShellDataFile -Path "$(Pipeline.Workspace)\PSReadLine\PSReadLine.psd1" + $moduleVersion = $psd1Data.ModuleVersion + $prerelease = $psd1Data.PrivateData.PSData.Prerelease + if ($prerelease) { $moduleVersion = "$moduleVersion-$prerelease" } + Send-VstsCommand "vso[task.setvariable variable=ModuleVersion]$moduleVersion" + displayName: Get Module Version + - template: assembly-module-compliance.yml@ComplianceRepo + parameters: + AnalyzeTarget: '$(Pipeline.Workspace)\PSReadLine\*.dll' + AnalyzeSymPath: 'SRV*' + sourceScanPath: '' + suppressionsFile: '' + optionsRulesDBPath: '' + optionsFTPath: '' + codeBaseName: 'PSReadLine_201912' + softwareFolder: '$(Pipeline.Workspace)\PSReadLine' + softwareName: 'PSReadLine' + softwareVersion: '$(ModuleVersion)' + connectionString: 'RunAs=App;AppId=$(APIScanClient);TenantId=$(APIScanTenant);AppKey=$(APIScanSecret)' \ No newline at end of file From bb10bd8cae5783cb2d81436f14a397c595b519a1 Mon Sep 17 00:00:00 2001 From: Dongbo Wang Date: Wed, 20 Mar 2024 10:36:57 -0700 Subject: [PATCH 3/9] Migrating to OneBranch for PSReadLine --- .config/tsaoptions.json | 9 ++ .pipelines/PSReadLine-Official.yml | 177 +++++++++++++++++------------ 2 files changed, 113 insertions(+), 73 deletions(-) create mode 100644 .config/tsaoptions.json diff --git a/.config/tsaoptions.json b/.config/tsaoptions.json new file mode 100644 index 000000000..0f1ded2de --- /dev/null +++ b/.config/tsaoptions.json @@ -0,0 +1,9 @@ +{ + "instanceUrl": "https://msazure.visualstudio.com", + "projectName": "One", + "areaPath": "One\\MGMT\\Compute\\Powershell\\Powershell\\PowerShell Core", + "notificationAliases": [ + "dongbow@microsoft.com", + "slee@microsoft.com" + ] +} diff --git a/.pipelines/PSReadLine-Official.yml b/.pipelines/PSReadLine-Official.yml index 3336d2109..6e6552e6f 100644 --- a/.pipelines/PSReadLine-Official.yml +++ b/.pipelines/PSReadLine-Official.yml @@ -1,6 +1,13 @@ -# This Yaml Document has been converted by ESAI Yaml Pipeline Conversion Tool. -# Please make sure to check all the converted content, it is your team's responsibility to make sure that the pipeline is still valid and functions as expected. -# This pipeline will be extended to the OneBranch template +################################################################################# +# OneBranch Pipelines # +# This pipeline was created by EasyStart from a sample located at: # +# https://aka.ms/obpipelines/easystart/samples # +# Documentation: https://aka.ms/obpipelines # +# Yaml Schema: https://aka.ms/obpipelines/yaml/schema # +# Retail Tasks: https://aka.ms/obpipelines/tasks # +# Support: https://aka.ms/onebranchsup # +################################################################################# + name: PSReadLine-ModuleBuild-$(Build.BuildId) trigger: none pr: none @@ -36,18 +43,18 @@ extends: forStages: [Build] credscan: enabled: true - scanFolder: $(Build.SourcesDirectory)\PSReadLine + scanFolder: $(Build.SourcesDirectory)\PSReadLine\PSReadLine binskim: enabled: true apiscan: enabled: false stages: - - stage: Build - displayName: Build and Sign + - stage: buildstage + displayName: Build and Sign PSReadLine jobs: - - job: build_windows - displayName: Build PSReadLine + - job: buildjob + displayName: Build PSReadLine Files variables: - name: ob_outputDirectory value: '$(Build.ArtifactStagingDirectory)/ONEBRANCH_ARTIFACT' @@ -83,7 +90,7 @@ extends: ob_restore_phase: true - pwsh: | - Write-Host "PS Version: $($($PSVersionTable.PSVersion))" + Write-Host "PS Version: $($PSVersionTable.PSVersion)" Set-Location -Path '$(repoRoot)' .\build.ps1 -Bootstrap displayName: Bootstrap @@ -102,20 +109,9 @@ extends: Language: csharp - pwsh: | - function Send-VstsCommand ($vstsCommandString) { - Write-Host ("sending: " + $vstsCommandString) - Write-Host "##$vstsCommandString" - } - Write-Host "PS Version: $($($PSVersionTable.PSVersion))" Set-Location -Path '$(repoRoot)' .\build.ps1 -Configuration Release -Framework net461 - - # Set target folder paths - New-Item -Path .\bin\Release\NuGetPackage -ItemType Directory > $null - Send-VstsCommand "vso[task.setvariable variable=NuGetPackage]$(Build.SourcesDirectory)\PSReadLine\bin\Release\NuGetPackage" - Send-VstsCommand "vso[task.setvariable variable=PSReadLine]$(Build.SourcesDirectory)\PSReadLine\bin\Release\PSReadLine" - Send-VstsCommand "vso[task.setvariable variable=Signed]$(Build.SourcesDirectory)\PSReadLine\bin\Release\Signed" displayName: Build env: # Set ob_restore_phase to run this step before '🔒 Setup Signing' step. @@ -136,71 +132,106 @@ extends: files_to_sign: '*.psd1;*.psm1;*.ps1;*.ps1xml;**\Microsoft*.dll;!Microsoft.PowerShell.Pager.dll' search_root: $(signSrcPath) + # Verify the signatures + - pwsh: | + $HasInvalidFiles = $false + $WrongCert = @{} + Get-ChildItem -Path $(signSrcPath) -Recurse -Include "*.dll","*.ps*1*" | ` + Get-AuthenticodeSignature | ForEach-Object { + $_ | Select-Object Path, Status + if ($_.Status -ne 'Valid') { $HasInvalidFiles = $true } + if ($_.SignerCertificate.Subject -notmatch 'CN=Microsoft Corporation.*') { + $WrongCert.Add($_.Path, $_.SignerCertificate.Subject) + } + } + + if ($HasInvalidFiles) { throw "Authenticode verification failed. There is one or more invalid files." } + if ($WrongCert.Count -gt 0) { + $WrongCert + throw "Certificate should have the subject starts with 'Microsoft Corporation'" + } + + ## Display files in the folder. + Get-ChildItem -Path $(signSrcPath) + displayName: 'Verify the signed files' + - task: CopyFiles@2 displayName: "Copy signed files to ob_outputDirectory - '$(ob_outputDirectory)'" inputs: - SourceFolder: "$(signSrcPath)" + SourceFolder: $(signSrcPath) Contents: '**' TargetFolder: $(ob_outputDirectory) - pwsh: | - try { - $RepoName = "PSRLLocal" - Register-PSRepository -Name $RepoName -SourceLocation $(NuGetPackage) -PublishLocation $(NuGetPackage) -InstallationPolicy Trusted - Publish-Module -Repository $RepoName -Path $(PSReadLine) - } finally { - Unregister-PSRepository -Name $RepoName -ErrorAction SilentlyContinue - } - Get-ChildItem -Path $(NuGetPackage) - displayName: 'Create the NuGet package' - - pwsh: | - Get-ChildItem -Path $(PSReadLine), $(NuGetPackage) - Write-Host "##vso[artifact.upload containerfolder=PSReadLine;artifactname=PSReadLine]$(PSReadLine)" - Write-Host "##vso[artifact.upload containerfolder=NuGetPackage;artifactname=NuGetPackage]$(NuGetPackage)" - displayName: 'Upload artifacts' - - stage: compliance - displayName: Compliance - dependsOn: Build - jobs: - - job: Compliance_Job - displayName: PSReadLine Compliance + $versionInfo = Get-Item "$(repoRoot)\Microsoft.PowerShell.PSReadLine2.dll | ForEach-Object VersionInfo" + $moduleVersion = $versionInfo.ProductVersion.Split('+')[0] + $vstsCommandString = "vso[task.setvariable variable=ob_sdl_sbom_packageversion]${moduleVersion}" + + Write-Host "sending $vstsCommandString" + Write-Host "##$vstsCommandString" + displayName: Setup SBOM Package Version + + - job: nupkg + dependsOn: buildjob + displayName: Package PSReadLine module variables: - - group: APIScan - - name: ob_outputDirectory - value: '$(Build.ArtifactStagingDirectory)/ONEBRANCH_ARTIFACT' - timeoutInMinutes: 240 + - name: ob_outputDirectory + value: '$(Build.ArtifactStagingDirectory)/ONEBRANCH_ARTIFACT' + - name: repoRoot + value: $(Build.SourcesDirectory)\PSReadLine + - name: ob_sdl_tsa_configFile + value: $(repoRoot)\.config\tsaoptions.json + # Disable because SBOM was already built in the previous job + - name: ob_sdl_sbom_enabled + value: false + - name: signOutPath + value: $(repoRoot)\signed\PSReadLine + - name: nugetPath + value: $(repoRoot)\signed\NuGetPackage + - name: ob_signing_setup_enabled + value: true + # This job is not compiling code, so disable codeQL + - name: ob_sdl_codeql_compiled_enabled + value: false + pool: type: windows steps: - checkout: self - - checkout: ComplianceRepo - - download: current - artifact: PSReadLine + + - task: DownloadPipelineArtifact@2 + displayName: 'Download build files' + inputs: + targetPath: $(signOutPath) + artifact: drop_buildstage_buildjob + - pwsh: | - Get-ChildItem -Path "$(Pipeline.Workspace)\PSReadLine" -Recurse - displayName: Capture downloaded artifacts + Set-Location "$(signOutPath)" + Get-ChildItem -Directory -Recurse * + New-Item -Path $(nugetPath) -ItemType Directory > $null + displayName: Capture artifacts structure + - pwsh: | - function Send-VstsCommand ($vstsCommandString) { - Write-Host ("sending: " + $vstsCommandString) - Write-Host "##$vstsCommandString" + try { + $RepoName = "PSRLLocal" + Register-PSRepository -Name $RepoName -SourceLocation $(nugetPath) -PublishLocation $(nugetPath) -InstallationPolicy Trusted + Publish-Module -Repository $RepoName -Path $(signOutPath) + } finally { + Unregister-PSRepository -Name $RepoName -ErrorAction SilentlyContinue } - # Get module version - $psd1Data = Import-PowerShellDataFile -Path "$(Pipeline.Workspace)\PSReadLine\PSReadLine.psd1" - $moduleVersion = $psd1Data.ModuleVersion - $prerelease = $psd1Data.PrivateData.PSData.Prerelease - if ($prerelease) { $moduleVersion = "$moduleVersion-$prerelease" } - Send-VstsCommand "vso[task.setvariable variable=ModuleVersion]$moduleVersion" - displayName: Get Module Version - - template: assembly-module-compliance.yml@ComplianceRepo - parameters: - AnalyzeTarget: '$(Pipeline.Workspace)\PSReadLine\*.dll' - AnalyzeSymPath: 'SRV*' - sourceScanPath: '' - suppressionsFile: '' - optionsRulesDBPath: '' - optionsFTPath: '' - codeBaseName: 'PSReadLine_201912' - softwareFolder: '$(Pipeline.Workspace)\PSReadLine' - softwareName: 'PSReadLine' - softwareVersion: '$(ModuleVersion)' - connectionString: 'RunAs=App;AppId=$(APIScanClient);TenantId=$(APIScanTenant);AppKey=$(APIScanSecret)' \ No newline at end of file + Get-ChildItem -Path $(nugetPath) + displayName: 'Create the NuGet package' + + - task: onebranch.pipeline.signing@1 + displayName: Sign nupkg + inputs: + command: 'sign' + signing_profile: external_distribution + files_to_sign: '*.nupkg' + search_root: $(nugetPath) + + - task: CopyFiles@2 + displayName: "Copy nupkg to ob_outputDirectory - '$(ob_outputDirectory)'" + inputs: + Contents: "$(nugetPath)*.nupkg" + TargetFolder: $(ob_outputDirectory) From 20d2f0b66a0bc1e98e341cb5908b26bc1ddf0c2a Mon Sep 17 00:00:00 2001 From: Dongbo Wang Date: Wed, 20 Mar 2024 11:03:22 -0700 Subject: [PATCH 4/9] Fix a typo --- .pipelines/PSReadLine-Official.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.pipelines/PSReadLine-Official.yml b/.pipelines/PSReadLine-Official.yml index 6e6552e6f..33baedd96 100644 --- a/.pipelines/PSReadLine-Official.yml +++ b/.pipelines/PSReadLine-Official.yml @@ -111,7 +111,7 @@ extends: - pwsh: | Write-Host "PS Version: $($($PSVersionTable.PSVersion))" Set-Location -Path '$(repoRoot)' - .\build.ps1 -Configuration Release -Framework net461 + .\build.ps1 -Configuration Release -Framework net462 displayName: Build env: # Set ob_restore_phase to run this step before '🔒 Setup Signing' step. From 187c8b6234df632b60a3a90066f1157860409c74 Mon Sep 17 00:00:00 2001 From: Dongbo Wang Date: Wed, 20 Mar 2024 11:29:02 -0700 Subject: [PATCH 5/9] Fix errors --- .pipelines/PSReadLine-Official.yml | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/.pipelines/PSReadLine-Official.yml b/.pipelines/PSReadLine-Official.yml index 33baedd96..59b0811d0 100644 --- a/.pipelines/PSReadLine-Official.yml +++ b/.pipelines/PSReadLine-Official.yml @@ -151,7 +151,7 @@ extends: throw "Certificate should have the subject starts with 'Microsoft Corporation'" } - ## Display files in the folder. + Write-Host "Display files in the folder ..." Get-ChildItem -Path $(signSrcPath) displayName: 'Verify the signed files' @@ -159,11 +159,11 @@ extends: displayName: "Copy signed files to ob_outputDirectory - '$(ob_outputDirectory)'" inputs: SourceFolder: $(signSrcPath) - Contents: '**' + Contents: '**\*' TargetFolder: $(ob_outputDirectory) - pwsh: | - $versionInfo = Get-Item "$(repoRoot)\Microsoft.PowerShell.PSReadLine2.dll | ForEach-Object VersionInfo" + $versionInfo = Get-Item "$(signSrcPath)\Microsoft.PowerShell.PSReadLine2.dll | ForEach-Object VersionInfo" $moduleVersion = $versionInfo.ProductVersion.Split('+')[0] $vstsCommandString = "vso[task.setvariable variable=ob_sdl_sbom_packageversion]${moduleVersion}" From b6743179aaa5162f3780cb2a22feb4ac257601f6 Mon Sep 17 00:00:00 2001 From: Dongbo Wang Date: Wed, 20 Mar 2024 11:48:40 -0700 Subject: [PATCH 6/9] Fix error (2) --- .pipelines/PSReadLine-Official.yml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/.pipelines/PSReadLine-Official.yml b/.pipelines/PSReadLine-Official.yml index 59b0811d0..e74081784 100644 --- a/.pipelines/PSReadLine-Official.yml +++ b/.pipelines/PSReadLine-Official.yml @@ -152,7 +152,7 @@ extends: } Write-Host "Display files in the folder ..." - Get-ChildItem -Path $(signSrcPath) + Get-ChildItem -Path $(signSrcPath) -Recurse | Out-String -Width 150 displayName: 'Verify the signed files' - task: CopyFiles@2 @@ -163,7 +163,7 @@ extends: TargetFolder: $(ob_outputDirectory) - pwsh: | - $versionInfo = Get-Item "$(signSrcPath)\Microsoft.PowerShell.PSReadLine2.dll | ForEach-Object VersionInfo" + $versionInfo = Get-Item "$(signSrcPath)\Microsoft.PowerShell.PSReadLine2.dll" | ForEach-Object VersionInfo $moduleVersion = $versionInfo.ProductVersion.Split('+')[0] $vstsCommandString = "vso[task.setvariable variable=ob_sdl_sbom_packageversion]${moduleVersion}" From e584e806ae4da7ac572603b700d012336cbf4ad1 Mon Sep 17 00:00:00 2001 From: Dongbo Wang Date: Wed, 20 Mar 2024 14:10:44 -0700 Subject: [PATCH 7/9] Fix error (3) --- .pipelines/PSReadLine-Official.yml | 11 +++++------ 1 file changed, 5 insertions(+), 6 deletions(-) diff --git a/.pipelines/PSReadLine-Official.yml b/.pipelines/PSReadLine-Official.yml index e74081784..5cb0af418 100644 --- a/.pipelines/PSReadLine-Official.yml +++ b/.pipelines/PSReadLine-Official.yml @@ -138,7 +138,7 @@ extends: $WrongCert = @{} Get-ChildItem -Path $(signSrcPath) -Recurse -Include "*.dll","*.ps*1*" | ` Get-AuthenticodeSignature | ForEach-Object { - $_ | Select-Object Path, Status + Write-Host "$($_.Path): $($_.Status)" if ($_.Status -ne 'Valid') { $HasInvalidFiles = $true } if ($_.SignerCertificate.Subject -notmatch 'CN=Microsoft Corporation.*') { $WrongCert.Add($_.Path, $_.SignerCertificate.Subject) @@ -151,8 +151,8 @@ extends: throw "Certificate should have the subject starts with 'Microsoft Corporation'" } - Write-Host "Display files in the folder ..." - Get-ChildItem -Path $(signSrcPath) -Recurse | Out-String -Width 150 + Write-Host "Display files in the folder ..." -ForegroundColor Yellow + Get-ChildItem -Path $(signSrcPath) -Recurse displayName: 'Verify the signed files' - task: CopyFiles@2 @@ -206,8 +206,7 @@ extends: artifact: drop_buildstage_buildjob - pwsh: | - Set-Location "$(signOutPath)" - Get-ChildItem -Directory -Recurse * + Get-ChildItem $(signOutPath) -Recurse New-Item -Path $(nugetPath) -ItemType Directory > $null displayName: Capture artifacts structure @@ -226,7 +225,7 @@ extends: displayName: Sign nupkg inputs: command: 'sign' - signing_profile: external_distribution + signing_profile: external_default files_to_sign: '*.nupkg' search_root: $(nugetPath) From 7264bcbb058504e06681fa8d9d71a61f50b7d676 Mon Sep 17 00:00:00 2001 From: Dongbo Wang Date: Wed, 20 Mar 2024 14:41:56 -0700 Subject: [PATCH 8/9] Fix error (4) --- .pipelines/PSReadLine-Official.yml | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/.pipelines/PSReadLine-Official.yml b/.pipelines/PSReadLine-Official.yml index 5cb0af418..ef4897ed7 100644 --- a/.pipelines/PSReadLine-Official.yml +++ b/.pipelines/PSReadLine-Official.yml @@ -152,7 +152,7 @@ extends: } Write-Host "Display files in the folder ..." -ForegroundColor Yellow - Get-ChildItem -Path $(signSrcPath) -Recurse + Get-ChildItem -Path $(signSrcPath) -Recurse | Out-String -Width 120 displayName: 'Verify the signed files' - task: CopyFiles@2 @@ -232,5 +232,6 @@ extends: - task: CopyFiles@2 displayName: "Copy nupkg to ob_outputDirectory - '$(ob_outputDirectory)'" inputs: - Contents: "$(nugetPath)*.nupkg" + SourceFolder: $(nugetPath) + Contents: '**\*' TargetFolder: $(ob_outputDirectory) From 0ae1f8010662b665057552e9a705726a6f225108 Mon Sep 17 00:00:00 2001 From: Dongbo Wang Date: Wed, 20 Mar 2024 15:50:33 -0700 Subject: [PATCH 9/9] Remove the old 1ES biuld --- .vsts-ci/releaseBuild.yml | 192 -------------------------------------- 1 file changed, 192 deletions(-) delete mode 100644 .vsts-ci/releaseBuild.yml diff --git a/.vsts-ci/releaseBuild.yml b/.vsts-ci/releaseBuild.yml deleted file mode 100644 index dd150aa9a..000000000 --- a/.vsts-ci/releaseBuild.yml +++ /dev/null @@ -1,192 +0,0 @@ -name: PSReadLine-ModuleBuild-$(Build.BuildId) -trigger: none -pr: none - -variables: - DOTNET_CLI_TELEMETRY_OPTOUT: 1 - POWERSHELL_TELEMETRY_OPTOUT: 1 - DOTNET_SKIP_FIRST_TIME_EXPERIENCE: 1 - SBOMGenerator_Formats: 'spdx:2.2' - -resources: - repositories: - - repository: ComplianceRepo - type: github - endpoint: ComplianceGHRepo - name: PowerShell/compliance - -stages: -- stage: Build - displayName: Build and Sign - pool: - name: PowerShell1ES - demands: - - ImageOverride -equals PSMMS2019-Secure - jobs: - - job: build_windows - displayName: Build PSReadLine - variables: - - group: ESRP - - steps: - - - checkout: self - clean: true - persistCredentials: true - - - pwsh: | - function Send-VstsCommand ($vstsCommandString) { - Write-Host ("sending: " + $vstsCommandString) - Write-Host "##$vstsCommandString" - } - Write-Host "PS Version: $($($PSVersionTable.PSVersion))" - Set-Location -Path '$(Build.SourcesDirectory)\PSReadLine' - .\build.ps1 -Bootstrap - .\build.ps1 -Configuration Release -Framework net462 - - # Set target folder paths - New-Item -Path .\bin\Release\NuGetPackage -ItemType Directory > $null - Send-VstsCommand "vso[task.setvariable variable=NuGetPackage]$(Build.SourcesDirectory)\PSReadLine\bin\Release\NuGetPackage" - Send-VstsCommand "vso[task.setvariable variable=PSReadLine]$(Build.SourcesDirectory)\PSReadLine\bin\Release\PSReadLine" - Send-VstsCommand "vso[task.setvariable variable=Signed]$(Build.SourcesDirectory)\PSReadLine\bin\Release\Signed" - displayName: Bootstrap & Build - - - task: ms.vss-governance-buildtask.governance-build-task-component-detection.ComponentGovernanceComponentDetection@0 - displayName: 'Component Governance Detection' - inputs: - sourceScanPath: '$(Build.SourcesDirectory)\PSReadLine' - snapshotForceEnabled: true - scanType: 'Register' - failOnAlert: true - - - checkout: ComplianceRepo - - # Sign the module files - - template: EsrpSign.yml@ComplianceRepo - parameters: - # the folder which contains the binaries to sign - buildOutputPath: $(PSReadLine) - # the location to put the signed output - signOutputPath: $(Signed) - # the certificate ID to use - certificateId: "CP-230012" - pattern: | - *.psd1 - *.psm1 - *.ps1 - *.ps1xml - **\*.dll - !System.Runtime.InteropServices.RuntimeInformation.dll - !Microsoft.PowerShell.Pager.dll - useMinimatch: true - - # Replace the *.psm1, *.ps1, *.psd1, *.dll files with the signed ones - - pwsh: | - # Show the signed files - Get-ChildItem -Path $(Signed) - Copy-Item -Path $(Signed)\* -Destination $(PSReadLine) -Recurse -Force - displayName: 'Replace unsigned files with signed ones' - - # Verify the signatures - - pwsh: | - $HasInvalidFiles = $false - $WrongCert = @{} - Get-ChildItem -Path $(PSReadLine) -Recurse -Include "*.dll","*.ps*1*" | ` - Get-AuthenticodeSignature | ForEach-Object { - $_ | Select-Object Path, Status - if ($_.Status -ne 'Valid') { $HasInvalidFiles = $true } - if ($_.SignerCertificate.Subject -notmatch 'CN=Microsoft Corporation.*') { - $WrongCert.Add($_.Path, $_.SignerCertificate.Subject) - } - } - - if ($HasInvalidFiles) { throw "Authenticode verification failed. There is one or more invalid files." } - if ($WrongCert.Count -gt 0) { - $WrongCert - throw "Certificate should have the subject starts with 'Microsoft Corporation'" - } - displayName: 'Verify the signed files' - - # Generate a Software Bill of Materials (SBOM) - - template: Sbom.yml@ComplianceRepo - parameters: - BuildDropPath: '$(PSReadLine)' - Build_Repository_Uri: 'https://github.com/PowerShell/PSReadLine.git' - displayName: Generate SBOM - - - pwsh: | - try { - $RepoName = "PSRLLocal" - Register-PSRepository -Name $RepoName -SourceLocation $(NuGetPackage) -PublishLocation $(NuGetPackage) -InstallationPolicy Trusted - Publish-Module -Repository $RepoName -Path $(PSReadLine) - } finally { - Unregister-PSRepository -Name $RepoName -ErrorAction SilentlyContinue - } - Get-ChildItem -Path $(NuGetPackage) - displayName: 'Create the NuGet package' - - - pwsh: | - Get-ChildItem -Path $(PSReadLine), $(NuGetPackage) - Write-Host "##vso[artifact.upload containerfolder=PSReadLine;artifactname=PSReadLine]$(PSReadLine)" - Write-Host "##vso[artifact.upload containerfolder=NuGetPackage;artifactname=NuGetPackage]$(NuGetPackage)" - displayName: 'Upload artifacts' - -- stage: compliance - displayName: Compliance - dependsOn: Build - pool: - name: PowerShell1ES - demands: - - ImageOverride -equals PSMMS2019-Secure - jobs: - - job: Compliance_Job - displayName: PSReadLine Compliance - variables: - - group: APIScan - - group: ApiScanMeta - # APIScan can take a long time - timeoutInMinutes: 240 - - steps: - - checkout: self - - checkout: ComplianceRepo - - download: current - artifact: PSReadLine - - - pwsh: | - Get-ChildItem -Path "$(Pipeline.Workspace)\PSReadLine" -Recurse - displayName: Capture downloaded artifacts - - - pwsh: | - function Send-VstsCommand ($vstsCommandString) { - Write-Host ("sending: " + $vstsCommandString) - Write-Host "##$vstsCommandString" - } - - # Get module version - $psd1Data = Import-PowerShellDataFile -Path "$(Pipeline.Workspace)\PSReadLine\PSReadLine.psd1" - $moduleVersion = $psd1Data.ModuleVersion - $prerelease = $psd1Data.PrivateData.PSData.Prerelease - if ($prerelease) { $moduleVersion = "$moduleVersion-$prerelease" } - Send-VstsCommand "vso[task.setvariable variable=ModuleVersion]$moduleVersion" - displayName: Get Module Version - - - template: assembly-module-compliance.yml@ComplianceRepo - parameters: - # binskim - AnalyzeTarget: '$(Pipeline.Workspace)\PSReadLine\*.dll' - AnalyzeSymPath: 'SRV*' - # component-governance - sourceScanPath: '' - # credscan - suppressionsFile: '' - # TermCheck - optionsRulesDBPath: '' - optionsFTPath: '' - # tsa-upload - codeBaseName: 'PSReadLine_201912' - # apiscan - softwareFolder: '$(Pipeline.Workspace)\PSReadLine' - softwareName: 'PSReadLine' - softwareVersion: '$(ModuleVersion)' - connectionString: 'RunAs=App;AppId=$(APIScanClient);TenantId=$(APIScanTenant);AppKey=$(APIScanSecret)'