diff --git a/.github/workflows/release-azure-pipelines.yml b/.github/workflows/release-azure-pipelines.yml index 0767004c..42189ff0 100644 --- a/.github/workflows/release-azure-pipelines.yml +++ b/.github/workflows/release-azure-pipelines.yml @@ -2,7 +2,6 @@ parameters: - name: version type: string - default: 0.8.6 - name: prerelease displayName: Prerelease? type: boolean @@ -38,6 +37,7 @@ variables: readonly: true trigger: none + pr: none resources: @@ -66,16 +66,16 @@ extends: - job: validate displayName: Validate steps: - - checkout: self - - task: UsePythonVersion@0 - displayName: Use Python $(pythonVersion) - inputs: - versionSpec: $(pythonVersion) - - task: Bash@3 - inputs: - targetType: inline - script: | - echo ${{ parameters.version }} | python ./bin/version.py + - checkout: self + - task: UsePythonVersion@0 + displayName: Use Python $(pythonVersion) + inputs: + versionSpec: $(pythonVersion) + - task: Bash@3 + inputs: + targetType: inline + script: | + echo ${{ parameters.version }} | python ./bin/version.py - stage: build displayName: Build @@ -93,40 +93,268 @@ extends: targetPath: dist/${{ config.runtime }} artifactName: azureauth-${{ parameters.version }}-${{ config.runtime }} steps: - - checkout: self - - task: UseDotNet@2 - displayName: Use .NET Core sdk 6.x - inputs: - version: 6.x + - checkout: self + - task: UseDotNet@2 + displayName: Use .NET Core sdk 6.x + inputs: + version: 6.x + - task: NuGetToolInstaller@0 + displayName: Use NuGet 6.x + inputs: + versionSpec: 6.x + - task: DotNetCoreCLI@2 + displayName: Install dependencies + inputs: + command: restore + feedsToUse: select + vstsFeed: $(VSTS_FEED_ID) + includeNuGetOrg: false + arguments: --runtime ${{ config.runtime }} + - task: DotNetCoreCLI@2 + displayName: Test + inputs: + command: test + arguments: --configuration release --no-restore + + - task: DotNetCoreCLI@2 + displayName: Build artifacts + env: + ADO_TOKEN: $(System.AccessToken) + inputs: + command: publish + projects: src/AzureAuth/AzureAuth.csproj + arguments: -p:Version=${{ parameters.version }} --configuration release --self-contained true --runtime ${{ config.runtime }} --output dist/${{ config.runtime }} + publishWebProjects: false + zipAfterPublish: false + modifyOutputPath: true - - task: NuGetToolInstaller@0 - displayName: Use NuGet 6.x - inputs: - versionSpec: 6.x + - stage: sign + displayName: Sign + dependsOn: build + jobs: + - ${{ each config in parameters.buildConfigs }}: + - job: sign_${{ replace(config.runtime,'-', '_') }} + displayName: Signing ${{ config.runtime }} + pool: + name: Azure-Pipelines-1ESPT-ExDShared + image: windows-latest + os: windows + templateContext: + inputs: + - input: pipelineArtifact + artifactName: azureauth-${{ parameters.version }}-${{ config.runtime }} + targetPath: $(Build.ArtifactStagingDirectory)/azureauth-${{ parameters.version }}-${{ config.runtime }} + outputs: + - output: pipelineArtifact + artifactName: azureauth-${{ parameters.version }}-${{ config.runtime }}-signed + targetPath: $(Build.ArtifactStagingDirectory)/azureauth-${{ parameters.version }}-${{ config.runtime }}-signed + steps: + - task: EsrpCodeSigning@5 + displayName: Sign artifacts win10-x64 + condition: eq('${{ config.runtime }}', 'win10-x64') + inputs: + ConnectedServiceName: $(ESRP_KV_SERVICE_CONNECTION) + AppRegistrationClientId: $(SIGNING_AAD_ID) + AppRegistrationTenantId: $(SIGNING_TENANT_ID) + AuthAKVName: $(AZURE_VAULT) + AuthCertName: $(AZURE_VAULT_ESRP_AAD_CERT_NAME) + AuthSignCertName: $(AZURE_VAULT_ESRP_REQ_CERT_NAME) + FolderPath: $(Build.ArtifactStagingDirectory)/azureauth-${{ parameters.version }}-${{ config.runtime }}/AzureAuth + Pattern: '*.dll,*.exe' + signConfigType: 'inlineSignParams' + inlineOperation: | + [ + { + "KeyCode": "$(SIGNING_KEY_CODE_AUTHENTICODE)", + "OperationCode": "SigntoolSign", + "ToolName": "sign", + "ToolVersion": "1.0", + "Parameters": { + "OpusName": "Microsoft", + "OpusInfo": "https://www.microsoft.com", + "FileDigest": "/fd SHA256", + "PageHash": "/NPH", + "TimeStamp": "/tr \"http://rfc3161.gtm.corp.microsoft.com/TSS/HttpTspServer\" /td sha256" + } + }, + { + "KeyCode": "$(SIGNING_KEY_CODE_AUTHENTICODE)", + "OperationCode": "SigntoolVerify", + "ToolName": "sign", + "ToolVersion": "1.0", + "Parameters": {} + } + ] + SessionTimeout: '60' + MaxConcurrency: '50' + MaxRetryAttempts: '5' + PendingAnalysisWaitTimeoutMinutes: '5' + # We need to zip the artifacts for osx before sending to ESRP for signing. + - task: ArchiveFiles@2 + displayName: Codesigning - zip artifacts to send to ESRP + condition: startsWith('${{ config.runtime }}', 'osx') + inputs: + rootFolderOrFile: $(Build.ArtifactStagingDirectory)/azureauth-${{ parameters.version }}-${{ config.runtime }} + includeRootFolder: false + archiveType: zip + archiveFile: $(Build.ArtifactStagingDirectory)/azureauth-${{ parameters.version }}-${{ config.runtime }}.zip + - task: EsrpCodeSigning@5 + displayName: Sign artifacts osx + condition: startsWith('${{ config.runtime }}', 'osx') + inputs: + ConnectedServiceName: $(ESRP_KV_SERVICE_CONNECTION) + AppRegistrationClientId: $(SIGNING_AAD_ID) + AppRegistrationTenantId: $(SIGNING_TENANT_ID) + AuthAKVName: $(AZURE_VAULT) + AuthCertName: $(AZURE_VAULT_ESRP_AAD_CERT_NAME) + AuthSignCertName: $(AZURE_VAULT_ESRP_REQ_CERT_NAME) + FolderPath: $(Build.ArtifactStagingDirectory) + Pattern: 'azureauth-${{ parameters.version }}-${{ config.runtime }}.zip' + signConfigType: 'inlineSignParams' + inlineOperation: | + [ + { + "KeyCode": "$(SIGNING_KEY_CODE_MAC)", + "OperationCode": "MacAppDeveloperSign", + "ToolName": "sign", + "ToolVersion": "1.0", + "Parameters": {} + }, + { + "KeyCode": "$(SIGNING_KEY_CODE_MAC)", + "OperationCode": "SigntoolVerify", + "ToolName": "sign", + "ToolVersion": "1.0", + "Parameters": {} + } + ] + SessionTimeout: '60' + MaxConcurrency: '50' + MaxRetryAttempts: '5' + PendingAnalysisWaitTimeoutMinutes: '5' + - task: ExtractFiles@1 + displayName: Extract signed artifacts osx + condition: startsWith('${{ config.runtime }}', 'osx') + inputs: + archiveFilePatterns: $(Build.ArtifactStagingDirectory)/azureauth-${{ parameters.version }}-${{ config.runtime }}.zip + destinationFolder: $(Build.ArtifactStagingDirectory)/azureauth-${{ parameters.version }}-${{ config.runtime }} + cleanDestinationFolder: true + overwriteExistingFiles: true + # We rename the signed artifacts to avoid conflicts with the unsigned pipeline artifacts from the previous stage. + - task: PowerShell@2 + displayName: Rename signed artifacts + inputs: + workingDirectory: $(Build.ArtifactStagingDirectory) + targetType: 'inline' + script: | + mv "azureauth-${{ parameters.version }}-${{ config.runtime }}" "azureauth-${{ parameters.version }}-${{ config.runtime }}-signed" - - task: DotNetCoreCLI@2 - displayName: Install dependencies - inputs: - command: restore - feedsToUse: select - vstsFeed: $(vstsFeedId) - includeNuGetOrg: false - arguments: --runtime ${{ config.runtime }} + # Currently we package artifacts into the most commonly accessible archive format for their respective platforms. + - stage: package + displayName: Package + dependsOn: sign + jobs: + - job: package + displayName: Package + pool: + name: Azure-Pipelines-1ESPT-ExDShared + image: ubuntu-latest + os: linux + templateContext: + inputs: + - ${{ each config in parameters.buildConfigs }}: + - input: pipelineArtifact + artifactName: azureauth-${{ parameters.version }}-${{ config.runtime }}-signed + targetPath: $(Build.ArtifactStagingDirectory)/azureauth-${{ parameters.version }}-${{ config.runtime }}-signed + outputs: + - ${{ each config in parameters.buildConfigs }}: + - output: pipelineArtifact + artifactName: azureauth-${{ parameters.version }}-${{ config.runtime }}.${{ config.archiveExt }} + targetPath: $(Build.SourcesDirectory)/azureauth-${{ parameters.version }}-${{ config.runtime }}.${{ config.archiveExt }} + steps: + - task: ArchiveFiles@2 + displayName: Create win10-x64 archive + inputs: + rootFolderOrFile: $(Build.ArtifactStagingDirectory)/azureauth-${{ parameters.version }}-win10-x64-signed/AzureAuth + includeRootFolder: false + archiveType: zip + archiveFile: azureauth-${{ parameters.version }}-win10-x64.zip + - task: Bash@3 + displayName: Prepare osx-x64 executables + inputs: + targetType: inline + workingDirectory: $(Build.ArtifactStagingDirectory) + script: | + cd azureauth-${{ parameters.version }}-osx-x64-signed/AzureAuth + chmod +x azureauth createdump *.dylib + - task: ArchiveFiles@2 + displayName: Create osx-x64 archive + inputs: + rootFolderOrFile: $(Build.ArtifactStagingDirectory)/azureauth-${{ parameters.version }}-osx-x64-signed/AzureAuth + includeRootFolder: false + archiveType: tar + tarCompression: gz + archiveFile: azureauth-${{ parameters.version }}-osx-x64.tar.gz + - task: Bash@3 + displayName: Prepare osx-arm64 executables + inputs: + workingDirectory: $(Build.ArtifactStagingDirectory) + targetType: inline + script: | + cd azureauth-${{ parameters.version }}-osx-arm64-signed/AzureAuth + chmod +x azureauth createdump *.dylib + - task: ArchiveFiles@2 + displayName: Create osx-arm64 archive + inputs: + rootFolderOrFile: $(Build.ArtifactStagingDirectory)/azureauth-${{ parameters.version }}-osx-arm64-signed/AzureAuth + includeRootFolder: false + archiveType: tar + tarCompression: gz + archiveFile: azureauth-${{ parameters.version }}-osx-arm64.tar.gz - - task: DotNetCoreCLI@2 - displayName: Test - inputs: - command: test - arguments: --configuration release --no-restore - - - task: DotNetCoreCLI@2 - displayName: Build artifacts - env: - ADO_TOKEN: $(System.AccessToken) - inputs: - command: publish - projects: src/AzureAuth/AzureAuth.csproj - arguments: -p:Version=${{ parameters.version }} --configuration release --self-contained true --runtime ${{ config.runtime }} --output dist/${{ config.runtime }} - publishWebProjects: false - zipAfterPublish: false - modifyOutputPath: true \ No newline at end of file + - stage: release + displayName: Release + dependsOn: package + jobs: + - job: approval + displayName: Manual Approval + pool: server + timeoutInMinutes: 5760 # job times out in 4 days + steps: + - task: ManualValidation@0 + timeoutInMinutes: 4320 # task times out in 3 days + inputs: + notifyUsers: $(REVIEWER) + instructions: 'Review the AzureAuth GitHub Release.' + - job: release + displayName: Release + dependsOn: approval + pool: + name: Azure-Pipelines-1ESPT-ExDShared + image: ubuntu-latest + os: linux + templateContext: + inputs: + - ${{ each config in parameters.buildConfigs }}: + - input: pipelineArtifact + artifactName: azureauth-${{ parameters.version }}-${{ config.runtime }}.${{ config.archiveExt }} + targetPath: $(Build.ArtifactStagingDirectory)/azureauth-${{ parameters.version }}-${{ config.runtime }}.${{ config.archiveExt }} + steps: + - task: GitHubRelease@1 + displayName: Create AzureAuth GitHub Release + inputs: + gitHubConnection: $(GITHUB_RELEASE_SERVICE_CONNECTION) + repositoryName: 'AzureAD/microsoft-authentication-cli' + action: 'create' + target: $(Build.SourceVersion) + tagSource: 'userSpecifiedTag' + tag: ${{ parameters.version }} + isPrerelease: ${{ parameters.prerelease }} + isDraft: true + addChangeLog: false + releaseNotesSource: 'inline' + releaseNotesInline: "Release ${{ parameters.version }}. See [`CHANGELOG.md`](https://github.com/AzureAD/microsoft-authentication-cli/blob/${{ parameters.version }}/CHANGELOG.md) for updates." + assets: | + $(Build.ArtifactStagingDirectory)/azureauth-${{ parameters.version }}-win10-x64.zip/azureauth-${{ parameters.version }}-win10-x64.zip + $(Build.ArtifactStagingDirectory)/azureauth-${{ parameters.version }}-osx-x64.tar.gz/azureauth-${{ parameters.version }}-osx-x64.tar.gz + $(Build.ArtifactStagingDirectory)/azureauth-${{ parameters.version }}-osx-arm64.tar.gz/azureauth-${{ parameters.version }}-osx-arm64.tar.gz \ No newline at end of file