Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
211 commits
Select commit Hold shift + click to select a range
6e08302
[Server] Add distributed high-availability node-state + session shari…
marcschier Jun 25, 2026
adcf8ea
[Server] Add secure distributed session manager for HA failover fast-…
marcschier Jun 25, 2026
502f948
[Server] Add real-server integration test for distributed session mir…
marcschier Jun 25, 2026
245b623
[Server] HA security hardening: hash session keys, restore audit even…
marcschier Jun 26, 2026
f6acbdc
[Server] HA docs + sample: Kubernetes deployment guide, session shari…
marcschier Jun 26, 2026
e6166fc
[Docs] plans/32: record A+FG done; add validated B1 (client token-reu…
marcschier Jun 26, 2026
652c85a
[Client] Add opt-in token-reuse failover for HA fast reconnect (REQ-U…
marcschier Jun 26, 2026
4cd265c
[Client] Two-server secured token-reuse failover e2e + HA docs (C)
marcschier Jun 26, 2026
deed6f2
Extract Opc.Ua.Server.Distributed assembly; address PR review feedback
marcschier Jun 26, 2026
4293cd2
Add CRDT active/active replication (Opc.Ua.Server.Distributed.Crdt)
marcschier Jun 26, 2026
e30947d
PR feedback: rename fluent API to Replicated*, integrate CRDT into sa…
marcschier Jun 26, 2026
cf2ea01
PR feedback: organize distributed projects into folders; extract Opc.…
marcschier Jun 26, 2026
4f4d7ed
test: raise Opc.Ua.Server.Distributed.Crdt patch coverage above 80%
marcschier Jun 26, 2026
d265764
feat: OPC UA Part 4 6.6 redundancy - full server + client, transparen…
marcschier Jun 27, 2026
e4f8ac9
feat: widen CRDT extension to all TFMs (Crdt 1.0.2) and remediate 6.6…
marcschier Jun 27, 2026
e8c6dd1
refactor: rename Distributed->Redundancy / Kubernetes->K8s, address r…
marcschier Jun 27, 2026
7ccbcd1
test: fix stale ManagedSession reflection constructor signatures
marcschier Jun 27, 2026
4211a19
build: fix RestrictForLegacyTfm no-op shell on netstandard2.x (CS8021)
marcschier Jun 27, 2026
dbbb7ba
test: cover K8s builder registration; exclude integration-only K8s IO…
marcschier Jun 27, 2026
4870a67
build: make RedundantServer sample follow CustomTestTarget (fix net8 …
marcschier Jun 27, 2026
9e9ea9b
build: don't build net10-only McpServer on net8/net9 all-TFM legs
marcschier Jun 27, 2026
35be537
docs: address PR review - remove redundancy migration section, TFM-av…
marcschier Jun 28, 2026
ddc47b9
Merge remote-tracking branch 'origin/master' into nodestatestorage
marcschier Jun 28, 2026
5b1552a
test: widen CRDT convergence deadline 10s->30s to fix CI starvation f…
marcschier Jun 28, 2026
30e7456
fix(crdt): guarantee value convergence under concurrent multi-writer …
marcschier Jun 28, 2026
6a287f0
samples: simplify RedundantClient to a transparent ManagedSession; ad…
marcschier Jun 28, 2026
eb3b787
refactor: relocate redundancy seams to Opc.Ua.Core (Opc.Ua.Redundancy)
marcschier Jun 29, 2026
c9eabbe
feat(client-redundancy): add Opc.Ua.Client.Redundancy coordinator lib…
marcschier Jun 29, 2026
a1f1b94
feat(client-redundancy): fluent builder, unit tests, HA.md how-to
marcschier Jun 29, 2026
fafd9eb
feat(client-redundancy): token-reuse fast-activate on promotion
marcschier Jun 29, 2026
9eb177c
build: add Opc.Ua.Redundancy using to remaining seam consumers (Aot/S…
marcschier Jun 29, 2026
acf2fab
refactor: tidy Opc.Ua.Client/Session into Redundancy/Subscription/Rec…
marcschier Jun 29, 2026
00c9f94
refactor: fold Opc.Ua.Client.Redundancy into Opc.Ua.Client/Session/Re…
marcschier Jun 29, 2026
a4c3255
refactor: merge Server.Redundancy+.Crdt to Opc.Ua.Redundancy.Server; …
marcschier Jun 29, 2026
b6a6086
feat(client): add IManagedSession:ISession entry-point exposing Redun…
marcschier Jun 29, 2026
ea79636
refactor!: remove RedundantManagedClient; ManagedSession is sole entr…
marcschier Jun 29, 2026
d31c412
feat: add Opc.Ua.Redundancy.Client (CRDT gossip client store for repl…
marcschier Jun 29, 2026
dd8aa8a
feat(client): redundancy transparent + on by default in ConnectAsync
marcschier Jun 29, 2026
7e902d8
docs: migration note for redundancy package re-topology + RedundantMa…
marcschier Jun 29, 2026
b4f8458
test: cover CrdtClientKeyValueStore round-trip (client redundancy)
marcschier Jun 29, 2026
63e669f
feat(sample): add --replicas client replica-set demo (ClientReplicaCo…
marcschier Jun 29, 2026
c6df8e6
test: consolidate redundancy test projects to mirror source
marcschier Jun 29, 2026
f25f2f4
refactor: extract shared CRDT into Opc.Ua.Redundancy; add client CRDT DI
marcschier Jun 29, 2026
1c0a330
feat(redundancy): add IRaftConsensus seam + in-process backend (Raft …
marcschier Jun 30, 2026
6950c63
feat(redundancy): add linearizable RaftSharedKeyValueStore + RaftLead…
marcschier Jun 30, 2026
893227d
feat(redundancy): add HybridSharedKeyValueStore + RedundancyConsisten…
marcschier Jun 30, 2026
be80368
feat(redundancy): server DI consistency-mode selection UseRedundancyC…
marcschier Jun 30, 2026
7244e9f
test(redundancy): nonce/lease auto-wire over Raft CAS (Raft phase 5)
marcschier Jun 30, 2026
2271cf3
feat(redundancy): client DI AddRaftClientSharedStore + mode-aware sto…
marcschier Jun 30, 2026
42455eb
feat(redundancy): scaffold RaftCsConsensus adapter for external RaftC…
marcschier Jun 30, 2026
dc5814f
docs(redundancy): document Raft consistency modes (Raft phase 8)
marcschier Jun 30, 2026
5f05f97
feat(redundancy): pull RaftCs 1.1.0 + Crdt 1.1.0 and wire the real Ra…
marcschier Jun 30, 2026
662a1a8
fix(redundancy): harden Raft proposal liveness + address-space watch …
marcschier Jun 30, 2026
ac5a7e8
feat(redundancy): add RaftCsConsensus.CreateCluster multi-node factor…
marcschier Jul 1, 2026
3268b86
feat(redundancy.k8s): add UseKubernetesRaftConsensus multi-pod wiring…
marcschier Jul 1, 2026
968c131
sample(redundancy): demonstrate strong (Raft) consistency in Redundan…
marcschier Jul 1, 2026
e2e597e
docs(redundancy): document CreateCluster + UseKubernetesRaftConsensus…
marcschier Jul 1, 2026
f5f2c97
test(redundancy): cover K8s durable file-WAL Raft path (rw-D)
marcschier Jul 1, 2026
ed7b8f4
Merge origin/master into nodestatestorage
marcschier Jul 1, 2026
66ead1c
Address PR review: extract continuation-point and sent-message handling
marcschier Jul 1, 2026
f3d91b0
docs(plans): consolidate distributed-HA plans 28-32 into a single rem…
marcschier Jul 1, 2026
43d02c0
feat(redundancy): GetEndpoints load direction across a RedundantServe…
marcschier Jul 1, 2026
d9fe5dd
feat(redundancy): load-direction strong routing, e2e test, sample (R1…
marcschier Jul 1, 2026
4cb2fcf
Make ISubscriptionStore definition-persistence async (breaking)
marcschier Jul 1, 2026
3a6b29b
Add transparent-redundancy worked sample (single virtual endpoint)
marcschier Jul 1, 2026
4e71f45
Stream variable values in bulk during address-space hydration
marcschier Jul 1, 2026
03df1d3
HA hydration: add write sequence + snapshot/delta-log store primitives
marcschier Jul 1, 2026
0345763
HA hydration: snapshot fast-path hydration + writer snapshot policy
marcschier Jul 1, 2026
dea022a
HA hydration: snapshot correctness + benchmark tests
marcschier Jul 1, 2026
6489960
docs(HA): document snapshot+delta hydration; scope remaining fault-in
marcschier Jul 1, 2026
28f87fe
PR feedback: docs, nullable, InternalsVisibleTo, hashing, RaftCs rename
marcschier Jul 1, 2026
ecb0b53
PR feedback: rename Opc.Ua.Redundancy.K8s -> Opc.Ua.Redundancy.Kubern…
marcschier Jul 1, 2026
400a07a
PR feedback: rename Crdt-prefixed classes to Replicated
marcschier Jul 1, 2026
5be6940
PR feedback: canonical active/passive compose + client monitors repli…
marcschier Jul 1, 2026
defa86c
PR feedback: remove dead codecov ignore entries for Kubernetes IO
marcschier Jul 1, 2026
82ed30d
PR feedback: style/analyzer cleanup pass on the redundancy PR files
marcschier Jul 1, 2026
a927024
docs: cover redundancy/HA in WhatsNew + Profiles; accuracy pass
marcschier Jul 2, 2026
bd31d43
Fix Server test: reflect SentMessageQueue.SentMessages property after…
marcschier Jul 2, 2026
23b4013
Add unit tests for PeerDirectionPublishStartupTask and NodeStateStore…
marcschier Jul 2, 2026
6eb2b59
Address PR #3918 review feedback: HA/Kubernetes docs, CA2000, plan
marcschier Jul 2, 2026
0cdf55e
Implement 4 HA client follow-ups: transparent ISession DI, single com…
marcschier Jul 2, 2026
99aebd3
Update HA remaining-work plan: add facade integration-test + optional…
marcschier Jul 2, 2026
c53f3f3
Track HA remaining items 1 and 2 as issues #3938 and #3939
marcschier Jul 2, 2026
7bf25cc
HA items 3 and 4: facade failover integration test, dynamic gossip sc…
marcschier Jul 2, 2026
56913b9
Address PR #3918 review feedback: compose folders, doc refs to issues…
marcschier Jul 2, 2026
200835f
Merge remote-tracking branch 'origin/master' into nodestatestorage
marcschier Jul 2, 2026
f6e61c7
Merge master: implement ISession.TryGetSubscriptionManager in redunda…
marcschier Jul 2, 2026
cd2a0b5
Merge remote-tracking branch 'origin/master' into nodestatestorage
marcschier Jul 2, 2026
9c0ba97
Merge fixes: use AcquireApplicationCertificateBySecurityPolicy (calle…
marcschier Jul 2, 2026
1927ff3
Address PR #3918 review feedback: PascalCase compose folders (LoadDir…
marcschier Jul 2, 2026
c794bd1
Add unit tests raising diff coverage for Redundancy libraries (Client…
marcschier Jul 3, 2026
999b4c1
Add coverage tests for base Raft lib, Core/Redundancy, and Server Sen…
marcschier Jul 3, 2026
7aeb890
Fix RedundancySample documented setups: enable None endpoint + per-no…
marcschier Jul 4, 2026
3fe1ee5
Fix active/active sample startup: opt into unauthenticated gossip + N…
marcschier Jul 4, 2026
1028775
Fix strong-consistency sample startup: register NullRecordProtector f…
marcschier Jul 4, 2026
285468d
Add regression test: V2 subscription delivers data changes with monit…
marcschier Jul 4, 2026
360454e
docs(RedundantServer): add Known limitations (external Crdt.Transport…
marcschier Jul 4, 2026
8c6462a
Register IDistributedValueCache in DI for UseDistributedAddressSpace …
marcschier Jul 4, 2026
ea3788e
Sample: wire HA Counter through DistributedValueParticipation so valu…
marcschier Jul 4, 2026
cea70c1
Sample: secure-by-default HA (HA_INSECURE explicit opt-out + warning;…
marcschier Jul 4, 2026
32dd42b
Add coverage: cross-replica value continuity, IDistributedValueCache …
marcschier Jul 4, 2026
bf132db
docs: document distributed value cache / DistributedValueParticipatio…
marcschier Jul 4, 2026
640cbf0
Server: restore monitored-item data/event queues on failover (#3939)
marcschier Jul 4, 2026
a2c3b44
Merge pull request #6 from marcschier/copilot/failover-restore-monito…
marcschier Jul 4, 2026
a9488e3
Merge branch 'master' into nodestatestorage
marcschier Jul 4, 2026
07ef936
Fix CI: register ITelemetryContext in UseDistributedSubscriptionMirro…
marcschier Jul 4, 2026
1921ad6
Add distributed certificate store over ISharedKeyValueStore (shared t…
marcschier Jul 5, 2026
c21c034
docs: add Distributed certificate store guide (shared trust lists) + …
marcschier Jul 5, 2026
cc083cd
docs: fold distributed certificate store into HighAvailability.md; li…
marcschier Jul 5, 2026
3953d36
PR #3918 review: remove in-process client replica set (process-per-re…
marcschier Jul 6, 2026
5889d5c
Merge remote-tracking branch 'origin/master' into nodestatestorage
marcschier Jul 6, 2026
1548cee
Merge remote-tracking branch 'origin/master' into nodestatestorage
marcschier Jul 6, 2026
495c9cb
Add fluent active/active DI API and dynamic peer discovery (PR #3918 …
marcschier Jul 6, 2026
c125488
Add tests covering new peer-discovery/active-active code paths
marcschier Jul 6, 2026
2dcdc1c
Cover LoadDirectionBuilderExtensions and RegistryBackedDistributedVal…
marcschier Jul 6, 2026
72fc7d7
Increase PR coverage: cover SessionEngineContext, CertificateManagerE…
marcschier Jul 6, 2026
f46d487
Docs: reword 'remain available' to 'are available' per review
marcschier Jul 6, 2026
832fb76
Merge remote-tracking branch 'origin/master' into nodestatestorage
marcschier Jul 7, 2026
fa206be
Add scalable RedundantClient docker-compose with failover/HA/data-los…
marcschier Jul 7, 2026
1f8f741
Fix CRDT gossip framing so active/active state converges over TCP/UDP
marcschier Jul 7, 2026
af20bfa
Merge RedundantClient compose into one env-driven HA matrix; add coor…
marcschier Jul 7, 2026
55060f2
Merge branch 'master' into nodestatestorage
marcschier Jul 7, 2026
90949fa
Fix RedundantClient net8.0 solution build (CS0433 Lock ambiguity)
marcschier Jul 7, 2026
3292483
Merge remote-tracking branch 'origin/master' into nodestatestorage
marcschier Jul 7, 2026
0756f96
Add Opc.Ua.PubSub.Redundancy: distributed active/standby bridges (Par…
marcschier Jul 7, 2026
88d2f49
PubSub HA: AddPubSubRedundancy DI wiring (Cold/Warm) + documentation
marcschier Jul 7, 2026
db96844
PubSub HA: Hot standby checkpoint seam + shared-store impl + DI
marcschier Jul 7, 2026
e3a52b6
PubSub HA: wire Hot checkpoint into the WriterGroup publish loop
marcschier Jul 7, 2026
5185cc8
PubSub HA: end-to-end failover integration tests
marcschier Jul 7, 2026
122aea3
PubSub HA: RedundantPubSub sample (active/standby publisher failover …
marcschier Jul 7, 2026
b8c73ba
RedundantPubSub sample: stop logging raw DataSet field values (CodeQL)
marcschier Jul 8, 2026
a6a0c05
Merge remote-tracking branch 'origin/master' into nodestatestorage
marcschier Jul 8, 2026
7d28a31
Fix CS0535: implement new IOpcUaServerBuilder.AddNodeManager(string,A…
marcschier Jul 8, 2026
95db0b5
Fix Client test NRE: update reflected ManagedSession ctor signature t…
marcschier Jul 8, 2026
50126c2
Merge branch 'master' into nodestatestorage
marcschier Jul 8, 2026
0a33a5b
Add tests for PubSub lease-renew success path and checkpoint-store gu…
marcschier Jul 8, 2026
949d4ef
Rename Opc.Ua.PubSub.Redundancy project/assembly/package to Opc.Ua.Re…
marcschier Jul 8, 2026
c0cd4da
RedundantPubSub sample: demonstrate HA subscribers, block namespaces,…
marcschier Jul 8, 2026
05e7d55
update
marcschier Jul 8, 2026
7076dab
Fix Kubernetes HA review findings (fnd-32 fnd-33 fnd-41)
marcschier Jul 8, 2026
de55ff6
Fix redundancy synchronizer role switching and coverage gaps (fnd-31,…
marcschier Jul 8, 2026
7dc39d9
Fix redundant sample findings fnd-46 fnd-47 fnd-48 fnd-49 fnd-50 fnd-75
marcschier Jul 8, 2026
cb7983b
Fix PubSub HA review findings fnd-51 fnd-52 fnd-71 fnd-72 fnd-73 fnd-74
marcschier Jul 8, 2026
d26a70d
Fix fnd-76 to fnd-80 review findings
marcschier Jul 8, 2026
1242226
Redundancy: runtime address-space role switching + fix HA_REDUNDANT_P…
marcschier Jul 8, 2026
10b897a
Fix session restore and hosted startup coverage (fnd-42 fnd-43 fnd-63…
marcschier Jul 8, 2026
7961952
Fix distributed restore and mirror coverage (fnd-38 fnd-40 fnd-53 fnd…
marcschier Jul 8, 2026
facef12
update
marcschier Jul 8, 2026
e0f6aad
Fix incorrect test expectations in fnd-62 BandedServerDirectionPolicy…
marcschier Jul 8, 2026
735b7b2
style: fix whitespace diagnostics (FINALNEWLINE/ENDOFLINE) across 16 …
marcschier Jul 8, 2026
214d869
style: remove redundant casts (IDE0004) and dead assignments (IDE0059)
marcschier Jul 8, 2026
6c767a1
Fix data-loss race in AddressSpaceSynchronizer demotion drain
marcschier Jul 8, 2026
6b44277
Fix client HA findings fnd-34 to fnd-70
marcschier Jul 8, 2026
32e24a8
style: remove unused usings and simplify names (IDE0005/IDE0001/IDE0002)
marcschier Jul 8, 2026
04e68a2
style: apply formatting analyzers (RCS0009/0010/0015/0021/0033/0055/0…
marcschier Jul 8, 2026
21e3794
style: apply collection expressions (IDE0028/0300/0301/0302/0303/0305…
marcschier Jul 8, 2026
ad2e7f4
style: modernize syntax and pattern matching (IDE0016/0017/0018/0031/…
marcschier Jul 8, 2026
2384ed0
style: use expression bodies (IDE0021/0022/0024/0025/0027/0053/0061/0…
marcschier Jul 8, 2026
953dcc0
style: align var vs explicit type usage (IDE0007/IDE0008/IDE0350)
marcschier Jul 8, 2026
a711c4b
style: apply idiom-polish analyzers (RCS1021/1069/1070/1075/1081/1085…
marcschier Jul 8, 2026
e6498c1
Merge fork/nodestatestorage: reconcile concurrent AddressSpaceSynchro…
marcschier Jul 8, 2026
6d8c7e4
Merge origin/master (#3967 Opc.Ua.Server coverage increase)
marcschier Jul 8, 2026
09b6b76
Fix ClientReplicaCoordinator leaving a broken session after a failed …
marcschier Jul 8, 2026
8110da2
style: second style pass (IDE0008/0025/0028/0040/0042/0047/0048/0059/…
marcschier Jul 9, 2026
c7cd383
style: analyzer idiom + residual formatting (RCS0010/0055, RCS1069/10…
marcschier Jul 9, 2026
3006b21
style: analyzer idiom residuals (RCS0010/0063, RCS1075/1085/1158/1214)
marcschier Jul 9, 2026
bb91d25
style: use System.Threading.Lock for sync roots (IDE0330)
marcschier Jul 9, 2026
4f8b757
style: collection expressions + misc simplifications (IDE0007/0008/00…
marcschier Jul 9, 2026
8e59e19
style: remove unused usings + simplify member access (IDE0001/0002/0005)
marcschier Jul 9, 2026
bb5102c
Document internal and public symbols across the redundancy PR
marcschier Jul 9, 2026
008d138
style: manual behavioural analyzer fixes (ASP0015, RCS1059/1130/1140/…
marcschier Jul 9, 2026
9b03cf8
fix: wire up unused members flagged by analyzers; suppress intentiona…
marcschier Jul 9, 2026
2ba7c33
style: apply safe explicit-type/collection residuals (IDE0007/0008)
marcschier Jul 9, 2026
c2b9447
style: suppress intentional analyzer diagnostics (RCS1075/1157/1158) …
marcschier Jul 9, 2026
11b0efd
Merge branch 'master' into nodestatestorage
marcschier Jul 9, 2026
a223e25
style: remove redundant null-forgiving on ArraySegment.Array (RCS1249)
marcschier Jul 9, 2026
78c2cee
style: merge adjacent pragmas (RCS1222) and correct apparent-type var…
marcschier Jul 9, 2026
e8230e2
Add redundant sample-app HA integration tests (short-haul + long-haul)
marcschier Jul 9, 2026
dd6649c
style: apply safe collection-expression and explicit-type residuals (…
marcschier Jul 9, 2026
204e526
Merge remote-tracking branch 'fork/nodestatestorage' into nodestatest…
marcschier Jul 9, 2026
8fcebbf
Merge remote-tracking branch 'origin/master' into nodestatestorage
marcschier Jul 9, 2026
a8b3250
fix: restore Opc.Ua.Security.Certificates using after merge
marcschier Jul 9, 2026
cfa5f21
style: re-apply analyzer/style cleanup over merged incoming code
marcschier Jul 9, 2026
e69c44f
Re-trigger CI: ADO required pipeline was cancelled by infrastructure
marcschier Jul 9, 2026
3fd0c20
style: break IDE0007 var oscillation and fix import ordering
marcschier Jul 9, 2026
e3c5a5f
Use generated ObjectTypeIds for redundancy type NodeIds (PR feedback)
marcschier Jul 9, 2026
d2813d4
Merge branch 'master' into nodestatestorage
marcschier Jul 9, 2026
5952e8c
Merge branch 'master' into nodestatestorage
marcschier Jul 9, 2026
c6ebbfa
style: apply safe IDE0001/IDE0028/IDE0039/IDE0391 fixes
marcschier Jul 9, 2026
1fad471
style: apply safe IDE0008 explicit-type fixes
marcschier Jul 9, 2026
c280cb7
style: add blank line between members (RCS0010)
marcschier Jul 9, 2026
b1ef9ac
style: break IDE0007 oscillation at ExpandedNodeId.ToNodeId site
marcschier Jul 9, 2026
37e8cf4
style: break IDE0007 oscillation at remaining ExpandedNodeId.ToNodeId…
marcschier Jul 9, 2026
794ee61
style: apply safe IDE0300/IDE0062/RCS0021 residual fixes
marcschier Jul 9, 2026
1e5b7dc
Merge remote-tracking branch 'fork/nodestatestorage' into nodestatest…
marcschier Jul 9, 2026
fc6e4ac
polyfill: add StringBuilder.AppendJoin for net48/netstandard2.0 and f…
marcschier Jul 9, 2026
14b0520
style: remove redundant null-forgiving operators (RCS1249)
marcschier Jul 9, 2026
1ddb702
style: simplify redundant name qualifications (IDE0001)
marcschier Jul 9, 2026
4d2c937
Fix CS8603 in SampleAppProcess.WaitForLineAsync
marcschier Jul 10, 2026
a456eb9
Model Server.ServerRedundancy via generated subtype instances (#3981)
Copilot Jul 10, 2026
92b3612
Fix AEAD DTLS record protection after analyzer cleanup
marcschier Jul 10, 2026
7353f18
Add MinMax timestamp provenance regression tests
marcschier Jul 10, 2026
e55638d
Fix SKS pull refresh loop hanging PubSub CI
marcschier Jul 10, 2026
9e74005
Containerize and publish all sample servers + RedundantClient + both …
Copilot Jul 10, 2026
54106b7
Address PR #9 review: capability interface + docs for subtype replace…
Copilot Jul 10, 2026
b718628
Merge pull request #9 from marcschier/marcschier/3981-redundancy-subt…
marcschier Jul 10, 2026
64727b6
Merge branch 'master' into nodestatestorage
marcschier Jul 10, 2026
14ff821
Fix Redundancy.Samples net48 ADO test target
marcschier Jul 10, 2026
94958ba
Merge remote-tracking branch 'fork/nodestatestorage' into nodestatest…
marcschier Jul 10, 2026
1be9a59
Remove PumpDeviceIntegrationServer from Docker image matrix
marcschier Jul 10, 2026
a59d742
Record a passing net48 Samples placeholder test
marcschier Jul 10, 2026
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
The table of contents is too big for display.
Diff view
Diff view
  •  
  •  
  •  
81 changes: 81 additions & 0 deletions .azurepipelines/sample-ha-longhaul.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,81 @@
# Azure DevOps pipeline: Sample HA Long-Haul Test.
#
# Long-haul high-availability soak of the redundant sample applications
# (RedundantServer / RedundantClient / RedundantPubSub). The tests are marked
# [Explicit] so they are never part of the PR gate; the short-haul variants run
# in the normal test stages. Register this file as its own pipeline in Azure
# DevOps and run it manually (choosing the duration) or let the weekly schedule
# run the default one-hour soak.

trigger: none
pr: none

schedules:
- cron: '0 4 * * 0'
displayName: 'Weekly HA long-haul soak (Sun 04:00 UTC)'
branches:
include:
- master
always: true

parameters:
- name: durationMinutes
displayName: 'High-availability soak duration in minutes'
type: number
default: 60

variables:
configuration: 'Release'
targetFramework: 'net10.0'
testProject: 'Tests/Opc.Ua.Redundancy.Samples.Tests/Opc.Ua.Redundancy.Samples.Tests.csproj'

pool:
vmImage: 'ubuntu-24.04'

steps:
- checkout: self
fetchDepth: 0

- task: UseDotNet@2
displayName: 'Install .NET 10 SDK'
inputs:
packageType: sdk
version: '10.0.x'

- pwsh: ./.azurepipelines/set-version.ps1
displayName: 'Set Cloud Version'

- script: dotnet restore 'UA.slnx'
displayName: 'Restore dependencies'

- script: >
dotnet build $(testProject)
--framework $(targetFramework)
--configuration $(configuration)
--no-restore
/p:CustomTestTarget=$(targetFramework)
displayName: 'Build sample HA tests (and the referenced sample apps)'

- script: >
dotnet test $(testProject)
--configuration $(configuration)
--no-build
--framework $(targetFramework)
/p:CustomTestTarget=$(targetFramework)
--filter "Category=SampleHaLongHaul"
--logger "trx;LogFileName=sample-ha-longhaul.trx"
--logger "console;verbosity=detailed"
--results-directory $(Agent.TempDirectory)/TestResults
displayName: 'Run long-haul HA soak (${{ parameters.durationMinutes }} min)'
timeoutInMinutes: 110
env:
SAMPLE_HA_DURATION_MINUTES: ${{ parameters.durationMinutes }}

- task: PublishTestResults@2
displayName: 'Publish test results'
condition: always()
inputs:
testResultsFormat: 'VSTest'
testResultsFiles: '**/sample-ha-longhaul.trx'
searchFolder: '$(Agent.TempDirectory)/TestResults'
failTaskOnFailedTests: true
36 changes: 30 additions & 6 deletions .github/workflows/docker-image.yml
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
name: Docker Reference Server CI
name: Docker Sample Images CI

on:
push:
Expand All @@ -18,13 +18,38 @@ concurrency:

env:
REGISTRY: ghcr.io
IMAGE_NAME: refserver
DOCKERSIGN: false

jobs:
build-and-push-image:
runs-on: ubuntu-latest
strategy:
fail-fast: false
matrix:
include:
# Sample servers
- image: refserver
dockerfile: ./Applications/ConsoleReferenceServer/Dockerfile
- image: ldsserver
dockerfile: ./Applications/ConsoleLdsServer/Dockerfile
- image: boilerserver
dockerfile: ./Applications/MinimalBoilerServer/Dockerfile
- image: calcserver
dockerfile: ./Applications/MinimalCalcServer/Dockerfile
- image: mcpserver
dockerfile: ./Applications/McpServer/Dockerfile
- image: redundantserver
dockerfile: ./Applications/RedundantServer/Dockerfile
# Redundant client
- image: redundantclient
dockerfile: ./Applications/RedundantClient/Dockerfile
# PubSub samples
- image: redundantpubsub
dockerfile: ./Applications/RedundantPubSub/Dockerfile
- image: pubsubclient
dockerfile: ./Applications/ConsoleReferencePubSubClient/Dockerfile
env:
IMAGE_NAME: ${{ matrix.image }}
IS_NOT_PR: ${{ !github.head_ref && true }}
permissions:
contents: read
Expand Down Expand Up @@ -114,11 +139,11 @@ jobs:
push: ${{ github.event_name != 'pull_request' }}
tags: ${{ env.TAG_BRANCH }},${{ env.TAG_LATEST }}${{ env.TAG_RELEASE }}
platforms: linux/amd64,linux/arm64/v8
file: ./Applications/ConsoleReferenceServer/Dockerfile
file: ${{ matrix.dockerfile }}
labels: ${{ steps.meta.outputs.labels }}
provenance: false
cache-from: type=gha
cache-to: type=gha,mode=max
cache-from: type=gha,scope=${{ matrix.image }}
cache-to: type=gha,mode=max,scope=${{ matrix.image }}

# Sign the resulting Docker image digest except on PRs.
# https://github.com/sigstore/cosign
Expand All @@ -131,4 +156,3 @@ jobs:
run: |
echo Signing ${{ env.IMAGE_REPOSITORY }}@${{ steps.build-and-push.outputs.digest }}
echo "${{ env.IMAGE_REPOSITORY }}" | xargs -I {} cosign sign {}@${{ steps.build-and-push.outputs.digest }}

85 changes: 85 additions & 0 deletions .github/workflows/sample-ha-longhaul.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,85 @@
name: Sample HA Long-Haul Test

# Long-haul high-availability soak of the redundant sample applications
# (RedundantServer / RedundantClient / RedundantPubSub). These tests are marked
# [Explicit] so they never run on pull requests; the short-haul variants of the
# same scenarios run automatically as part of the normal Build and Test workflow.
#
# Run on demand (Actions -> Sample HA Long-Haul Test -> Run workflow) and choose
# the duration, or let the weekly schedule exercise the default one-hour soak.
on:
workflow_dispatch:
inputs:
duration:
description: 'High-availability soak duration in minutes'
required: false
default: '60'
type: string
schedule:
# Weekly, Sunday 04:00 UTC (after the nightly build/stress windows).
- cron: '0 4 * * 0'

permissions:
contents: read

jobs:
sample-ha-longhaul:
name: Sample HA Long-Haul (${{ github.event.inputs.duration || '60' }} min)
runs-on: ubuntu-latest
# Allow generous head-room beyond the configured soak duration for build,
# startup and teardown.
timeout-minutes: 120

env:
DOTNET_VERSION: '10.0.x'
TARGET_FRAMEWORK: 'net10.0'
CONFIGURATION: 'Release'
TESTPROJECT: './Tests/Opc.Ua.Redundancy.Samples.Tests/Opc.Ua.Redundancy.Samples.Tests.csproj'
SAMPLE_HA_DURATION_MINUTES: ${{ github.event.inputs.duration || '60' }}

steps:
- name: Checkout code
uses: actions/checkout@v7
with:
fetch-depth: 0

- name: Setup .NET ${{ env.DOTNET_VERSION }}
uses: actions/setup-dotnet@v5
with:
dotnet-version: ${{ env.DOTNET_VERSION }}

- name: Set Cloud Version
shell: pwsh
run: ./.azurepipelines/set-version.ps1

- name: Restore dependencies
run: dotnet restore 'UA.slnx'

- name: Build sample HA tests (and the referenced sample apps)
run: >
dotnet build ${{ env.TESTPROJECT }}
--framework ${{ env.TARGET_FRAMEWORK }}
--configuration ${{ env.CONFIGURATION }}
--no-restore
/p:CustomTestTarget=${{ env.TARGET_FRAMEWORK }}

- name: Run long-haul HA soak
run: |
echo "Running the sample HA long-haul soak for $SAMPLE_HA_DURATION_MINUTES minute(s)."
dotnet test ${{ env.TESTPROJECT }} \
--configuration ${{ env.CONFIGURATION }} \
--no-build \
--framework ${{ env.TARGET_FRAMEWORK }} \
/p:CustomTestTarget=${{ env.TARGET_FRAMEWORK }} \
--filter "Category=SampleHaLongHaul" \
--logger "trx;LogFileName=sample-ha-longhaul.trx" \
--logger "console;verbosity=detailed" \
--results-directory ./TestResults
timeout-minutes: 110

- name: Upload test results
uses: actions/upload-artifact@v7
with:
name: sample-ha-longhaul-results
path: ./TestResults
if: always()
19 changes: 19 additions & 0 deletions Applications/ConsoleLdsServer/Dockerfile
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
# OPC UA ConsoleLdsServer (Local Discovery Server) sample image.
#
# The build context must be the repository ROOT so the project references resolve.
# Build directly:
# docker build -f Applications/ConsoleLdsServer/Dockerfile -t opcua-lds-server .
FROM mcr.microsoft.com/dotnet/sdk AS build
WORKDIR /src
ENV DOTNET_EnableWriteXorExecute=0
COPY . .
RUN dotnet publish "Applications/ConsoleLdsServer/ConsoleLdsServer.csproj" \
-c Release -f net10.0 -p:PublishAot=false -p:CustomTestTarget=net10.0 \
-o /app/publish

FROM mcr.microsoft.com/dotnet/runtime AS final
WORKDIR /app
COPY --from=build /app/publish .
# OPC UA Local Discovery Server endpoint port.
EXPOSE 4840
ENTRYPOINT ["dotnet", "ConsoleLdsServer.dll"]
1 change: 0 additions & 1 deletion Applications/ConsoleReferenceClient/ClientSamples.cs
Original file line number Diff line number Diff line change
Expand Up @@ -40,7 +40,6 @@
using Microsoft.Extensions.Logging;
using Opc.Ua;
using Opc.Ua.Client;
using Opc.Ua.Client.ComplexTypes;

namespace Quickstarts
{
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -72,9 +72,10 @@ public ValueTask WriteAsync(
{
builder.Append(", ");
}
builder.Append(string.IsNullOrEmpty(field.Name) ? $"f{i}" : field.Name);
builder.Append('=');
builder.Append(field.Value.IsNull ? "(null)" : field.Value.ToString());
builder
.Append(string.IsNullOrEmpty(field.Name) ? $"f{i}" : field.Name)
.Append('=')
.Append(field.Value.IsNull ? "(null)" : field.Value.ToString());
}
m_logger.LogInformation(
"DataSet #{Sequence} received ({FieldCount} fields): {Fields}",
Expand Down
19 changes: 19 additions & 0 deletions Applications/ConsoleReferencePubSubClient/Dockerfile
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
# OPC UA ConsoleReferencePubSubClient sample image.
#
# The build context must be the repository ROOT so the project references resolve.
# Build directly:
# docker build -f Applications/ConsoleReferencePubSubClient/Dockerfile -t opcua-pubsub-client .
FROM mcr.microsoft.com/dotnet/sdk AS build
WORKDIR /src
ENV DOTNET_EnableWriteXorExecute=0
COPY . .
RUN dotnet publish "Applications/ConsoleReferencePubSubClient/ConsoleReferencePubSubClient.csproj" \
-c Release -f net10.0 -p:PublishAot=false -p:CustomTestTarget=net10.0 \
-o /app/publish

FROM mcr.microsoft.com/dotnet/runtime AS final
WORKDIR /app
COPY --from=build /app/publish .
# OPC UA endpoint and PubSub (UADP/MQTT) ports.
EXPOSE 4840 4841
ENTRYPOINT ["dotnet", "ConsoleReferencePubSubClient.dll"]
Original file line number Diff line number Diff line change
Expand Up @@ -97,10 +97,10 @@ public static PubSubConfigurationDataType BuildConfiguration(BridgeMode modes, s
}

bool includePublisher = modes.HasFlag(BridgeMode.Publisher);
bool includeSubscriber = modes.HasFlag(BridgeMode.Subscriber)
|| modes.HasFlag(BridgeMode.Responder);
bool includeSubscriber = modes.HasFlag(BridgeMode.Subscriber) ||
modes.HasFlag(BridgeMode.Responder);

PubSubConfigurationBuilder builder = PubSubConfigurationBuilder.Create();
var builder = PubSubConfigurationBuilder.Create();
if (includePublisher)
{
AddExternalServerDataSet(builder);
Expand Down Expand Up @@ -183,9 +183,7 @@ private static void AddExternalServerDataSet(PubSubConfigurationBuilder builder)

private static void AddWriterGroup(PubSubConnectionBuilder connection)
{
connection.AddWriterGroup("WriterGroup 1", group =>
{
group
connection.AddWriterGroup("WriterGroup 1", group => group
.WithWriterGroupId(WriterGroupId)
.WithPublishingInterval(PublishingIntervalMs)
.WithMessageSettings(WriterGroupMessageSettings())
Expand All @@ -195,8 +193,7 @@ private static void AddWriterGroup(PubSubConnectionBuilder connection)
.WithDataSetName(DataSetName)
.WithKeyFrameCount(1)
.WithFieldContentMask(DataSetFieldContentMask.RawData)
.WithMessageSettings(WriterMessageSettings()));
});
.WithMessageSettings(WriterMessageSettings())));
}

private static void AddReaderGroup(PubSubConnectionBuilder connection)
Expand All @@ -221,7 +218,7 @@ private static string ConnectionName(BridgeMode modes)
{
return "External Server Publisher Connection";
}
if (modes == BridgeMode.Subscriber || modes == BridgeMode.Responder)
if (modes is BridgeMode.Subscriber or BridgeMode.Responder)
{
return "External Server Subscriber Connection";
}
Expand Down Expand Up @@ -321,12 +318,12 @@ private static UadpWriterGroupMessageDataType WriterGroupMessageSettings()
{
DataSetOrdering = DataSetOrderingType.AscendingWriterId,
NetworkMessageContentMask = (uint)(
UadpNetworkMessageContentMask.PublisherId
| UadpNetworkMessageContentMask.GroupHeader
| UadpNetworkMessageContentMask.WriterGroupId
| UadpNetworkMessageContentMask.PayloadHeader
| UadpNetworkMessageContentMask.NetworkMessageNumber
| UadpNetworkMessageContentMask.SequenceNumber)
UadpNetworkMessageContentMask.PublisherId |
UadpNetworkMessageContentMask.GroupHeader |
UadpNetworkMessageContentMask.WriterGroupId |
UadpNetworkMessageContentMask.PayloadHeader |
UadpNetworkMessageContentMask.NetworkMessageNumber |
UadpNetworkMessageContentMask.SequenceNumber)
};
}

Expand All @@ -335,8 +332,8 @@ private static UadpDataSetWriterMessageDataType WriterMessageSettings()
return new UadpDataSetWriterMessageDataType
{
DataSetMessageContentMask = (uint)(
UadpDataSetMessageContentMask.Status
| UadpDataSetMessageContentMask.SequenceNumber)
UadpDataSetMessageContentMask.Status |
UadpDataSetMessageContentMask.SequenceNumber)
};
}

Expand All @@ -345,15 +342,15 @@ private static UadpDataSetReaderMessageDataType ReaderMessageSettings()
return new UadpDataSetReaderMessageDataType
{
NetworkMessageContentMask = (uint)(
UadpNetworkMessageContentMask.PublisherId
| UadpNetworkMessageContentMask.GroupHeader
| UadpNetworkMessageContentMask.WriterGroupId
| UadpNetworkMessageContentMask.PayloadHeader
| UadpNetworkMessageContentMask.NetworkMessageNumber
| UadpNetworkMessageContentMask.SequenceNumber),
UadpNetworkMessageContentMask.PublisherId |
UadpNetworkMessageContentMask.GroupHeader |
UadpNetworkMessageContentMask.WriterGroupId |
UadpNetworkMessageContentMask.PayloadHeader |
UadpNetworkMessageContentMask.NetworkMessageNumber |
UadpNetworkMessageContentMask.SequenceNumber),
DataSetMessageContentMask = (uint)(
UadpDataSetMessageContentMask.Status
| UadpDataSetMessageContentMask.SequenceNumber)
UadpDataSetMessageContentMask.Status |
UadpDataSetMessageContentMask.SequenceNumber)
};
}
}
Expand Down
Loading
Loading