4 Commits

Author SHA1 Message Date
romanett d623007a3f Remove the Azure Pipelines CI and publishing definitions from master (#4575)
# Description

Removes the Azure Pipelines CI and package-publishing definitions from
`master`. GitHub Actions already owns all CI and package publishing for
`master`, but pushes to `master` still queued the Azure definitions.
They duplicated the Actions work and posted failing checks, for example
[`Nuget Preview (Push Nuget Preview Pack Nugets
Debug)`](https://github.com/OPCFoundation/UA-.NETStandard/runs/109065914524)
on `19dc504c5`.

## Removed

- `azure-pipelines.yml`, `azure-pipelines-preview.yml`
- `.azurepipelines/` templates: `ci.yml`, `coverage.yml`, `preview.yml`,
`sample-ha-longhaul.yml`, `sln.yml`, `test.yml`, `test-aot.yml`
- Helpers only those templates used: `get-matrix.ps1`, `get-root.ps1`,
`evaluate-test-results.ps1`
- `TrxGateScriptTests`: it tested only `evaluate-test-results.ps1`. The
Actions equivalent, `.github/scripts/get-test-verdict.ps1`, keeps its
own `CiTestVerdictTests`.

## Kept

**OneFuzz:** `.azurepipelines/onefuzz.yml` stays. Submitting to the
internal OneFuzz service needs the Azure DevOps-only `onefuzz-task`,
which has no GitHub Actions equivalent. The pipeline has no push, PR or
schedule trigger, so it never runs on `master` pushes. The public drop
build keeps running in the GitHub `fuzz-public-drop` job.

**Scripts GitHub Actions still invokes:** these stay in
`.azurepipelines/`, so every workflow path and `release.yml`'s
candidate-bound checkout keep working. Only `generate-slnx.ps1` changes,
and only its comment.

| Script | Used by |
| --- | --- |
| `set-version.ps1` | buildandtest, nightly, nuget-publish,
docker-image, stress / stability / long-haul, `run-dotnet-tests` action
|
| `generate-slnx.ps1`, `signlist{Debug,Release}.txt`,
`validate-source-generator-packages.ps1` (+ `expected-packages.txt`) |
nuget-publish |
| `package-version-policy.ps1`, `validate-nuget-package-set.ps1`,
`validate-preview-package-ordering.ps1`,
`assert-published-packages-match.ps1` | nuget-publish, release |
| `check-coverage.ps1` | buildandtest, nightly |
| `validate-migration-plugin.ps1` | buildandtest |

I didn't rename the directory on purpose. `release.yml` checks out the
candidate commit and runs `./.azurepipelines/package-version-policy.ps1`
from it, so moving the scripts would break promotion of any candidate
built before the move.

## Docs and comments

- `UA.slnx` drops the deleted files.
- `codecov.yml`, `coverage-thresholds.json`, `targets.props`, the
Redundancy sample test comments, the `.github` scripts and workflows,
`CONTRIBUTING.md`, `docs/` and `fuzzing/` no longer describe Azure as
running on `master` (`/azp run`, the `azure` Codecov flag, "the Azure
gate", the Azure long-haul and AoT legs).
- In the Developer Guide, the "Triggering a pipeline run" and "Migration
status" sections are replaced by "Pull requests from outside
contributors" and "Azure Pipelines on other branches".
- The new section names `onefuzz.yml` as the one remaining Azure
definition.
- It keeps the warning that the `Release` ruleset's Azure required check
must be lifted before cutting a new `release/2.<minor>` branch.
- `master` is merged in, including the #4555 docs rewrite. Its new
`docs/RedundancySampleTests.md` needed the Azure references removed
again. `docs/README.md` already had none.

## Reviewer notes

- **Azure DevOps side (admin action, not in this PR):** the definitions
are configured in the Azure DevOps portal. With the YAML gone, `master`
pushes give the CI and preview definitions nothing to run. Disabling
definition 14's push trigger/schedule, definition 16's build-completion
trigger, and the stale definition 13 stops any residual "file not found"
runs. Leave the OneFuzz definition enabled.
- `master378`, the 1.x `release/*` lines and the frozen `release/2.0.0`
keep their own `azure-pipelines.yml`. This PR only touches `master`.

## Related Issues

- Follow-up to #4513 (GitHub Actions for CI and nightly).

## Checklist

- [ ] I have signed the
[CLA](https://opcfoundation.org/license/cla/ContributorLicenseAgreementv1.0.pdf)
and read the
[CONTRIBUTING](https://github.com/OPCFoundation/UA-.NETStandard/blob/master/CONTRIBUTING.md)
doc.
- [ ] I have added tests that prove my fix is effective or that my
feature works and increased code coverage.
- [x] I have added all necessary documentation.
- [ ] I have verified that my changes do not introduce (new) build or
analyzer warnings.
- [ ] I ran **all** tests locally using the **UA.slnx** solution against
at least .net **framework** and .net **10**, and all passed.
- [ ] I fixed **all** failing and flaky tests in the CI pipelines and
**all** CodeQL warnings.
- [ ] I have addressed **all** PR feedback received.

This PR removes a test and adds none. Locally, at `9b00da817`, the full
`Opc.Ua.Tools.Tests` suite passed on net10.0: 884 passed, 1 skipped. The
later commits (OneFuzz restore, merge with `master`) touch only YAML and
docs.

🤖 Generated with [Claude Code](https://claude.com/claude-code)

---------

Co-authored-by: Claude Opus 5.5 <noreply@anthropic.com>
2026-09-29 07:44:36 +02:00
Marc Schier e9313ef957 Only use GitHub action for CI and nightly, establish release-branch-only package publication (#4513)
## Description

Two related changes to how the 2.0 line is built and shipped.

### 1. Release-branch-only package publication

- `master` produces development previews only.
- Stable packages can only be built from a canonical
`release/<major>.<minor>` branch and are promoted manually from the
exact signed candidate artifact.
- Core packages use explicit `major.minor.patch` versions (`2.0.0`,
`2.0.1`, then `2.1.0`); git height never changes a stable package patch.
- XRegistry, WoT Connectivity, Vision, Robotics, Redundancy,
Positioning, OpenUSD, ISA95, AI, DI, the relevant MCP extensions, and
OpenUSD connector tools remain `-preview.N` while following the core
numeric version.
- nuget.org receives only non-`.Debug` package IDs; GitHub Packages
retains the complete signed Release/Debug candidate.
- `docs/ReleaseProcess.md` is a reproducible runbook for developers and
agents, with each step stating its completion evidence.

Promotion is source-bound and byte-checked: `release.yml` checks out
nothing until the candidate SHA is known, and
`assert-published-packages-match.ps1` proves that any version already on
a feed holds *this* candidate's content before `--skip-duplicate` is
allowed to skip it. Canonical release-branch naming is matched
case-sensitively with no leading zeroes, and `version.json`'s
`publicReleaseRefSpec`, both policy helpers and the copy `release.yml`
inlines are pinned to one expression by tests.

### 2. PR CI moved to GitHub-hosted runners

- `.github/workflows/buildandtest.yml` (**CI**) now owns pull-request
validation outright, covering the Windows Debug/Release net48 + net10.0
solution builds and fast tests that only Azure Pipelines ran, alongside
the existing Linux/macOS, all-target and NativeAOT legs. `build-and-test
summary` remains the stable required check name.
- `.github/workflows/nightly.yml` is a new **manual-only**
(`workflow_dispatch`) full-scope workflow covering the Azure nightly
workload: all solutions x seven target profiles x Debug/Release, the
net472/netstandard profiles, Windows + Linux NativeAOT, and the
long-running and durable tiers.
- Shared deterministic discovery/batching lives in
`.github/scripts/get-ci-matrix.ps1` with a local composite action, so
both entry points expand the same workload manifest instead of
duplicating a large embedded script.
- `azure-pipelines.yml` is set to `pr: none`.
- The standalone pump sample image workflow is folded into the
consolidated **Images CI** workflow, which now builds all ten images and
publishes an `images summary` rollup suitable as a required check.

## Related Issues

No related issue provided.

## Checklist

- [ ] I have signed the
[CLA](https://opcfoundation.org/license/cla/ContributorLicenseAgreementv1.0.pdf)
and read the
[CONTRIBUTING](https://github.com/OPCFoundation/UA-.NETStandard/blob/master/CONTRIBUTING.md)
doc.
- [x] I have added tests that prove my fix is effective or that my
feature works and increased code coverage.
- [x] I have added all necessary documentation.
- [x] I have verified that my changes do not introduce (new) build or
analyzer warnings.
- [ ] I ran **all** tests locally using the **UA.slnx** solution against
at least .net **framework** and .net **10**, and all passed.
- [ ] I fixed **all** failing and flaky tests in the CI pipelines and
**all** CodeQL warnings.
- [x] I have addressed **all** PR feedback received.

## Validation

- `Opc.Ua.Tools.Tests` full `net10.0` suite: **959 passed, 1 skipped, 0
failed**.
- Version/package-policy regression subset
(`PackageVersionPolicyTests`): **60 passed, 0 failed**.
- GitHub Actions **CI** run 35719807620: **149/149 jobs green** on
GitHub-hosted runners.
- Canonical release-branch rule verified against the pinned nbgv 3.7.115
by building throwaway branches: `release/2.0`, `release/0.9`,
`release/10.42` -> `PublicRelease=True`; `release/02.0`, `release/2.00`,
`Release/2.0` -> `False`.
- Package identity gate verified against a live nuget.org package:
served packages carry a repository `.signature.p7s`, so equality is
decided on content excluding that part. Re-signing and zip reordering
produce an identical digest; a one-byte content change does not.
- Synthetic Release-only, Debug-only, combined, preview, duplicate,
orphaned-symbol, mismatched-root and accidental-stable-family package
sets exercise the shared validator.
- Stable-release rehearsal in an isolated `release/2.0` clone:
`Opc.Ua.Di` packed as `2.0.0-preview.6` depending on stable Core
`2.0.0`; `Opc.Ua.Di.Client` likewise against stable Client `2.0.0`.
- All workflow YAML, `version.json`, the package-policy PowerShell
scripts and the internal release-runbook anchors parse.

## Known validation limits

- Full `UA.slnx` `net48` and `net10.0` local validation remains blocked
by pre-existing `NETSDK1005` and dependency-version failures in
unmodified fuzz/sample projects; the corresponding checklist items
intentionally stay open.
- The TRX-driven test verdict added for the intermittent at-exit host
stall is proven by `CiTestVerdictTests`; the stall itself has not
recurred since.
- `nightly.yml` has not yet been run against a full-scope Azure run for
tuple-level parity — see below.

## Operational follow-up

This remains a preparation PR targeting `master`. It does **not**
authorize a release.

Release sequence:

1. Merge this PR.
2. Create canonical `release/2.0`, advance `master` to
`2.1.0-preview.{height}`, and open a separate `2.0.0` version PR against
`release/2.0`.
3. Follow
[`docs/ReleaseProcess.md`](https://github.com/OPCFoundation/UA-.NETStandard/blob/master/docs/ReleaseProcess.md)
for candidate dry-run, environment approval, promotion, tag/release
finalization, and next-patch preview setup.

CI migration steps still needing administrator access are tracked in
[`docs/DeveloperGuide.md#migration-status`](https://github.com/OPCFoundation/UA-.NETStandard/blob/master/docs/DeveloperGuide.md#migration-status):
proving `nightly.yml` parity on a trusted SHA with the private fuzz
corpus provisioned, turning off definition 14's service-side PR
override, retiring the Azure full-scope schedules and push trigger, and
retiring the duplicate `azure-pipelines-preview.yml` publisher.

> **Before cutting `release/2.0`:** the `Release` ruleset requires the
Azure context for *every* `refs/heads/release/*`, but a new 2.x branch
inherits `pr: none`, so that context would never report and would block
every PR into the new line. Exclude the new ref from that ruleset, or
add a 2.x ruleset requiring `build-and-test summary`, as part of
creating the branch.

---------

Co-authored-by: Copilot Autofix powered by AI <175728472+Copilot@users.noreply.github.com>
2026-09-23 15:47:43 +00:00
Marc Schier ea0f266b66 Move build and test to the Azure DevOps managed pool and replace Codecov with an in-pipeline coverage gate (#4122)
# Description

Moves the all-target-framework build, the cross-platform test matrix and
the Native AoT run from GitHub Actions onto the Azure DevOps
`netstandard` Managed DevOps Pool, and replaces Codecov with a coverage
gate that runs inside the pipeline.

## 1. CI backend switch

One conceptual switch decides who owns that work. It is checked into
source in **two places that must be flipped together**:

| File | Setting | Default |
| --- | --- | --- |
| `azure-pipelines.yml` | `parameters.ciBuildBackend` | `ado` |
| `.github/workflows/buildandtest.yml` | `env.CI_BUILD_BACKEND` | `ado`
|

Setting both to `actions` restores the previous behaviour exactly.

Azure Pipelines gains what it was missing to take the work over:

- A **Linux all-TFM `sln.yml` leg**, replacing `build-all-tfm-linux`.
`sln.yml` gets a `configurations` parameter so this leg builds `Release`
only instead of doubling the managed-pool job count.
- A **Linux agent in the `net10.0` `testfastpr` matrix**, replacing the
ubuntu `build-and-test` job.
- **Native AoT and Code Coverage now gate pull requests** instead of
running only on Schedule/Manual. The coverage stage drops its
`testdebug` dependency, which is Schedule/Manual-only and would
otherwise have skipped coverage on every PR.
- On a PR, Windows builds the .NET Framework TFMs and Linux the modern
ones — mirroring the split the GitHub Actions jobs used — so all seven
TFMs stay covered without fanning every TFM across both pools.

Two things are deliberately **not** covered by the switch:

- **macOS** stays on GitHub-hosted runners, because Managed DevOps Pools
provide no macOS image.
- **`master378` and `develop/*`** keep running the GitHub Actions jobs,
since Azure Pipelines only builds `master`/`main` from this file.

GitHub Actions does not expose the `env` context to job-level `if:`
conditions, so the switch is resolved once in the existing `discover`
job and re-exported as job outputs.

A new **`build-and-test summary`** job gives branch protection one
stable check to require, instead of the generated matrix job names. It
treats an intentionally skipped job as success but still fails on a real
failure or cancellation.

The `paths:` allow-list was moved off the `pull_request` trigger and
into `discover`. A workflow filtered out by `paths` never reports its
checks, and a required check that never reports leaves a PR permanently
*"Expected — waiting for status to be reported"*. That would have made
the routine "ratchet the coverage floor" PR (which touches only
`coverage-thresholds.json` and docs) unmergeable.

## 2. Coverage gate replacing Codecov

Codecov is removed entirely — `codecov.yml`, both uploads, the badge,
and the token usage. `.azurepipelines/check-coverage.ps1` runs at the
end of the `Code Coverage` stage against the Cobertura report
ReportGenerator already merges, driven by `coverage-thresholds.json`:

| Check | Behaviour |
| --- | --- |
| Project floor | **Blocking** — total line and branch rates against an
absolute floor. |
| Patch coverage | **Blocking on PRs** — changed lines must reach
`patch.target`, tolerating `patch.threshold` percentage points (the same
semantics `codecov/patch` had). |
| Baseline delta | **Advisory** — reports the change against the
recorded baseline, never fails. |

The project rate is recomputed from the per-line data rather than read
off the Cobertura root element, so the `ignore` globs carried over from
`codecov.yml` apply to the project floor as well as to the changed-lines
gate — otherwise samples and generated code would count towards one gate
but not the other.

`testcc.yml` gains an explicit `checkout: self` with `fetchDepth: 0`,
because the default shallow clone cannot diff against the base branch.

## Follow-up actions for maintainers

Two items cannot be automated from source:

1. **Enable the `/azp run` gate.** In the Azure DevOps portal: pipeline
→ **More actions** → **Triggers** → **Pull request validation** →
**Require a team member's comment before building a pull request**,
scoped to *Only on pull requests from non-team members*. This makes
Copilot-authored and outside-contributor PRs wait for a maintainer's
`/azp run`, mirroring the approval GitHub Actions already requires. The
documentation added here describes the workflow and the
private-org-membership gotcha; **the setting itself still has to be
switched on.**
2. **Update branch protection and secrets.** Drop the `codecov/project`
and `codecov/patch` required checks, require `build-and-test summary`
and the ADO coverage check instead, and remove `CODECOV_TOKEN` from the
GitHub repository secrets and the ADO variable group.

Also note the thresholds in `coverage-thresholds.json` are seeded from
the last Codecov reading (73.61 %) with headroom, because the
in-pipeline number had not been observed yet. The first full `Code
Coverage` run on master should confirm it and the floors should be
tightened then — the gate prints the exact figure it computes.

## Related Issues

_No tracking issue; this is CI infrastructure work requested directly._

## Checklist

- [x] I have signed the
[CLA](https://opcfoundation.org/license/cla/ContributorLicenseAgreementv1.0.pdf)
and read the
[CONTRIBUTING](https://github.com/OPCFoundation/UA-.NETStandard/blob/master/CONTRIBUTING.md)
doc.
- [x] I have added tests that prove my fix is effective or that my
feature works and increased code coverage.
- No product code changed, so there are no unit tests to add. The new
logic was verified with purpose-built harnesses instead:
- All 8 branch/event/backend combinations of the `discover` switch,
confirming `master378` and `develop/*` are untouched and that `actions`
restores the old behaviour.
- 12 scenarios for `check-coverage.ps1`: the project floor, the patch
gate, ignore globs applying to *both* gates, three path-normalization
shapes, and the advisory delta.
- 14 path-relevance cases confirming the in-job filter matches the
retired `paths:` allow-list exactly.
- End-to-end against a **real** ReportGenerator report: correctly
resolved `src/Opc.Ua.PubSub/DependencyInjection/PubSubBuilder.cs`, found
exactly the four modified tracked lines and reported 50 % patch coverage
(2 covered, 2 uncovered).
- [x] I have added all necessary documentation.
- New **Continuous integration** section in `docs/DeveloperGuide.md`, a
CI note in `CONTRIBUTING.md`, and links from `docs/README.md`. Also
corrected the CI matrix description, which claimed the PR gate ran net48
+ **net8.0** — it runs net48 + **net10.0**.
- [x] I have verified that my changes do not introduce (new) build or
analyzer warnings.
- `dotnet build src/Opc.Ua.Server` → 0 warnings, 0 errors. No product
code changed.
- [ ] I ran **all** tests locally using the **UA.slnx** solution against
at least .net **framework** and .net **10**, and all passed.
- Not applicable — no product code changed. `Opc.Ua.Server.Tests` was
run on net10.0 during development (3480 passed; the single
`ServerFluentApiHostingTests` failure is pre-existing and reproduces on
master).
- [ ] I fixed **all** failing and flaky tests in the CI pipelines and
**all** CodeQL warnings.
- [x] I have addressed **all** PR feedback received.
- A review pass over this branch flagged the `paths:`-filter deadlock
described above; it is fixed in `1926e240e`.

---------

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Copilot-Session: 181ba7ea-c72f-42d7-a737-00a3faadaa17
Copilot-Session: 26aa55a2-5731-4a4c-b61c-df2f7a785eca
2026-07-31 21:06:25 +00:00
Martin Regen 8d0eb40206 Update README.md and templates (#1749)
- fix a few badges
- add new template for issues and PR
2022-03-29 14:23:55 +02:00