Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
51 commits
Select commit Hold shift + click to select a range
36d67b3
[Client] Central channel manager with shared, ref-counted transport c…
marcschier Jun 5, 2026
82347dc
Address PR #3852 review feedback
marcschier Jun 5, 2026
0a32452
Merge branch 'master' into channelrefinements
marcschier Jun 5, 2026
06fbbb5
Add channel-manager stress/chaos test suite (Tests/Opc.Ua.Channels.St…
marcschier Jun 5, 2026
3a5477b
Fix CI failures: HTTPS factory regression + parallel build file lock
marcschier Jun 6, 2026
81e3d4b
Fix CI follow-ups: serialize project build + relax cert leak tolerance
marcschier Jun 6, 2026
0b61c6d
Fix Sessions failover tests masked by budget-aware delegate
marcschier Jun 6, 2026
48b24be
Fix CodeQL whole-solution build failures across legacy TFMs
marcschier Jun 6, 2026
d5f1dbb
Restore CustomTestTarget passthrough for Channels.Stress.Tests
marcschier Jun 6, 2026
cf6bd37
Address PR feedback: small-scope cleanup
marcschier Jun 6, 2026
2efd335
Phase C: move ClientChannelManagerManagedTests out of Core.Tests
marcschier Jun 6, 2026
35f9749
Phase A+B: merge stress test projects + rename workflow
marcschier Jun 6, 2026
193fd4e
Phase D: refactor ClientChannelManager to single non-partial class + …
marcschier Jun 6, 2026
ff33cdd
Phase E: auto-reset faulted ChannelEntry on ReconnectAsync(lease, ...)
marcschier Jun 6, 2026
788567a
Merge branch 'master' of https://github.com/OPCFoundation/UA-.NETStan…
marcschier Jun 8, 2026
de83b91
update
marcschier Jun 8, 2026
b1ba2cc
Merge branch 'master' into channelrefinements
marcschier Jun 8, 2026
961329e
Merge branch 'channelrefinements' of https://github.com/OPCFoundation…
marcschier Jun 8, 2026
c23f477
Merge branch 'master' into channelrefinements
marcschier Jun 8, 2026
81acd94
Close channel-manager production gaps and eliminate Tests/.../Gaps/
marcschier Jun 8, 2026
ce4a1b0
Fix ClientChannelManager.DelaySwapAsync to honor TimeProvider on net48
marcschier Jun 9, 2026
8116f79
Fix ChannelManagerExhaustionEscalatesAndRecoversWhenServerReturns mac…
marcschier Jun 9, 2026
51e7f42
Fix SwapFaultedEntryAsync: re-activate released lease before reattach
marcschier Jun 9, 2026
53ff029
Fix MetricsAreEmittedForReconnectAndGateWaitAsync race on fast runners
marcschier Jun 10, 2026
392ad0d
Merge origin/master into channelrefinements
marcschier Jun 10, 2026
9c5f875
Honor ShutdownToken in ChannelEntry reconnect loop (PR #3852 feedback)
marcschier Jun 10, 2026
5ca95ab
[security] HttpsTransportChannel: refuse factory path when OPC UA cer…
marcschier Jun 11, 2026
3f4db2a
[security] stress-test.yml: env-var indirection for workflow_dispatch…
marcschier Jun 11, 2026
30495fb
[security] buildandtest.yml: add workflow-scoped permissions: content…
marcschier Jun 11, 2026
03df798
[security] ClientChannelManagerDiagnostics: do not leak inner-excepti…
marcschier Jun 11, 2026
39eb086
ChannelEntry: track tightest IRetryBudget across coalesced joiners; C…
marcschier Jun 11, 2026
2a4f4f6
ManagedTransportChannelLease: non-blocking sync Dispose (deadlock und…
marcschier Jun 11, 2026
d0ef235
RetryBudget: swap Reset() write order to avoid stale-tick race
marcschier Jun 11, 2026
b50ffa0
[security] stability-test.yml: read TEST_DURATION_MINUTES as a shell …
marcschier Jun 11, 2026
38d4a29
[security] McpServer NodeSetExportTools: constrain MCP-tool file path…
marcschier Jun 11, 2026
2be0f5c
[docs] Document the secure-by-default DI HttpClient fallback and the …
marcschier Jun 11, 2026
25dc407
[security] ClientChannelManagerCertRotation: refuse rotation events t…
marcschier Jun 11, 2026
04f3d12
[security] Bound the participant metric tag to per-kind cardinality (…
marcschier Jun 11, 2026
a3ae6db
[test] Accommodate non-blocking lease Dispose with thread-safe listen…
marcschier Jun 11, 2026
5353c69
Merge branch 'master' into channelrefinements
marcschier Jun 11, 2026
22828d9
[ci] Stress.Tests: produce a placeholder assembly for net48/472/netst…
marcschier Jun 12, 2026
5c68a6b
Add OPC UA packet capture, offline decoding and replay (Opc.Ua.Bindin…
marcschier Jun 12, 2026
870bd0d
Merge origin/master into channelrefinements
marcschier Jun 12, 2026
9d500da
[ci] Fix compile errors in upstream-merged test files
marcschier Jun 12, 2026
6c9ce69
[ci] Fix ChannelManagerMaxChannelsTests using-alias for nested IChannel
marcschier Jun 12, 2026
b820352
[ci] Fix Pcap test failures: 5 production / test-infra bugs
marcschier Jun 12, 2026
5cc4860
[ci] Fix 3 Pcap test cross-platform / timing issues
marcschier Jun 12, 2026
f691872
Merge branch 'master' into channelrefinements
marcschier Jun 13, 2026
6382a8c
[ci] Drop duplicate Microsoft.Extensions.TimeProvider.Testing Package…
marcschier Jun 13, 2026
862cd36
[ci] Gate Opc.Ua.Network.Fuzz* projects on CustomTestTarget like Pcap
marcschier Jun 13, 2026
7e37ab1
[test] Poll channel.State for Ready after channel-manager swap
marcschier Jun 13, 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
  •  
  •  
  •  
19 changes: 19 additions & 0 deletions .azurepipelines/signlistDebug.txt
Original file line number Diff line number Diff line change
Expand Up @@ -96,4 +96,23 @@ Libraries\Opc.Ua.WotCon.Server\bin\Debug\net48\Opc.Ua.WotCon.Server.dll
Libraries\Opc.Ua.WotCon.Server\bin\Debug\net8.0\Opc.Ua.WotCon.Server.dll
Libraries\Opc.Ua.WotCon.Server\bin\Debug\net9.0\Opc.Ua.WotCon.Server.dll
Libraries\Opc.Ua.WotCon.Server\bin\Debug\net10.0\Opc.Ua.WotCon.Server.dll
Libraries\Opc.Ua.Di\bin\Debug\netstandard2.1\Opc.Ua.Di.dll
Libraries\Opc.Ua.Di\bin\Debug\net472\Opc.Ua.Di.dll
Libraries\Opc.Ua.Di\bin\Debug\net48\Opc.Ua.Di.dll
Libraries\Opc.Ua.Di\bin\Debug\net8.0\Opc.Ua.Di.dll
Libraries\Opc.Ua.Di\bin\Debug\net9.0\Opc.Ua.Di.dll
Libraries\Opc.Ua.Di\bin\Debug\net10.0\Opc.Ua.Di.dll
Libraries\Opc.Ua.Di.Client\bin\Debug\netstandard2.1\Opc.Ua.Di.Client.dll
Libraries\Opc.Ua.Di.Client\bin\Debug\net472\Opc.Ua.Di.Client.dll
Libraries\Opc.Ua.Di.Client\bin\Debug\net48\Opc.Ua.Di.Client.dll
Libraries\Opc.Ua.Di.Client\bin\Debug\net8.0\Opc.Ua.Di.Client.dll
Libraries\Opc.Ua.Di.Client\bin\Debug\net9.0\Opc.Ua.Di.Client.dll
Libraries\Opc.Ua.Di.Client\bin\Debug\net10.0\Opc.Ua.Di.Client.dll
Libraries\Opc.Ua.Di.Server\bin\Debug\netstandard2.1\Opc.Ua.Di.Server.dll
Libraries\Opc.Ua.Di.Server\bin\Debug\net472\Opc.Ua.Di.Server.dll
Libraries\Opc.Ua.Di.Server\bin\Debug\net48\Opc.Ua.Di.Server.dll
Libraries\Opc.Ua.Di.Server\bin\Debug\net8.0\Opc.Ua.Di.Server.dll
Libraries\Opc.Ua.Di.Server\bin\Debug\net9.0\Opc.Ua.Di.Server.dll
Libraries\Opc.Ua.Di.Server\bin\Debug\net10.0\Opc.Ua.Di.Server.dll
Stack\Opc.Ua.Bindings.Pcap\bin\Debug\net10.0\Opc.Ua.Bindings.Pcap.dll
Applications\McpServer\bin\Debug\net10.0\Opc.Ua.Mcp.dll
19 changes: 19 additions & 0 deletions .azurepipelines/signlistRelease.txt
Original file line number Diff line number Diff line change
Expand Up @@ -96,4 +96,23 @@ Libraries\Opc.Ua.WotCon.Server\bin\Release\net48\Opc.Ua.WotCon.Server.dll
Libraries\Opc.Ua.WotCon.Server\bin\Release\net8.0\Opc.Ua.WotCon.Server.dll
Libraries\Opc.Ua.WotCon.Server\bin\Release\net9.0\Opc.Ua.WotCon.Server.dll
Libraries\Opc.Ua.WotCon.Server\bin\Release\net10.0\Opc.Ua.WotCon.Server.dll
Libraries\Opc.Ua.Di\bin\Release\netstandard2.1\Opc.Ua.Di.dll
Libraries\Opc.Ua.Di\bin\Release\net472\Opc.Ua.Di.dll
Libraries\Opc.Ua.Di\bin\Release\net48\Opc.Ua.Di.dll
Libraries\Opc.Ua.Di\bin\Release\net8.0\Opc.Ua.Di.dll
Libraries\Opc.Ua.Di\bin\Release\net9.0\Opc.Ua.Di.dll
Libraries\Opc.Ua.Di\bin\Release\net10.0\Opc.Ua.Di.dll
Libraries\Opc.Ua.Di.Client\bin\Release\netstandard2.1\Opc.Ua.Di.Client.dll
Libraries\Opc.Ua.Di.Client\bin\Release\net472\Opc.Ua.Di.Client.dll
Libraries\Opc.Ua.Di.Client\bin\Release\net48\Opc.Ua.Di.Client.dll
Libraries\Opc.Ua.Di.Client\bin\Release\net8.0\Opc.Ua.Di.Client.dll
Libraries\Opc.Ua.Di.Client\bin\Release\net9.0\Opc.Ua.Di.Client.dll
Libraries\Opc.Ua.Di.Client\bin\Release\net10.0\Opc.Ua.Di.Client.dll
Libraries\Opc.Ua.Di.Server\bin\Release\netstandard2.1\Opc.Ua.Di.Server.dll
Libraries\Opc.Ua.Di.Server\bin\Release\net472\Opc.Ua.Di.Server.dll
Libraries\Opc.Ua.Di.Server\bin\Release\net48\Opc.Ua.Di.Server.dll
Libraries\Opc.Ua.Di.Server\bin\Release\net8.0\Opc.Ua.Di.Server.dll
Libraries\Opc.Ua.Di.Server\bin\Release\net9.0\Opc.Ua.Di.Server.dll
Libraries\Opc.Ua.Di.Server\bin\Release\net10.0\Opc.Ua.Di.Server.dll
Stack\Opc.Ua.Bindings.Pcap\bin\Release\net10.0\Opc.Ua.Bindings.Pcap.dll
Applications\McpServer\bin\Release\net10.0\Opc.Ua.Mcp.dll
2 changes: 1 addition & 1 deletion .azurepipelines/test.yml
Original file line number Diff line number Diff line change
Expand Up @@ -135,7 +135,7 @@ jobs:
condition: and(contains(variables['file'], 'Fuzz.Tests'), ne(variables['fuzzingartifacts.secureFilePath'], ''))
inputs:
archiveFilePatterns: '$(Agent.TempDirectory)/FuzzingArtifacts.zip'
destinationFolder: ./Fuzzing/Encoders/Fuzz.Tests
destinationFolder: ./Fuzzing/Opc.Ua.Encoders.Fuzz.Tests
cleanDestinationFolder: false
overwriteExistingFiles: true
continueOnError: true
Expand Down
2 changes: 1 addition & 1 deletion .azurepipelines/testcc.yml
Original file line number Diff line number Diff line change
Expand Up @@ -67,7 +67,7 @@ jobs:
condition: ne(variables['fuzzingartifacts.secureFilePath'], '')
inputs:
archiveFilePatterns: '$(Agent.TempDirectory)/FuzzingArtifacts.zip'
destinationFolder: ./Fuzzing/Encoders/Fuzz.Tests
destinationFolder: ./Fuzzing/Opc.Ua.Encoders.Fuzz.Tests
cleanDestinationFolder: false
overwriteExistingFiles: true
continueOnError: true
Expand Down
793 changes: 793 additions & 0 deletions .github/agents/fuzz-tester.agent.md

Large diffs are not rendered by default.

141 changes: 139 additions & 2 deletions .github/agents/opcua-interop-tester.agent.md
Original file line number Diff line number Diff line change
Expand Up @@ -9,12 +9,13 @@ You are an expert OPC UA interoperability test engineer. Your role is to systema

## MCP Tools — Primary Test Method

This repository includes an **OPC UA MCP Server** (`Applications/McpServer`) that exposes all OPC UA Part 4 services as MCP tools. **Always prefer using the MCP tools over writing custom C# test code** — they are faster, require no compilation, and cover all standard services.
This repository includes an **OPC UA MCP Server** (`Applications/McpServer`) that exposes all OPC UA Part 4 services AND a full packet-capture / offline-decode / replay tool set as MCP tools. **Always prefer using the MCP tools over writing custom C# test code** — they are faster, require no compilation, and cover all standard services plus deep wire-level diagnostics.

### When to Use MCP Tools
- **Always** for initial connection, browsing, reading, writing, method calling, subscription testing
- **Always** for discovery (FindServers, GetEndpoints)
- **Always** for quick interop validation and smoke tests
- **Always** for wire-level diagnostics — start an in-process packet capture (`start_capture` with `source: "inproc-client"`) at the beginning of every non-trivial test scenario so you have a decoded service-call timeline to attach to bug reports
- **Prefer** for systematic feature testing (Read all attributes, Browse full hierarchy, test all data types)

### When to Write Custom Code Instead
Expand Down Expand Up @@ -116,6 +117,136 @@ Tool: Connect
Tool: Disconnect
```

**Step 9: Packet capture & wire-level diagnostics (REQUIRED for any reported bug)**

Wire-level packet capture is the single most useful tool for diagnosing interop issues — it produces a deterministic, replayable record of exactly what crossed the wire. **Always start a capture at the beginning of a non-trivial test scenario and stop it once you have a clean repro.**

The capture / decode / replay tools live alongside the Part 4 tools:

```
Tool: list_interfaces
→ Returns the local NICs SharpPcap can capture from. Use the
'name' or 'description' as 'interfaceName' for source='nic'.
Requires libpcap (Linux/macOS) or Npcap (Windows). If you get
an error, fall back to source='inproc-client' which needs no
native dependency.

Tool: start_capture
Arguments:
request:
source: "inproc-client" # full key material recorded; no
# OS privileges required
maxDurationSeconds: 60 # hard cap
sessionFolder: "C:/tmp/repro-001" # optional; default is a temp folder
→ Returns sessionId. IMPORTANT: only attaches to channels that exist at
the moment start_capture runs; call it BEFORE the Connect tool for any
interop scenario you care about.

Tool: start_capture # NIC mode for traffic the MCP
Arguments: # server itself doesn't make
request:
source: "nic"
interfaceName: "<from list_interfaces>"
bpfFilter: "tcp port 4840 or tcp portrange 48010-48020"
maxDurationSeconds: 60

Tool: list_active_channels
→ Shows every secure channel the MCP server currently holds plus its
channel id, token id, security policy and mode. Confirm the capture
will see what you expect before you start exercising the server.

Tool: stop_capture
Arguments:
sessionId: "<from start_capture>"
→ Flushes the pcap and the .uakeys.json keylog to disk. Always call
this BEFORE get_capture / decode_pcap_with_keys.

Tool: get_capture
Arguments:
sessionId: "<from start_capture>"
format: "service-timeline" # default; OPC UA-decoded call timeline
# other formats: pcap | pcapng | json | csv | text
→ Returns the captured trace. For bug reports always attach BOTH
format="pcap" (or "pcapng") and format="service-timeline".

Tool: dump_keys
Arguments:
sessionId: "<from start_capture>"
format: "json" # also: text (Wireshark-style)
→ Returns the channel key material in serialisable form so the
capture can be decoded later on a different machine. Treat as a
SECRET — keys decrypt every chunk in the pcap.

Tool: summarize_service_calls
Arguments:
sessionId: "<from start_capture>"
→ Aggregate counts, error rate and latency per service name. Run
this first to see what actually happened during the scenario before
drilling into individual calls.

Tool: capture_now
Arguments:
request:
start: { source: "inproc-client", maxDurationSeconds: 30 }
durationSeconds: 30
format: "service-timeline"
→ One-shot: start, wait, stop, return decoded timeline. Great for
short interactive probes.
```

**Step 10: Replay a captured trace (for hard-to-reproduce regressions)**

When a user reports a bug they observed on their server and they attach a pcap + uakeys file, you have two replay modes available:

```
Tool: decode_pcap_with_keys # OFFLINE — no live server needed
Arguments:
pcapPath: "C:/tmp/user.pcap"
keyLogPath: "C:/tmp/user.uakeys.json"
format: "service-timeline"
→ Reuses the stack's own UaSCUaBinaryChannel decoder to decrypt and
dissect every chunk. Works for every security profile the stack
supports (Basic128Rsa15 / Basic256 / Basic256Sha256 /
Aes128_Sha256_RsaOaep / Aes256_Sha256_RsaPss / RSA_DH_AesGcm /
RSA_DH_ChaChaPoly / all ECC_* with AES-GCM and ChaCha20-Poly1305).

Tool: replay_pcap
Arguments:
pcapPath: "C:/tmp/user.pcap"
mode: "mock-server" # replays captured server bytes to
# a real client connecting back
listenPort: 0 # 0 = ephemeral
→ Returns sessionId + a listenUri the user's client (or the MCP
Connect tool) can target to reproduce the exact server side of the
interaction.

Tool: replay_pcap
Arguments:
pcapPath: "C:/tmp/user.pcap"
keyLogPath: "C:/tmp/user.uakeys.json"
mode: "mock-client"
targetEndpointUrl: "opc.tcp://server-under-test:4840"
speed: 1.0
→ Re-issues the captured Read / Browse / Call requests against a live
target. Other request kinds are logged "not implemented" and
skipped.

Tool: stop_replay / list_replays # housekeeping
```

**Standard repro workflow for an interop bug:**

1. `start_capture` (source=inproc-client) BEFORE any Connect.
2. Connect → exercise the failing scenario via Part 4 tools.
3. `stop_capture` once the failure is observed.
4. `summarize_service_calls` → confirm the failing service is recorded.
5. `get_capture format=service-timeline` → human-readable view to attach.
6. `get_capture format=pcap` → binary pcap (Wireshark-openable) to attach.
7. `dump_keys format=json` → keylog to attach (mark as sensitive!).
8. Once attached to the bug report, anyone can later run
`decode_pcap_with_keys` for offline analysis or `replay_pcap` to
reproduce.

### Interpreting MCP Tool Results
- All tools return JSON with a `responseHeader` containing `serviceResult`
- A `serviceResult` of `"Good"` means the operation succeeded
Expand Down Expand Up @@ -156,10 +287,12 @@ For every issue discovered:
4. **Impact**: Severity (critical/high/medium/low), affected features, user impact
5. **Error messages**: Complete stack traces, exception details, logs
6. **Server context**: Which security mode, auth method, connection state, feature combination triggered it
7. **Packet capture artifacts** (mandatory for non-trivial bugs): attach the `pcap` + `.uakeys.json` keylog produced by `start_capture` / `stop_capture` / `get_capture` / `dump_keys`, plus the `service-timeline` text rendering. This makes the bug reproducible offline via `decode_pcap_with_keys` and `replay_pcap` without needing the original server.

### 4. Quality Assurance Checks
- Before flagging an issue as a bug: Verify it's not due to test configuration or environmental issues
- Reproduce each issue at least twice to confirm it's not intermittent
- For every intermittent or unclear failure, run a capture during the second repro and compare the `service-timeline` output across runs — wire-level evidence trumps stack traces
- Check if the issue is documented in known limitations or open issues
- Cross-reference with OPC UA specification (Part 4: Services, Part 5: Information Model)
- Verify the issue reproduces with different data/parameter combinations
Expand All @@ -186,15 +319,18 @@ Provide results as a structured report:
- Server: [server name/version]
- Stack version: [version tested]
- Connection configurations: [list attempted]
- Capture session id(s): [sessionIds from start_capture]
- Capture artifacts: [paths to pcap + uakeys.json files]

### Summary
- Total features tested: X
- Features working: Y
- Issues discovered: Z
- Pass rate: Y/X%
- Service-call totals (from summarize_service_calls): [counts per service]

### Critical Issues
[List with full details]
[List with full details, each linking to its pcap+keylog excerpt]

### High Priority Issues
[List with full details]
Expand Down Expand Up @@ -233,6 +369,7 @@ Provide results as a structured report:
You have successfully completed this task when:
- You have tested all major OPC UA features listed in section 2
- Every discovered issue has reproducible steps documented
- Every non-trivial discovered issue has a packet capture (`pcap` + `.uakeys.json`) and a decoded `service-timeline` text rendering attached so it can be replayed offline
- You've verified issues aren't due to test setup or environment
- You've created a prioritized remediation plan with at least root cause hypothesis
- The report is detailed enough for developers to understand and fix issues
Expand Down
35 changes: 31 additions & 4 deletions .github/workflows/buildandtest.yml
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,9 @@ on:
- '**.cs'
- '**.csproj'

permissions:
contents: read

concurrency:
group: ${{ github.workflow }}-${{ github.event.pull_request.number || github.ref }}
cancel-in-progress: true
Expand All @@ -28,8 +31,8 @@ jobs:
# Discover test projects from the filesystem so this matrix does
# not have to be hand-maintained as projects are added/renamed.
# Projects whose name is in EXCLUDE are run by other workflows
# (AOT has its own workflow; Stress + Fuzz are opt-in haul/fuzz
# runs).
# (AOT has its own workflow; the Stress suite is opt-in via the
# stress-test workflow).
$exclude = @('Aot', 'Stress')
$projects = Get-ChildItem -Path Tests -Directory -Filter 'Opc.Ua.*.Tests' |
Where-Object { Test-Path (Join-Path $_.FullName "$($_.Name).csproj") } |
Expand Down Expand Up @@ -79,11 +82,35 @@ jobs:
run: ./.azurepipelines/set-version.ps1

- name: Build
run: dotnet build ${{ env.CSPROJECT }} --framework ${{ matrix.framework }} --configuration ${{ matrix.configuration }} /p:CustomTestTarget=${{ matrix.customtesttarget }}
run: dotnet build ${{ env.CSPROJECT }} --framework ${{ matrix.framework }} --configuration ${{ matrix.configuration }} /p:CustomTestTarget=${{ matrix.customtesttarget }} /p:UseSharedCompilation=false -maxcpucount:1

- name: Test
# note: /p:CollectCoverage=true is only used to disable deterministic builds
run: dotnet test ${{ env.CSPROJECT }} --no-build --framework ${{ matrix.framework }} --logger trx --configuration ${{ matrix.configuration }} /p:CollectCoverage=true /p:CustomTestTarget=${{ matrix.customtesttarget }} --collect:"XPlat Code Coverage" --settings ./Tests/coverlet.runsettings.xml --results-directory ${{ env.TESTRESULTS }}
shell: pwsh
run: |
$testArgs = @(
'${{ env.CSPROJECT }}',
'--no-build',
'--framework',
'${{ matrix.framework }}',
'--logger',
'trx',
'--configuration',
'${{ matrix.configuration }}',
'/p:CollectCoverage=true',
'/p:CustomTestTarget=${{ matrix.customtesttarget }}',
'--collect:XPlat Code Coverage',
'--settings',
'./Tests/coverlet.runsettings.xml',
'--results-directory',
'${{ env.TESTRESULTS }}')

if ('${{ matrix.csproj }}' -eq 'Channels.Stress')
{
$testArgs += @('--filter', '(Category=Contract|Category=Integration)&Category!=ChaosTCP&Category!=Soak')
}

dotnet test @testArgs

- name: Upload test results
uses: actions/upload-artifact@v7
Expand Down
6 changes: 6 additions & 0 deletions .github/workflows/codeql-analysis.yml
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,12 @@ on:
- cron: '30 6 * * 6'
workflow_dispatch:

permissions:
actions: read
contents: read
packages: read
security-events: write

concurrency:
group: ${{ github.workflow }}-${{ github.event.pull_request.number || github.ref }}
cancel-in-progress: true
Expand Down
8 changes: 4 additions & 4 deletions .github/workflows/stability-test.yml
Original file line number Diff line number Diff line change
Expand Up @@ -12,15 +12,15 @@ on:
default: '90'
type: string

permissions:
contents: read

jobs:
stability-test:
name: Connection Stability Test
runs-on: ubuntu-latest
timeout-minutes: 120 # Allow extra time beyond test duration for setup/teardown

permissions:
contents: read

env:
DOTNET_VERSION: '10.0.x'
TARGET_FRAMEWORK: 'net10.0'
Expand Down Expand Up @@ -50,7 +50,7 @@ jobs:

- name: Run Connection Stability Test
run: |
echo "Starting connection stability test for ${{ env.TEST_DURATION_MINUTES }} minutes"
echo "Starting connection stability test for $TEST_DURATION_MINUTES minutes"
dotnet test ./Tests/Opc.Ua.Client.Tests/Opc.Ua.Client.Tests.csproj \
--configuration ${{ env.CONFIGURATION }} \
--no-build \
Expand Down
Loading
Loading