diff --git a/.azure-pipelines/cd-publish-python.yml b/.azure-pipelines/cd-publish-python.yml new file mode 100644 index 00000000..c27139b4 --- /dev/null +++ b/.azure-pipelines/cd-publish-python.yml @@ -0,0 +1,345 @@ +# Copyright (c) Microsoft Corporation. All rights reserved. +# Licensed under the MIT License. + +# Build, package, and deploy Kiota Python packages to PyPI + +name: $(BuildDefinitionName)_$(SourceBranchName)_$(Date:yyyyMMdd)$(Rev:.r) + +trigger: + tags: + include: + - 'microsoft-kiota-abstractions-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 + sdl: + sourceAnalysisPool: + name: Azure-Pipelines-1ESPT-ExDShared + image: windows-2022 + os: windows + stages: + + - stage: build + displayName: 'Build and Package Kiota Python Packages' + condition: or(contains(variables['Build.SourceBranch'], 'microsoft-kiota-abstractions-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: + - task: UsePythonVersion@0 + displayName: 'Install Python $(pythonVersion)' + inputs: + versionSpec: '$(pythonVersion)' + addToPath: true + + - 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" + + - script: | + pip install poetry + pip install poetry-plugin-mono-repo-deps + displayName: 'Install Poetry and mono-repo-deps plugin' + + # Build and test kiota_abstractions + - script: poetry install + displayName: 'Install abstractions dependencies' + workingDirectory: '$(Build.SourcesDirectory)/packages/abstractions' + + - script: poetry run yapf -dr kiota_abstractions + displayName: 'Check code format - abstractions' + workingDirectory: '$(Build.SourcesDirectory)/packages/abstractions' + + - script: poetry run isort kiota_abstractions + displayName: 'Check import order - abstractions' + workingDirectory: '$(Build.SourcesDirectory)/packages/abstractions' + + - script: poetry run pylint kiota_abstractions --disable=W --rcfile=.pylintrc + displayName: 'Lint with Pylint - abstractions' + workingDirectory: '$(Build.SourcesDirectory)/packages/abstractions' + + - script: poetry run pytest + displayName: 'Run tests - abstractions' + workingDirectory: '$(Build.SourcesDirectory)/packages/abstractions' + + - script: poetry build + displayName: 'Build package - abstractions' + workingDirectory: '$(Build.SourcesDirectory)/packages/abstractions' + + # Build and test kiota_authentication_azure + - script: poetry install + displayName: 'Install authentication_azure dependencies' + workingDirectory: '$(Build.SourcesDirectory)/packages/authentication/azure' + + - script: poetry run yapf -dr kiota_authentication_azure + displayName: 'Check code format - authentication_azure' + workingDirectory: '$(Build.SourcesDirectory)/packages/authentication/azure' + + - script: poetry run isort kiota_authentication_azure + displayName: 'Check import order - authentication_azure' + workingDirectory: '$(Build.SourcesDirectory)/packages/authentication/azure' + + - script: poetry run pylint kiota_authentication_azure --disable=W --rcfile=.pylintrc + displayName: 'Lint with Pylint - authentication_azure' + workingDirectory: '$(Build.SourcesDirectory)/packages/authentication/azure' + + - script: poetry run pytest + displayName: 'Run tests - authentication_azure' + workingDirectory: '$(Build.SourcesDirectory)/packages/authentication/azure' + + - script: poetry build + displayName: 'Build package - authentication_azure' + workingDirectory: '$(Build.SourcesDirectory)/packages/authentication/azure' + + # Build and test kiota_http + - script: poetry install + displayName: 'Install http dependencies' + workingDirectory: '$(Build.SourcesDirectory)/packages/http/httpx' + + - script: poetry run yapf -dr kiota_http + displayName: 'Check code format - http' + workingDirectory: '$(Build.SourcesDirectory)/packages/http/httpx' + + - script: poetry run isort kiota_http + displayName: 'Check import order - http' + workingDirectory: '$(Build.SourcesDirectory)/packages/http/httpx' + + - script: poetry run pylint kiota_http --disable=W --rcfile=.pylintrc + displayName: 'Lint with Pylint - http' + workingDirectory: '$(Build.SourcesDirectory)/packages/http/httpx' + + - script: poetry run pytest + displayName: 'Run tests - http' + workingDirectory: '$(Build.SourcesDirectory)/packages/http/httpx' + + - script: poetry build + displayName: 'Build package - http' + workingDirectory: '$(Build.SourcesDirectory)/packages/http/httpx' + + # Build and test kiota_serialization_form + - script: poetry install + displayName: 'Install serialization_form dependencies' + workingDirectory: '$(Build.SourcesDirectory)/packages/serialization/form' + + - script: poetry run yapf -dr kiota_serialization_form + displayName: 'Check code format - serialization_form' + workingDirectory: '$(Build.SourcesDirectory)/packages/serialization/form' + + - script: poetry run isort kiota_serialization_form + displayName: 'Check import order - serialization_form' + workingDirectory: '$(Build.SourcesDirectory)/packages/serialization/form' + + - script: poetry run pylint kiota_serialization_form --disable=W --rcfile=.pylintrc + displayName: 'Lint with Pylint - serialization_form' + workingDirectory: '$(Build.SourcesDirectory)/packages/serialization/form' + + - script: poetry run pytest + displayName: 'Run tests - serialization_form' + workingDirectory: '$(Build.SourcesDirectory)/packages/serialization/form' + + - script: poetry build + displayName: 'Build package - serialization_form' + workingDirectory: '$(Build.SourcesDirectory)/packages/serialization/form' + + # Build and test kiota_serialization_json + - script: poetry install + displayName: 'Install serialization_json dependencies' + workingDirectory: '$(Build.SourcesDirectory)/packages/serialization/json' + + - script: poetry run yapf -dr kiota_serialization_json + displayName: 'Check code format - serialization_json' + workingDirectory: '$(Build.SourcesDirectory)/packages/serialization/json' + + - script: poetry run isort kiota_serialization_json + displayName: 'Check import order - serialization_json' + workingDirectory: '$(Build.SourcesDirectory)/packages/serialization/json' + + - script: poetry run pylint kiota_serialization_json --disable=W --rcfile=.pylintrc + displayName: 'Lint with Pylint - serialization_json' + workingDirectory: '$(Build.SourcesDirectory)/packages/serialization/json' + + - script: poetry run pytest + displayName: 'Run tests - serialization_json' + workingDirectory: '$(Build.SourcesDirectory)/packages/serialization/json' + + - script: poetry build + displayName: 'Build package - serialization_json' + workingDirectory: '$(Build.SourcesDirectory)/packages/serialization/json' + + # Build and test kiota_serialization_text + - script: poetry install + displayName: 'Install serialization_text dependencies' + workingDirectory: '$(Build.SourcesDirectory)/packages/serialization/text' + + - script: poetry run yapf -dr kiota_serialization_text + displayName: 'Check code format - serialization_text' + workingDirectory: '$(Build.SourcesDirectory)/packages/serialization/text' + + - script: poetry run isort kiota_serialization_text + displayName: 'Check import order - serialization_text' + workingDirectory: '$(Build.SourcesDirectory)/packages/serialization/text' + + - script: poetry run pylint kiota_serialization_text --disable=W --rcfile=.pylintrc + displayName: 'Lint with Pylint - serialization_text' + workingDirectory: '$(Build.SourcesDirectory)/packages/serialization/text' + + - script: poetry run pytest + displayName: 'Run tests - serialization_text' + workingDirectory: '$(Build.SourcesDirectory)/packages/serialization/text' + + - script: poetry build + displayName: 'Build package - serialization_text' + workingDirectory: '$(Build.SourcesDirectory)/packages/serialization/text' + + # Build and test kiota_serialization_multipart + - script: poetry install + displayName: 'Install serialization_multipart dependencies' + workingDirectory: '$(Build.SourcesDirectory)/packages/serialization/multipart' + + - script: poetry run yapf -dr kiota_serialization_multipart + displayName: 'Check code format - serialization_multipart' + workingDirectory: '$(Build.SourcesDirectory)/packages/serialization/multipart' + + - script: poetry run isort kiota_serialization_multipart + displayName: 'Check import order - serialization_multipart' + workingDirectory: '$(Build.SourcesDirectory)/packages/serialization/multipart' + + - script: poetry run pylint kiota_serialization_multipart --disable=W --rcfile=.pylintrc + displayName: 'Lint with Pylint - serialization_multipart' + workingDirectory: '$(Build.SourcesDirectory)/packages/serialization/multipart' + + - script: poetry run pytest + displayName: 'Run tests - serialization_multipart' + workingDirectory: '$(Build.SourcesDirectory)/packages/serialization/multipart' + + - script: poetry build + displayName: 'Build package - serialization_multipart' + workingDirectory: '$(Build.SourcesDirectory)/packages/serialization/multipart' + + # Build and test kiota_bundle + - script: poetry install + displayName: 'Install bundle dependencies' + workingDirectory: '$(Build.SourcesDirectory)/packages/bundle' + + - script: poetry run yapf -dr kiota_bundle + displayName: 'Check code format - bundle' + workingDirectory: '$(Build.SourcesDirectory)/packages/bundle' + + - script: poetry run isort kiota_bundle + displayName: 'Check import order - bundle' + workingDirectory: '$(Build.SourcesDirectory)/packages/bundle' + + - script: poetry run pylint kiota_bundle --disable=W --rcfile=.pylintrc + displayName: 'Lint with Pylint - bundle' + workingDirectory: '$(Build.SourcesDirectory)/packages/bundle' + + - script: poetry run pytest + displayName: 'Run tests - bundle' + workingDirectory: '$(Build.SourcesDirectory)/packages/bundle' + + - script: poetry build + displayName: 'Build package - bundle' + workingDirectory: '$(Build.SourcesDirectory)/packages/bundle' + + # Copy all built packages to staging + - task: CopyFiles@2 + displayName: 'Copy all package artifacts to staging' + inputs: + CleanTargetFolder: true + sourceFolder: '$(Build.SourcesDirectory)' + targetFolder: '$(Build.ArtifactStagingDirectory)/python/kiota_packages' + Contents: | + packages/abstractions/dist/*.tar.gz + packages/abstractions/dist/*.whl + packages/authentication/azure/dist/*.tar.gz + packages/authentication/azure/dist/*.whl + packages/http/httpx/dist/*.tar.gz + packages/http/httpx/dist/*.whl + packages/serialization/form/dist/*.tar.gz + packages/serialization/form/dist/*.whl + packages/serialization/json/dist/*.tar.gz + packages/serialization/json/dist/*.whl + packages/serialization/text/dist/*.tar.gz + packages/serialization/text/dist/*.whl + packages/serialization/multipart/dist/*.tar.gz + packages/serialization/multipart/dist/*.whl + packages/bundle/dist/*.tar.gz + packages/bundle/dist/*.whl + flattenFolders: true + + templateContext: + outputs: + - output: pipelineArtifact + displayName: 'Stage Kiota Python package artifacts' + artifactName: pypi_kiota_packages + targetPath: '$(Build.ArtifactStagingDirectory)/python/kiota_packages' + condition: or(contains(variables['Build.SourceBranch'], 'microsoft-kiota-abstractions-v'), eq(variables['Build.Reason'], 'Manual')) + + - stage: deploy + displayName: 'Publish Kiota Python Packages to PyPI' + dependsOn: build + condition: or(and(contains(variables['Build.SourceBranch'], 'microsoft-kiota-abstractions-v'), succeeded()), eq(variables['Build.Reason'], 'Manual')) + jobs: + - deployment: publish_python_packages + displayName: 'Publish Kiota Python Packages' + environment: pypi_prod + pool: + name: Azure-Pipelines-1ESPT-ExDShared + image: ubuntu-latest + os: linux + + templateContext: + type: releaseJob + isProduction: true + inputs: + - input: pipelineArtifact + artifactName: pypi_kiota_packages + targetPath: '$(Build.ArtifactStagingDirectory)/python' + strategy: + runOnce: + deploy: + steps: + - task: EsrpRelease@9 + displayName: 'Publish Kiota Python packages 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: 'mmainer@microsoft.com,gavinbarron@microsoft.com' + approvers: 'mmainer@microsoft.com,christiano@microsoft.com,gavinbarron@microsoft.com,lramosvea@microsoft.com' + serviceendpointurl: 'https://api.esrp.microsoft.com' + mainpublisher: 'ESRPRELPACMAN' + domaintenantid: 'cdc5aeea-15c5-4db6-b079-fcadd2505dc2' diff --git a/.github/workflows/publish.yml b/.github/workflows/publish.yml deleted file mode 100644 index 09c5c15b..00000000 --- a/.github/workflows/publish.yml +++ /dev/null @@ -1,75 +0,0 @@ -name: Publish package to PyPI - -on: - push: - tags: - - "microsoft-kiota-abstractions-v*" # Push events to matching microsoft-kiota-abstractions-v*, i.e. microsoft-kiota-abstractions-v1.0, microsoft-kiota-abstractions-v20.15.10 - # All packages are ideally released together so we can use the same tag for all packages - -permissions: - contents: write - -jobs: - build: - uses: ./.github/workflows/build.yml - - publish: - name: Publish distribution to PyPI - runs-on: ubuntu-latest - if: startsWith(github.ref, 'refs/tags/microsoft-kiota-abstractions-v') - environment: pypi_prod - needs: [build] - env: - POETRY_PYPI_TOKEN_PYPI: ${{ secrets.PYPI_API_TOKEN }} - steps: - - name: Checkout code - uses: actions/checkout@v6 - - name: Set up Python - uses: actions/setup-python@v6 - with: - python-version: "3.14" - - name: Install poetry and mono-repo-deps plugin - run: | - python -m pip install --upgrade poetry - python -m pip install --upgrade poetry-plugin-mono-repo-deps - - name: Publish kiota_abstractions to PyPI - run: | - poetry install - poetry publish --build - working-directory: "./packages/abstractions" - - name: Publish kiota_authentication_azure to PyPI - run: | - poetry install - poetry publish --build - working-directory: "./packages/authentication/azure" - - name: Publish kiota_http to PyPI - run: | - poetry install - poetry publish --build - working-directory: "./packages/http/httpx" - - name: Publish kiota_serialization_form to PyPI - run: | - poetry install - poetry publish --build - working-directory: "./packages/serialization/form" - - name: Publish kiota_serialization_json to PyPI - run: | - poetry install - poetry publish --build - working-directory: "./packages/serialization/json" - - name: Publish kiota_serialization_text to PyPI - run: | - poetry install - poetry publish --build - working-directory: "./packages/serialization/text" - - name: Publish kiota_serialization_multipart to PyPI - run: | - poetry install - poetry publish --build - working-directory: "./packages/serialization/multipart" - - name: Publish kiota_bundle to PyPI - run: | - poetry install - poetry publish --build - working-directory: "./packages/bundle" - \ No newline at end of file diff --git a/.vscode/settings.json b/.vscode/settings.json index 790145ea..7d688dd3 100644 --- a/.vscode/settings.json +++ b/.vscode/settings.json @@ -16,5 +16,6 @@ "--rootdir=${workspaceFolder}" ], "python.testing.unittestEnabled": false, - "python.testing.pytestEnabled": false, // Disable pytest (does not work with poetry yet) + "python.testing.pytestEnabled": false, + "azure-pipelines.1ESPipelineTemplatesSchemaFile": true, // Disable pytest (does not work with poetry yet) } \ No newline at end of file