From 713490c8110fe322692f7d10e8a8063d0f0684ae Mon Sep 17 00:00:00 2001 From: "Michael Mainer (from Dev Box)" <8527305+MIchaelMainer@users.noreply.github.com> Date: Wed, 3 Jun 2026 11:26:49 -0700 Subject: [PATCH 1/8] feat(pipeline): add Azure Pipelines configuration for building and publishing Python packages to PyPI --- .azure-pipelines/cd-publish-python.yml | 142 +++++++++++++++++++++++++ .github/workflows/publish.yml | 35 ------ 2 files changed, 142 insertions(+), 35 deletions(-) create mode 100644 .azure-pipelines/cd-publish-python.yml delete mode 100644 .github/workflows/publish.yml diff --git a/.azure-pipelines/cd-publish-python.yml b/.azure-pipelines/cd-publish-python.yml new file mode 100644 index 00000000..a8b05028 --- /dev/null +++ b/.azure-pipelines/cd-publish-python.yml @@ -0,0 +1,142 @@ +# Copyright (c) Microsoft Corporation. All rights reserved. +# Licensed under the MIT License. + +# Build, package, and deploy msgraph-sdk-python-core to PyPI. + +name: $(BuildDefinitionName)_$(SourceBranchName)_$(Date:yyyyMMdd)$(Rev:.r) + +trigger: + branches: + include: + - main + tags: + include: + - 'v*' + +pr: none + +variables: + pythonVersion: '3.14' + +resources: + repositories: + - repository: 1ESPipelineTemplates + type: git + name: 1ESPipelineTemplates/1ESPipelineTemplates + ref: refs/tags/release + +extends: + template: v1/1ES.Official.PipelineTemplate.yml@1ESPipelineTemplates + parameters: + pool: + name: Azure-Pipelines-1ESPT-ExDShared + image: ubuntu-latest + os: linux + stages: + - stage: build + displayName: 'Build and Package msgraph-sdk-python-core' + condition: or(startsWith(variables['Build.SourceBranch'], 'refs/tags/v'), eq(variables['Build.Reason'], 'Manual')) + jobs: + - job: build_python + displayName: 'Build, Test, and Package' + pool: + name: Azure-Pipelines-1ESPT-ExDShared + image: ubuntu-latest + os: linux + steps: + - checkout: self + + - task: UsePythonVersion@0 + displayName: 'Install Python $(pythonVersion)' + inputs: + versionSpec: '$(pythonVersion)' + addToPath: true + + - script: python -m pip install --upgrade pip + displayName: 'Upgrade pip' + + - script: pip install -r requirements-dev.txt + displayName: 'Install dependencies' + + - script: yapf -dr src + displayName: 'Check code format' + + - script: isort src + displayName: 'Check import order' + + - script: mypy src + displayName: 'Static type checking with Mypy' + + - script: pylint src --disable=W --rcfile=.pylintrc + displayName: 'Lint with Pylint' + + - script: pytest + displayName: 'Run unit tests' + + - script: pip install build + displayName: 'Install package builder' + + - script: python -m build + displayName: 'Build package artifacts' + + - task: CopyFiles@2 + displayName: 'Copy package artifacts to staging' + inputs: + CleanTargetFolder: true + sourceFolder: '$(Build.SourcesDirectory)' + targetFolder: '$(Build.ArtifactStagingDirectory)/python/msgraph_core' + Contents: | + dist/*.tar.gz + dist/*.whl + flattenFolders: true + + templateContext: + outputs: + - output: pipelineArtifact + displayName: 'Stage msgraph-core package artifacts' + artifactName: pypi_msgraph_core_package + targetPath: '$(Build.ArtifactStagingDirectory)/python/msgraph_core' + condition: or(startsWith(variables['Build.SourceBranch'], 'refs/tags/v'), eq(variables['Build.Reason'], 'Manual')) + + - stage: deploy + displayName: 'Publish msgraph-sdk-python-core to PyPI' + dependsOn: build + condition: or(and(startsWith(variables['Build.SourceBranch'], 'refs/tags/v'), succeeded()), eq(variables['Build.Reason'], 'Manual')) + jobs: + - deployment: publish_python_package + displayName: 'Publish msgraph-core package' + environment: pypi_prod + pool: + name: Azure-Pipelines-1ESPT-ExDShared + image: ubuntu-latest + os: linux + templateContext: + type: releaseJob + isProduction: true + inputs: + - input: pipelineArtifact + artifactName: pypi_msgraph_core_package + targetPath: '$(Build.ArtifactStagingDirectory)/python' + strategy: + runOnce: + deploy: + steps: + - task: EsrpRelease@9 + displayName: 'Publish msgraph-core 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: 'PYPI' + contentsource: 'Folder' + folderlocation: '$(Build.ArtifactStagingDirectory)/python' + waitforreleasecompletion: true + owners: 'graphtooling+python@microsoft.com' + approvers: 'graphtooling+python@microsoft.com' + serviceendpointurl: 'https://api.esrp.microsoft.com' + mainpublisher: 'ESRPRELPACMAN' + domaintenantid: 'cdc5aeea-15c5-4db6-b079-fcadd2505dc2' \ No newline at end of file diff --git a/.github/workflows/publish.yml b/.github/workflows/publish.yml deleted file mode 100644 index 75da478e..00000000 --- a/.github/workflows/publish.yml +++ /dev/null @@ -1,35 +0,0 @@ -name: Publish package to PyPI and create release - -on: - push: - tags: - - "v*" # Push events to matching v*, i.e. v1.0, v20.15.10 - -jobs: - build: - uses: ./.github/workflows/build.yml - - publish: - name: Publish distribution to PyPI - runs-on: ubuntu-latest - if: startsWith(github.ref, 'refs/tags/v') - environment: pypi_prod - needs: [build] - steps: - - name: Checkout code - uses: actions/checkout@v6 - - name: Set up Python 3.13 - uses: actions/setup-python@v6 - with: - python-version: 3.13 - - name: Install dependencies - run: | - python -m pip install --upgrade pip - pip install build - - name: Build package - run: python -m build - - name: Publish package - uses: pypa/gh-action-pypi-publish@cef221092ed1bacb1cc03d23a2d87d1d172e277b - with: - user: __token__ - password: ${{ secrets.PYPI_TOKEN }} From a36e3a1278b153b021114169ad1889f2352318c3 Mon Sep 17 00:00:00 2001 From: "Michael Mainer (from Dev Box)" <8527305+MIchaelMainer@users.noreply.github.com> Date: Wed, 3 Jun 2026 11:27:02 -0700 Subject: [PATCH 2/8] feat(pipeline): add Azure Pipelines configuration for building and publishing Python packages to PyPI --- .azure-pipelines/cd-publish-python.yml | 76 +++++++++++++------------- 1 file changed, 38 insertions(+), 38 deletions(-) diff --git a/.azure-pipelines/cd-publish-python.yml b/.azure-pipelines/cd-publish-python.yml index a8b05028..3b2a45d5 100644 --- a/.azure-pipelines/cd-publish-python.yml +++ b/.azure-pipelines/cd-publish-python.yml @@ -11,12 +11,12 @@ trigger: - main tags: include: - - 'v*' + - "v*" pr: none variables: - pythonVersion: '3.14' + pythonVersion: "3.14" resources: repositories: @@ -34,11 +34,11 @@ extends: os: linux stages: - stage: build - displayName: 'Build and Package msgraph-sdk-python-core' + displayName: "Build and Package msgraph-sdk-python-core" condition: or(startsWith(variables['Build.SourceBranch'], 'refs/tags/v'), eq(variables['Build.Reason'], 'Manual')) jobs: - job: build_python - displayName: 'Build, Test, and Package' + displayName: "Build, Test, and Package" pool: name: Azure-Pipelines-1ESPT-ExDShared image: ubuntu-latest @@ -47,44 +47,44 @@ extends: - checkout: self - task: UsePythonVersion@0 - displayName: 'Install Python $(pythonVersion)' + displayName: "Install Python $(pythonVersion)" inputs: - versionSpec: '$(pythonVersion)' + versionSpec: "$(pythonVersion)" addToPath: true - script: python -m pip install --upgrade pip - displayName: 'Upgrade pip' + displayName: "Upgrade pip" - script: pip install -r requirements-dev.txt - displayName: 'Install dependencies' + displayName: "Install dependencies" - script: yapf -dr src - displayName: 'Check code format' + displayName: "Check code format" - script: isort src - displayName: 'Check import order' + displayName: "Check import order" - script: mypy src - displayName: 'Static type checking with Mypy' + displayName: "Static type checking with Mypy" - script: pylint src --disable=W --rcfile=.pylintrc - displayName: 'Lint with Pylint' + displayName: "Lint with Pylint" - script: pytest - displayName: 'Run unit tests' + displayName: "Run unit tests" - script: pip install build - displayName: 'Install package builder' + displayName: "Install package builder" - script: python -m build - displayName: 'Build package artifacts' + displayName: "Build package artifacts" - task: CopyFiles@2 - displayName: 'Copy package artifacts to staging' + displayName: "Copy package artifacts to staging" inputs: CleanTargetFolder: true - sourceFolder: '$(Build.SourcesDirectory)' - targetFolder: '$(Build.ArtifactStagingDirectory)/python/msgraph_core' + sourceFolder: "$(Build.SourcesDirectory)" + targetFolder: "$(Build.ArtifactStagingDirectory)/python/msgraph_core" Contents: | dist/*.tar.gz dist/*.whl @@ -93,18 +93,18 @@ extends: templateContext: outputs: - output: pipelineArtifact - displayName: 'Stage msgraph-core package artifacts' + displayName: "Stage msgraph-core package artifacts" artifactName: pypi_msgraph_core_package - targetPath: '$(Build.ArtifactStagingDirectory)/python/msgraph_core' + targetPath: "$(Build.ArtifactStagingDirectory)/python/msgraph_core" condition: or(startsWith(variables['Build.SourceBranch'], 'refs/tags/v'), eq(variables['Build.Reason'], 'Manual')) - stage: deploy - displayName: 'Publish msgraph-sdk-python-core to PyPI' + displayName: "Publish msgraph-sdk-python-core to PyPI" dependsOn: build condition: or(and(startsWith(variables['Build.SourceBranch'], 'refs/tags/v'), succeeded()), eq(variables['Build.Reason'], 'Manual')) jobs: - deployment: publish_python_package - displayName: 'Publish msgraph-core package' + displayName: "Publish msgraph-core package" environment: pypi_prod pool: name: Azure-Pipelines-1ESPT-ExDShared @@ -116,27 +116,27 @@ extends: inputs: - input: pipelineArtifact artifactName: pypi_msgraph_core_package - targetPath: '$(Build.ArtifactStagingDirectory)/python' + targetPath: "$(Build.ArtifactStagingDirectory)/python" strategy: runOnce: deploy: steps: - task: EsrpRelease@9 - displayName: 'Publish msgraph-core package via ESRP Release' + displayName: "Publish msgraph-core package via ESRP Release" inputs: - connectedservicename: 'Federated DevX ESRP Managed Identity Connection' + 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: 'PYPI' - contentsource: 'Folder' - folderlocation: '$(Build.ArtifactStagingDirectory)/python' + keyvaultname: "akv-prod-eastus" + authcertname: "ReferenceLibraryPrivateCert" + signcertname: "ReferencePackagePublisherCertificate" + clientid: "65035b7f-7357-4f29-bf25-c5ee5c3949f8" + intent: "PackageDistribution" + contenttype: "PYPI" + contentsource: "Folder" + folderlocation: "$(Build.ArtifactStagingDirectory)/python" waitforreleasecompletion: true - owners: 'graphtooling+python@microsoft.com' - approvers: 'graphtooling+python@microsoft.com' - serviceendpointurl: 'https://api.esrp.microsoft.com' - mainpublisher: 'ESRPRELPACMAN' - domaintenantid: 'cdc5aeea-15c5-4db6-b079-fcadd2505dc2' \ No newline at end of file + owners: "graphtooling+python@microsoft.com" + approvers: "graphtooling+python@microsoft.com" + serviceendpointurl: "https://api.esrp.microsoft.com" + mainpublisher: "ESRPRELPACMAN" + domaintenantid: "cdc5aeea-15c5-4db6-b079-fcadd2505dc2" From b7902b310c9878f05cc1f7e882ce57e0bf5a0443 Mon Sep 17 00:00:00 2001 From: "Michael Mainer (from Dev Box)" <8527305+MIchaelMainer@users.noreply.github.com> Date: Wed, 3 Jun 2026 13:26:09 -0700 Subject: [PATCH 3/8] chore(pipeline): add pool for sdl --- .azure-pipelines/cd-publish-python.yml | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/.azure-pipelines/cd-publish-python.yml b/.azure-pipelines/cd-publish-python.yml index 3b2a45d5..bfb30bb2 100644 --- a/.azure-pipelines/cd-publish-python.yml +++ b/.azure-pipelines/cd-publish-python.yml @@ -32,6 +32,11 @@ extends: name: Azure-Pipelines-1ESPT-ExDShared image: ubuntu-latest os: linux + sdl: + sourceAnalysisPool: + name: Azure-Pipelines-1ESPT-ExDShared + image: windows-2022 + os: windows stages: - stage: build displayName: "Build and Package msgraph-sdk-python-core" From efb693d3d8e5c29009318a390e5b7be11b2e5300 Mon Sep 17 00:00:00 2001 From: "Michael Mainer (from Dev Box)" <8527305+MIchaelMainer@users.noreply.github.com> Date: Wed, 3 Jun 2026 13:28:49 -0700 Subject: [PATCH 4/8] chore(pipeline): remove environment we gate releases in other ways --- .azure-pipelines/cd-publish-python.yml | 1 - 1 file changed, 1 deletion(-) diff --git a/.azure-pipelines/cd-publish-python.yml b/.azure-pipelines/cd-publish-python.yml index bfb30bb2..b6e07594 100644 --- a/.azure-pipelines/cd-publish-python.yml +++ b/.azure-pipelines/cd-publish-python.yml @@ -110,7 +110,6 @@ extends: jobs: - deployment: publish_python_package displayName: "Publish msgraph-core package" - environment: pypi_prod pool: name: Azure-Pipelines-1ESPT-ExDShared image: ubuntu-latest From 79128d4bc4a7d6268f498be83fe6b300784eb8e9 Mon Sep 17 00:00:00 2001 From: "Michael Mainer (from Dev Box)" <8527305+MIchaelMainer@users.noreply.github.com> Date: Wed, 3 Jun 2026 13:29:43 -0700 Subject: [PATCH 5/8] chore(pipeline): add environment --- .azure-pipelines/cd-publish-python.yml | 1 + 1 file changed, 1 insertion(+) diff --git a/.azure-pipelines/cd-publish-python.yml b/.azure-pipelines/cd-publish-python.yml index b6e07594..bfb30bb2 100644 --- a/.azure-pipelines/cd-publish-python.yml +++ b/.azure-pipelines/cd-publish-python.yml @@ -110,6 +110,7 @@ extends: jobs: - deployment: publish_python_package displayName: "Publish msgraph-core package" + environment: pypi_prod pool: name: Azure-Pipelines-1ESPT-ExDShared image: ubuntu-latest From ec85078af31efbdd85e81264a44f4022a0088653 Mon Sep 17 00:00:00 2001 From: "Michael Mainer (from Dev Box)" <8527305+MIchaelMainer@users.noreply.github.com> Date: Wed, 3 Jun 2026 13:53:25 -0700 Subject: [PATCH 6/8] chore: update settings and requirements for improved pipeline compatibility --- .vscode/settings.json | 3 ++- requirements-dev.txt | 4 ++-- 2 files changed, 4 insertions(+), 3 deletions(-) diff --git a/.vscode/settings.json b/.vscode/settings.json index 0df470aa..f5e20fd7 100644 --- a/.vscode/settings.json +++ b/.vscode/settings.json @@ -4,5 +4,6 @@ "tests" ], "python.testing.unittestEnabled": false, - "python.testing.pytestEnabled": true + "python.testing.pytestEnabled": true, + "azure-pipelines.1ESPipelineTemplatesSchemaFile": true } \ No newline at end of file diff --git a/requirements-dev.txt b/requirements-dev.txt index 054faa02..f9e28294 100644 --- a/requirements-dev.txt +++ b/requirements-dev.txt @@ -27,7 +27,7 @@ coverage[toml]==7.10.6 ; python_version >= '3.7' cryptography==46.0.7 ; python_version >= '3.7' -dill==0.4.0 ; python_version < '3.11' +dill==0.4.0 exceptiongroup==1.3.0 ; python_version < '3.11' @@ -116,7 +116,7 @@ urllib3==2.7.0 ; python_version >= '3.7' typing-extensions==4.15.0 ; python_version >= '3.7' -wrapt==1.17.3 ; python_version < '3.11' +wrapt==1.17.3 yapf==0.43.0 From ffc2c48373eff3554a3699c1aba63506f35aef16 Mon Sep 17 00:00:00 2001 From: "Michael Mainer (from Dev Box)" <8527305+MIchaelMainer@users.noreply.github.com> Date: Wed, 3 Jun 2026 14:11:04 -0700 Subject: [PATCH 7/8] chore(pipeline): add artifact feed --- .azure-pipelines/cd-publish-python.yml | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/.azure-pipelines/cd-publish-python.yml b/.azure-pipelines/cd-publish-python.yml index bfb30bb2..8d424231 100644 --- a/.azure-pipelines/cd-publish-python.yml +++ b/.azure-pipelines/cd-publish-python.yml @@ -60,6 +60,12 @@ extends: - script: python -m pip install --upgrade pip displayName: "Upgrade pip" + - task: PipAuthenticate@1 + displayName: "Authenticate pip to Azure Artifacts" + inputs: + artifactFeeds: "$(System.TeamProject)/msgraph-python-dev" + onlyAddExtraIndex: true + - script: pip install -r requirements-dev.txt displayName: "Install dependencies" From de36d24deaa18afd8681f1a0db65d4215e2f4279 Mon Sep 17 00:00:00 2001 From: "Michael Mainer (from Dev Box)" <8527305+MIchaelMainer@users.noreply.github.com> Date: Wed, 3 Jun 2026 14:19:53 -0700 Subject: [PATCH 8/8] chore(pipeline): remove onlyAddExtraIndex --- .azure-pipelines/cd-publish-python.yml | 1 - 1 file changed, 1 deletion(-) diff --git a/.azure-pipelines/cd-publish-python.yml b/.azure-pipelines/cd-publish-python.yml index 8d424231..0058e52f 100644 --- a/.azure-pipelines/cd-publish-python.yml +++ b/.azure-pipelines/cd-publish-python.yml @@ -64,7 +64,6 @@ extends: displayName: "Authenticate pip to Azure Artifacts" inputs: artifactFeeds: "$(System.TeamProject)/msgraph-python-dev" - onlyAddExtraIndex: true - script: pip install -r requirements-dev.txt displayName: "Install dependencies"