diff --git a/.vsts.pipelines/builds/matrix.yml b/.vsts.pipelines/builds/matrix.yml index 9136ed99c8..2a7b2c52a5 100644 --- a/.vsts.pipelines/builds/matrix.yml +++ b/.vsts.pipelines/builds/matrix.yml @@ -72,3 +72,16 @@ jobs: scriptPrefix: ./ scriptSuffix: .sh setupMac: true + +# Prepare artifacts in all situations but public PR validation. +- ${{ if not(and(eq(variables['System.TeamProject'], 'public'), in(variables['Build.Reason'], 'PullRequest'))) }}: + - template: ../jobs/prepare-artifacts.yml + parameters: + # Gather from all jobs that have offline in the matrix. This also defines dependencies. + gatherJobs: + - job: centos71 + - job: centos8 + - job: debian9 + artifactName: Tarball debian9 Online + - job: fedora30 + gatherPortableJob: centos71 diff --git a/.vsts.pipelines/jobs/prepare-artifacts.yml b/.vsts.pipelines/jobs/prepare-artifacts.yml new file mode 100644 index 0000000000..339e282731 --- /dev/null +++ b/.vsts.pipelines/jobs/prepare-artifacts.yml @@ -0,0 +1,84 @@ +parameters: + gatherJobs: [] + gatherPortableJob: '' + + # downloadBuildConfig by default uses the current build, but can be changed to point at an + # existing/previous build by passing properties like these, instead: + # + # buildType: specific + # buildVersionToDownload: specific + # project: 'public' + # definition: 'source-build-CI' + # buildId: 741400 + # + # By defining this in one place, it's easier to set this up if necessary. This may be useful + # because the build takes a long time relative to prepare-artifacts, and we may want to tweak + # prepare-artifacts in case it fails due to a bug in the future. ...It's also nice to have the + # properties listed in this comment even if we don't use them here, because it's hard to figure + # them out from the docs alone--it'll be a nice reference. + downloadBuildConfig: + buildType: current + +jobs: +- job: PrepareArtifacts + pool: + vmImage: 'ubuntu-18.04' + dependsOn: + - ${{ each gather in parameters.gatherJobs }}: + - ${{ gather.job }} + timeoutInMinutes: 300 + workspace: + clean: all + variables: + artifactStageDir: '$(Build.SourcesDirectory)/artifacts/stage' + nonportableSourceBuiltStageDir: '$(artifactStageDir)/nonportableSourceBuilt' + portableSourceBuiltStageDir: '$(artifactStageDir)/portableSourceBuilt' + allSourceBuiltStageDir: '$(artifactStageDir)/allSourceBuilt' + outputTarballFile: '$(artifactStageDir)/Private.SourceBuilt.Artifacts.$(Build.BuildId).tar.gz' + steps: + - ${{ each gather in parameters.gatherJobs }}: + - task: DownloadBuildArtifacts@0 + displayName: 'Download ${{ gather.job }} nonportable' + inputs: + ${{ insert }}: ${{ parameters.downloadBuildConfig }} + downloadType: single + artifactName: ${{ coalesce(gather.artifactName, format('Tarball {0} Offline', gather.job)) }} + downloadPath: $(nonportableSourceBuiltStageDir) + allowPartiallySucceededBuilds: true + + - task: DownloadBuildArtifacts@0 + displayName: 'Download ${{ parameters.gatherPortableJob }} portable' + inputs: + ${{ insert }}: ${{ parameters.downloadBuildConfig }} + downloadType: single + artifactName: 'Tarball ${{ parameters.gatherPortableJob }} Offline Portable' + downloadPath: $(portableSourceBuiltStageDir) + allowPartiallySucceededBuilds: true + + - script: | + find "$(artifactStageDir)" -type f -exec du -h {} \; + displayName: Show downloaded artifacts + + - script: | + set -xeuo pipefail + mkdir -p "$(allSourceBuiltStageDir)" + + # Extract all source-built assets into a single place. Overlap and overwrites are expected. + # What matters is the portable ones are copied last and ultimately win. + find \ + "$(nonportableSourceBuiltStageDir)" \ + "$(portableSourceBuiltStageDir)" \ + -iname 'Private.SourceBuilt.Artifacts.*.tar.gz' \ + -exec tar -xf {} -C "$(allSourceBuiltStageDir)" \; + + # Intentionally don't create a top-level directory. Matches earlier versions of this artifact. + cd "$(allSourceBuiltStageDir)" + tar --numeric-owner -czf "$(outputTarballFile)" * + displayName: Create source-built artifacts tar.gz + + - publish: '$(outputTarballFile)' + artifact: Private.SourceBuilt.Artifacts + + - script: | + tar -tf "$(outputTarballFile)" | sort + displayName: Show tarball contents diff --git a/scripts/fetch-azdo-artifact-tarball.sh b/scripts/fetch-azdo-artifact-tarball.sh index b37dc9b032..303ff925e7 100644 --- a/scripts/fetch-azdo-artifact-tarball.sh +++ b/scripts/fetch-azdo-artifact-tarball.sh @@ -1,17 +1,21 @@ #!/usr/bin/env bash -set -euo pipefail +# Library. Source this script or copy-paste it into a shell to import its functions. -# Logic is encapsulated to make this function easy to copy-paste to a machine that doesn't have a -# clone of this repository. This may be common when downloading a tarball. +# Set up AzDO authentication if not already done in this environment, download a file, and extract +# it to the current dir. Logic is encapsulated to make this function easy to copy-paste to a machine +# that doesn't have a clone of this repository, which is common when downloading a tarball onto a +# fresh machine to validate it. +# +# Usage: download_tarball +# url: the URL to download. Wrap it in single quotes to avoid issues with special chars. download_tarball() { + [ "${azdo_build_pat:-}" ] || read -p 'AzDO dnceng PAT with build read permission: ' -s azdo_build_pat ( set -euo pipefail url=$1 temp_name=${temp_name:-tarball.tar.gz} - [ "$azdo_build_pat" ] || read -p 'AzDO dnceng PAT with build read permission: ' -s azdo_build_pat - echo; echo 'Starting download...' curl -o "$temp_name" -u "intentionally_blank:$azdo_build_pat" "$url" @@ -19,6 +23,7 @@ download_tarball() { echo "Extracted using tar -xf" # Fall back to 'gunzip' as an intermediate to avoid problems found # decompressing archives with 'tar' when downloaded directly from AzDO. + # AzDO seems to double-compress the tar.gz: https://superuser.com/a/841876 elif gunzip -d < "$temp_name" | tar -zx; then echo "Extracted using gunzip" else @@ -30,5 +35,3 @@ download_tarball() { echo 'Complete!' ) } - -download_tarball "$@"