Skip to content
Open
Changes from 7 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
266 changes: 266 additions & 0 deletions .Pipelines/pipeline-unit-tests.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,266 @@
# ADO pipeline for the msal Python test suite.
# Two stages → two GitHub checks (Unit tests, E2E tests). Each stage is one
# job that fans out the Python matrix as parallel bash background processes
# so wall-clock time ≈ slowest single Python version, not the sum.

trigger:
branches:
include:
- 4gust/ado-pipeline
- dev

pr:
branches:
include:
- dev
drafts: false

stages:

# ─────────────────────────────────────────────────────────────────────────────
# Stage 1 · Unit tests — no Key Vault, no service connection.
# ─────────────────────────────────────────────────────────────────────────────
- stage: UnitTests
displayName: 'Unit test'
jobs:
- job: Pytest
displayName: 'Unit test'
pool:
vmImage: ubuntu-22.04
timeoutInMinutes: 30
steps:
- task: UsePythonVersion@0
displayName: 'Use Python 3.9'
inputs: { versionSpec: '3.9' }
- task: UsePythonVersion@0
displayName: 'Use Python 3.10'
inputs: { versionSpec: '3.10' }
- task: UsePythonVersion@0
displayName: 'Use Python 3.11'
inputs: { versionSpec: '3.11' }
- task: UsePythonVersion@0
displayName: 'Use Python 3.12'
inputs: { versionSpec: '3.12' }
- task: UsePythonVersion@0
displayName: 'Use Python 3.13'
inputs: { versionSpec: '3.13' }
- task: UsePythonVersion@0
displayName: 'Use Python 3.14'
inputs: { versionSpec: '3.14' }

- bash: |
set -uo pipefail
mkdir -p test-results logs

run_unit() {
local V="$1"
local LOG="logs/unit-${V}.log"
{
echo "=== Unit tests · Python ${V} (parallel) ==="
local PY="python${V}"
if ! command -v "$PY" >/dev/null; then
echo "ERROR: $PY not on PATH"
exit 1
fi
"$PY" -m venv ".venv-unit-${V}"
# shellcheck disable=SC1090
source ".venv-unit-${V}/bin/activate"
python -m pip install --upgrade pip
pip install -r requirements.txt
pip install pytest pytest-azurepipelines
pytest -vv \
--junitxml="test-results/junit-unit-${V}.xml" \
--ignore=tests/test_e2e.py \
--ignore=tests/test_e2e_manual.py \
--ignore=tests/test_fmi_e2e.py
local RC=$?
deactivate
exit $RC
} >"$LOG" 2>&1
}

VERSIONS=(3.9 3.10 3.11 3.12 3.13 3.14)
PIDS=()
for V in "${VERSIONS[@]}"; do
run_unit "$V" &
PIDS+=($!)
done

OVERALL_RC=0
declare -A RESULTS
for i in "${!VERSIONS[@]}"; do
V="${VERSIONS[$i]}"
PID="${PIDS[$i]}"
if wait "$PID"; then
RESULTS[$V]="PASS"
else
RESULTS[$V]="FAIL (rc=$?)"
OVERALL_RC=1
fi
done

for V in "${VERSIONS[@]}"; do
echo ""
echo "############################################################"
echo "# Unit tests · Python ${V} · ${RESULTS[$V]}"
echo "############################################################"
cat "logs/unit-${V}.log"
done

echo ""
echo "=== Summary ==="
for V in "${VERSIONS[@]}"; do
echo " Python ${V}: ${RESULTS[$V]}"
done

exit $OVERALL_RC
displayName: 'Run pytest (unit, all Python versions in parallel)'

- task: PublishTestResults@2
displayName: 'Publish JUnit test results'
condition: succeededOrFailed()
inputs:
testResultsFormat: 'JUnit'
testResultsFiles: 'test-results/junit-unit-*.xml'
failTaskOnFailedTests: true
testRunTitle: 'Unit tests'
mergeTestResults: true

# ─────────────────────────────────────────────────────────────────────────────
# Stage 2 · E2E tests — runs only if unit tests pass. Fetches the MSID Lab
# certificate from Key Vault (mirrors MSAL.NET's
# build/template-install-keyvault-secrets.yaml).
# ─────────────────────────────────────────────────────────────────────────────
- stage: E2ETests
displayName: 'E2E tests'
dependsOn: UnitTests
condition: succeeded()
jobs:
- job: Pytest
displayName: 'E2E tests'
pool:
vmImage: ubuntu-22.04
timeoutInMinutes: 60
steps:
- task: UsePythonVersion@0
displayName: 'Use Python 3.9'
inputs: { versionSpec: '3.9' }
- task: UsePythonVersion@0
displayName: 'Use Python 3.10'
inputs: { versionSpec: '3.10' }
- task: UsePythonVersion@0
displayName: 'Use Python 3.11'
inputs: { versionSpec: '3.11' }
- task: UsePythonVersion@0
displayName: 'Use Python 3.12'
inputs: { versionSpec: '3.12' }
- task: UsePythonVersion@0
displayName: 'Use Python 3.13'
inputs: { versionSpec: '3.13' }
- task: UsePythonVersion@0
displayName: 'Use Python 3.14'
inputs: { versionSpec: '3.14' }

- task: AzureKeyVault@2
displayName: 'Fetch MSID Lab certificate from Key Vault'
inputs:
azureSubscription: 'AuthSdkResourceManager'
KeyVaultName: 'msidlabs'
SecretsFilter: 'LabAuth'
RunAsPreJob: false
Comment on lines +106 to +113

- bash: |
set -euo pipefail
if [ -z "${LAB_AUTH_B64:-}" ]; then
echo "##vso[task.logissue type=error]LabAuth secret is empty — Key Vault retrieval failed."
exit 1
fi
CERT_PATH="$(Agent.TempDirectory)/lab-auth.pfx"
printf '%s' "$LAB_AUTH_B64" | base64 -d > "$CERT_PATH"
echo "##vso[task.setvariable variable=LAB_APP_CLIENT_CERT_PFX_PATH]$CERT_PATH"
echo "Lab cert written to: $CERT_PATH ($(wc -c < "$CERT_PATH") bytes)"
displayName: 'Decode lab certificate to PFX'
env:
LAB_AUTH_B64: $(LabAuth)

- bash: |
set -uo pipefail
mkdir -p test-results logs

run_e2e() {
local V="$1"
local LOG="logs/e2e-${V}.log"
{
echo "=== E2E tests · Python ${V} (parallel) ==="
local PY="python${V}"
if ! command -v "$PY" >/dev/null; then
echo "ERROR: $PY not on PATH"
exit 1
fi
"$PY" -m venv ".venv-e2e-${V}"
# shellcheck disable=SC1090
source ".venv-e2e-${V}/bin/activate"
python -m pip install --upgrade pip
pip install -r requirements.txt
pip install pytest pytest-azurepipelines
pytest -vv \
--junitxml="test-results/junit-e2e-${V}.xml" \
tests/test_e2e.py tests/test_fmi_e2e.py
local RC=$?
deactivate
exit $RC
} >"$LOG" 2>&1
}

VERSIONS=(3.9 3.10 3.11 3.12 3.13 3.14)
PIDS=()
for V in "${VERSIONS[@]}"; do
run_e2e "$V" &
PIDS+=($!)
done

OVERALL_RC=0
declare -A RESULTS
for i in "${!VERSIONS[@]}"; do
V="${VERSIONS[$i]}"
PID="${PIDS[$i]}"
if wait "$PID"; then
RESULTS[$V]="PASS"
else
RESULTS[$V]="FAIL (rc=$?)"
OVERALL_RC=1
fi
done

for V in "${VERSIONS[@]}"; do
echo ""
echo "############################################################"
echo "# E2E tests · Python ${V} · ${RESULTS[$V]}"
echo "############################################################"
cat "logs/e2e-${V}.log"
done

echo ""
echo "=== Summary ==="
for V in "${VERSIONS[@]}"; do
echo " Python ${V}: ${RESULTS[$V]}"
done

exit $OVERALL_RC
displayName: 'Run pytest (E2E, all Python versions in parallel)'
env:
LAB_APP_CLIENT_CERT_PFX_PATH: $(LAB_APP_CLIENT_CERT_PFX_PATH)

- task: PublishTestResults@2
displayName: 'Publish JUnit test results'
condition: succeededOrFailed()
inputs:
testResultsFormat: 'JUnit'
testResultsFiles: 'test-results/junit-e2e-*.xml'
failTaskOnFailedTests: true
testRunTitle: 'E2E tests'
mergeTestResults: true

- bash: rm -f "$(Agent.TempDirectory)/lab-auth.pfx"
displayName: 'Remove lab certificate from agent'
condition: always()
Loading