rewrite scripts to csharp#1163
Open
PTKu wants to merge 23 commits into
Open
Conversation
…ile transitive dependencies
…ndencies - Implemented `update-vulnerable-deps.ps1` script to scan for vulnerable dependencies and apply safe fixes. - Introduced `_deps-common.ps1` for shared helper functions used in dependency management. - Updated `Directory.Packages.props` to include security pins for vulnerable packages. - Added `.gitignore` entries to exclude vulnerability scan reports. - Created `apax.yml` for managing dependencies in the apax traversal project.
…st stable versions
….56.4 Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
…ependency; enhance npm project discovery in update scripts
Automated by scripts/update-ax-catalog.ps1. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
- Implemented a PowerShell script to update @ax/* dependencies in the local apax catalog. - The script includes two phases: Phase 1 for updating and publishing the catalog, and Phase 2 for verifying the build. - Added parameters for controlling behavior such as -AfterPublish, -Prerelease, -CatalogVersion, -NoPublish, -DryRun, and -Detailed. - Introduced functions for dependency resolution, consumer synchronization, and report generation. - Ensured safe handling of git operations to maintain a clean working directory during updates.
…up of unused workflows
…dev) Port the SIMATIC-AX developer workflow from src/scripts/*.sh (+2 .ps1) and scripts/check_requisites.ps1 / copy-ctrl-folders.ps1 into a TDD-tested C# library reused by a packed dotnet tool and the in-repo apax aliases. - AXOpen.Dev: all logic behind IProcessRunner (apax/dotnet/openssl wrappers, cert SHA1 compare, HwIdentifiers/IoAddresses generators verified byte-identical, asset discovery, scaffolding, validators, compare exit-code mapping, orchestrators, full faithful check_requisites + copy-ctrl-folders). - AXOpen.Dev.Tool: Spectre.Console.Cli verbs (descriptive name + apax alias), packs as dotnet tool 'axdev' via AxdevApp.Build(). - AXOpen.Dev.Tests: 168 xUnit tests (red-first pure logic + golden files). - AXOpen.Dev.E2E.Tests: optional env-gated PLC/data end-to-end tests. - src/scripts/dev.cs: file-based dispatcher (#:project the tool) sharing AxdevApp.Build; src/scripts/Directory.Packages.props disables CPM there. - src/showcase/app/apax.yml: all 24 script aliases rewired to 'dotnet run ../../scripts/dev.cs -- <verb>'; password via AX_TARGET_PWD env. Verified: apax hdl end-to-end against the PLC; full check_requisites report runs green on Windows. .sh files retained pending manual removal. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Add AXOpen.Dev.Tool to AXOpen-packable-only.proj so the existing CI PackNuGets + PushPackages flow builds and pushes the GitVersion-stamped 'axdev' dotnet tool to nuget.pkg.github.com/inxton. AXOpen.proj already globs the axopen.dev projects, so restore/build is covered (NoRestore pack is safe); the test projects are not matched by the packable globs, so only the tool is packed.
Repo-wide CentralPackageTransitivePinningEnabled meant bumping Spectre.Console.Cli to 0.50.0 (for the axdev tool) also forced Cake.Cli 4.0.0's transitive Spectre to 0.50.0, which dropped IConfigurator.AddExample(string[]) that Cake.Frosting calls -> cake aborted at startup with MissingMethodException. Pin both Spectre packages to 0.47.0 (the version Cake.Cli 4.0.0 declares); the axdev tool only uses APIs present in 0.47.0. Verified: cake runs the full task graph, 168 unit tests pass, the tool runs.
Test level 2 now builds the showcase app the way `apax alf` does, minus every step that needs PLC/PLCSIM access (plcsim, clean_plc, ssc, hardware/software download), then starts the Blazor server with a dummy connector and probes it over HTTPS. Gives a full offline UI smoke test on runners without hardware or a simulator. - Entry.cs: select connector via AXOPEN_USE_DUMMY_CONNECTOR env var; load the PLC certificate lazily so the dummy path needs no cert
| { | ||
| Output.Warning("check-requisites is a Windows developer-machine bootstrap; running the portable subset only."); | ||
| var portable = new RequisiteChecker(runner); | ||
| var ok = await portable.CheckApaxAsync(ct) & await portable.CheckNugetAsync(ct) & portable.CheckCustomRegistry(); |
| { | ||
| Output.Warning("check-requisites is a Windows developer-machine bootstrap; running the portable subset only."); | ||
| var portable = new RequisiteChecker(runner); | ||
| var ok = await portable.CheckApaxAsync(ct) & await portable.CheckNugetAsync(ct) & portable.CheckCustomRegistry(); |
| public override async Task<int> ExecuteAsync(CommandContext context) | ||
| { | ||
| var checker = new RequisiteChecker(new ProcessRunner()); | ||
| var ok = await checker.CheckApaxAsync() & await checker.CheckNugetAsync() & checker.CheckCustomRegistry(); |
| public override async Task<int> ExecuteAsync(CommandContext context) | ||
| { | ||
| var checker = new RequisiteChecker(new ProcessRunner()); | ||
| var ok = await checker.CheckApaxAsync() & await checker.CheckNugetAsync() & checker.CheckCustomRegistry(); |
Comment on lines
+59
to
+65
| foreach (var file in Directory.EnumerateFiles(assetsDir, "*", SearchOption.AllDirectories)) | ||
| { | ||
| if (nameMatches(Path.GetFileName(file))) | ||
| { | ||
| operations.Add(new CopyOperation(file, destinationFor(assetsDir, file))); | ||
| } | ||
| } |
Comment on lines
+53
to
+66
| foreach (var guard in new[] | ||
| { | ||
| securityConfig, | ||
| Path.Combine(certsDir, "containerWithPublicAndPrivateKeys_x509.p12"), | ||
| Path.Combine(certsDir, "reference_x509.crt"), | ||
| Path.Combine(certsDir, $"{plcName}.cer"), | ||
| }) | ||
| { | ||
| if (File.Exists(guard)) | ||
| { | ||
| Output.Warning($"File '{guard}' already exists. {alreadyConfigured}"); | ||
| return 1; | ||
| } | ||
| } |
Comment on lines
+67
to
+73
| foreach (var dir in directories) | ||
| { | ||
| if (Path.GetFileName(dir).Contains(templateName, StringComparison.Ordinal)) | ||
| { | ||
| RenameLeaf(dir, templateName, componentName); | ||
| } | ||
| } |
Comment on lines
+40
to
+46
| foreach (var octet in ip.Split('.')) | ||
| { | ||
| if (!int.TryParse(octet, out var n) || n < 0 || n > 255) | ||
| { | ||
| return false; | ||
| } | ||
| } |
Comment on lines
+75
to
+79
| foreach (var leftover in new[] { keyFile, certFile, configFile }) | ||
| { | ||
| var p = Path.Combine(certsDir, leftover); | ||
| if (File.Exists(p)) File.Delete(p); | ||
| } |
The broad `certs` HWC-secrets rule also matched the AXOpen.Dev/Certs source namespace, so CertService.cs never reached CI and the build failed with CS0234 (AXOpen.Dev.Certs not found). Add a scoped negation so the source folder is tracked while real cert stores stay ignored.
The `certs` HWC-secrets gitignore rule swallowed the source folder. Relocating to CertificateService/ avoids depending on a fragile gitignore negation. Namespace AXOpen.Dev.Certs is unchanged, so call sites compile as-is.
Add UserSecretsLoader that reads the twin project's user-secrets store into the process environment, so PLC verbs resolve AX_TARGET_PWD / AX_USERNAME without a prior `source load-secrets.sh`. Locates the <UserSecretsId> by probing ../axpansion/twin then . (override via AX_SECRETS_PROJECT), reads secrets.json from the OS user-secrets root, flattens nested keys as key:subkey. Route both the packed tool (Program.cs) and the in-repo dispatcher (dev.cs) through a shared AxdevApp.Run(args) that loads secrets before build+run. An already-set env var wins; missing project/store is a silent no-op. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
PasswordValidator rejected $ & ( ) *, but configure-secrets.sh requires a special char from the set !@#$%^&*()_+-=. A complexity-valid password was then rejected at use time by axdev alf / axdev all. Remove those five chars from the blocklist; keep only genuinely-dangerous shell metacharacters and whitespace. Safe because args reach apax/openssl via CliWrap, not a shell. Update error message and tests. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
AXSharp 0.47 codegen now emits [SourceFileAttribute] on generated classes; refresh the committed .g.cs test artifacts to match. Showcase HMI security config (cert/PKI) and tailwind css are regeneration side effects. Refs 00502ba
Comment on lines
+26
to
+32
| foreach (var c in password) | ||
| { | ||
| if (char.IsWhiteSpace(c) || Problematic.IndexOf(c) >= 0) | ||
| { | ||
| return false; | ||
| } | ||
| } |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
src/scriptsPLC-lifecycle shell workflow as theaxdevdeveloper CLI (src/axopen.dev) — a Spectre.Console.Cli app with apax-compatible verb aliases, plus anAXOpen.Dev.Toolpackable asdotnet axdev.AxdevApp.Run(args)surface consumed by both the packed tool and the in-repodotnet run src/scripts/dev.csdispatcher.axdevloads dotnet user-secrets at startup, so PLC verbs resolveAX_TARGET_PWD/AX_USERNAMEwithoutsource load-secrets.sh; password guard realigned to theconfigure-secretscomplexity policy.0.47bump; cake runs the showcase offline build + Blazor at test level 2.Changes from CHANGELOG
[FIX]
axdevpassword guard contradicted the secrets complexity policyAXOpen.Dev.Validation.PasswordValidatorno longer rejects$ & ( ) *. These are endorsed by the set-time complexity policy (configure-secrets.shrequires a special char from!@#$%^&*()_+-=), so a password that satisfied the complexity rule was then rejected at use time byaxdev alf/axdev allwith "The PASSWORD contains problematic characters." The blocklist now keeps only genuinely-dangerous shell metacharacters (` \ " ' | ; < > ? [ ] { }and whitespace) — safe because arguments reach apax/openssl via CliWrap (no shell). Error message andPasswordValidatorTestsupdated.Impact:
apax alf/apax allaccept the same passwords the secrets-setup flow accepts; no more spurious rejection of compliant passwords.Testing:
dotnet test src/axopen.dev/AXOpen.Dev.Tests— 180 passed.[BUILD]
axdevloads dotnet user-secrets at startupAXOpen.Dev.Secrets.UserSecretsLoaderreads dotnet user-secrets into the process environment so PLC verbs resolveAX_TARGET_PWD/AX_USERNAMEwithout a priorsource load-secrets.sh. It locates the twin project's<UserSecretsId>(probes../axpansion/twinthen., overridable via theAX_SECRETS_PROJECTenvironment variable), reads itssecrets.jsonfrom the OS user-secrets root, and flattens nested keys with the standardkey:subkeyconvention.AxdevApp.Run(args)callsUserSecretsLoader.Load()then builds and runs the command app. Both the packeddotnet axdevtool (AXOpen.Dev.Tool/Program.cs) and the in-repo dispatcher (src/scripts/dev.cs) now callAxdevApp.Runinstead ofAxdevApp.Build().Run.AXOpen.Dev.Tests/Secrets/UserSecretsLoaderTests.cscovers apply-from-store, existing-env-wins precedence, missing project / missing store / malformed JSON / no-UserSecretsIdno-ops, theAX_SECRETS_PROJECToverride, and nested-key flattening.Impact:
dotnet user-secrets) is preserved while removing the bashsource load-secrets.shstep, so apax verbs can callaxdevdirectly on any platform.-p/--passwordstill overrides everything inPlcCommandSettings.ResolvePassword.Risks/Review:
AX_TARGET_PWDenvironment variable overrides the user-secrets store — a stale persistent env var can shadow the intended secret during provisioning (documented footgun).Testing:
dotnet test src/axopen.dev/AXOpen.Dev.Tests— full suite green (180 passed), including the newUserSecretsLoaderTests.[BUILD] Dependency-maintenance tooling + AXSharp
0.47bumpscripts/update-latest-deps.ps1— bumps all non-AXSharp dependencies (NuGet + npm) to their latest stable versions, sharing common helpers viascripts/_deps-common.ps1.scripts/update-vulnerable-deps.ps1— scans npm and NuGet dependencies for known vulnerabilities and emits a report.scripts/update-ax-catalog.ps1— manages@ax/*catalog dependencies.0.47.0-alpha.489inDirectory.Packages.props, transitive dependencies reconciled,.config/dotnet-tools.jsonupdated to match; generated artifacts regenerated for AXSharp 0.47.package.json/package-lock.jsonfiles across several components to clean up the tree;developGitVersion mode →ContinuousDeployment; styling deps refreshed (momentum.cssregenerated).Impact: Routine dependency bumps and vulnerability scanning are now scriptable and reproducible; AXSharp consumers build against
0.47.Risks/Review: Dependency bumps can introduce behavioural drift — verify a full
dotnet buildand the styling render after pulling.Commits
feat
fix
refactor
build
docs
chore
Other
Diff stat
Test plan
dotnet buildof the AXOpen solution succeedsdotnet testacross theAXOpen.Dev.*test projects is green (180 tests)dotnet axdev --help(packed tool) anddotnet run src/scripts/dev.cs -- --help(in-repo) list the full verb setAX_TARGET_PWD/AX_USERNAMEwithoutsource load-secrets.sh; an existing env var still winsapax buildfromsrc/showcase/appruns the migratedapax.ymlverbs viadev.csapax buildfromsrc/ax.axopen.*/ctrlsucceeds against the bumped AXSharp 0.47 package setGenerated by
/pr-description-update. Last regenerated: 2026-05-31.