From 13b246d3c230d1d2c8802cda40b7fef34fd9707b Mon Sep 17 00:00:00 2001 From: Microsoft Graph DevX Tooling Date: Fri, 23 Oct 2026 12:53:26 -0700 Subject: [PATCH 1/3] ci: migrate production build to official 1ES template Separate SDK build and tests from opt-in release artifact publication. Preserve the Node.js matrix and Linux build, and document pipeline authorization and downstream artifact compatibility. Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com> --- .azure-pipelines/ci-build-production.yml | 182 ++++++++++++++--------- CONTRIBUTING.md | 14 ++ 2 files changed, 124 insertions(+), 72 deletions(-) diff --git a/.azure-pipelines/ci-build-production.yml b/.azure-pipelines/ci-build-production.yml index f091b9c09..e4cbf0a1a 100644 --- a/.azure-pipelines/ci-build-production.yml +++ b/.azure-pipelines/ci-build-production.yml @@ -1,10 +1,11 @@ -# Node.js -# Build a general Node.js project with npm. -# Add steps that analyze code, save build artifacts, deploy, and more: -# https://docs.microsoft.com/azure/devops/pipelines/languages/javascript - name: $(BuildDefinitionName)_$(SourceBranchName)_$(Date:yyyyMMdd)$(Rev:.r) +parameters: + - name: publishReleaseArtifact + displayName: Publish release-drop for the external release pipeline (manual main runs only) + type: boolean + default: false + trigger: branches: include: @@ -12,77 +13,114 @@ trigger: pr: none -stages: -- stage: "Test" - jobs: - - job: +resources: + repositories: + - repository: 1ESPipelineTemplates + type: git + name: 1ESPipelineTemplates/1ESPipelineTemplates + ref: refs/tags/release + +extends: + template: v1/1ES.Official.PipelineTemplate.yml@1ESPipelineTemplates + parameters: pool: - vmImage: windows-latest - strategy: - matrix: - Node 22: - NODE_VERSION: '22.x' - Node 24: - NODE_VERSION: '24.x' - Node 26: - NODE_VERSION: '26.x' - maxParallel: 2 - steps: - - template: ./common-templates/security-pre-checks.yml - - task: UseNode@1 - inputs: - version: $(NODE_VERSION) - displayName: 'Install Node.js' + name: Azure-Pipelines-1ESPT-ExDShared + image: windows-latest + os: windows - - script: npm ci - displayName: 'npm install for tests' - - script: npm run build - displayName: 'npm build for tests' - - script: npm run test - displayName: 'Run the node tests' - - script: npm run karma - displayName: 'Run karma tests' + stages: + - stage: Build + displayName: Build and test SDK + jobs: + - job: Test + displayName: Test supported Node.js versions + strategy: + matrix: + Node22: + NODE_VERSION: '22.x' + Node24: + NODE_VERSION: '24.x' + Node26: + NODE_VERSION: '26.x' + maxParallel: 2 + steps: + - checkout: self + - task: UseNode@1 + inputs: + version: $(NODE_VERSION) + displayName: Install Node.js - - task: PublishTestResults@2 - displayName: 'Publish Unit Test Results' - inputs: - testResultsFormat: 'JUnit' - testResultsFiles: '**/testResult.xml' - failTaskOnFailedTests: true + - script: npm ci + displayName: Install test dependencies + - script: npm run build + displayName: Build SDK for tests + - script: npm test + displayName: Run Node.js and browser tests - - template: ./common-templates/security-post-checks.yml + - task: PublishTestResults@2 + displayName: Publish unit test results + condition: succeededOrFailed() + inputs: + testResultsFormat: JUnit + testResultsFiles: '**/testResult.xml' + testRunTitle: Node.js $(NODE_VERSION) + failTaskOnFailedTests: true -- stage: "Build" - jobs: - - job: - - pool: - vmImage: ubuntu-latest - steps: - - task: UseNode@1 - inputs: - version: '22.x' - displayName: 'Install Node.js' + - job: BuildPackage + displayName: Build production artifact + pool: + name: Azure-Pipelines-1ESPT-ExDShared + image: ubuntu-latest + os: linux + templateContext: + outputs: + - output: pipelineArtifact + displayName: Publish SDK build for validation + artifactName: sdk-build + targetPath: $(Build.ArtifactStagingDirectory) + steps: + - checkout: self + - task: UseNode@1 + inputs: + version: '22.x' + displayName: Install Node.js - - script: | - npm ci - npm run build - displayName: 'Build for production artifact' - - task: CopyFiles@2 - inputs: - sourceFolder: '$(Build.SourcesDirectory)' - targetFolder: $(Build.ArtifactStagingDirectory) - Contents: | - **/* - !.azure-pipelines/** - !.github/** - !.git/** - !.vscode/** - displayName: 'Copy npm package' + - script: npm ci + displayName: Install production build dependencies + - script: npm run build + displayName: Build production SDK + - task: CopyFiles@2 + inputs: + sourceFolder: $(Build.SourcesDirectory) + targetFolder: $(Build.ArtifactStagingDirectory) + Contents: | + **/* + !.azure-pipelines/** + !.github/** + !.git/** + !.vscode/** + displayName: Stage npm package - - task: PublishBuildArtifacts@1 - inputs: - pathtoPublish: $(Build.ArtifactStagingDirectory) - artifactName: "release-drop" - displayName: 'Publish artifacts' - + - stage: Publish + displayName: Publish release artifact + dependsOn: Build + condition: and(succeeded(), ${{ eq(parameters.publishReleaseArtifact, true) }}, eq(variables['Build.Reason'], 'Manual'), eq(variables['Build.SourceBranch'], 'refs/heads/main')) + jobs: + - job: PublishReleaseArtifact + displayName: Publish validated SDK for external release + pool: + name: Azure-Pipelines-1ESPT-ExDShared + image: ubuntu-latest + os: linux + templateContext: + inputs: + - input: pipelineArtifact + artifactName: sdk-build + targetPath: $(Build.ArtifactStagingDirectory) + outputs: + - output: pipelineArtifact + displayName: Publish release-drop + artifactName: release-drop + targetPath: $(Build.ArtifactStagingDirectory) + steps: + - checkout: none diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md index d296d5461..e5d3d1f5d 100644 --- a/CONTRIBUTING.md +++ b/CONTRIBUTING.md @@ -136,6 +136,20 @@ To run linting, npm run lint ``` +#### Production pipeline + +The Azure DevOps production pipeline in `.azure-pipelines/ci-build-production.yml` extends `v1/1ES.Official.PipelineTemplate.yml@1ESPipelineTemplates`. The official template manages SDL scanning and artifact publication instead of the legacy security-check step templates. + +The **Build** stage tests the SDK on Windows with Node.js 22, 24, and 26, and builds the production SDK on Linux with Node.js 22. It publishes an intermediate `sdk-build` pipeline artifact for inspection. Pushes to `main` run this stage without publishing `release-drop`. + +To validate the migration before merging, manually queue **Graph JS SDK Build pipeline** against the PR branch and leave **Publish release-drop for the external release pipeline** unchecked. An Azure DevOps administrator may need to authorize the `1ESPipelineTemplates/1ESPipelineTemplates` repository and the `Azure-Pipelines-1ESPT-ExDShared` pool for this pipeline. Confirm that the pool provides the Windows and Ubuntu images used here, including Chrome for the Windows browser tests, and that the template's SDL checks pass. + +After a successful validation and merge, manually queue the pipeline against `main` with **Publish release-drop for the external release pipeline** checked. The separate **Publish** stage runs only after the build and tests succeed, and only for manual runs on `main`. It republishes the same `sdk-build` contents as `release-drop` without rebuilding or installing dependencies. This pipeline does not publish to npm. + +`release-drop` is now a Pipeline Artifact rather than the Build Artifact produced by `PublishBuildArtifacts@1`. Before enabling publication, confirm the external release pipeline can download Pipeline Artifacts and triggers only on runs with `release-drop` (not build-only runs with `sdk-build`). Update its artifact download and trigger configuration if needed. The artifact name and staged file layout are unchanged. + +#### Commit your changes + The files in `C:\Users\\` are a working copy of the new branch that you created in your local repository. Changing anything in this folder doesn't affect the local repository until you commit a change. To commit a change to the local repository, type the following commands in GitBash: git add . From a37a4b8f8ee36977e2a680fbc3fae1bdd7348709 Mon Sep 17 00:00:00 2001 From: Microsoft Graph DevX Tooling Date: Wed, 28 Oct 2026 13:09:56 -0700 Subject: [PATCH 2/3] ci: publish release artifacts only on version tag pushes Bump package and generated SDK version to 3.1.0. Replace manual publication with tag-push CI gating, validate tags against the package version, and update release instructions. Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com> --- .azure-pipelines/ci-build-production.yml | 23 ++++++++++++++++------- CONTRIBUTING.md | 4 ++-- package-lock.json | 4 ++-- package.json | 2 +- src/Version.ts | 2 +- 5 files changed, 22 insertions(+), 13 deletions(-) diff --git a/.azure-pipelines/ci-build-production.yml b/.azure-pipelines/ci-build-production.yml index e4cbf0a1a..c90da3d7f 100644 --- a/.azure-pipelines/ci-build-production.yml +++ b/.azure-pipelines/ci-build-production.yml @@ -1,15 +1,12 @@ name: $(BuildDefinitionName)_$(SourceBranchName)_$(Date:yyyyMMdd)$(Rev:.r) -parameters: - - name: publishReleaseArtifact - displayName: Publish release-drop for the external release pipeline (manual main runs only) - type: boolean - default: false - trigger: branches: include: - main + tags: + include: + - '*' pr: none @@ -85,6 +82,18 @@ extends: version: '22.x' displayName: Install Node.js + - script: | + node -e " + const version = require('./package.json').version; + const branch = process.env.BUILD_SOURCEBRANCH; + if (branch.startsWith('refs/tags/')) { + const tag = branch.slice('refs/tags/'.length); + if (tag !== version) { + throw new Error('Release tag ' + tag + ' must match package version ' + version); + } + } + " + displayName: Validate release tag matches package version - script: npm ci displayName: Install production build dependencies - script: npm run build @@ -104,7 +113,7 @@ extends: - stage: Publish displayName: Publish release artifact dependsOn: Build - condition: and(succeeded(), ${{ eq(parameters.publishReleaseArtifact, true) }}, eq(variables['Build.Reason'], 'Manual'), eq(variables['Build.SourceBranch'], 'refs/heads/main')) + condition: and(succeeded(), startsWith(variables['Build.SourceBranch'], 'refs/tags/'), in(variables['Build.Reason'], 'IndividualCI', 'BatchedCI')) jobs: - job: PublishReleaseArtifact displayName: Publish validated SDK for external release diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md index e5d3d1f5d..754438926 100644 --- a/CONTRIBUTING.md +++ b/CONTRIBUTING.md @@ -142,9 +142,9 @@ The Azure DevOps production pipeline in `.azure-pipelines/ci-build-production.ym The **Build** stage tests the SDK on Windows with Node.js 22, 24, and 26, and builds the production SDK on Linux with Node.js 22. It publishes an intermediate `sdk-build` pipeline artifact for inspection. Pushes to `main` run this stage without publishing `release-drop`. -To validate the migration before merging, manually queue **Graph JS SDK Build pipeline** against the PR branch and leave **Publish release-drop for the external release pipeline** unchecked. An Azure DevOps administrator may need to authorize the `1ESPipelineTemplates/1ESPipelineTemplates` repository and the `Azure-Pipelines-1ESPT-ExDShared` pool for this pipeline. Confirm that the pool provides the Windows and Ubuntu images used here, including Chrome for the Windows browser tests, and that the template's SDL checks pass. +To validate the migration before merging, manually queue **Graph JS SDK Build pipeline** against the PR branch. Manual runs never publish `release-drop`, including manual runs targeting a tag. An Azure DevOps administrator may need to authorize the `1ESPipelineTemplates/1ESPipelineTemplates` repository and the `Azure-Pipelines-1ESPT-ExDShared` pool for this pipeline. Confirm that the pool provides the Windows and Ubuntu images used here, including Chrome for the Windows browser tests, and that the template's SDL checks pass. -After a successful validation and merge, manually queue the pipeline against `main` with **Publish release-drop for the external release pipeline** checked. The separate **Publish** stage runs only after the build and tests succeed, and only for manual runs on `main`. It republishes the same `sdk-build` contents as `release-drop` without rebuilding or installing dependencies. This pipeline does not publish to npm. +After a successful validation and merge to `main`, push a release tag that exactly matches `package.json`'s version, such as `3.1.0` (without a `v` prefix), on the intended release commit. Tag pushes trigger the pipeline, and a mismatched tag fails the production build before artifact creation. The separate **Publish** stage runs only after the build and tests succeed, and only for CI runs triggered by a tag push. It republishes the same `sdk-build` contents as `release-drop` without rebuilding or installing dependencies. This pipeline does not publish to npm. Creating or pushing a release tag is a release action; do not do so for build-only validation. `release-drop` is now a Pipeline Artifact rather than the Build Artifact produced by `PublishBuildArtifacts@1`. Before enabling publication, confirm the external release pipeline can download Pipeline Artifacts and triggers only on runs with `release-drop` (not build-only runs with `sdk-build`). Update its artifact download and trigger configuration if needed. The artifact name and staged file layout are unchanged. diff --git a/package-lock.json b/package-lock.json index 8361e8ce1..889f6589e 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1,12 +1,12 @@ { "name": "@microsoft/microsoft-graph-client", - "version": "3.0.8", + "version": "3.1.0", "lockfileVersion": 2, "requires": true, "packages": { "": { "name": "@microsoft/microsoft-graph-client", - "version": "3.0.8", + "version": "3.1.0", "license": "MIT", "dependencies": { "@babel/runtime": "^7.12.5", diff --git a/package.json b/package.json index a6213492a..9c6d00462 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "@microsoft/microsoft-graph-client", - "version": "3.0.8", + "version": "3.1.0", "description": "Microsoft Graph Client Library", "keywords": [ "Microsoft", diff --git a/src/Version.ts b/src/Version.ts index 1b7fc28bb..ecbef5382 100644 --- a/src/Version.ts +++ b/src/Version.ts @@ -12,4 +12,4 @@ * @module Version */ -export const PACKAGE_VERSION = "3.0.7"; +export const PACKAGE_VERSION = "3.1.0"; From c58f0be2118053b67c7b8abe3bf50753ddec43d6 Mon Sep 17 00:00:00 2001 From: Microsoft Graph DevX Tooling Date: Wed, 28 Oct 2026 13:16:37 -0700 Subject: [PATCH 3/3] ci: model npm releases on the TypeScript SDK ESRP pipeline Pack the built single-package SDK without lifecycle scripts and deploy the immutable tarball through the shared production ESRP environment. Retain tag-push-only release gating and document resource authorization, package scope, and legacy publisher cutover. Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com> --- .azure-pipelines/ci-build-production.yml | 54 +++++++++++++++--------- CONTRIBUTING.md | 12 ++++-- 2 files changed, 43 insertions(+), 23 deletions(-) diff --git a/.azure-pipelines/ci-build-production.yml b/.azure-pipelines/ci-build-production.yml index c90da3d7f..a997cd753 100644 --- a/.azure-pipelines/ci-build-production.yml +++ b/.azure-pipelines/ci-build-production.yml @@ -72,7 +72,7 @@ extends: templateContext: outputs: - output: pipelineArtifact - displayName: Publish SDK build for validation + displayName: Publish packed SDK for validation artifactName: sdk-build targetPath: $(Build.ArtifactStagingDirectory) steps: @@ -98,38 +98,54 @@ extends: displayName: Install production build dependencies - script: npm run build displayName: Build production SDK - - task: CopyFiles@2 - inputs: - sourceFolder: $(Build.SourcesDirectory) - targetFolder: $(Build.ArtifactStagingDirectory) - Contents: | - **/* - !.azure-pipelines/** - !.github/** - !.git/** - !.vscode/** - displayName: Stage npm package + - script: npm pack --ignore-scripts --pack-destination "$(Build.ArtifactStagingDirectory)" + displayName: Pack built SDK without rerunning prepack - stage: Publish - displayName: Publish release artifact + displayName: Publish SDK to npm via ESRP dependsOn: Build condition: and(succeeded(), startsWith(variables['Build.SourceBranch'], 'refs/tags/'), in(variables['Build.Reason'], 'IndividualCI', 'BatchedCI')) jobs: - - job: PublishReleaseArtifact - displayName: Publish validated SDK for external release + - deployment: PublishNpm + displayName: Publish validated SDK via ESRP Release + environment: msgraph-npm-org pool: name: Azure-Pipelines-1ESPT-ExDShared image: ubuntu-latest os: linux templateContext: + type: releaseJob + isProduction: true inputs: - input: pipelineArtifact artifactName: sdk-build - targetPath: $(Build.ArtifactStagingDirectory) + targetPath: $(Build.ArtifactStagingDirectory)/npm outputs: - output: pipelineArtifact displayName: Publish release-drop artifactName: release-drop - targetPath: $(Build.ArtifactStagingDirectory) - steps: - - checkout: none + targetPath: $(Build.ArtifactStagingDirectory)/npm + strategy: + runOnce: + deploy: + steps: + - checkout: none + - download: none + - task: EsrpRelease@9 + displayName: Publish npm package via ESRP Release + inputs: + connectedservicename: Federated DevX ESRP Managed Identity Connection + usemanagedidentity: false + keyvaultname: akv-prod-eastus + authcertname: ReferenceLibraryPrivateCert + signcertname: ReferencePackagePublisherCertificate + clientid: 65035b7f-7357-4f29-bf25-c5ee5c3949f8 + intent: PackageDistribution + contenttype: npm + contentsource: Folder + folderlocation: $(Build.ArtifactStagingDirectory)/npm + owners: christiano@microsoft.com,ramsess@microsoft.com,gavinbarron@microsoft.com,jingjingjia@microsoft.com,peombwa@microsoft.com,treicys@microsoft.com + approvers: christiano@microsoft.com,ramsess@microsoft.com,gavinbarron@microsoft.com,jingjingjia@microsoft.com,peombwa@microsoft.com,treicys@microsoft.com + serviceendpointurl: https://api.esrp.microsoft.com + mainpublisher: ESRPRELPACMAN + domaintenantid: cdc5aeea-15c5-4db6-b079-fcadd2505dc2 diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md index 754438926..0688708d8 100644 --- a/CONTRIBUTING.md +++ b/CONTRIBUTING.md @@ -140,13 +140,17 @@ npm run lint The Azure DevOps production pipeline in `.azure-pipelines/ci-build-production.yml` extends `v1/1ES.Official.PipelineTemplate.yml@1ESPipelineTemplates`. The official template manages SDL scanning and artifact publication instead of the legacy security-check step templates. -The **Build** stage tests the SDK on Windows with Node.js 22, 24, and 26, and builds the production SDK on Linux with Node.js 22. It publishes an intermediate `sdk-build` pipeline artifact for inspection. Pushes to `main` run this stage without publishing `release-drop`. +The release flow follows the [TypeScript SDK's Azure release pipeline](https://github.com/microsoftgraph/msgraph-sdk-typescript/blob/main/.azure-pipelines/release.yml): build and pack npm tarballs, then deploy those tarballs through ESRP. Version bumps and release tags remain explicit; this repository does not adopt the TypeScript SDK's Release Please automation. -To validate the migration before merging, manually queue **Graph JS SDK Build pipeline** against the PR branch. Manual runs never publish `release-drop`, including manual runs targeting a tag. An Azure DevOps administrator may need to authorize the `1ESPipelineTemplates/1ESPipelineTemplates` repository and the `Azure-Pipelines-1ESPT-ExDShared` pool for this pipeline. Confirm that the pool provides the Windows and Ubuntu images used here, including Chrome for the Windows browser tests, and that the template's SDL checks pass. +The **Build** stage tests the SDK on Windows with Node.js 22, 24, and 26, and builds the production SDK on Linux with Node.js 22. It runs `npm pack --ignore-scripts` to package the built SDK without invoking the `prepack` hook, which would otherwise reinstall dependencies, rebuild, and rerun tests. The intermediate `sdk-build` Pipeline Artifact contains the npm tarball, not a source-directory snapshot. Pushes to `main` run this stage without publishing to npm or creating `release-drop`. -After a successful validation and merge to `main`, push a release tag that exactly matches `package.json`'s version, such as `3.1.0` (without a `v` prefix), on the intended release commit. Tag pushes trigger the pipeline, and a mismatched tag fails the production build before artifact creation. The separate **Publish** stage runs only after the build and tests succeed, and only for CI runs triggered by a tag push. It republishes the same `sdk-build` contents as `release-drop` without rebuilding or installing dependencies. This pipeline does not publish to npm. Creating or pushing a release tag is a release action; do not do so for build-only validation. +To validate the migration before merging, manually queue **Graph JS SDK Build pipeline** against the PR branch. Manual runs never deploy to npm or publish `release-drop`, including manual runs targeting a tag. An Azure DevOps administrator may need to authorize the `1ESPipelineTemplates/1ESPipelineTemplates` repository and the `Azure-Pipelines-1ESPT-ExDShared` pool for this pipeline. Confirm that the pool provides the Windows and Ubuntu images used here, including Chrome for the Windows browser tests, and that the template's SDL checks pass. Download `sdk-build` and inspect/install the tarball in a clean consumer project before releasing. -`release-drop` is now a Pipeline Artifact rather than the Build Artifact produced by `PublishBuildArtifacts@1`. Before enabling publication, confirm the external release pipeline can download Pipeline Artifacts and triggers only on runs with `release-drop` (not build-only runs with `sdk-build`). Update its artifact download and trigger configuration if needed. The artifact name and staged file layout are unchanged. +After a successful validation and merge to `main`, push a release tag that exactly matches `package.json`'s version, such as `3.1.0` (without a `v` prefix), on the intended release commit. Tag pushes trigger the pipeline, and a mismatched tag fails the production build before artifact creation. The separate **Publish** stage runs only after the build and tests succeed, and only for CI runs triggered by a tag push. Its production deployment job downloads the same `sdk-build` tarball and submits it to `EsrpRelease@9` for npm package distribution. It also publishes the tarball as `release-drop`; neither packing nor building runs again during deployment. Creating or pushing a release tag is a release action; do not do so for build-only validation. + +Deployment reuses the TypeScript SDK's `msgraph-npm-org` environment, federated DevX ESRP service connection, certificate references, and configured release owners/approvers. Before pushing a release tag, authorize this pipeline to use those resources, verify the environment's approval/check policies, confirm ESRP is authorized to distribute `@microsoft/microsoft-graph-client`, and confirm the intended npm dist-tag policy. The shared configuration's name alone does not establish access to this package's `@microsoft` scope. Check that the release version is not already published. + +Disable any legacy external npm publication trigger for this pipeline before enabling the ESRP release path, to avoid duplicate publication. `release-drop` is now a Pipeline Artifact containing the packed `.tgz`, not the previous source-directory Build Artifact. Any remaining consumers must support both the artifact type and the new contents. Do not retry publication blindly after a partial ESRP failure; first check ESRP and npm for the submitted version. #### Commit your changes