diff --git a/common/config/azure-pipelines/esrp-publish-rush.yaml b/common/config/azure-pipelines/esrp-publish-rush.yaml new file mode 100644 index 0000000000..8310745af2 --- /dev/null +++ b/common/config/azure-pipelines/esrp-publish-rush.yaml @@ -0,0 +1,70 @@ +# Pipeline: rushstack-esrp-publish-rush (AzDO project GitHubProjectsPublish) +# Trigger: Automatically when a version bump PR from the Rush bump pipeline (definition 12) merges to main. +# Purpose: Publish the tarballs packed by that bump pipeline run to the npm feed via ESRP. + +trigger: + branches: + include: + - main + paths: + include: + - '**/CHANGELOG.md' + - 'common/config/rush/version-policies.json' + +pr: none + +parameters: + - name: publishToNpmFeed + displayName: 'Publish to npm feed' + type: boolean + default: true + - name: NpmTag + displayName: 'NPM dist-tag' + type: string + default: latest + - name: DryRun + displayName: 'Dry run' + type: boolean + default: false + - name: CommitShaOverride + displayName: 'Commit SHA Override (for testing)' + type: string + default: '' + +variables: + - name: FORCE_COLOR + value: 1 + - name: PackagesPath + value: $(Pipeline.Workspace)/packages + +resources: + repositories: + - repository: 1esPipelines + type: git + name: 1ESPipelineTemplates/1ESPipelineTemplates + ref: refs/tags/release + - repository: publishConfig + type: git + name: GitHubProjectsPublish/GitHubProjectsPublish + ref: refs/heads/main + +extends: + template: v1/1ES.Official.PipelineTemplate.yml@1esPipelines + parameters: + settings: + networkIsolationPolicy: CFSClean,CFSClean2,CFSClean3,DefaultDeny + pool: + name: Azure-Pipelines-1ESPT-ExDShared + os: windows + stages: + - template: /common/config/azure-pipelines/templates/esrp-publish-stages.yaml@self + parameters: + # https://dev.azure.com/RushStack/GitHubProjects/_build?definitionId=12 + BumpPipelineId: 12 + BumpPipelineProject: GitHubProjects + StageNameSuffix: Rush + DisplayNameSuffix: Rush + PublishToNpmFeed: ${{ parameters.publishToNpmFeed }} + NpmTag: ${{ parameters.NpmTag }} + DryRun: ${{ parameters.DryRun }} + CommitShaOverride: ${{ parameters.CommitShaOverride }} diff --git a/common/config/azure-pipelines/esrp-publish-rushstack.yaml b/common/config/azure-pipelines/esrp-publish-rushstack.yaml new file mode 100644 index 0000000000..bd5be66827 --- /dev/null +++ b/common/config/azure-pipelines/esrp-publish-rushstack.yaml @@ -0,0 +1,70 @@ +# Pipeline: rushstack-esrp-publish (AzDO project GitHubProjectsPublish) +# Trigger: Automatically when a version bump PR from the non-Rush bump pipeline (definition 10) merges to main. +# Purpose: Publish the tarballs packed by that bump pipeline run to the npm feed via ESRP. + +trigger: + branches: + include: + - main + paths: + include: + - '**/CHANGELOG.md' + - 'common/config/rush/version-policies.json' + +pr: none + +parameters: + - name: publishToNpmFeed + displayName: 'Publish to npm feed' + type: boolean + default: true + - name: NpmTag + displayName: 'NPM dist-tag' + type: string + default: latest + - name: DryRun + displayName: 'Dry run' + type: boolean + default: false + - name: CommitShaOverride + displayName: 'Commit SHA Override (for testing)' + type: string + default: '' + +variables: + - name: FORCE_COLOR + value: 1 + - name: PackagesPath + value: $(Pipeline.Workspace)/packages + +resources: + repositories: + - repository: 1esPipelines + type: git + name: 1ESPipelineTemplates/1ESPipelineTemplates + ref: refs/tags/release + - repository: publishConfig + type: git + name: GitHubProjectsPublish/GitHubProjectsPublish + ref: refs/heads/main + +extends: + template: v1/1ES.Official.PipelineTemplate.yml@1esPipelines + parameters: + settings: + networkIsolationPolicy: CFSClean,CFSClean2,CFSClean3,DefaultDeny + pool: + name: Azure-Pipelines-1ESPT-ExDShared + os: windows + stages: + - template: /common/config/azure-pipelines/templates/esrp-publish-stages.yaml@self + parameters: + # https://dev.azure.com/RushStack/GitHubProjects/_build?definitionId=10 + BumpPipelineId: 10 + BumpPipelineProject: GitHubProjects + StageNameSuffix: Rushstack + DisplayNameSuffix: Rushstack + PublishToNpmFeed: ${{ parameters.publishToNpmFeed }} + NpmTag: ${{ parameters.NpmTag }} + DryRun: ${{ parameters.DryRun }} + CommitShaOverride: ${{ parameters.CommitShaOverride }} diff --git a/common/config/azure-pipelines/npm-post-publish.yaml b/common/config/azure-pipelines/npm-post-publish.yaml index 04549b7107..06bde01cc1 100644 --- a/common/config/azure-pipelines/npm-post-publish.yaml +++ b/common/config/azure-pipelines/npm-post-publish.yaml @@ -10,22 +10,24 @@ variables: - name: FORCE_COLOR value: 1 -# This pipeline is triggered only by pipeline resources (npm publish pipelines), +# This pipeline is triggered only by pipeline resources (esrp publish pipelines), # not by CI pushes or PR builds. trigger: none pr: none resources: pipelines: - - pipeline: npmPublish - source: 'rushstack NPM Publish' + - pipeline: esrpPublishRushstack + source: 'rushstack-esrp-publish' + project: GitHubProjectsPublish trigger: enabled: true branches: include: - refs/heads/main - - pipeline: npmPublishRush - source: 'rushstack NPM Publish (rush)' + - pipeline: esrpPublishRush + source: 'rushstack-esrp-publish-rush' + project: GitHubProjectsPublish trigger: enabled: true branches: @@ -45,6 +47,8 @@ resources: extends: template: v1/1ES.Official.PipelineTemplate.yml@1esPipelines parameters: + settings: + networkIsolationPolicy: CFSClean,CFSClean2,CFSClean3,DefaultDeny sdl: sourceRepositoriesToScan: exclude: @@ -222,8 +226,8 @@ extends: displayName: 'Download API review files' inputs: source: specific - project: GitHubProjects - pipeline: 'rushstack NPM Publish' + project: GitHubProjectsPublish + pipeline: 'rushstack-esrp-publish' preferTriggeringPipeline: true runVersion: latest artifact: api diff --git a/common/config/azure-pipelines/npm-publish-rush.yaml b/common/config/azure-pipelines/npm-publish-rush.yaml index 70727beb73..2bf716b191 100644 --- a/common/config/azure-pipelines/npm-publish-rush.yaml +++ b/common/config/azure-pipelines/npm-publish-rush.yaml @@ -1,82 +1,54 @@ -parameters: - - name: publishToNpmFeed - displayName: 'Publish to npm feed' - type: boolean - default: true - -variables: - - name: FORCE_COLOR - value: 1 - - name: SourceBranch - value: $[ replace(replace(resources.repositories.self.ref, 'refs/heads/', ''), 'refs/pull/', 'refs/remotes/pull/') ] - -resources: - repositories: - - repository: 1esPipelines - type: git - name: 1ESPipelineTemplates/1ESPipelineTemplates - ref: refs/tags/release - -extends: - template: v1/1ES.Official.PipelineTemplate.yml@1esPipelines - parameters: - pool: - name: Azure-Pipelines-1ESPT-ExDShared - os: windows - stages: - - stage: - jobs: - - job: - pool: - name: publish-rushstack - os: linux - templateContext: - outputParentDirectory: $(Build.ArtifactStagingDirectory) - outputs: - - output: pipelineArtifact - targetPath: $(Build.ArtifactStagingDirectory)/published-versions - artifactName: published-versions - - output: pipelineArtifact - targetPath: $(Build.ArtifactStagingDirectory)/json-schemas - artifactName: json-schemas - - output: pipelineArtifact - targetPath: $(Build.ArtifactStagingDirectory)/packages - artifactName: packages - - output: pipelineArtifact - targetPath: $(Build.ArtifactStagingDirectory)/api - artifactName: api - steps: - - checkout: self - persistCredentials: true - - - template: /common/config/azure-pipelines/templates/install-node.yaml@self - - - template: /common/config/azure-pipelines/templates/build.yaml@self - - - template: /common/config/azure-pipelines/templates/bump-versions.yaml@self - parameters: - VersionPolicyName: noRush - BranchName: $(SourceBranch) - - - template: /common/config/azure-pipelines/templates/bump-versions.yaml@self - parameters: - VersionPolicyName: rush - BranchName: $(SourceBranch) - - - script: 'node libraries/rush-lib/scripts/plugins-prepublish.js' - displayName: 'Prepublish workaround for rush-lib' - - - template: /common/config/azure-pipelines/templates/pack.yaml@self - - - ${{ if eq(parameters.publishToNpmFeed, true) }}: - - template: /common/config/azure-pipelines/templates/publish.yaml@self - parameters: - VersionPolicyName: noRush - BranchName: $(SourceBranch) - - - template: /common/config/azure-pipelines/templates/publish.yaml@self - parameters: - VersionPolicyName: rush - BranchName: $(SourceBranch) - - - template: /common/config/azure-pipelines/templates/post-publish.yaml@self +# Pipeline: Bump Versions (Rush) -- AzDO definition 12 in the GitHubProjects project +# Trigger: Automatically when changes merge to main that include change files or pipeline YAML. +# Purpose: Bump versions for the "rush" version policy, build, pack, create/update GitHub PR. +# The packed tarballs are published by the "esrp-publish-rush.yaml" pipeline once the +# resulting version bump PR is merged. + +trigger: + batch: true + branches: + include: + - main + paths: + include: + - 'common/changes/*' + - 'common/config/rush/version-policies.json' + - 'common/config/azure-pipelines/**' + +pr: none + +variables: + - name: FORCE_COLOR + value: 1 + - name: BaseBranch + value: $[ replace(variables['Build.SourceBranch'], 'refs/heads/', '') ] + +resources: + repositories: + - repository: 1esPipelines + type: git + name: 1ESPipelineTemplates/1ESPipelineTemplates + ref: refs/tags/release + +extends: + template: v1/1ES.Official.PipelineTemplate.yml@1esPipelines + parameters: + settings: + networkIsolationPolicy: CFSClean,CFSClean2,CFSClean3,DefaultDeny + pool: + name: Azure-Pipelines-1ESPT-ExDShared + os: windows + stages: + - template: /common/config/azure-pipelines/templates/bump-versions-stages.yaml@self + parameters: + VersionPolicyName: rush + StageName: BumpRushVersions + StageDisplayName: 'Bump Rush Versions and Create PR' + FeatureBranch: 'automated/bump-versions-rush' + PrTitle: 'Bump Rush package versions' + PrDescription: | + Automated version bump generated by Azure DevOps Pipeline. + + This PR contains version bumps for the "rush" version policy. + + **Pipeline Run:** $(System.CollectionUri)$(System.TeamProject)/_build/results?buildId=$(Build.BuildId) diff --git a/common/config/azure-pipelines/npm-publish.yaml b/common/config/azure-pipelines/npm-publish.yaml index 2b589c4a73..9b252348ab 100644 --- a/common/config/azure-pipelines/npm-publish.yaml +++ b/common/config/azure-pipelines/npm-publish.yaml @@ -1,72 +1,54 @@ -parameters: - - name: publishToNpmFeed - displayName: 'Publish to npm feed' - type: boolean - default: true - -variables: - - name: FORCE_COLOR - value: 1 - - name: SourceBranch - value: $[ replace(replace(resources.repositories.self.ref, 'refs/heads/', ''), 'refs/pull/', 'refs/remotes/pull/') ] - -resources: - repositories: - - repository: 1esPipelines - type: git - name: 1ESPipelineTemplates/1ESPipelineTemplates - ref: refs/tags/release - -extends: - template: v1/1ES.Official.PipelineTemplate.yml@1esPipelines - parameters: - pool: - name: Azure-Pipelines-1ESPT-ExDShared - os: windows - stages: - - stage: - jobs: - - job: - pool: - name: publish-rushstack - os: linux - templateContext: - outputParentDirectory: $(Build.ArtifactStagingDirectory) - outputs: - - output: pipelineArtifact - targetPath: $(Build.ArtifactStagingDirectory)/published-versions - artifactName: published-versions - - output: pipelineArtifact - targetPath: $(Build.ArtifactStagingDirectory)/json-schemas - artifactName: json-schemas - - output: pipelineArtifact - targetPath: $(Build.ArtifactStagingDirectory)/packages - artifactName: packages - - output: pipelineArtifact - targetPath: $(Build.ArtifactStagingDirectory)/api - artifactName: api - steps: - - checkout: self - persistCredentials: true - - - template: /common/config/azure-pipelines/templates/install-node.yaml@self - - - template: /common/config/azure-pipelines/templates/build.yaml@self - - - template: /common/config/azure-pipelines/templates/bump-versions.yaml@self - parameters: - VersionPolicyName: noRush - BranchName: $(SourceBranch) - - - script: 'node libraries/rush-lib/scripts/plugins-prepublish.js' - displayName: 'Prepublish workaround for rush-lib' - - - template: /common/config/azure-pipelines/templates/pack.yaml@self - - - ${{ if eq(parameters.publishToNpmFeed, true) }}: - - template: /common/config/azure-pipelines/templates/publish.yaml@self - parameters: - VersionPolicyName: noRush - BranchName: $(SourceBranch) - - - template: /common/config/azure-pipelines/templates/post-publish.yaml@self +# Pipeline: Bump Versions (non-Rush) -- AzDO definition 10 in the GitHubProjects project +# Trigger: Automatically when changes merge to main that include change files or pipeline YAML. +# Purpose: Bump versions for the "noRush" version policy, build, pack, create/update GitHub PR. +# The packed tarballs are published by the "esrp-publish-rushstack.yaml" pipeline once the +# resulting version bump PR is merged. + +trigger: + batch: true + branches: + include: + - main + paths: + include: + - 'common/changes/*' + - 'common/config/rush/version-policies.json' + - 'common/config/azure-pipelines/**' + +pr: none + +variables: + - name: FORCE_COLOR + value: 1 + - name: BaseBranch + value: $[ replace(variables['Build.SourceBranch'], 'refs/heads/', '') ] + +resources: + repositories: + - repository: 1esPipelines + type: git + name: 1ESPipelineTemplates/1ESPipelineTemplates + ref: refs/tags/release + +extends: + template: v1/1ES.Official.PipelineTemplate.yml@1esPipelines + parameters: + settings: + networkIsolationPolicy: CFSClean,CFSClean2,CFSClean3,DefaultDeny + pool: + name: Azure-Pipelines-1ESPT-ExDShared + os: windows + stages: + - template: /common/config/azure-pipelines/templates/bump-versions-stages.yaml@self + parameters: + VersionPolicyName: noRush + StageName: BumpRushstackVersions + StageDisplayName: 'Bump Rushstack Versions and Create PR' + FeatureBranch: 'automated/bump-versions-rushstack' + PrTitle: 'Bump Rushstack package versions' + PrDescription: | + Automated version bump generated by Azure DevOps Pipeline. + + This PR contains version bumps for the "noRush" version policy. + + **Pipeline Run:** $(System.CollectionUri)$(System.TeamProject)/_build/results?buildId=$(Build.BuildId) diff --git a/common/config/azure-pipelines/templates/bump-versions-stages.yaml b/common/config/azure-pipelines/templates/bump-versions-stages.yaml new file mode 100644 index 0000000000..3dc1291c8c --- /dev/null +++ b/common/config/azure-pipelines/templates/bump-versions-stages.yaml @@ -0,0 +1,121 @@ +# Shared stage definition for the "bump versions" pipelines. +# +# There is one bump pipeline per version policy; each of them builds the repo, bumps the versions +# for its own version policy, packs the resulting tarballs and opens a GitHub PR with the changes. +# The packed tarballs are published to the npm feed later by the matching "esrp publish" pipeline, +# which locates this pipeline run via the "bump-versions|" build tag. + +parameters: + - name: VersionPolicyName + type: string + - name: StageName + type: string + - name: StageDisplayName + type: string + - name: FeatureBranch + type: string + - name: PrTitle + type: string + - name: PrDescription + type: string + +stages: + - stage: ${{ parameters.StageName }} + displayName: ${{ parameters.StageDisplayName }} + jobs: + - job: BumpVersions + displayName: 'Bump Versions' + pool: + name: publish-rushstack + os: linux + templateContext: + outputParentDirectory: $(Build.ArtifactStagingDirectory) + outputs: + - output: pipelineArtifact + targetPath: $(Build.ArtifactStagingDirectory)/published-versions + artifactName: published-versions + - output: pipelineArtifact + targetPath: $(Build.ArtifactStagingDirectory)/json-schemas + artifactName: json-schemas + - output: pipelineArtifact + targetPath: $(Build.ArtifactStagingDirectory)/packages + artifactName: packages + - output: pipelineArtifact + targetPath: $(Build.ArtifactStagingDirectory)/api + artifactName: api + - output: pipelineArtifact + targetPath: $(Build.ArtifactStagingDirectory)/artifact-metadata.json + artifactName: metadata + - output: pipelineArtifact + targetPath: $(Build.ArtifactStagingDirectory)/package-versions + artifactName: package-versions + steps: + - checkout: self + persistCredentials: true + + - template: /common/config/azure-pipelines/templates/configure-git-user.yaml@self + + - bash: | + git checkout -b ${{ parameters.FeatureBranch }} + echo "Created feature branch: ${{ parameters.FeatureBranch }}" + displayName: 'Create Feature Branch' + + - template: /common/config/azure-pipelines/templates/install-node.yaml@self + + - template: /common/config/azure-pipelines/templates/build.yaml@self + + - template: /common/config/azure-pipelines/templates/bump-versions.yaml@self + parameters: + VersionPolicyName: ${{ parameters.VersionPolicyName }} + + - bash: | + git add -u -- common/changes + git add -- '**/CHANGELOG.*' '**/package.json' + + if [ -n "$(git diff --cached --numstat)" ]; then + git commit -m "Applying package version bumps + + Pipeline Run: $(System.CollectionUri)$(System.TeamProject)/_build/results?buildId=$(Build.BuildId) + Run ID: $(Build.BuildId)" + echo "Changes committed" + echo "##vso[task.setvariable variable=HasChanges]true" + else + echo "No changes to commit" + echo "##vso[task.setvariable variable=HasChanges]false" + fi + displayName: 'Commit Version Bumps' + + - script: 'node libraries/rush-lib/scripts/plugins-prepublish.js' + displayName: 'Prepublish workaround for rush-lib' + + - template: /common/config/azure-pipelines/templates/pack.yaml@self + parameters: + VersionPolicyName: ${{ parameters.VersionPolicyName }} + + - template: /common/config/azure-pipelines/templates/post-publish.yaml@self + + - template: /common/config/azure-pipelines/templates/push-and-create-github-pr.yaml@self + parameters: + BranchName: ${{ parameters.FeatureBranch }} + PrTitle: ${{ parameters.PrTitle }} + PrDescription: ${{ parameters.PrDescription }} + + - bash: | + set -e + BUMP_SHA=$(git rev-parse HEAD) + echo "##vso[task.setvariable variable=BumpSha;isOutput=true]${BUMP_SHA}" + echo "##vso[build.addbuildtag]bump-versions|${BUMP_SHA}" + echo "Tagged build with bump SHA: ${BUMP_SHA}" + name: TagBuild + displayName: 'Tag build with bump commit SHA' + condition: and(succeeded(), eq(variables['HasChanges'], 'true')) + + - bash: | + mkdir -p "$(Build.ArtifactStagingDirectory)/packages" + mkdir -p "$(Build.ArtifactStagingDirectory)/package-versions" + displayName: 'Create artifact staging directories' + condition: always() + + - template: /common/config/azure-pipelines/templates/prepare-publish-artifacts.yaml@self + + - template: /common/config/azure-pipelines/templates/record-versions.yaml@self diff --git a/common/config/azure-pipelines/templates/bump-versions.yaml b/common/config/azure-pipelines/templates/bump-versions.yaml index 17f8922afb..4f5ae64806 100644 --- a/common/config/azure-pipelines/templates/bump-versions.yaml +++ b/common/config/azure-pipelines/templates/bump-versions.yaml @@ -1,9 +1,6 @@ parameters: - name: VersionPolicyName type: string - - name: BranchName - type: string - default: $(Build.SourceBranchName) steps: - template: /common/config/azure-pipelines/templates/install-run-rush.yaml@self @@ -12,5 +9,4 @@ steps: version --bump --version-policy ${{ parameters.VersionPolicyName }} - --target-branch ${{ parameters.BranchName }} DisplayName: 'Rush Version (Policy: ${{ parameters.VersionPolicyName }})' diff --git a/common/config/azure-pipelines/templates/configure-git-user.yaml b/common/config/azure-pipelines/templates/configure-git-user.yaml new file mode 100644 index 0000000000..f894ee6c00 --- /dev/null +++ b/common/config/azure-pipelines/templates/configure-git-user.yaml @@ -0,0 +1,11 @@ +parameters: + - name: RepoPath + type: string + default: '$(Build.SourcesDirectory)' + +steps: + - script: | + git config --local user.email "rushbot@users.noreply.github.com" + git config --local user.name "Rushbot" + displayName: 'Configure Git User' + workingDirectory: ${{ parameters.RepoPath }} diff --git a/common/config/azure-pipelines/templates/esrp-publish-stages.yaml b/common/config/azure-pipelines/templates/esrp-publish-stages.yaml new file mode 100644 index 0000000000..ca18ebf66d --- /dev/null +++ b/common/config/azure-pipelines/templates/esrp-publish-stages.yaml @@ -0,0 +1,156 @@ +# Shared stage definition for the "esrp publish" pipelines. +# +# There is one publish pipeline per version policy. Each of them is triggered when the version bump +# PR produced by the matching bump pipeline is merged to main; it locates the originating bump +# pipeline run (via the "bump-versions|" build tag) and publishes the tarballs that were packed +# by that run to the npm feed via ESRP. + +parameters: + # Definition ID of the bump pipeline that packed the tarballs to publish. + - name: BumpPipelineId + type: number + # Azure DevOps team project that hosts the bump pipeline. + - name: BumpPipelineProject + type: string + - name: StageNameSuffix + type: string + - name: DisplayNameSuffix + type: string + - name: PublishToNpmFeed + type: boolean + - name: NpmTag + type: string + - name: DryRun + type: boolean + - name: CommitShaOverride + type: string + +stages: + - stage: Prepare${{ parameters.StageNameSuffix }} + dependsOn: [] + displayName: 'Prepare ${{ parameters.DisplayNameSuffix }} NPM Publish' + jobs: + - job: PrepareNpmPublish + displayName: 'Prepare ${{ parameters.DisplayNameSuffix }} NPM Publish' + pool: + name: publish-rushstack + os: linux + templateContext: + outputParentDirectory: $(Build.ArtifactStagingDirectory) + outputs: + - output: pipelineArtifact + targetPath: $(Build.ArtifactStagingDirectory)/published-versions + artifactName: published-versions + - output: pipelineArtifact + targetPath: $(Build.ArtifactStagingDirectory)/json-schemas + artifactName: json-schemas + - output: pipelineArtifact + targetPath: $(Build.ArtifactStagingDirectory)/api + artifactName: api + steps: + - checkout: self + persistCredentials: true + + - template: /common/config/azure-pipelines/templates/install-node.yaml@self + + - bash: | + mkdir -p "$(Build.ArtifactStagingDirectory)/published-versions" + mkdir -p "$(Build.ArtifactStagingDirectory)/json-schemas" + mkdir -p "$(Build.ArtifactStagingDirectory)/api" + displayName: 'Initialize artifact staging directories' + condition: always() + + - template: /common/config/azure-pipelines/templates/find-bump-pipeline-run.yaml@self + parameters: + PipelineId: ${{ parameters.BumpPipelineId }} + CommitSha: ${{ coalesce(parameters.CommitShaOverride, '$(Build.SourceVersion)') }} + TeamProject: ${{ parameters.BumpPipelineProject }} + Name: FindBumpRun + WorkingDirectory: $(Build.SourcesDirectory) + + - task: DownloadPipelineArtifact@2 + condition: eq(variables['FindBumpRun.IsVersionBumpMerge'], 'true') + inputs: + artifactName: package-versions + targetPath: $(Agent.TempDirectory)/package-versions + project: ${{ parameters.BumpPipelineProject }} + definition: $(FindBumpRun.BumpPipelineDefinitionId) + pipelineId: $(FindBumpRun.BumpPipelineRunId) + buildType: specific + buildVersionToDownload: specific + displayName: 'Download package versions' + + - bash: | + cp "$(Agent.TempDirectory)/package-versions"/*.json "$(Build.ArtifactStagingDirectory)/published-versions/" + condition: eq(variables['FindBumpRun.IsVersionBumpMerge'], 'true') + displayName: 'Stage published versions artifact' + + - task: DownloadPipelineArtifact@2 + condition: eq(variables['FindBumpRun.IsVersionBumpMerge'], 'true') + inputs: + artifactName: json-schemas + targetPath: $(Build.ArtifactStagingDirectory)/json-schemas + project: ${{ parameters.BumpPipelineProject }} + definition: $(FindBumpRun.BumpPipelineDefinitionId) + pipelineId: $(FindBumpRun.BumpPipelineRunId) + buildType: specific + buildVersionToDownload: specific + displayName: 'Download JSON schema artifact' + + - task: DownloadPipelineArtifact@2 + condition: eq(variables['FindBumpRun.IsVersionBumpMerge'], 'true') + inputs: + artifactName: api + targetPath: $(Build.ArtifactStagingDirectory)/api + project: ${{ parameters.BumpPipelineProject }} + definition: $(FindBumpRun.BumpPipelineDefinitionId) + pipelineId: $(FindBumpRun.BumpPipelineRunId) + buildType: specific + buildVersionToDownload: specific + displayName: 'Download API review artifact' + + - ${{ if eq(parameters.PublishToNpmFeed, true) }}: + - stage: Publish${{ parameters.StageNameSuffix }} + displayName: 'Publish ${{ parameters.DisplayNameSuffix }} NPM Packages' + dependsOn: + - Prepare${{ parameters.StageNameSuffix }} + condition: and(succeeded('Prepare${{ parameters.StageNameSuffix }}'), eq(dependencies.Prepare${{ parameters.StageNameSuffix }}.outputs['PrepareNpmPublish.FindBumpRun.IsVersionBumpMerge'], 'true')) + jobs: + - job: PublishNpmPackages + displayName: 'Publish ${{ parameters.DisplayNameSuffix }} NPM Packages' + pool: + name: publish-rushstack + os: linux + variables: + - name: BumpPipelineRunId + value: $[ stageDependencies.Prepare${{ parameters.StageNameSuffix }}.PrepareNpmPublish.outputs['FindBumpRun.BumpPipelineRunId'] ] + - name: BumpPipelineDefinitionId + value: $[ stageDependencies.Prepare${{ parameters.StageNameSuffix }}.PrepareNpmPublish.outputs['FindBumpRun.BumpPipelineDefinitionId'] ] + templateContext: + type: releaseJob + isProduction: true + steps: + - checkout: none + + - template: /common/config/azure-pipelines/templates/install-node.yaml@self + + - task: 1ES.DownloadPipelineArtifact@1 + inputs: + artifactName: packages + targetPath: $(PackagesPath) + project: ${{ parameters.BumpPipelineProject }} + definition: $(BumpPipelineDefinitionId) + pipelineId: $(BumpPipelineRunId) + buildType: specific + buildVersionToDownload: specific + displayName: 'Download packed npm packages' + + - bash: | + ls -la "$(PackagesPath)" + displayName: 'List downloaded packages' + + - template: /common/config/azure-pipelines/templates/esrp-release.yaml@publishConfig + parameters: + packagesPath: $(PackagesPath) + npmTag: ${{ parameters.NpmTag }} + dryRun: ${{ parameters.DryRun }} diff --git a/common/config/azure-pipelines/templates/find-bump-pipeline-run.yaml b/common/config/azure-pipelines/templates/find-bump-pipeline-run.yaml new file mode 100644 index 0000000000..7467f7970f --- /dev/null +++ b/common/config/azure-pipelines/templates/find-bump-pipeline-run.yaml @@ -0,0 +1,95 @@ +parameters: + - name: PipelineId + type: number + - name: CommitSha + type: string + - name: TeamProject + type: string + - name: Name + type: string + - name: WorkingDirectory + type: string + +steps: + - bash: | + set -euo pipefail + + set_output_variable() { + local name="$1" + local value="$2" + echo "##vso[task.setvariable variable=${name};isOutput=true]${value}" + } + + set_output_variable IsVersionBumpMerge false + + REPO_SLUG=$(git remote get-url origin | sed -E 's#.*github\.com[:/](.+/[^.]+)(\.git)?$#\1#') + echo "Repository: ${REPO_SLUG}" + + AUTH_HEADER=$(git config --get-regexp 'http\..*\.extraheader' | head -1 | sed 's/^[^ ]* //') + if [ -z "$AUTH_HEADER" ]; then + echo "##[error]Could not extract authorization header from git config. Ensure persistCredentials is enabled on the checkout step." + exit 1 + fi + + CURL_CONFIG=$(mktemp) + trap 'rm -f "$CURL_CONFIG"' EXIT + echo "-H \"${AUTH_HEADER}\"" > "$CURL_CONFIG" + echo '-H "Accept: application/vnd.github+json"' >> "$CURL_CONFIG" + + github_api() { + local response http_code body + response=$(curl -s -w "\n%{http_code}" -K "$CURL_CONFIG" "$@") + http_code=$(echo "$response" | tail -n1) + body=$(echo "$response" | sed '$d') + + if [[ "$http_code" -ge 200 && "$http_code" -lt 300 ]]; then + echo "$body" + else + echo "##[error]GitHub API returned HTTP ${http_code}:" >&2 + echo "$body" >&2 + return 1 + fi + } + + url_encode() { + node -e 'process.stdout.write(encodeURIComponent(process.argv[1]))' "$1" + } + + PIPELINE_ID="${{ parameters.PipelineId }}" + + set_output_variable BumpPipelineDefinitionId "$PIPELINE_ID" + + echo "Looking up merged PR for commit ${{ parameters.CommitSha }}" + PR_JSON=$(github_api "https://api.github.com/repos/${REPO_SLUG}/commits/${{ parameters.CommitSha }}/pulls") + PR_NUMBER=$(echo "$PR_JSON" | jq 'map(select(.merged_at != null))[0].number // empty') + HEAD_SHA=$(echo "$PR_JSON" | jq -r 'map(select(.merged_at != null))[0].head.sha // empty') + + if [ -z "$PR_NUMBER" ] || [ -z "$HEAD_SHA" ]; then + echo "No merged PR with a head SHA was found for this commit. Skipping publish." + exit 0 + fi + + echo "Found merged PR #${PR_NUMBER}; head SHA: ${HEAD_SHA}" + + BUMP_TAG="bump-versions|${HEAD_SHA}" + ENCODED_TAG=$(url_encode "$BUMP_TAG") + BUILDS_URL="${SYSTEM_COLLECTIONURI}${{ parameters.TeamProject }}/_apis/build/builds?definitions=${PIPELINE_ID}&tagFilters=${ENCODED_TAG}&queryOrder=finishTimeDescending&\$top=1&api-version=7.1" + + echo "Searching for bump pipeline build tagged ${BUMP_TAG}" + BUILD_RESPONSE=$(curl -sS -u ":${SYSTEM_ACCESSTOKEN}" "$BUILDS_URL") + BUILD_ID=$(echo "$BUILD_RESPONSE" | jq -r '.value[0].id // empty') + + if [ -z "$BUILD_ID" ]; then + echo "No bump pipeline build found for tag ${BUMP_TAG}. Skipping publish." + exit 0 + fi + + echo "Found bump pipeline run: ${BUILD_ID}" + set_output_variable IsVersionBumpMerge true + set_output_variable BumpPipelineRunId "$BUILD_ID" + set_output_variable BumpCommitSha "$HEAD_SHA" + name: ${{ parameters.Name }} + displayName: 'Find Bump Pipeline Run' + workingDirectory: ${{ parameters.WorkingDirectory }} + env: + SYSTEM_ACCESSTOKEN: $(System.AccessToken) diff --git a/common/config/azure-pipelines/templates/pack.yaml b/common/config/azure-pipelines/templates/pack.yaml index 9021c17144..c5d46fdfe2 100644 --- a/common/config/azure-pipelines/templates/pack.yaml +++ b/common/config/azure-pipelines/templates/pack.yaml @@ -1,12 +1,14 @@ +parameters: + # Only the packages belonging to this version policy are packed. + - name: VersionPolicyName + type: string + steps: - template: /common/config/azure-pipelines/templates/install-run-rush.yaml@self parameters: Arguments: '--help' DisplayName: 'Install Rush' - - bash: 'rm -f "$HOME/.npmrc"' - displayName: 'Clear user npmrc for publish' - - template: /common/config/azure-pipelines/templates/install-run-rush.yaml@self parameters: Arguments: > @@ -14,5 +16,6 @@ steps: --publish --pack --include-all + --version-policy ${{ parameters.VersionPolicyName }} --release-folder $(Build.ArtifactStagingDirectory)/packages - DisplayName: 'Rush Pack' + DisplayName: 'Rush Pack (Policy: ${{ parameters.VersionPolicyName }})' diff --git a/common/config/azure-pipelines/templates/prepare-publish-artifacts.yaml b/common/config/azure-pipelines/templates/prepare-publish-artifacts.yaml new file mode 100644 index 0000000000..85815e9b90 --- /dev/null +++ b/common/config/azure-pipelines/templates/prepare-publish-artifacts.yaml @@ -0,0 +1,18 @@ +steps: + - pwsh: | + $metadataFile = "$(Build.ArtifactStagingDirectory)/artifact-metadata.json" + + $metadata = @{ + pipelineRunId = "$(Build.BuildId)" + pipelineRunNumber = "$(Build.BuildNumber)" + commitHash = "$(Build.SourceVersion)" + commitBranch = "$(Build.SourceBranch)" + timestamp = (Get-Date -AsUTC -Format "yyyy-MM-ddTHH:mm:ssZ") + pipelineUrl = "$(System.CollectionUri)$(System.TeamProject)/_build/results?buildId=$(Build.BuildId)" + } + + $metadata | ConvertTo-Json | Set-Content -Path $metadataFile + + Write-Host "Created artifact metadata file:" + Get-Content $metadataFile + displayName: 'Generate Artifact Metadata' diff --git a/common/config/azure-pipelines/templates/publish.yaml b/common/config/azure-pipelines/templates/publish.yaml deleted file mode 100644 index 578cac0f31..0000000000 --- a/common/config/azure-pipelines/templates/publish.yaml +++ /dev/null @@ -1,27 +0,0 @@ -parameters: - - name: VersionPolicyName - type: string - - name: BranchName - type: string - default: $(Build.SourceBranchName) - -steps: - - template: /common/config/azure-pipelines/templates/install-run-rush.yaml@self - parameters: - Arguments: '--help' - DisplayName: 'Install Rush' - - - bash: 'rm -f "$HOME/.npmrc"' - displayName: 'Clear user npmrc for publish' - - - template: /common/config/azure-pipelines/templates/install-run-rush.yaml@self - parameters: - Arguments: > - publish - --apply - --publish - --include-all - --target-branch ${{ parameters.BranchName }} - --add-commit-details --set-access-level public - DisplayName: 'Rush Publish (Policy: ${{ parameters.VersionPolicyName }})' - NpmAuthToken: $(npmToken) diff --git a/common/config/azure-pipelines/templates/record-versions.yaml b/common/config/azure-pipelines/templates/record-versions.yaml new file mode 100644 index 0000000000..894cdb1b9a --- /dev/null +++ b/common/config/azure-pipelines/templates/record-versions.yaml @@ -0,0 +1,13 @@ +parameters: + - name: RepoPath + type: string + default: '$(Build.SourcesDirectory)' + +steps: + - template: /common/config/azure-pipelines/templates/install-run-rush.yaml@self + parameters: + Arguments: > + record-published-versions + --output-path $(Build.ArtifactStagingDirectory)/package-versions/published-versions.json + DisplayName: 'Record Published Versions' + RepoPath: '${{ parameters.RepoPath }}' diff --git a/common/config/azure-pipelines/vscode-extension-publish.yaml b/common/config/azure-pipelines/vscode-extension-publish.yaml index 0c23c46d4e..3d438dd4f1 100644 --- a/common/config/azure-pipelines/vscode-extension-publish.yaml +++ b/common/config/azure-pipelines/vscode-extension-publish.yaml @@ -38,6 +38,8 @@ resources: extends: template: v1/1ES.Official.PipelineTemplate.yml@1esPipelines parameters: + settings: + networkIsolationPolicy: CFSClean,CFSClean2,CFSClean3,DefaultDeny pool: name: Azure-Pipelines-1ESPT-ExDShared os: windows diff --git a/common/config/rush/.npmrc-publish b/common/config/rush/.npmrc-publish index a0ffdc9d32..b87f054dae 100644 --- a/common/config/rush/.npmrc-publish +++ b/common/config/rush/.npmrc-publish @@ -14,12 +14,7 @@ # It is NOT recommended to store authentication tokens in a text file on a lab machine, because # other unrelated processes may be able to read the file. Also, the file may persist indefinitely, # for example if the machine loses power. A safer practice is to pass the token via an -# environment variable, which can be referenced from .npmrc using ${} expansion. For example: -# -# //registry.npmjs.org/:_authToken=${NPM_AUTH_TOKEN} -# +# environment variable, which can be referenced from .npmrc using ${} expansion. -registry=https://registry.npmjs.org/ always-auth=true -//registry.npmjs.org/:_authToken=${NPM_AUTH_TOKEN} - +registry=https://packagefeedproxy.microsoft.io/npm/ diff --git a/common/config/subspaces/build-tests-subspace/.npmrc b/common/config/subspaces/build-tests-subspace/.npmrc index 9ce3b02e82..340385524b 100644 --- a/common/config/subspaces/build-tests-subspace/.npmrc +++ b/common/config/subspaces/build-tests-subspace/.npmrc @@ -18,10 +18,7 @@ # It is NOT recommended to store authentication tokens in a text file on a lab machine, because # other unrelated processes may be able to read that file. Also, the file may persist indefinitely, # for example if the machine loses power. A safer practice is to pass the token via an -# environment variable, which can be referenced from .npmrc using ${} expansion. For example: -# -# //registry.npmjs.org/:_authToken=${NPM_AUTH_TOKEN} -# +# environment variable, which can be referenced from .npmrc using ${} expansion. registry=https://packagefeedproxy.microsoft.io/npm/ always-auth=false # No phantom dependencies allowed in this repository diff --git a/common/config/subspaces/default/.npmrc b/common/config/subspaces/default/.npmrc index 9ce3b02e82..340385524b 100644 --- a/common/config/subspaces/default/.npmrc +++ b/common/config/subspaces/default/.npmrc @@ -18,10 +18,7 @@ # It is NOT recommended to store authentication tokens in a text file on a lab machine, because # other unrelated processes may be able to read that file. Also, the file may persist indefinitely, # for example if the machine loses power. A safer practice is to pass the token via an -# environment variable, which can be referenced from .npmrc using ${} expansion. For example: -# -# //registry.npmjs.org/:_authToken=${NPM_AUTH_TOKEN} -# +# environment variable, which can be referenced from .npmrc using ${} expansion. registry=https://packagefeedproxy.microsoft.io/npm/ always-auth=false # No phantom dependencies allowed in this repository