Skip to content
Closed
Show file tree
Hide file tree
Changes from all 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
39 changes: 39 additions & 0 deletions CONTRIBUTING.md
Original file line number Diff line number Diff line change
Expand Up @@ -99,6 +99,45 @@ When evaluating adding new tests, please search in the existing test files if th
1. Check for [test failures](#test-failures) and address them if they are not transient.
1. Review the **Checks** section to confirm there are no pending steps that might be blocking your work from merging.

### How CI works for pull requests from forks

The repository's CI is split into two layers because Azure DevOps does not
expose secret variables (such as Cosmos DB connection strings) to builds
triggered by pull requests from forks. This is an Azure DevOps security
default, not a project-specific restriction.

* **`dotnet-v3-ci`** ([`azure-pipelines.yml`](azure-pipelines.yml)) runs
automatically on every pull request, including fork PRs. It covers the
build, static analysis, unit tests, encryption tests, samples, CTL,
benchmarks, and all Emulator tests that do not require a live Cosmos
account. **Fork contributors can self-serve this entire pipeline.**

* **`dotnet-v3-live-account`** ([`azure-pipelines-live-account.yml`](azure-pipelines-live-account.yml))
runs the live-account tests (`MultiRegion`, `MultiMaster`) which depend on
the `COSMOSDB_MULTI_REGION` and `COSMOSDB_MULTIMASTER` secret variables.
It will **not** auto-run on a fork PR. A maintainer must comment
`/azp run dotnet-v3-live-account` on the PR to dispatch the run against
the PR's commit.

If you are an external contributor and you see the `dotnet-v3-live-account`
check pending on your PR, that is expected. A maintainer will trigger it
once they have reviewed your change and are comfortable running it against
the team's Azure resources. You do **not** need to do anything to make this
work, and you cannot fix `dotnet-v3-live-account` failures from your fork
branch alone — if a maintainer has trusted the change but the live
checks fail, leave a comment and a maintainer can re-trigger after a fix.

### Working on the pipeline split itself

If you are changing the pipeline layout, keep this invariant: no template
referenced from `azure-pipelines.yml` may consume `$(COSMOSDB_MULTI_REGION)`,
`$(COSMOSDB_MULTIMASTER)`, or any other secret variable, and no job in those
templates may read those values out of `parameters`. Any new live-account
test should be added to [`templates/build-test-live.yml`](templates/build-test-live.yml)
and surfaced through [`azure-pipelines-live-account.yml`](azure-pipelines-live-account.yml)
plus the trusted internal pipelines (`azure-pipelines-official.yml`,
`azure-pipelines-rolling.yml`).

## Changelog entry

Every pull request that changes shipped behavior must add a changelog
Expand Down
68 changes: 68 additions & 0 deletions azure-pipelines-live-account.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,68 @@
# File: azure-pipelines-live-account.yml
#
# On-demand "live-account" CI pipeline for the Microsoft.Azure.Cosmos SDK.
# Runs the MultiRegion and MultiMaster EmulatorTests, which require real
# Azure Cosmos DB connection-string secrets (COSMOSDB_MULTI_REGION,
# COSMOSDB_MULTIMASTER).
#
# WHY THIS PIPELINE EXISTS
# ------------------------
# The default PR-validation pipeline (azure-pipelines.yml) runs on every pull
# request, including PRs opened from forks. Azure DevOps does not expose
# secret variables to builds triggered by fork PRs (a security default), so
# any job needing live-account secrets would fail on those builds. To avoid
# this, the live-account jobs were extracted into templates/build-test-live.yml
# and this pipeline is the only fork-eligible entry point that invokes them.
#
# HOW IT IS TRIGGERED
# -------------------
# * Automatic on `main` and `releases/*` for code changes that could affect
# multi-region behavior (see the trigger block below).
# * Manually, for a specific pull request, by a team member commenting
# `/azp run dotnet-v3-live-account` on the PR.
# * It is also expected to be configured in the ADO pipeline UI with:
# - Build pull requests from forks: ON
# - Make secrets available to builds of forks: ON
# - Require a team member's comment before building a pull request: ON
# which together implement the "team member approval" gate.
#
# REQUIRED ADO PIPELINE VARIABLES (defined in the pipeline UI as SECRETS):
# * COSMOSDB_MULTI_REGION - connection string for the shared multi-region
# test account.
# * COSMOSDB_MULTIMASTER - connection string for the shared multi-master
# test account.
#
# Required GitHub branch protection: list the build status from this pipeline
# as a *required* check on `main` so no PR can merge without it being green.

trigger:
branches:
include:
- main
- releases/*
paths:
include:
- 'Microsoft.Azure.Cosmos/src/**'
- 'Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.EmulatorTests/**'
- 'templates/build-test-live.yml'
- 'azure-pipelines-live-account.yml'
exclude:
- '*.md'
- 'docs/**/*'
- 'Microsoft.Azure.Cosmos/contracts/**/*'

# `pr: none` keeps Azure DevOps from auto-running this pipeline on every PR.
# Maintainers trigger it on a PR with `/azp run dotnet-v3-live-account`.
pr: none

variables:
ReleaseArguments: ' --filter "TestCategory!=Quarantine & TestCategory!=Ignore" --verbosity normal '
VmImage: windows-latest

jobs:
- template: templates/build-test-live.yml
parameters:
BuildConfiguration: Release
VmImage: $(VmImage)
MultiRegionConnectionString: $(COSMOSDB_MULTI_REGION)
MultiRegionMultiMasterConnectionString: $(COSMOSDB_MULTIMASTER)
5 changes: 5 additions & 0 deletions azure-pipelines-official.yml
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,11 @@ stages:
BuildConfiguration: '${{ variables.BuildConfiguration }}'
Arguments: '${{ variables.ReleaseArguments }}'
VmImage: '${{ variables.VmImage }}'

- template: templates/build-test-live.yml
parameters:
BuildConfiguration: '${{ variables.BuildConfiguration }}'
VmImage: '${{ variables.VmImage }}'
MultiRegionConnectionString: $(COSMOSDB_MULTI_REGION)
MultiRegionMultiMasterConnectionString: $(COSMOSDB_MULTIMASTER)

Expand Down
18 changes: 14 additions & 4 deletions azure-pipelines-rolling.yml
Original file line number Diff line number Diff line change
Expand Up @@ -27,23 +27,33 @@ jobs:
BuildConfiguration: Release
Arguments: $(ReleaseArguments)
VmImage: $(VmImage)
MultiRegionConnectionString: $(COSMOSDB_MULTI_REGION)
MultiRegionMultiMasterConnectionString: $(COSMOSDB_MULTIMASTER)
IncludeEncryption: true
IncludePerformance: true
IncludeCoverage: true

- template: templates/build-test-live.yml
parameters:
BuildConfiguration: Release
VmImage: $(VmImage)
MultiRegionConnectionString: $(COSMOSDB_MULTI_REGION)
MultiRegionMultiMasterConnectionString: $(COSMOSDB_MULTIMASTER)

- template: templates/build-test.yml
parameters:
BuildConfiguration: Release /p:IsPreview=true
Arguments: $(ReleaseArguments)
VmImage: $(VmImage)
MultiRegionConnectionString: $(COSMOSDB_MULTI_REGION)
MultiRegionMultiMasterConnectionString: $(COSMOSDB_MULTIMASTER)
IncludeEncryption: true
IncludePerformance: true
IncludeCoverage: true

- template: templates/build-test-live.yml
parameters:
BuildConfiguration: Release /p:IsPreview=true
VmImage: $(VmImage)
MultiRegionConnectionString: $(COSMOSDB_MULTI_REGION)
MultiRegionMultiMasterConnectionString: $(COSMOSDB_MULTIMASTER)

# Run the preview-flag build (which includes the Encryption / Encryption.Custom
# SDK-source project-ref + NuGet-surface parity builds added in PR #5798) on
# the rolling schedule so any newly-added abstract member on Container under
Expand Down
8 changes: 6 additions & 2 deletions azure-pipelines.yml
Original file line number Diff line number Diff line change
Expand Up @@ -50,11 +50,15 @@ jobs:
BuildConfiguration: Release
Arguments: $(ReleaseArguments)
VmImage: $(VmImage)
MultiRegionConnectionString: $(COSMOSDB_MULTI_REGION)
MultiRegionMultiMasterConnectionString: $(COSMOSDB_MULTIMASTER)
IncludePerformance: true
IncludeCoverage: true

# NOTE: Live-account tests (MultiRegion, MultiMaster) intentionally do NOT run
# in this pipeline. They require the $(COSMOSDB_MULTI_REGION) and
# $(COSMOSDB_MULTIMASTER) secret variables, which Azure DevOps does not expose
# to fork-PR builds for security reasons. See azure-pipelines-live-account.yml
# and CONTRIBUTING.md for how those tests run.

- template: templates/build-internal.yml
parameters:
BuildConfiguration: Release
Expand Down
44 changes: 43 additions & 1 deletion docs/builds-and-pipelines.md
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
# Build pipelines for the Azure Cosmos DB .NET SDK

This repository contains 6 pipelines that are used on different scenarios.
This repository contains 7 pipelines that are used on different scenarios.

## PR Validation

Expand All @@ -15,8 +15,22 @@ This repository contains 6 pipelines that are used on different scenarios.
* [Verify the project builds with the PREVIEW flag, Unit tests for PREVIEW pass, Encryption and Benchmark projects for PREVIEW build](../templates/build-preview.yml) -> PREVIEW is used to ship the `-preview` SDK package.
* [Verify the Benchmark project builds, including PREVIEW flag build](../templates/build-benchmark.yml) -> [Benchmark project](../Microsoft.Azure.Cosmos.Samples/Tools/Benchmark/README.md) enables users to execute benchmark runs on their accounts.

This pipeline does **not** run live-account tests (`MultiRegion`, `MultiMaster`) because those require secret variables that Azure DevOps refuses to mount on builds triggered by pull requests from forks. The live-account jobs were intentionally extracted from [`templates/build-test.yml`](../templates/build-test.yml) into [`templates/build-test-live.yml`](../templates/build-test-live.yml) and are surfaced through the [Live account validation](#live-account-validation) pipeline described below.

This pipeline executes on Azure Pipelines as [dotnet-v3-ci](https://cosmos-db-sdk-public.visualstudio.com/cosmos-db-sdk-public/_build?definitionId=63).

## Live account validation

[azure-pipelines-live-account.yml](../azure-pipelines-live-account.yml) runs the live-account EmulatorTests categories — `MultiRegion` and `MultiMaster` — via [`templates/build-test-live.yml`](../templates/build-test-live.yml). These jobs depend on the `$(COSMOSDB_MULTI_REGION)` and `$(COSMOSDB_MULTIMASTER)` secret variables.

This pipeline is configured (in the Azure DevOps UI) so that:

* It auto-runs on merges into `main` and `releases/*`.
* It does **not** auto-run on pull requests from forks. A team member must comment `/azp run dotnet-v3-live-account` on the PR to dispatch a run against the PR's commit. This is the same "team-member approval" pattern that `azure-sdk-for-rust`, `azure-sdk-for-java`, and `azure-sdk-for-python` use for live-test stages.
* It is listed in GitHub branch protection on `main` as a required status check, so no PR can merge without it having completed successfully on the head commit.

This pipeline is expected to execute on Azure Pipelines as `dotnet-v3-live-account`. See [docs/builds-and-pipelines.md#manual-ado-setup](#manual-ado-setup) for the one-time ADO configuration required.

## SDK release

[azure-pipelines-official.yml](../azure-pipelines-official.yml) is used during the release process of a new version:
Expand Down Expand Up @@ -71,3 +85,31 @@ This pipeline executes on Azure Pipelines as [dotnet-v3-encryption-release](http
* Publish the package on the `cosmosdb/csharp/encryption.custom/<version>` storage container.

This pipeline executes on Azure Pipelines as [dotnet-v3-encryption-custom-release](https://cosmos-db-sdk-public.visualstudio.com/cosmos-db-sdk-public/_build?definitionId=67).

## Manual ADO setup

The [Live account validation](#live-account-validation) pipeline requires one-time configuration in Azure DevOps and GitHub that is not expressible in YAML. These steps are performed by a repository administrator the first time `azure-pipelines-live-account.yml` lands on `main`:

1. **Create the pipeline definition in Azure DevOps.**
* In the `cosmos-db-sdk-public` ADO project, create a new pipeline named `dotnet-v3-live-account` that points at `azure-pipelines-live-account.yml` in this repository.
2. **Define the secret variables on that pipeline definition.**
* `COSMOSDB_MULTI_REGION` &mdash; connection string for the shared multi-region test Cosmos DB account, marked as secret.
* `COSMOSDB_MULTIMASTER` &mdash; connection string for the shared multi-master test Cosmos DB account, marked as secret.
3. **Configure the pipeline's "Pull request validation" settings (Triggers tab):**
* `Build pull requests from forks of this repository`: **ON**
* `Make secrets available to builds of forks`: **ON**
* `Require a team member's comment before building a pull request`: **ON** (this is what makes `/azp run` the required gate for fork PRs).
4. **Add the new pipeline as a required check in GitHub branch protection.**
* Go to *Settings -> Branches -> Branch protection rule for `main`* in GitHub.
* Add `dotnet-v3-live-account` to the list of required status checks.
5. **(Recommended) Verify the symmetric configuration on `dotnet-v3-ci`** (the public PR pipeline) just so the contract is explicit:
* `Build pull requests from forks of this repository`: **ON**
* `Make secrets available to builds of forks`: **OFF**
* `Require a team member's comment before building a pull request`: **OFF**
6. **Smoke test.** Open a throwaway fork PR and verify that:
* `dotnet-v3-ci` runs automatically and passes.
* `dotnet-v3-live-account` does **not** run automatically and shows as pending/required.
* Commenting `/azp run dotnet-v3-live-account` triggers the live pipeline and it succeeds.

These steps are configuration of the Azure DevOps and GitHub services themselves and cannot be committed to the repository. Review them when this PR is merged.

108 changes: 108 additions & 0 deletions templates/build-test-live.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,108 @@
# File: templates/build-test-live.yml
#
# Live-account EmulatorTests (MultiRegion + MultiMaster). These tests require
# real Azure Cosmos DB connection strings (the $(COSMOSDB_MULTI_REGION) and
# $(COSMOSDB_MULTIMASTER) secret variables) and therefore CANNOT run on builds
# triggered by pull requests from forks, because Azure DevOps does not mount
# secret variables on fork-triggered builds by default.
#
# This template is referenced by:
# - azure-pipelines-official.yml (release pipeline; trusted)
# - azure-pipelines-rolling.yml (scheduled rolling pipeline; trusted)
# - azure-pipelines-live-account.yml (on-demand live tests for PRs;
# manually dispatched by a maintainer
# via an `/azp run` comment)
#
# Do NOT reference this template from the public PR pipeline
# (azure-pipelines.yml). That pipeline runs on fork PRs without secrets and
# the jobs below would fail-fast trying to construct a CosmosClient.

parameters:
BuildConfiguration: ''
VmImage: '' # https://docs.microsoft.com/en-us/azure/devops/pipelines/agents/hosted?view=azure-devops
OS: 'Windows'
MultiRegionConnectionString: ''
MultiRegionMultiMasterConnectionString: ''
MultiRegionArguments: ' --filter "TestCategory=MultiRegion" --verbosity normal '
MultiMasterArguments: ' --filter "TestCategory=MultiMaster" --verbosity normal '
MultiRegionCategoryListName: ' MultiRegion '
MultiMasterCategoryListName: ' MultiMaster '

jobs:
- job:
displayName: EmulatorTests ${{ parameters.BuildConfiguration }} - ${{ parameters.MultiRegionCategoryListName }}
timeoutInMinutes: 60
condition: and(succeeded(), eq('${{ parameters.OS }}', 'Windows'))
pool:
name: 'OneES'

steps:
- checkout: self # self represents the repo where the initial Pipelines YAML file was found
clean: true # if true, execute `execute git clean -ffdx && git reset --hard HEAD` before fetching

# Add this Command to Include the .NET 6 SDK
- task: UseDotNet@2
displayName: Use .NET 6.0
inputs:
packageType: 'runtime'
version: '6.x'

- task: UseDotNet@2
displayName: Use .NET 8.0
inputs:
packageType: 'sdk'
version: '8.x'

- task: DotNetCoreCLI@2
displayName: Microsoft.Azure.Cosmos.EmulatorTests
retryCountOnTaskFailure: 2
condition: succeeded()
inputs:
command: test
projects: 'Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.EmulatorTests/*.csproj'
arguments: ${{ parameters.MultiRegionArguments }} --configuration ${{ parameters.BuildConfiguration }} /p:OS=${{ parameters.OS }}
nugetConfigPath: NuGet.config
publishTestResults: true
testRunTitle: Microsoft.Azure.Cosmos.EmulatorTests
env:
COSMOSDB_MULTI_REGION: ${{ parameters.MultiRegionConnectionString }}
AZURE_COSMOS_NON_STREAMING_ORDER_BY_FLAG_DISABLED: true

- job:
displayName: EmulatorTests ${{ parameters.BuildConfiguration }} - ${{ parameters.MultiMasterCategoryListName }}
timeoutInMinutes: 60
condition: and(succeeded(), eq('${{ parameters.OS }}', 'Windows'))
pool:
name: 'OneES'

steps:
- checkout: self # self represents the repo where the initial Pipelines YAML file was found
clean: true # if true, execute `execute git clean -ffdx && git reset --hard HEAD` before fetching

# Add this Command to Include the .NET 6 SDK
- task: UseDotNet@2
displayName: Use .NET 6.0
inputs:
packageType: 'runtime'
version: '6.x'

- task: UseDotNet@2
displayName: Use .NET 8.0
inputs:
packageType: 'sdk'
version: '8.x'

- task: DotNetCoreCLI@2
displayName: Microsoft.Azure.Cosmos.EmulatorTests
retryCountOnTaskFailure: 2
condition: succeeded()
inputs:
command: test
projects: 'Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.EmulatorTests/*.csproj'
arguments: ${{ parameters.MultiMasterArguments }} --configuration ${{ parameters.BuildConfiguration }} /p:OS=${{ parameters.OS }}
nugetConfigPath: NuGet.config
publishTestResults: true
testRunTitle: Microsoft.Azure.Cosmos.EmulatorTests
env:
COSMOSDB_MULTI_REGION: ${{ parameters.MultiRegionMultiMasterConnectionString }}
AZURE_COSMOS_NON_STREAMING_ORDER_BY_FLAG_DISABLED: true
Loading