Skip to content

Commit 51f8d89

Browse files
committed
Add maintained peer lab command script rendering
1 parent 9626ba9 commit 51f8d89

5 files changed

Lines changed: 111 additions & 2 deletions

File tree

README.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -208,7 +208,7 @@ The roadmap is intentionally conservative:
208208
4. Harden TCAP with external interoperability vectors and MAP profile validation.
209209

210210
Phase 27 completed the maintained external peer lab foundation, including package-neutral binding, host prerequisites, validated lab configuration, deterministic artifact planning, command planning, traffic vectors, manual self-hosted CI policy, digest-covered retained evidence gates, and status reporting.
211-
Phase 28 builds the automation and evidence handoff layer above that foundation, starting with a single run manifest, deterministic environment file rendering, and digest manifests for retained lab artifacts.
211+
Phase 28 builds the automation and evidence handoff layer above that foundation, starting with a single run manifest, deterministic environment file rendering, command script rendering, and digest manifests for retained lab artifacts.
212212
5. Harden MAP SMS with external interoperability vectors and operator-profile validation.
213213
6. Use completed interoperability tooling to run external lab validation, native SCTP verification, and release automation hardening.
214214
7. Complete commercial readiness gates and publish governed release candidates.

docs/PHASE28_MAINTAINED_PEER_LAB_AUTOMATION.md

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -37,6 +37,17 @@ This gives real lab scripts a stable input file while keeping package-specific v
3737

3838
The manifest does not generate digests itself. Real lab automation must calculate the digests from retained files and pass them into this contract.
3939

40+
## Unit 4 - Command Script Renderer
41+
42+
`SigtranMaintainedPeerLabCommandScripts` now renders the ordered command plan as a shell script with:
43+
44+
- `#!/usr/bin/env bash`
45+
- `set -euo pipefail`
46+
- A sourced environment file.
47+
- The ordered prepare, capture, peer, SDK, compare, and collect commands.
48+
49+
The renderer gives operators a deterministic script body while still allowing local lab automation to map package-neutral runner commands to site-specific scripts.
50+
4051
## Validation
4152

4253
Each unit in this phase is validated with:

docs/SDK_ROADMAP.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -251,7 +251,7 @@ Status: Phase 27 is foundation-complete. It has canonical `Sigtran.NET` naming,
251251
- Render environment files, command scripts, workflow templates, comparison reports, and evidence handoff bundles.
252252
- Keep automation package-neutral and separate planned contracts from retained commercial evidence.
253253

254-
Status: Phase 28 has a run manifest that aggregates binding, configuration, artifact, command, traffic vector, and CI contracts, deterministic environment file rendering for lab scripts, and artifact digest manifests for evidence handoff.
254+
Status: Phase 28 has a run manifest that aggregates binding, configuration, artifact, command, traffic vector, and CI contracts, deterministic environment file rendering, command script rendering, and artifact digest manifests for evidence handoff.
255255

256256
## Recommended First Deliverable
257257

src/Sigtran.NET.Tests/Program.cs

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -48,6 +48,7 @@
4848
Run("SIGTRAN maintained peer lab run manifest aggregates executable contracts", SigtranMaintainedPeerLabRunManifestAggregatesExecutableContracts);
4949
Run("SIGTRAN maintained peer lab environment file renders manifest values", SigtranMaintainedPeerLabEnvironmentFileRendersManifestValues);
5050
Run("SIGTRAN maintained peer lab artifact digest manifest gates handoff", SigtranMaintainedPeerLabArtifactDigestManifestGatesHandoff);
51+
Run("SIGTRAN maintained peer lab command script renders command plan", SigtranMaintainedPeerLabCommandScriptRendersCommandPlan);
5152
Run("SIGTRAN trace comparison reports ordered mismatches", SigtranTraceComparisonReportsOrderedMismatches);
5253
Run("SIGTRAN interoperability evidence promotion requires passing lab run", SigtranInteropEvidencePromotionRequiresPassingLabRun);
5354
Run("SIGTRAN interoperability lab CI profile is opt-in", SigtranInteropLabCiProfileIsOptIn);
@@ -965,6 +966,20 @@ static void SigtranMaintainedPeerLabArtifactDigestManifestGatesHandoff()
965966
Assert(!invalid.HasValidDigests, invalid.Describe());
966967
}
967968

969+
static void SigtranMaintainedPeerLabCommandScriptRendersCommandPlan()
970+
{
971+
SigtranMaintainedPeerLabRunManifest runManifest = SigtranMaintainedPeerLabRunManifests.CreateDefault("phase28-unit4");
972+
SigtranMaintainedPeerLabCommandScript script = SigtranMaintainedPeerLabCommandScripts.CreateDefault(runManifest);
973+
string rendered = script.Render();
974+
975+
Assert(rendered.StartsWith("#!/usr/bin/env bash", StringComparison.Ordinal), rendered);
976+
Assert(rendered.Contains("set -euo pipefail", StringComparison.Ordinal), rendered);
977+
Assert(rendered.Contains("source 'artifacts/external-peer/maintained/config/phase28-unit4-peer.env'", StringComparison.Ordinal), rendered);
978+
Assert(rendered.Contains("tcpdump -i lo", StringComparison.Ordinal), rendered);
979+
Assert(rendered.Contains("sigtran-trace-compare", StringComparison.Ordinal), rendered);
980+
Assert(script.CoversCommandPlan, script.Describe());
981+
}
982+
968983
static void SigtranTraceComparisonReportsOrderedMismatches()
969984
{
970985
SigtranInteropLabTemplate template = SigtranInteropPeerProfiles.CreateExternalPeerM3uaAspToSgTemplate();
Lines changed: 83 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,83 @@
1+
using System.Text;
2+
3+
namespace Sigtran.NET.Core.Utilities;
4+
5+
/// <summary>
6+
/// Describes a rendered maintained external peer lab command script.
7+
/// </summary>
8+
public sealed class SigtranMaintainedPeerLabCommandScript
9+
{
10+
/// <summary>Creates a maintained external peer lab command script.</summary>
11+
/// <param name="runManifest">The run manifest.</param>
12+
/// <param name="environmentFilePath">The environment file path sourced by the script.</param>
13+
public SigtranMaintainedPeerLabCommandScript(
14+
SigtranMaintainedPeerLabRunManifest runManifest,
15+
string environmentFilePath)
16+
{
17+
ArgumentNullException.ThrowIfNull(runManifest);
18+
RunManifest = runManifest;
19+
EnvironmentFilePath = string.IsNullOrWhiteSpace(environmentFilePath)
20+
? throw new ArgumentException("Environment file path is required.", nameof(environmentFilePath))
21+
: environmentFilePath;
22+
}
23+
24+
/// <summary>The run manifest.</summary>
25+
public SigtranMaintainedPeerLabRunManifest RunManifest { get; }
26+
27+
/// <summary>The environment file path sourced by the script.</summary>
28+
public string EnvironmentFilePath { get; }
29+
30+
/// <summary>Renders the command script content.</summary>
31+
/// <returns>The command script content.</returns>
32+
public string Render()
33+
{
34+
StringBuilder builder = new();
35+
builder.AppendLine("#!/usr/bin/env bash");
36+
builder.AppendLine("set -euo pipefail");
37+
builder.AppendLine();
38+
builder.Append("source ");
39+
builder.AppendLine(Quote(EnvironmentFilePath));
40+
builder.AppendLine();
41+
42+
foreach (SigtranMaintainedPeerLabCommand command in RunManifest.CommandPlan.Commands)
43+
{
44+
builder.Append("# ");
45+
builder.AppendLine(command.Describe());
46+
builder.AppendLine(command.CommandLine);
47+
builder.AppendLine();
48+
}
49+
50+
return builder.ToString();
51+
}
52+
53+
/// <summary>Whether the rendered script covers every command in the manifest.</summary>
54+
public bool CoversCommandPlan => RunManifest.CommandPlan.Commands.All(command => Render().Contains(command.CommandLine, StringComparison.Ordinal));
55+
56+
/// <summary>Formats a compact command script summary.</summary>
57+
/// <returns>The command script summary.</returns>
58+
public string Describe()
59+
{
60+
return $"run={RunManifest.RunId} env={EnvironmentFilePath} commands={RunManifest.CommandPlan.Commands.Count} rendered={Render().Length}";
61+
}
62+
63+
private static string Quote(string value)
64+
{
65+
return "'" + value.Replace("'", "'\"'\"'", StringComparison.Ordinal) + "'";
66+
}
67+
}
68+
69+
/// <summary>
70+
/// Provides maintained external peer lab command script helpers.
71+
/// </summary>
72+
public static class SigtranMaintainedPeerLabCommandScripts
73+
{
74+
/// <summary>Creates the default command script for a maintained peer lab run.</summary>
75+
/// <param name="runManifest">The run manifest.</param>
76+
/// <returns>The rendered command script model.</returns>
77+
public static SigtranMaintainedPeerLabCommandScript CreateDefault(SigtranMaintainedPeerLabRunManifest runManifest)
78+
{
79+
ArgumentNullException.ThrowIfNull(runManifest);
80+
string environmentFilePath = $"{runManifest.ArtifactPlan.ArtifactRoot}/config/{runManifest.RunId}-peer.env";
81+
return new(runManifest, environmentFilePath);
82+
}
83+
}

0 commit comments

Comments
 (0)