Skip to content

rewrite scripts to csharp#1163

Open
PTKu wants to merge 23 commits into
devfrom
rewrite-scripts-to-csharp
Open

rewrite scripts to csharp#1163
PTKu wants to merge 23 commits into
devfrom
rewrite-scripts-to-csharp

Conversation

@PTKu
Copy link
Copy Markdown
Contributor

@PTKu PTKu commented May 31, 2026

Summary

  • C# port of the src/scripts PLC-lifecycle shell workflow as the axdev developer CLI (src/axopen.dev) — a Spectre.Console.Cli app with apax-compatible verb aliases, plus an AXOpen.Dev.Tool packable as dotnet axdev.
  • One shared AxdevApp.Run(args) surface consumed by both the packed tool and the in-repo dotnet run src/scripts/dev.cs dispatcher.
  • axdev loads dotnet user-secrets at startup, so PLC verbs resolve AX_TARGET_PWD / AX_USERNAME without source load-secrets.sh; password guard realigned to the configure-secrets complexity policy.
  • Dependency-maintenance tooling (latest-deps, vulnerable-deps, ax-catalog) + AXSharp 0.47 bump; cake runs the showcase offline build + Blazor at test level 2.

Changes from CHANGELOG

[FIX] axdev password guard contradicted the secrets complexity policy

  • fix: AXOpen.Dev.Validation.PasswordValidator no longer rejects $ & ( ) *. These are endorsed by the set-time complexity policy (configure-secrets.sh requires a special char from !@#$%^&*()_+-=), so a password that satisfied the complexity rule was then rejected at use time by axdev alf / axdev all with "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 and PasswordValidatorTests updated.

Impact: apax alf / apax all accept 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] axdev loads dotnet user-secrets at startup

  • feat: AXOpen.Dev.Secrets.UserSecretsLoader reads dotnet user-secrets into the process environment so PLC verbs resolve AX_TARGET_PWD / AX_USERNAME without a prior source load-secrets.sh. It locates the twin project's <UserSecretsId> (probes ../axpansion/twin then ., overridable via the AX_SECRETS_PROJECT environment variable), reads its secrets.json from the OS user-secrets root, and flattens nested keys with the standard key:subkey convention.
  • feat: New shared entry point AxdevApp.Run(args) calls UserSecretsLoader.Load() then builds and runs the command app. Both the packed dotnet axdev tool (AXOpen.Dev.Tool/Program.cs) and the in-repo dispatcher (src/scripts/dev.cs) now call AxdevApp.Run instead of AxdevApp.Build().Run.
  • test: AXOpen.Dev.Tests/Secrets/UserSecretsLoaderTests.cs covers apply-from-store, existing-env-wins precedence, missing project / missing store / malformed JSON / no-UserSecretsId no-ops, the AX_SECRETS_PROJECT override, and nested-key flattening.

Impact:

  • The template's credential UX (per-project dotnet user-secrets) is preserved while removing the bash source load-secrets.sh step, so apax verbs can call axdev directly on any platform.
  • Precedence is non-surprising: an already-set environment variable (or apax variable) always wins over the secrets store; an explicit -p/--password still overrides everything in PlcCommandSettings.ResolvePassword.

Risks/Review:

  • Secret loading is best-effort: a missing twin project, missing store, or unreadable JSON is a silent no-op, and the per-command argument guards still report any genuinely missing credential.
  • An already-set AX_TARGET_PWD environment 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 new UserSecretsLoaderTests.

[BUILD] Dependency-maintenance tooling + AXSharp 0.47 bump

  • feat: scripts/update-latest-deps.ps1 — bumps all non-AXSharp dependencies (NuGet + npm) to their latest stable versions, sharing common helpers via scripts/_deps-common.ps1.
  • feat: scripts/update-vulnerable-deps.ps1 — scans npm and NuGet dependencies for known vulnerabilities and emits a report.
  • feat: scripts/update-ax-catalog.ps1 — manages @ax/* catalog dependencies.
  • chore: AXSharp packages bumped to 0.47.0-alpha.489 in Directory.Packages.props, transitive dependencies reconciled, .config/dotnet-tools.json updated to match; generated artifacts regenerated for AXSharp 0.47.
  • chore: Removed obsolete package.json / package-lock.json files across several components to clean up the tree; develop GitVersion mode → ContinuousDeployment; styling deps refreshed (momentum.css regenerated).

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 build and the styling render after pulling.

Commits

feat

  • 3fe533f feat(scripts): port src/scripts shell workflow to C# (AXOpen.Dev + axdev)
  • b73e009 feat(axopen.dev): load dotnet user-secrets at axdev startup
  • 7381d0d feat(cake): run showcase offline build + Blazor at test level 2
  • 2d820d1 feat: enhance testing capabilities with level 4 integration and cleanup of unused workflows
  • a889c87 feat: add update-ax-catalog.ps1 script for managing @ax/* dependencies
  • 1c93135 feat(deps): update NuGet.Packaging to 6.14.3 and add NuGet.Protocol; enhance npm project discovery
  • 334cd26 feat(deps): add script to update all non-AXSharp dependencies to latest stable versions
  • 029813e feat: add vulnerability scanning and reporting for npm and NuGet dependencies

fix

  • dde024f fix(axopen.dev): align password guard with secrets complexity policy
  • fd0154f fix(axopen.dev): track Certs source folder ignored by gitignore
  • cd2ad89 fix(deps): pin Spectre.Console* to 0.47.0 to keep Cake build working

refactor

  • 6435640 refactor(axopen.dev): move CertService out of ignored Certs dir

build

  • 3adec44 build(cake): pack + publish the axdev tool to the inxton feed

docs

  • 59fc0c1 docs(changelog): add deps-update entry; bump next-version 0.56.3 -> 0.56.4

chore

  • 774505a chore: regenerate artifacts for AXSharp 0.47
  • 00502ba chore(deps): bump AXSharp to 0.47.0-alpha.489
  • 7dc678a chore(catalog): update @ax deps + bump ax.catalog
  • fd90b84 chore: change develop branch mode to ContinuousDeployment in GitVersion.yml
  • f0bd4da chore: add skill for updating AXSharp and Inxton.Operon package versions
  • 32e04d4 chore: remove package-lock.json from AXOpen.Data.Blazor
  • 0929211 chore: update AXSharp package versions to 0.47.0-alpha.484 and reconcile transitive deps

Other

  • caf3e4b Remove unused package.json and apax.yml files to clean up the project structure
  • ae16242 Refactor code structure for improved readability and maintainability

Diff stat

 .claude/skills/update-axsharp-version/SKILL.md     |  167 +++
 .config/dotnet-tools.json                          |    6 +-
 .github/workflows/nightly.yml                      |    2 +-
 .github/workflows/single_app_run.yml               |  127 ---
 .gitignore                                         |    3 +
 CHANGELOG.md                                       |   52 +
 Directory.Packages.props                           |   37 +-
 GitVersion.yml                                     |    4 +-
 cake/AppsRunTaskHelpers.cs                         |  378 +++----
 cake/BuildParameters.cs                            |    8 +-
 cake/DotNetCmd.cs                                  |  128 +++
 cake/Program.cs                                    |  141 +--
 cake/Properties/launchSettings.json                |  122 +-
 scripts/_deps-common.ps1                           |  153 +++
 scripts/test_L4.ps1                                |    4 +
 scripts/update-ax-catalog.ps1                      |  731 ++++++++++++
 scripts/update-latest-deps.ps1                     |  692 ++++++++++++
 scripts/update-vulnerable-deps-npm-app.ps1         |  140 ---
 scripts/update-vulnerable-deps.ps1                 |  593 ++++++++++
 scripts/update_axsharp_versions.ps1                |  170 ++-
 src/AXOpen-packable-only.proj                      |    8 +-
 src/ax.catalog/apax.yml                            |   36 +-
 src/axopen.dev/**  (new AXOpen.Dev + Tool + Tests + E2E.Tests projects)
 src/scripts/dev.cs                                 |    9 +
 src/showcase/app/apax.yml                          |   66 +-
 src/showcase/app/ix/Entry.cs                       |   18 +-
 … and 135 more files
 161 files changed, 9216 insertions(+), 5737 deletions(-)

Test plan

  • dotnet build of the AXOpen solution succeeds
  • dotnet test across the AXOpen.Dev.* test projects is green (180 tests)
  • dotnet axdev --help (packed tool) and dotnet run src/scripts/dev.cs -- --help (in-repo) list the full verb set
  • Secrets path: a populated dotnet user-secrets store resolves AX_TARGET_PWD / AX_USERNAME without source load-secrets.sh; an existing env var still wins
  • Showcase apax build from src/showcase/app runs the migrated apax.yml verbs via dev.cs
  • cake showcase offline build + Blazor passes at test level 2
  • apax build from src/ax.axopen.*/ctrl succeeds against the bumped AXSharp 0.47 package set
  • CHANGELOG entry covers all branch commits and flags the feed-publish prerequisite for the packed tool

Generated by /pr-description-update. Last regenerated: 2026-05-31.

PTKu and others added 17 commits May 29, 2026 14:52
…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.
….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.
…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 thread src/axopen.dev/AXOpen.Dev/Validation/PasswordValidator.cs Fixed
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);
}
PTKu and others added 6 commits May 31, 2026 08:36
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;
}
}
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