Skip to content

Enable CFSClean* policies for dotnet-maui pipeline#34540

Merged
mmitche merged 1 commit intodotnet:mainfrom
mmitche:enable-cfsclean-main
Apr 7, 2026
Merged

Enable CFSClean* policies for dotnet-maui pipeline#34540
mmitche merged 1 commit intodotnet:mainfrom
mmitche:enable-cfsclean-main

Conversation

@mmitche
Copy link
Copy Markdown
Member

@mmitche mmitche commented Mar 18, 2026

Adds CFSClean and CFSClean2 network isolation policies.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Copilot AI review requested due to automatic review settings March 18, 2026 16:00
@github-actions
Copy link
Copy Markdown
Contributor

🚀 Dogfood this PR with:

⚠️ WARNING: Do not do this without first carefully reviewing the code of this PR to satisfy yourself it is safe.

curl -fsSL https://raw.githubusercontent.com/dotnet/maui/main/eng/scripts/get-maui-pr.sh | bash -s -- 34540

Or

  • Run remotely in PowerShell:
iex "& { $(irm https://raw.githubusercontent.com/dotnet/maui/main/eng/scripts/get-maui-pr.ps1) } 34540"
@dotnet-policy-service dotnet-policy-service Bot added the community ✨ Community Contribution label Mar 18, 2026
@dotnet-policy-service
Copy link
Copy Markdown
Contributor

Hey there @@mmitche! Thank you so much for your PR! Someone from the team will get assigned to your PR shortly and we'll get it reviewed.

Copy link
Copy Markdown
Contributor

Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Enables additional network isolation policies for the official Azure DevOps pipeline configuration in dotnet-maui, by updating the 1ES pipeline template settings.

Changes:

  • Adds a settings block under extends.parameters in the official CI pipeline.
  • Configures networkIsolationPolicy to include CFSClean and CFSClean2 (in addition to Permissive).

You can also share your feedback on Copilot code review. Take the survey.

Comment thread eng/pipelines/ci-official.yml
@rmarinho
Copy link
Copy Markdown
Member

/azp run

@azure-pipelines
Copy link
Copy Markdown

Azure Pipelines successfully started running 3 pipeline(s).
@rmarinho
Copy link
Copy Markdown
Member

Seems there s already a CFSClean3 ?

@mmitche
Copy link
Copy Markdown
Member Author

mmitche commented Mar 26, 2026

Seems there s already a CFSClean3 ?

It appears so, though it's not active yet? It covers some additional endpoints.

@mmitche
Copy link
Copy Markdown
Member Author

mmitche commented Mar 26, 2026

The official build is green there. Merge as you wish.

PureWeen added a commit that referenced this pull request Apr 27, 2026
…nce (#35089)

<!-- Please let the below note in for people that find this PR -->
> [!NOTE]
> Are you waiting for the changes in this PR to be merged?
> It would be very helpful if you could [test the resulting
artifacts](https://github.com/dotnet/maui/wiki/Testing-PR-Builds) from
this PR and let us know in a comment if this change resolves your issue.
Thank you!

## Problem

The official build pipeline (`dotnet-maui`, def 1095) fails because
[CFSClean network isolation](#34540)
blocks direct access to `repo.maven.apache.org`. This breaks two
separate Gradle invocations:

1. **`src/Core/AndroidNative` build** — our own Gradle project
2. **`Microsoft.Android.Sdk.Bindings.Gradle.targets`** — Android SDK
binding generator in `Core.csproj`

Per [1ES CFS guidance](https://aka.ms/1es/netiso/CFS), the fix is to
route all Maven dependency resolution through an Azure Artifacts feed
with upstream sources.

## Fix

### Gradle configuration changes
- **`settings.gradle`** — Replace `mavenCentral()`, `google()`,
`gradlePluginPortal()` with the `dotnet-public-maven` Azure Artifacts
feed. Add the [Azure Artifacts Gradle credential
provider](https://pkgs.dev.azure.com/artifacts-public/PublicTools/_packaging/AzureArtifacts/maven/v1)
plugin (v1.1.1) for local authentication.
- **`build.gradle`** — Point `buildscript.repositories` to the same feed
for AGP classpath resolution.
- **`eng/init.gradle`** — Global Gradle init script that redirects any
remaining Maven Central/Google Maven references (e.g. from
`Microsoft.Android.Sdk.Bindings.Gradle.targets`) to the feed. Installed
into `GRADLE_USER_HOME` by the pipeline.

### Pipeline changes
- **`cache-gradle.yml`** — Copy `init.gradle` into `GRADLE_USER_HOME`
**after** cache restore to prevent stale cached copies. Uses
`$(GRADLE_USER_HOME)` variable for the destination path.

### Why the ingestion script (`eng/ingest-maven-deps.sh`) is needed

The `dotnet-public-maven` feed proxies Maven Central, but new packages
require an **authenticated first-time pull** to be saved. The Gradle
credential provider plugin has two limitations that prevent `dotnet
build` from self-ingesting:

1. **Skips entirely in CI** — when `TF_BUILD=True` (Azure Pipelines),
the plugin is a no-op
2. **Doesn't cover all Gradle scopes** — the plugin injects auth into
`pluginManagement.repositories` and `project.repositories`, but NOT
`buildscript.repositories` or AGP's internal `detachedConfiguration`
scopes. This means `dotnet build` locally cannot ingest new packages
through the Android SDK binding targets even with correct credentials.

We verified this by adding an un-ingested package
(`io.coil-kt:coil:2.7.0`) — `dotnet build` fails with 401 despite the
credential provider authenticating successfully.

**Upstream issue:**
[microsoft/artifacts-credprovider#671](microsoft/artifacts-credprovider#671)

The script works around these gaps by:
1. Acquiring an auth token via the .NET credential provider (MSAL)
2. Pre-ingesting platform-specific artifacts (aapt2) for all OS variants
(macOS/Linux/Windows)
3. Running Gradle with `--refresh-dependencies` to bypass local cache
4. Falling back to `curl` with Bearer token for unreachable scopes

**Run `./eng/ingest-maven-deps.sh` after adding or updating any
Maven/Gradle dependency.**

### Documentation updates
- `settings.gradle` — explains the feed setup and when to run the script
- `gradle-wrapper.properties` — warning not to upgrade Gradle past 8.x
(`dotnet/android#10738`)
- `copilot-instructions.md` — always-on guidance for Gradle 401 failures
- `azdo-build-investigator/SKILL.md` — error signatures and DO NOTs for
CI investigation
- `android.instructions.md` — quick reference for Android developers

## Verified

- ✅ Internal official build
[2961149](https://dev.azure.com/dnceng/internal/_build/results?buildId=2961149)
passed — Pack macOS + Pack Windows both green
- ✅ Same pattern used by dotnet/aspnetcore ([PR
#64962](dotnet/aspnetcore#64962))
- ✅ Feed is public — no auth needed to read already-ingested packages,
external contributors can build without credentials
- ✅ Locally verified: `dotnet build` works for already-ingested
packages, fails for new ones (confirming script is needed)

---------

Co-authored-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com>
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Co-authored-by: Matt Mitchell (.NET) <mmitche@microsoft.com>
@PureWeen PureWeen added this to the .NET 10 SR6 milestone Apr 29, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

community ✨ Community Contribution

4 participants