Skip to content

Commit c504b41

Browse files
RyAuld4gust
andauthored
Migrate CI/CD from GitHub Actions to ADO; remove GH Actions workflow (#895)
* Add ADO pipeline hyperlinks to CI-AND-RELEASE-PIPELINES.md * Add Python 3.8 to ADO CI matrix * Move benchmarks from GH Actions to ADO; remove cb job from GH workflow * Remove GH Actions CI/CD workflow — tests and publish fully covered by ADO pipelines 3064 and 3067 * Address Copilot review: fix benchmark branch condition, switch to PublishPipelineArtifact@1; add TSA config, PostBuildCleanup, job retries * Fix: move retries from job to retryCountOnTaskFailure on pytest step (matrix jobs don't support retries) * Address Copilot review: wire tsaConfig.json to PublishSecurityAnalysisLogs@3; fix Cache@2 key escaping * Move cryptography version-gating tests to warning-only step The cryptography ceiling tests fail whenever a new major version of the cryptography package is released. These are maintenance-reminder tests and should not block unrelated PRs. Run them in a separate step with continueOnError: true so they appear as warnings rather than failures. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> * Add Benchmark stage to pipeline documentation Update pipeline purpose, stage diagram, and stage table to include the Benchmark stage that runs on post-merge pushes to dev. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> * Address Copilot review: benchmark skip, pytest install, artifact guard - Add --benchmark-skip to CI pytest runs so benchmarks only run in the dedicated Benchmark stage, not on every PR across all Python versions - Explicitly install pytest in the Benchmark job instead of relying on transitive dependency from pytest-benchmark - Guard PublishPipelineArtifact with a file existence check so a missing benchmark.json does not mask the underlying failure Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> * Fix: allow Build/Publish stages to proceed on SucceededWithIssues The cryptography ceiling check runs with continueOnError: true, which causes the CI stage to finish as SucceededWithIssues rather than Succeeded. The strict eq(..., 'Succeeded') conditions on Build, PublishMSALPython, and PublishPyPI stages caused them to skip. Change all three conditions to use in(..., 'Succeeded', 'SucceededWithIssues') so warning-only tasks don't block the release. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> * Upgrade EsrpRelease task from v9 to v12 Per ESRP team feedback, v12 returns errors properly. * updated for e2e tests * updated the pipeline runtime and updated the version for sku for rc * Update template-pipeline-stages.yml * Update template-pipeline-stages.yml * Resolved comments --------- Co-authored-by: Nilesh Choudhary <nichoudhary@microsoft.com>
1 parent 192a82d commit c504b41

8 files changed

Lines changed: 419 additions & 319 deletions

File tree

.Pipelines/CI-AND-RELEASE-PIPELINES.md

Lines changed: 35 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -7,45 +7,52 @@ including what each pipeline does, when it runs, and how to trigger a release.
77

88
## Pipeline Files
99

10-
| File | Purpose |
11-
|------|---------|
12-
| [`azure-pipelines.yml`](../azure-pipelines.yml) | PR gate and post-merge CI — calls the shared template with `runPublish: false` |
13-
| [`pipeline-publish.yml`](pipeline-publish.yml) | Release pipeline — manually queued, builds and publishes to PyPI |
14-
| [`template-pipeline-stages.yml`](template-pipeline-stages.yml) | Shared stages template — PreBuildCheck, Validate, and CI stages reused by both pipelines |
15-
| [`credscan-exclusion.json`](credscan-exclusion.json) | CredScan suppression file for known test fixtures |
10+
| File | ADO Pipeline | Purpose |
11+
|------|-------------|---------|
12+
| [`azure-pipelines.yml`](../azure-pipelines.yml) | [MSAL.Python-PR-OneBranch-Official (3064)](https://dev.azure.com/IdentityDivision/IDDP/_build?definitionId=3064) | PR gate, post-merge CI, and performance benchmarks — calls the shared template with `runPublish: false`; runs benchmarks on post-merge pushes to `dev` |
13+
| [`pipeline-publish.yml`](pipeline-publish.yml) | [MSAL.Python-Publish (3067)](https://dev.azure.com/IdentityDivision/IDDP/_build?definitionId=3067) | Release pipeline — manually queued, builds and publishes to PyPI |
14+
| [`template-pipeline-stages.yml`](template-pipeline-stages.yml) | | Shared stages template — PreBuildCheck, Validate, UnitTests, and E2ETests stages reused by both pipelines |
15+
| [`credscan-exclusion.json`](credscan-exclusion.json) | | CredScan suppression file for known test fixtures |
1616

1717
---
1818

19-
## PR / CI Pipeline (`azure-pipelines.yml`)
19+
## PR / CI Pipeline [MSAL.Python-PR-OneBranch-Official (3064)](https://dev.azure.com/IdentityDivision/IDDP/_build?definitionId=3064)
2020

2121
### Triggers
2222

2323
| Event | Branches |
2424
|-------|----------|
25-
| Pull request opened / updated | all branches |
26-
| Push / merge | `dev`, `azure-pipelines` |
25+
| Pull request opened / updated | `dev` (PRs targeting `dev` only) |
26+
| Push / merge | `dev` |
2727
| Scheduled | Daily at 11:45 PM Pacific, `dev` branch (only when there are new changes) |
2828

29+
Fast unit-test feedback for PRs targeting **other** branches (e.g. `release-x.y.z`)
30+
is provided separately by the GitHub Actions workflow
31+
[`.github/workflows/python-package.yml`](../.github/workflows/python-package.yml),
32+
which runs the package build and unit tests on every PR.
33+
2934
### Stages
3035

3136
```
32-
PreBuildCheck ─► CI
37+
PreBuildCheck ─► UnitTests ─► E2ETests ─► Benchmark (post-merge to dev only)
3338
```
3439

35-
| Stage | What it does |
36-
|-------|-------------|
37-
| **PreBuildCheck** | Runs SDL security scans: PoliCheck (policy/offensive content), CredScan (leaked credentials), and PostAnalysis (breaks the build on findings) |
38-
| **CI** | Runs the full test suite on Python 3.9, 3.10, 3.11, 3.12, 3.13, and 3.14 |
40+
| Stage | What it does | When it runs |
41+
|-------|-------------|-------------|
42+
| **PreBuildCheck** | Runs SDL security scans: PoliCheck (policy/offensive content), CredScan (leaked credentials), and PostAnalysis (breaks the build on findings) | Always |
43+
| **UnitTests** | Runs the unit test suite on Python 3.9, 3.10, 3.11, 3.12, 3.13, and 3.14 (no Key Vault required) | After PreBuildCheck |
44+
| **E2ETests** | Fetches the MSID Lab certificate from Key Vault and runs `tests/test_e2e.py` + `tests/test_fmi_e2e.py` on the same Python matrix. On forked PRs the stage still runs, but the Key Vault tasks are skipped and the E2E tests self-skip (because `LAB_APP_CLIENT_CERT_PFX_PATH` is unset), so the stage reports green with all E2E tests marked Skipped in the Tests tab. | After UnitTests |
45+
| **Benchmark** | Runs performance benchmarks on Python 3.9 and publishes `benchmark-results` artifact | Post-merge pushes to `dev` and manual runs only |
3946

40-
The Validate stage is **skipped** on PR/CI runs (it only applies to release builds).
47+
The `Validate` stage is **skipped** on PR/CI runs (it only applies to release builds).
4148

4249
> **SDL coverage:** The PreBuildCheck stage satisfies the OneBranch SDL requirement.
4350
> It runs on every PR, every merge to `dev`, and on the daily schedule — ensuring
4451
> continuous security scanning without a separate dedicated SDL pipeline.
4552
4653
---
4754

48-
## Release Pipeline (`pipeline-publish.yml`)
55+
## Release Pipeline [MSAL.Python-Publish (3067)](https://dev.azure.com/IdentityDivision/IDDP/_build?definitionId=3067)
4956

5057
### Triggers
5158

@@ -62,18 +69,25 @@ with both parameters filled in.
6269
### Stage Flow
6370

6471
```
65-
PreBuildCheck ─► Validate ─► CI ─► Build ─┬─► PublishMSALPython (publishTarget == 'test.pypi.org (Preview / RC)')
66-
└─► PublishPyPI (publishTarget == 'pypi.org (ESRP Production)')
72+
PreBuildCheck ─► Validate ─► UnitTests ─► E2ETests ─► Build ─┬─► PublishMSALPython (publishTarget == 'test.pypi.org (Preview / RC)')
73+
└─► PublishPyPI (publishTarget == 'pypi.org (ESRP Production)')
6774
```
6875

6976
| Stage | What it does | Condition |
7077
|-------|-------------|-----------|
7178
| **PreBuildCheck** | PoliCheck + CredScan scans | Always |
7279
| **Validate** | Asserts the `packageVersion` parameter matches `msal/sku.py __version__` | Always (release runs only) |
73-
| **CI** | Full test matrix (Python 3.9–3.14) | After Validate passes |
74-
| **Build** | Builds `sdist` and `wheel` via `python -m build`; publishes `python-dist` artifact | After CI passes |
80+
| **UnitTests** | Unit test matrix (Python 3.9–3.14) | After Validate passes |
81+
| **E2ETests** | E2E test matrix (Python 3.9–3.14) with MSID Lab cert from Key Vault | After UnitTests passes |
82+
| **Build** | Builds `sdist` and `wheel` via `python -m build`; publishes `python-dist` artifact | After E2ETests passes |
7583
| **PublishMSALPython** | Uploads to test.pypi.org | `publishTarget == test.pypi.org (Preview / RC)` |
76-
| **PublishPyPI** | Uploads to PyPI via ESRP; requires manual approval | `publishTarget == pypi.org (ESRP Production)` |
84+
| **PublishPyPI** | Uploads to PyPI via ESRP (`EsrpRelease@12`); requires manual approval | `publishTarget == pypi.org (ESRP Production)` |
85+
86+
> ⚠️ **TestPyPI publishing is currently a no-op.** The `MSAL-Test-Python-Upload`
87+
> service connection has not yet been created (pending a test.pypi.org API
88+
> token), so the `PublishMSALPython` stage prints a skip message rather than
89+
> uploading. Until the SC exists, use the `pypi.org (ESRP Production)` path
90+
> with an RC version (e.g. `1.36.0rc1`) for end-to-end validation.
7791
7892
---
7993

.Pipelines/pipeline-publish.yml

Lines changed: 9 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,7 @@
66
# Publish targets:
77
# test.pypi.org (Preview / RC) — preview releases via MSAL-Test-Python-Upload SC
88
# (SC creation pending test.pypi.org API token)
9-
# pypi.org (ESRP Production) — production releases via ESRP (EsrpRelease@9) using MSAL-ESRP-AME SC
9+
# pypi.org (ESRP Production) — production releases via ESRP (EsrpRelease@12) using MSAL-ESRP-AME SC
1010
#
1111
# For pipeline documentation, see .Pipelines/CI-AND-RELEASE-PIPELINES.md.
1212

@@ -27,12 +27,12 @@ pr: none
2727

2828
# Stage flow:
2929
#
30-
# PreBuildCheck ─► Validate ─► CI ─► Build ─► PublishMSALPython (publishTarget == Preview)
31-
# └─► PublishPyPI (publishTarget == ESRP Production)
30+
# PreBuildCheck ─► Validate ─► UnitTests ─► E2ETests ─► Build ─► PublishMSALPython (publishTarget == Preview)
31+
# └─► PublishPyPI (publishTarget == ESRP Production)
3232

3333
stages:
3434

35-
# PreBuildCheck, Validate, and CI stages are defined in the shared template.
35+
# PreBuildCheck, Validate, UnitTests, and E2ETests stages are defined in the shared template.
3636
- template: template-pipeline-stages.yml
3737
parameters:
3838
packageVersion: ${{ parameters.packageVersion }}
@@ -43,8 +43,8 @@ stages:
4343
# ══════════════════════════════════════════════════════════════════════════════
4444
- stage: Build
4545
displayName: 'Build package'
46-
dependsOn: CI
47-
condition: eq(dependencies.CI.result, 'Succeeded')
46+
dependsOn: E2ETests
47+
condition: eq(dependencies.E2ETests.result, 'Succeeded')
4848
jobs:
4949
- job: BuildDist
5050
displayName: 'Build sdist + wheel (Python 3.12)'
@@ -130,10 +130,10 @@ stages:
130130

131131
# ══════════════════════════════════════════════════════════════════════════════
132132
# Stage 4b · Publish to PyPI (ESRP Production)
133-
# Uses EsrpRelease@9 via the MSAL-ESRP-AME service connection.
133+
# Uses EsrpRelease@12 via the MSAL-ESRP-AME service connection.
134134
# IMPORTANT: configure a required manual approval on this environment in
135135
# ADO → Pipelines → Environments → MSAL-Python-Release → Approvals and checks.
136-
# IMPORTANT: EsrpRelease@9 requires a Windows agent.
136+
# IMPORTANT: EsrpRelease@12 requires a Windows agent.
137137
# ══════════════════════════════════════════════════════════════════════════════
138138
- stage: PublishPyPI
139139
displayName: 'Publish to PyPI (ESRP Production)'
@@ -159,7 +159,7 @@ stages:
159159
artifactName: python-dist
160160
targetPath: $(Pipeline.Workspace)/python-dist
161161

162-
- task: EsrpRelease@9
162+
- task: EsrpRelease@12
163163
displayName: 'Publish to PyPI via ESRP'
164164
inputs:
165165
connectedservicename: 'MSAL-ESRP-AME'

0 commit comments

Comments
 (0)