diff --git a/.github/actions/spelling/allow/microsoft.txt b/.github/actions/spelling/allow/microsoft.txt index 80335179b3..1ed1c6da89 100644 --- a/.github/actions/spelling/allow/microsoft.txt +++ b/.github/actions/spelling/allow/microsoft.txt @@ -4,6 +4,7 @@ advapi altform altforms appendwttlogging +appinstaller appx appxbundle appxerror diff --git a/build/config/template.appinstaller b/build/config/template.appinstaller new file mode 100644 index 0000000000..7977fd950b --- /dev/null +++ b/build/config/template.appinstaller @@ -0,0 +1,38 @@ + + + + + + + + + + + + + + + diff --git a/build/pipelines/nightly.yml b/build/pipelines/nightly.yml index 025a643509..6ec737157f 100644 --- a/build/pipelines/nightly.yml +++ b/build/pipelines/nightly.yml @@ -10,6 +10,12 @@ schedules: name: $(BuildDefinitionName)_$(date:yyMM).$(date:dd)$(rev:rrr) +parameters: + - name: publishToAzure + displayName: "Deploy to **PUBLIC** Azure Storage" + type: boolean + default: true + extends: template: templates-v2\pipeline-full-release-build.yml parameters: @@ -21,3 +27,17 @@ extends: publishSymbolsToPublic: true publishVpackToWindows: false symbolExpiryTime: 15 # Nightly builds do not keep symbols for very long! + ${{ if eq(true, parameters.publishToAzure) }}: + extraPublishJobs: + - template: job-deploy-to-azure-storage.yml + parameters: + pool: + name: SHINE-INT-S + dependsOn: [PublishSymbols] + storagePublicRootURL: $(AppInstallerRootURL) + subscription: $(AzureSubscriptionName) + storageAccount: $(AzureStorageAccount) + storageContainer: $(AzureStorageContainer) + buildConfiguration: Release + environment: production-canary + diff --git a/build/pipelines/templates-v2/job-deploy-to-azure-storage.yml b/build/pipelines/templates-v2/job-deploy-to-azure-storage.yml new file mode 100644 index 0000000000..140a513ee1 --- /dev/null +++ b/build/pipelines/templates-v2/job-deploy-to-azure-storage.yml @@ -0,0 +1,70 @@ +parameters: + - name: buildConfiguration + type: string + - name: pool + type: object + default: [] + - name: dependsOn + type: object + default: null + - name: artifactStem + type: string + default: '' + - name: variables + type: object + default: {} + - name: environment + type: string + - name: storagePublicRootURL + type: string + - name: subscription + type: string + - name: storageAccount + type: string + - name: storageContainer + type: string + +jobs: +- deployment: DeployAzure + ${{ if ne(length(parameters.pool), 0) }}: + pool: ${{ parameters.pool }} + displayName: Publish to Azure Storage (Prod) + dependsOn: ${{ parameters.dependsOn }} + variables: + ${{ insert }}: ${{ parameters.variables }} + environment: ${{ parameters.environment }} + strategy: + runOnce: + deploy: + steps: + - download: none + + - checkout: self + clean: true + fetchDepth: 1 + fetchTags: false # Tags still result in depth > 1 fetch; we don't need them here + submodules: true + persistCredentials: True + + - task: DownloadPipelineArtifact@2 + displayName: Download MSIX Bundle Artifact + inputs: + artifactName: appxbundle-${{ parameters.buildConfiguration }}${{ parameters.artifactStem }} + downloadPath: '$(Build.SourcesDirectory)/_out' + itemPattern: '**/*.msixbundle' + + - pwsh: |- + $b = Get-Item _out/*.msixbundle + ./build/scripts/New-AppInstallerFromTemplateAndBundle.ps1 -BundlePath $b.FullName -AppInstallerTemplatePath ./build/config/template.appinstaller -AppInstallerRoot "${{ parameters.storagePublicRootURL }}" -OutputPath _out/Microsoft.WindowsTerminalCanary.appinstaller + displayName: "Produce AppInstaller for MSIX bundle" + + - task: AzureFileCopy@5 + displayName: Publish to Storage Account + inputs: + sourcePath: _out/* + Destination: AzureBlob + azureSubscription: ${{ parameters.subscription }} + storage: ${{ parameters.storageAccount }} + ContainerName: ${{ parameters.storageContainer }} + AdditionalArgumentsForBlobCopy: "--content-type application/octet-stream" + diff --git a/build/pipelines/templates-v2/job-merge-msix-into-bundle.yml b/build/pipelines/templates-v2/job-merge-msix-into-bundle.yml index 121e07b441..1457178f97 100644 --- a/build/pipelines/templates-v2/job-merge-msix-into-bundle.yml +++ b/build/pipelines/templates-v2/job-merge-msix-into-bundle.yml @@ -48,6 +48,8 @@ jobs: BundleStemName: Microsoft.WindowsTerminal ${{ elseif eq(parameters.branding, 'Preview') }}: BundleStemName: Microsoft.WindowsTerminalPreview + ${{ elseif eq(parameters.branding, 'Canary') }}: + BundleStemName: Microsoft.WindowsTerminalCanary ${{ else }}: BundleStemName: WindowsTerminalDev JobOutputDirectory: '$(System.ArtifactsDirectory)/bundle' diff --git a/build/pipelines/templates-v2/pipeline-full-release-build.yml b/build/pipelines/templates-v2/pipeline-full-release-build.yml index 42c5c6250d..b785deef64 100644 --- a/build/pipelines/templates-v2/pipeline-full-release-build.yml +++ b/build/pipelines/templates-v2/pipeline-full-release-build.yml @@ -51,6 +51,9 @@ parameters: type: boolean default: false + - name: extraPublishJobs + type: object + default: [] - name: pool type: object default: @@ -193,4 +196,5 @@ stages: includePublicSymbolServer: ${{ parameters.publishSymbolsToPublic }} symbolExpiryTime: ${{ parameters.symbolExpiryTime }} + - ${{ parameters.extraPublishJobs }} ... diff --git a/build/scripts/New-AppInstallerFromTemplateAndBundle.ps1 b/build/scripts/New-AppInstallerFromTemplateAndBundle.ps1 new file mode 100644 index 0000000000..b49ad244ff --- /dev/null +++ b/build/scripts/New-AppInstallerFromTemplateAndBundle.ps1 @@ -0,0 +1,42 @@ +[CmdletBinding()] +Param( + [Parameter(Mandatory, + HelpMessage="Path to the .msixbundle")] + [string] + $BundlePath, + + [Parameter(Mandatory, + HelpMessage="Path to the .appinstaller template")] + [string] + $AppInstallerTemplatePath, + + [string] + $AppInstallerRoot, + + [Parameter(Mandatory, + HelpMessage="Output Path")] + [string] + $OutputPath +) + +$ErrorActionPreference = "Stop" + +$sentinelFile = New-TemporaryFile +$directory = New-Item -Type Directory "$($sentinelFile.FullName)_Package" +Remove-Item $sentinelFile -Force -EA:Ignore + +$bundle = (Get-Item $BundlePath) +& tar.exe -x -f $bundle.FullName -C $directory AppxMetadata/AppxBundleManifest.xml + +$xml = [xml](Get-Content (Join-Path $directory "AppxMetadata\AppxBundleManifest.xml")) +$name = $xml.Bundle.Identity.Name +$version = $xml.Bundle.Identity.Version + +$doc = (Get-Content -ReadCount 0 $AppInstallerTemplatePath) +$doc = $doc -Replace '\$\$ROOT\$\$',$AppInstallerRoot +$doc = $doc -Replace '\$\$NAME\$\$',$name +$doc = $doc -Replace '\$\$VERSION\$\$',$version +$doc = $doc -Replace '\$\$PACKAGE\$\$',$bundle.Name +$doc | Out-File -Encoding utf8NoBOM $OutputPath + +Get-Item $OutputPath