Skip to content

New Task Frends.Opcua.Write#7

Open
RikuVirtanen wants to merge 10 commits into
mainfrom
custom-write
Open

New Task Frends.Opcua.Write#7
RikuVirtanen wants to merge 10 commits into
mainfrom
custom-write

Conversation

@RikuVirtanen

@RikuVirtanen RikuVirtanen commented May 22, 2026

Copy link
Copy Markdown

Please review my changes :)

Task Harmonization PR template

Review Checklist

1. Frends Task Project File

  • Path: Frends.*/Frends.*/*.csproj
  • Contains required fields:
    • <TargetFramework>net8.0</TargetFramework>
    • <Version>x.0.0</Version>
    • <Authors>Frends</Authors>
    • <PackageLicenseExpression>MIT</PackageLicenseExpression>
    • <GenerateDocumentationFile>true</GenerateDocumentationFile>
    • <Description>
    • [ ]
      <RepositoryUrl>https://github.com/FrendsPlatform/Frends.SYSTEM/tree/main/Frends.SYSTEM.ACTION</RepositoryUrl>
    • <Nullable>disable</Nullable>
  • Contains required package references:
    • StyleCop.Analyzers v1.2.0-beta.556
    • FrendsTaskAnalyzers v1.*
  • Contains required files:
    • <Content Include="migration.json" PackagePath="/" Pack="true"/>
    • <Content Include="../CHANGELOG.md" PackagePath="/" Pack="true"/>
    • <AdditionalFiles Include="FrendsTaskMetadata.json" PackagePath="/" Pack="true"/>
  • Auto formatting applied

2. Frends Task Test Project File

  • Path: Frends.*/Frends.*.Tests/*.Tests.csproj
  • Contains required fields:
    • <TargetFramework>net8.0</TargetFramework>
    • <IsPackable>false</IsPackable>
    • <Nullable>disable</Nullable>
  • Contains required package references:
    • StyleCop.Analyzers v1.2.0-beta.556
  • Auto formatting applied

3. Additional Files

  • Present only one LICENSE file per repository
    • Should be MIT License unless otherwise specified
  • Present only one .gitignore file per repository
    • Includes .idea/ folders
  • Present: Frends.*/README.md
    • Contains badges (build, license, coverage)
    • Includes developer setup instructions
    • Includes test setup instructions
    • Does not include parameter descriptions
  • Present: Frends.*/CHANGELOG.md
    • Includes all functional changes
    • Indicates breaking changes with upgrade notes
    • Avoids non-functional notes like "refactored xyz"
    • Uses the KeepAChangelog format
  • Present: Frends.*/Frends.*/FrendsTaskMetadata.json
    • Contains task method reference Frends.System.Action.System.Action
  • Present: Frends.*/Frends.*/migration.json
    • Contains breaking change migration information for Frends if breaking changes exist
  • StyleCop.Analyzers suppression files added and setup:
    • Present: Frends.*/Frends.*/GlobalSuppressions.cs
    • Present: Frends.*/Frends.*.Tests/GlobalSuppressions.cs
    • Follows standards from Frends Task Template
  • Auto formatting applied

4. Source Code

  • Solution builds
  • File-scoped namespace applied
  • Usings placed before the namespace
  • Unused code is removed
  • Warnings resolved (if possible)
  • Follows Microsoft C# code conventions
  • Typos and grammar mistakes resolved
  • Auto formatting applied

5. GitHub Actions Workflows

  • Path: .github/workflows/*.yml
  • Task has required workflow files:
    • *_release.yml
      • contains secret feed_api_key: ${{ secrets.TASKS_FEED_API_KEY }}
    • *_test_on_main.yml
      • contains secret badge_service_api_key: ${{ secrets.BADGE_SERVICE_API_KEY }}
    • *_test_on_push.yml
      • contains secret badge_service_api_key: ${{ secrets.BADGE_SERVICE_API_KEY }}
      • contains secret test_feed_api_key: ${{ secrets.TASKS_TEST_FEED_API_KEY }}
  • default permissions set for GITHUB_TOKEN
  • workdir: Frends.SYSTEM.ACTION
  • strict_analyzers: true
  • dotnet_version: 8.0.x
  • Docker setup included if task depends on external system (prebuild_command: docker-compose up -d)

Summary by CodeRabbit

  • New Features

    • Added OPC UA Write task: batch writing via structured or JSON input; supports anonymous, username/password, and certificate authentication, configurable security modes/policies and PKI options, and configurable error-handling with optional custom messages.
  • Tests

    • Added unit and end-to-end functional tests covering auth modes, certificate scenarios, and error handling; includes test tooling to generate certificates and local test services.
  • Documentation

    • README and initial changelog entry added.
  • Chores

    • CI workflows for build, test, and release added.

@coderabbitai

coderabbitai Bot commented May 22, 2026

Copy link
Copy Markdown

Review Change Stack

Warning

Review limit reached

@RikuVirtanen, we couldn't start this review because you've reached your PR review rate limit.

More reviews will be available in 28 minutes and 41 seconds. Learn how PR review limits work.

Your organization has run out of usage credits. Purchase more in the billing tab.

⌛ How to resolve this issue?

After more reviews become available, a review can be triggered using the @coderabbitai review command as a PR comment. Alternatively, push new commits to this PR.

We recommend that you space out your commits to avoid hitting the rate limit.

🚦 How do rate limits work?

CodeRabbit enforces hourly rate limits for each developer per organization.

Our paid plans include higher PR review limits than trial, open-source, and free plans. In all cases, reviews become available again over time. During sustained high-volume PR review activity, CodeRabbit may temporarily slow when the next review becomes available.

Please see our Fair Usage Limits Policy for further information.

ℹ️ Review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro

Run ID: cc41710b-687a-4a64-8e6d-bb13bb7c8350

📥 Commits

Reviewing files that changed from the base of the PR and between ded8677 and e26e649.

📒 Files selected for processing (3)
  • Frends.Opcua.Write/Frends.Opcua.Write.Tests/FunctionalTests.cs
  • Frends.Opcua.Write/Frends.Opcua.Write.Tests/generate-certs.sh
  • Frends.Opcua.Write/Frends.Opcua.Write/Frends.Opcua.Write.cs

Walkthrough

This PR adds the Frends.Opcua.Write task: DTOs/enums, validation attributes, connection/session management, core Write implementation, test infrastructure (Docker + certs), functional and unit tests, project/packaging metadata, and CI workflows for testing and release.

Changes

Frends.Opcua.Write Task Implementation

Layer / File(s) Summary
Enums and simple data types
Frends.Opcua.Write/Enums/*, Frends.Opcua.Write/Definitions/Error.cs, Frends.Opcua.Write/Definitions/Result.cs, Frends.Opcua.Write/Definitions/WriteNode.cs, Frends.Opcua.Write/FrendsTaskMetadata.json
AuthenticationMode, InputType, OpcMessageSecurityMode, OpcSecurityPolicy enums and Error/Result/WriteNode DTOs plus task metadata TaskMethod mapping.
Validation attributes
Frends.Opcua.Write/Attributes/RequiredIfAttribute.cs, Frends.Opcua.Write/Attributes/RequiredToExistIfAttribute.cs, Frends.Opcua.Write/Attributes/ValidJsonArrayAttribute.cs
Custom validators for conditional requirements, file-existence checks for certificates, and JSON-array structure/field validation.
Configuration models with validation
Frends.Opcua.Write/Definitions/Connection.cs, Frends.Opcua.Write/Definitions/Input.cs, Frends.Opcua.Write/Definitions/Options.cs
Connection models endpoint/auth/security settings with conditional UI/validation; Input supports object-array or JSON payload; Options control app name, PKI path, and error behavior.
Test infrastructure: Docker, certificates, and test project setup
Frends.Opcua.Write.Tests/docker-compose.yml, Frends.Opcua.Write.Tests/generate-certs.sh, Frends.Opcua.Write.Tests/*.csproj, Frends.Opcua.Write.Tests/TestBase.cs, Frends.Opcua.Write.Tests/GlobalSuppressions.cs
Docker Compose defines three OPC UA test servers; script generates PKI/PFX/DER and nodesfile.json; test project configured for net8.0 with NUnit and coverage; test helpers and suppressions included.
OPC UA session creation and lifecycle management
Frends.Opcua.Write/Helpers/OpcUaSession.cs, Frends.Opcua.Write/Helpers/SessionFactory.cs
OpcUaSession ensures async cleanup; SessionFactory builds ApplicationConfiguration, discovers/selects endpoints, maps security/policy, creates user identities, and loads/creates certificates.
Core Write task and supporting helpers
Frends.Opcua.Write/Frends.Opcua.Write.cs, Frends.Opcua.Write/Helpers/ErrorHandler.cs, Frends.Opcua.Write/Helpers/ValidationHandler.cs
Main Write entry validates inputs, creates session, writes nodes (array or JSON), maps per-node results and status descriptions; ErrorHandler and ValidationHandler centralize error/result and validation behavior.
End-to-end functional tests
Frends.Opcua.Write.Tests/FunctionalTests.cs
NUnit functional suite covering anonymous (host/IP), username/password, invalid credentials, certificate-based writes, and certificate-path validation with per-node "Good" status assertions or expected error messages.
Error handling unit tests
Frends.Opcua.Write.Tests/ErrorHandlerTest.cs
Unit tests for ThrowErrorOnFailure true/false and custom ErrorMessageOnFailure behavior.
Project files, task metadata, and documentation
Frends.Opcua.Write/Frends.Opcua.Write.csproj, Frends.Opcua.Write/Frends.Opcua.Write.sln, Frends.Opcua.Write/FrendsTaskMetadata.json, Frends.Opcua.Write/migration.json, Frends.Opcua.Write/GlobalSuppressions.cs, Frends.Opcua.Write/CHANGELOG.md, Frends.Opcua.Write/README.md, README.md
Project targets net8.0 with OPC UA client and analyzers, solution and packaging metadata added, migration and task metadata included, StyleCop suppressions and docs/changelog updated.
CI/CD workflows
.github/workflows/Write_release.yml, .github/workflows/Write_test_on_main.yml, .github/workflows/Write_test_on_push.yml
Release (workflow_dispatch) and test workflows that reuse FrendsTasks reusable workflows; main/push workflows run prebuild cert generation and Docker Compose for integration tests and wire required secrets.

Estimated code review effort

🎯 4 (Complex) | ⏱️ ~60 minutes

Suggested reviewers

  • MatteoDelOmbra

Poem

🐰 I hopped through code with bits in tow,
Built certs and Docker, made tests go,
Nodes write "Good" in a tidy row,
Enums, guards, and sessions all in tow —
A small rabbit cheers: hop, test, and show!

🚥 Pre-merge checks | ✅ 4 | ❌ 1

❌ Failed checks (1 warning)

Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 8.57% which is insufficient. The required threshold is 80.00%. Write docstrings for the functions missing them to satisfy the coverage threshold.
✅ Passed checks (4 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title accurately summarizes the primary change: a new OPC UA Write task has been added to the repository alongside existing task infrastructure.
Linked Issues check ✅ Passed Check skipped because no linked issues were found for this pull request.
Out of Scope Changes check ✅ Passed Check skipped because no linked issues were found for this pull request.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.

✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch custom-write

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands and usage tips.

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Actionable comments posted: 18

🧹 Nitpick comments (3)
Frends.Opcua.Write/Frends.Opcua.Write/Helpers/ErrorHandler.cs (1)

26-29: ⚡ Quick win

Preserve original stack trace when rethrowing cancellation.

Line 28 uses throw exception;, which resets the stack trace. Use ExceptionDispatchInfo.Capture(exception).Throw() for accurate diagnostics.

Suggested fix
+using System.Runtime.ExceptionServices;
 using System;
 using Frends.Opcua.Write.Definitions;
@@
 private static void ThrowIfCanceled(Exception exception, bool throwCanceled = true)
 {
-    if (throwCanceled && exception is OperationCanceledException) throw exception;
+    if (throwCanceled && exception is OperationCanceledException)
+        ExceptionDispatchInfo.Capture(exception).Throw();
 }
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@Frends.Opcua.Write/Frends.Opcua.Write/Helpers/ErrorHandler.cs` around lines
26 - 29, The ThrowIfCanceled method currently rethrows
OperationCanceledException using "throw exception;" which resets the stack
trace; update ThrowIfCanceled(Exception exception, bool throwCanceled = true) to
rethrow via ExceptionDispatchInfo.Capture(exception).Throw() (and ensure the
appropriate using for System.Runtime.ExceptionServices is added) so the original
stack trace is preserved when exception is an OperationCanceledException and
throwCanceled is true.
Frends.Opcua.Write/Frends.Opcua.Write/Attributes/ValidJsonArrayAttribute.cs (1)

3-3: ⚡ Quick win

Add an explicit Newtonsoft.Json package reference (avoid relying on transitive dependencies).

Frends.Opcua.Write/Frends.Opcua.Write/Attributes/ValidJsonArrayAttribute.cs (and other files in this repo) use using Newtonsoft.Json.Linq;, but none of the projects’ .csproj files include a direct PackageReference to Newtonsoft.Json—so the build depends on whatever transitive package currently brings it in.

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@Frends.Opcua.Write/Frends.Opcua.Write/Attributes/ValidJsonArrayAttribute.cs`
at line 3, The project relies on Newtonsoft.Json via transitive dependencies but
files like ValidJsonArrayAttribute.cs (class ValidJsonArrayAttribute) reference
Newtonsoft.Json.Linq directly; add an explicit PackageReference for
Newtonsoft.Json to the project that contains ValidJsonArrayAttribute (and any
other projects that directly use Newtonsoft.Json types) in its .csproj so the
build does not rely on transitive packages, then run dotnet restore / rebuild to
verify resolution.
Frends.Opcua.Write/Frends.Opcua.Write.Tests/FunctionalTests.cs (1)

68-68: ⚡ Quick win

Remove debug artifacts from the test code.

Line 68 contains commented-out path code, and Lines 149-152 print diagnostic output to console. These should be removed to keep tests clean and stable in CI logs.

Suggested change
-    PrivateKeyPath = string.Empty, // Path.Combine(AppDomain.CurrentDomain.BaseDirectory, "../../../Volumes/trusted-user/certs/user.key"),
+    PrivateKeyPath = string.Empty,
@@
-    Console.WriteLine($"Volumes dir: {connectionSecure.CertificatePath}");
-    Console.WriteLine($"Absolute path: {Path.GetFullPath(connectionSecure.CertificatePath)}");
-    Console.WriteLine($"Volumes exists: {Directory.Exists(connectionSecure.CertificatePath)}");

As per coding guidelines, Frends.*/**/*.cs: Clean structure and no unused code.

Also applies to: 149-152

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@Frends.Opcua.Write/Frends.Opcua.Write.Tests/FunctionalTests.cs` at line 68,
Remove the debug artifacts from the FunctionalTests class: delete the
commented-out hardcoded path fragment from the PrivateKeyPath assignment (the
commented Path.Combine line next to PrivateKeyPath = string.Empty) and remove
the diagnostic Console.WriteLine calls printed in the test (the console output
around lines 149–152) so the test contains no commented-out test paths or
transient diagnostic prints; keep the PrivateKeyPath set to string.Empty and
ensure no other references to the removed debug prints remain in the
FunctionalTests class.
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In @.github/workflows/Write_release.yml:
- Line 10: The workflow references a reusable workflow with a mutable ref
("FrendsPlatform/FrendsTasks/.github/workflows/release.yml@main"); replace the
mutable branch ref `@main` with an immutable commit SHA for that reusable workflow
(i.e., change the ref after the `uses:` entry to the specific commit SHA) so the
action is pinned to a single commit and cannot change unexpectedly.

In @.github/workflows/Write_test_on_main.yml:
- Line 15: The workflow reference currently pins to a mutable branch in the line
using "uses:
FrendsPlatform/FrendsTasks/.github/workflows/linux_build_main.yml@main"; replace
the "`@main`" suffix with a vetted commit SHA for that repository (e.g.
"@<commit-sha>") to pin the reusable workflow, and update any other occurrences
of ".../workflows/*`@main`" in this file to the appropriate vetted SHAs so the
referenced reusable workflows are immutable and reproducible.

In @.github/workflows/Write_test_on_push.yml:
- Line 15: The workflow currently references a reusable workflow using a mutable
ref ("uses:
FrendsPlatform/FrendsTasks/.github/workflows/linux_build_test.yml@main" in the
build job); replace the mutable ref `@main` with an immutable commit SHA of the
referenced repository (the exact commit that matches the intended workflow
version) so the build job's reusable workflow is pinned and CI is reproducible,
and update that SHA whenever you intentionally upgrade the reusable workflow.

In `@Frends.Opcua.Write/CHANGELOG.md`:
- Around line 3-7: Replace the vague "- Initial implementation" entry under "##
[1.0.0] - 2026-05-22" / "### Added" with a bulleted list of concrete,
user-visible features (e.g., "Added OPC UA write task with single/multi-node
support", "Supported auth modes: Anonymous, Username/Password, Certificate",
"Input validation for node ids and value types", "Retry/backoff behavior and
error semantics", "Test infrastructure: integration tests + CI job"), and add an
"### Changed" or "### Fixed" section if applicable plus an "### BREAKING
CHANGES" or "Upgrade notes" subsection describing any config or API changes
users must perform; ensure the document follows Keep a Changelog style (dateed
header, categorized sections) and replace the original "- Initial
implementation" line accordingly.

In `@Frends.Opcua.Write/Frends.Opcua.Write.Tests/FunctionalTests.cs`:
- Around line 38-53: The test currently hardcodes sensitive values in the
Connection instance (variable connectionUsernamePassword) — specifically the
Username, Password and ApplicationCertificatePassword properties — so change the
test to load these from environment variables (use dotenv in the test setup and
read via Environment.GetEnvironmentVariable) and assign those variables to
connectionUsernamePassword.Username, connectionUsernamePassword.Password and
connectionUsernamePassword.ApplicationCertificatePassword; keep fallback or
assert they exist in setup to fail fast if the env vars are missing.
- Around line 142-144: The test currently only asserts the error message after
calling Opcua.Write; add an explicit assertion that the call failed by checking
the Success flag (e.g., assert result.Success is false) in the same test so the
failure contract is validated, then keep the existing Assert on
result.Error.Message to verify the reason; locate the test that calls
Opcua.Write and add an assertion against result.Success (or
Assert.IsFalse(result.Success)/Assert.That(result.Success, Is.False)) before or
alongside the existing message assertion.

In `@Frends.Opcua.Write/Frends.Opcua.Write.Tests/generate-certs.sh`:
- Line 115: The script currently writes nodesfile.json to a hardcoded path using
"cat > Volumes/nodesfile.json << 'EOF'", which ignores the configurable
OUTPUT_DIR; change that invocation to use the OUTPUT_DIR variable (e.g., "cat >
${OUTPUT_DIR}/nodesfile.json << 'EOF'") so the --output/OUTPUT_DIR option
controls where nodesfile.json is written; update any other hardcoded references
to Volumes for nodesfile.json to reference OUTPUT_DIR as well.

In `@Frends.Opcua.Write/Frends.Opcua.Write/Attributes/ValidJsonArrayAttribute.cs`:
- Around line 33-39: The validation currently indexes each JToken (token[field])
assuming it's an object which throws for non-object items; inside the
ValidJsonArrayAttribute validation method (the loop over parsed and
requiredFields), first check that token.Type == JTokenType.Object (or token is
JObject) and if not return a ValidationResult indicating the offending
non-object entry, then only access token[field] to check for missing required
fields; apply the same clear ValidationResult message format used elsewhere so
validation returns an error instead of throwing.

In `@Frends.Opcua.Write/Frends.Opcua.Write/Definitions/Connection.cs`:
- Around line 26-29: The Port property (and other numeric timeout properties in
the same class) lack range validation and can accept 0/negative values; add
DataAnnotations Range attributes to enforce valid values: annotate Port with
[Range(1, 65535)] and annotate each timeout-related int property with [Range(1,
int.MaxValue)] (or a sensible upper bound) and keep the existing default values;
also add the using for System.ComponentModel.DataAnnotations if missing so the
attributes compile.
- Around line 42-43: The AutoAcceptUntrustedCertificates property in the
Connection class currently defaults to true, which is insecure; change its
default to false and update the [DefaultValue] attribute to match so the
property and metadata reflect the secure default—locate the
AutoAcceptUntrustedCertificates property in class Connection and set its
initializer and DefaultValue to false.

In `@Frends.Opcua.Write/Frends.Opcua.Write/Definitions/Error.cs`:
- Line 20: The public result type exposes an Exception via the AdditionalInfo
property on the Error class; change AdditionalInfo to a simple serializable type
(e.g., string or a small DTO) to avoid returning Exception objects. Update the
Error class (the AdditionalInfo property) to hold a flat payload such as string
AdditionalInfo or a custom ErrorDetail DTO (e.g., ErrorDetail { string Message;
string Type; string StackTrace? }) and adjust any code that sets AdditionalInfo
(constructors/factories in the same class or callers) to populate the new simple
fields instead of assigning Exception instances.

In `@Frends.Opcua.Write/Frends.Opcua.Write/Definitions/Result.cs`:
- Line 19: The public property Nodes in the Result class is declared as dynamic;
replace it with a strongly typed collection that matches the documented node
result shape (e.g. List<NodeResult> or IReadOnlyList<NodeResult>) and add a new
NodeResult (or NodeWriteResult) DTO that contains the documented fields; update
the Result.Nodes type to that collection and adjust any
serialization/constructor/consumer code that reads/writes Nodes (methods
referencing Result.Nodes, serializers, and tests) to use the new NodeResult type
so tooling and compile-time checks can validate the contract.

In `@Frends.Opcua.Write/Frends.Opcua.Write/Enums/InputType.cs`:
- Line 13: The enum member InputType.JSON should be renamed to InputType.Json to
follow C# naming rules for abbreviations; update the declaration in the
InputType enum and then update all usages and any serialization/parse logic that
reference the old JSON name (search for "InputType.JSON", string literals,
switch cases, and any JSON/enum mapping code) to use InputType.Json so the API
remains consistent and compilation succeeds.

In `@Frends.Opcua.Write/Frends.Opcua.Write/Frends.Opcua.Write.cs`:
- Line 163: The fallback error message incorrectly says "OPC UA node read
failed" even though this is in the write task; update the fallback string used
where statusCode is mapped (the switch/expression that returns $"OPC UA node
read failed with status: {statusCode}") to say "OPC UA node write failed with
status: {statusCode}" so the error references a write operation (adjust the
expression in Frends.Opcua.Write.cs where statusCode is formatted).

In `@Frends.Opcua.Write/Frends.Opcua.Write/Frends.Opcua.Write.csproj`:
- Line 15: The <RepositoryUrl> element currently points to the Read project;
update the <RepositoryUrl> value so it references the Write project (change the
URL from .../Frends.Opcua.Read to .../Frends.Opcua.Write) in the project file so
tools and users are directed to the correct repository page; ensure the tag
remains
<RepositoryUrl>https://github.com/FrendsPlatform/Frends.Opcua/tree/main/Frends.Opcua.Write</RepositoryUrl>.

In `@Frends.Opcua.Write/Frends.Opcua.Write/Helpers/OpcUaSession.cs`:
- Around line 24-30: The DisposeAsync method in class OpcUaSession should
guarantee Session.Dispose() runs even if Session.CloseAsync() throws: wrap the
CloseAsync call in a try/finally (or try/catch/finally) so that you await
Session.CloseAsync() only if Session.Connected but always call Session.Dispose()
in the finally block; reference the DisposeAsync method and the
Session.CloseAsync and Session.Dispose members when making the change.

In `@Frends.Opcua.Write/Frends.Opcua.Write/Helpers/SessionFactory.cs`:
- Around line 182-184: The temporary RSA instance created with RSA.Create()
(variable privateKey) must be disposed deterministically; in SessionFactory.cs
wrap the RSA creation/import block in a using (or otherwise call Dispose) so you
import the PEM into privateKey, call cert.CopyWithPrivateKey(privateKey) to
produce the new certificate, and then return that new certificate after the RSA
has been disposed; reference RSA.Create(), ImportFromPem, privateKey, and
cert.CopyWithPrivateKey to locate and update the code.

In `@Frends.Opcua.Write/Frends.Opcua.Write/migration.json`:
- Line 3: The migration.json currently sets the migration target "Task" to
"Frends.Opcua.Read" which is incorrect for this project; update the "Task" value
in migration.json to "Frends.Opcua.Write" so the migration metadata applies to
the correct task identifier.

---

Nitpick comments:
In `@Frends.Opcua.Write/Frends.Opcua.Write.Tests/FunctionalTests.cs`:
- Line 68: Remove the debug artifacts from the FunctionalTests class: delete the
commented-out hardcoded path fragment from the PrivateKeyPath assignment (the
commented Path.Combine line next to PrivateKeyPath = string.Empty) and remove
the diagnostic Console.WriteLine calls printed in the test (the console output
around lines 149–152) so the test contains no commented-out test paths or
transient diagnostic prints; keep the PrivateKeyPath set to string.Empty and
ensure no other references to the removed debug prints remain in the
FunctionalTests class.

In `@Frends.Opcua.Write/Frends.Opcua.Write/Attributes/ValidJsonArrayAttribute.cs`:
- Line 3: The project relies on Newtonsoft.Json via transitive dependencies but
files like ValidJsonArrayAttribute.cs (class ValidJsonArrayAttribute) reference
Newtonsoft.Json.Linq directly; add an explicit PackageReference for
Newtonsoft.Json to the project that contains ValidJsonArrayAttribute (and any
other projects that directly use Newtonsoft.Json types) in its .csproj so the
build does not rely on transitive packages, then run dotnet restore / rebuild to
verify resolution.

In `@Frends.Opcua.Write/Frends.Opcua.Write/Helpers/ErrorHandler.cs`:
- Around line 26-29: The ThrowIfCanceled method currently rethrows
OperationCanceledException using "throw exception;" which resets the stack
trace; update ThrowIfCanceled(Exception exception, bool throwCanceled = true) to
rethrow via ExceptionDispatchInfo.Capture(exception).Throw() (and ensure the
appropriate using for System.Runtime.ExceptionServices is added) so the original
stack trace is preserved when exception is an OperationCanceledException and
throwCanceled is true.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro

Run ID: dd96591c-483b-4e13-8f24-2a58ecf25cb0

📥 Commits

Reviewing files that changed from the base of the PR and between ef3ae94 and 0f25de3.

📒 Files selected for processing (36)
  • .github/workflows/Write_release.yml
  • .github/workflows/Write_test_on_main.yml
  • .github/workflows/Write_test_on_push.yml
  • Frends.Opcua.Write/CHANGELOG.md
  • Frends.Opcua.Write/Frends.Opcua.Write.Tests/ErrorHandlerTest.cs
  • Frends.Opcua.Write/Frends.Opcua.Write.Tests/Frends.Opcua.Write.Tests.csproj
  • Frends.Opcua.Write/Frends.Opcua.Write.Tests/FunctionalTests.cs
  • Frends.Opcua.Write/Frends.Opcua.Write.Tests/GlobalSuppressions.cs
  • Frends.Opcua.Write/Frends.Opcua.Write.Tests/TestBase.cs
  • Frends.Opcua.Write/Frends.Opcua.Write.Tests/docker-compose.yml
  • Frends.Opcua.Write/Frends.Opcua.Write.Tests/generate-certs.sh
  • Frends.Opcua.Write/Frends.Opcua.Write.sln
  • Frends.Opcua.Write/Frends.Opcua.Write/Attributes/RequiredIfAttribute.cs
  • Frends.Opcua.Write/Frends.Opcua.Write/Attributes/RequiredToExistIfAttribute.cs
  • Frends.Opcua.Write/Frends.Opcua.Write/Attributes/ValidJsonArrayAttribute.cs
  • Frends.Opcua.Write/Frends.Opcua.Write/Definitions/Connection.cs
  • Frends.Opcua.Write/Frends.Opcua.Write/Definitions/Error.cs
  • Frends.Opcua.Write/Frends.Opcua.Write/Definitions/Input.cs
  • Frends.Opcua.Write/Frends.Opcua.Write/Definitions/Options.cs
  • Frends.Opcua.Write/Frends.Opcua.Write/Definitions/Result.cs
  • Frends.Opcua.Write/Frends.Opcua.Write/Definitions/WriteNode.cs
  • Frends.Opcua.Write/Frends.Opcua.Write/Enums/AuthenticationMode.cs
  • Frends.Opcua.Write/Frends.Opcua.Write/Enums/InputType.cs
  • Frends.Opcua.Write/Frends.Opcua.Write/Enums/OpcMessageSecurityMode.cs
  • Frends.Opcua.Write/Frends.Opcua.Write/Enums/OpcSecurityPolicy.cs
  • Frends.Opcua.Write/Frends.Opcua.Write/Frends.Opcua.Write.cs
  • Frends.Opcua.Write/Frends.Opcua.Write/Frends.Opcua.Write.csproj
  • Frends.Opcua.Write/Frends.Opcua.Write/FrendsTaskMetadata.json
  • Frends.Opcua.Write/Frends.Opcua.Write/GlobalSuppressions.cs
  • Frends.Opcua.Write/Frends.Opcua.Write/Helpers/ErrorHandler.cs
  • Frends.Opcua.Write/Frends.Opcua.Write/Helpers/OpcUaSession.cs
  • Frends.Opcua.Write/Frends.Opcua.Write/Helpers/SessionFactory.cs
  • Frends.Opcua.Write/Frends.Opcua.Write/Helpers/ValidationHandler.cs
  • Frends.Opcua.Write/Frends.Opcua.Write/migration.json
  • Frends.Opcua.Write/README.md
  • README.md

Comment thread .github/workflows/Write_release.yml
Comment thread .github/workflows/Write_test_on_main.yml
Comment thread .github/workflows/Write_test_on_push.yml
Comment thread Frends.Opcua.Write/CHANGELOG.md
Comment thread Frends.Opcua.Write/Frends.Opcua.Write.Tests/FunctionalTests.cs
Comment thread Frends.Opcua.Write/Frends.Opcua.Write/Frends.Opcua.Write.cs Outdated
Comment thread Frends.Opcua.Write/Frends.Opcua.Write/Frends.Opcua.Write.csproj Outdated
Comment thread Frends.Opcua.Write/Frends.Opcua.Write/Helpers/OpcUaSession.cs
Comment thread Frends.Opcua.Write/Frends.Opcua.Write/Helpers/SessionFactory.cs Outdated
Comment thread Frends.Opcua.Write/Frends.Opcua.Write/migration.json Outdated

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Actionable comments posted: 2

🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In `@Frends.Opcua.Write/Frends.Opcua.Write.Tests/generate-certs.sh`:
- Line 115: The redirection target in generate-certs.sh uses an unquoted
variable (cat > $OUTPUT_DIR/nodesfile.json << 'EOF') which will break on paths
with spaces or glob characters; change the redirection to use a quoted expansion
for the output path (i.e. redirect to "$OUTPUT_DIR/nodesfile.json") so the shell
treats the whole path as a single token while preserving the here-doc and the
nodesfile.json filename.

In `@Frends.Opcua.Write/Frends.Opcua.Write/Definitions/Connection.cs`:
- Around line 103-104: ConnectionTimeout and SessionTimeout can overflow when
multiplied by 1000 in SessionFactory (used for sessionTimeout:
(uint)(connection.SessionTimeout * 1000), OperationTimeout =
connection.ConnectionTimeout * 1000, DefaultSessionTimeout =
connection.SessionTimeout * 1000); tighten the allowed range or clamp values
before millisecond conversion to prevent overflow: update the Range on
ConnectionTimeout and SessionTimeout to use a max of int.MaxValue/1000 (or a
safe constant like 2_147_483) and/or ensure the multiplication uses a safe clamp
(e.g., Math.Min(value, int.MaxValue / 1000)) and then cast to uint/long as
needed in SessionFactory to guarantee no overflow when multiplying by 1000.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro

Run ID: cceba95a-f87c-473d-bf34-cfe7dd9e8380

📥 Commits

Reviewing files that changed from the base of the PR and between 0f25de3 and 39154cd.

📒 Files selected for processing (11)
  • Frends.Opcua.Write/Frends.Opcua.Write.Tests/FunctionalTests.cs
  • Frends.Opcua.Write/Frends.Opcua.Write.Tests/generate-certs.sh
  • Frends.Opcua.Write/Frends.Opcua.Write/Attributes/ValidJsonArrayAttribute.cs
  • Frends.Opcua.Write/Frends.Opcua.Write/Definitions/Connection.cs
  • Frends.Opcua.Write/Frends.Opcua.Write/Definitions/Input.cs
  • Frends.Opcua.Write/Frends.Opcua.Write/Enums/InputType.cs
  • Frends.Opcua.Write/Frends.Opcua.Write/Frends.Opcua.Write.cs
  • Frends.Opcua.Write/Frends.Opcua.Write/Frends.Opcua.Write.csproj
  • Frends.Opcua.Write/Frends.Opcua.Write/Helpers/OpcUaSession.cs
  • Frends.Opcua.Write/Frends.Opcua.Write/Helpers/SessionFactory.cs
  • Frends.Opcua.Write/Frends.Opcua.Write/migration.json

Comment thread Frends.Opcua.Write/Frends.Opcua.Write.Tests/generate-certs.sh
Comment thread Frends.Opcua.Write/Frends.Opcua.Write/Definitions/Connection.cs Outdated
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant