Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
30 changes: 30 additions & 0 deletions .github/workflows/example-regen.yml
Original file line number Diff line number Diff line change
Expand Up @@ -1605,6 +1605,36 @@ jobs:
fi
echo "==> add-component csharp: seeds, builds, and serves on the pinned generator."

- name: The C# starter contract holds on real generator output
if: steps.token.outputs.have == 'true'
# ci.yml proves the starter contract on a synthetic tree. This runs it
# where it will actually be used: the component the previous step
# seeded and regenerated with the pinned jar. A pin whose output breaks
# a marker, layering or wiring rule fails here, not in an adopter's
# first regen PR. Skips are expected for rules whose surface hello-orders
# does not generate (handler and application-service bases); a miss is
# a rule that cannot fail on real output.
run: |
set -euo pipefail
python3 -m pip install --quiet 'specfuse-loop>=0.30'
cd "$RUNNER_TEMP/component-cs/Backend"
KIT="$GITHUB_WORKSPACE/templates/component-contract/csharp"
cp "$KIT/gen-contract.yml" .
mkdir -p scripts docs gen-patches
cp "$KIT/scripts/"* scripts/
cp "$KIT/docs/generated-code-expectations.md" docs/
cp "$KIT/gen-patches/README.md" gen-patches/
sed -i 's/__Prefix__/HelloOrders/g' gen-contract.yml docs/generated-code-expectations.md
chmod +x scripts/*.sh
git -c [email protected] -c user.name=ci add -A
git -c [email protected] -c user.name=ci commit -q -m "seed and regen"
./scripts/check-gen-contract.sh
./scripts/apply-gen-patches.sh --check
out="$(./scripts/test-gen-contract.sh)" || { printf '%s\n' "$out"; exit 1; }
printf '%s\n' "$out"
grep -q ' 0 missed' <<<"$out" || { echo "::error::a starter rule did not bite on real generator output"; exit 1; }
echo "==> the C# starter contract is green on the pinned generator's output, and its rules bite there."

- name: A seeded Python component installs, imports and passes its tests (add-component drift guard, #177)
if: steps.token.outputs.have == 'true'
# The project is renamed PascalCase in this copy only: the generator
Expand Down
1 change: 1 addition & 0 deletions scripts/test-csharp-contract-template.sh
Original file line number Diff line number Diff line change
Expand Up @@ -67,6 +67,7 @@ EOF
cat > .gitignore <<'EOF'
bin/
obj/
# *.generated-paths.json is deliberately NOT ignored (the seed's own comment).
EOF

header() {
Expand Down
3 changes: 2 additions & 1 deletion templates/component-contract/csharp/gen-contract.yml
Original file line number Diff line number Diff line change
Expand Up @@ -267,7 +267,8 @@ rules:
the repo and a layout move reads as an unexplained delete plus add.
check: forbid_pattern
scope: gitignore
pattern: 'generated-paths'
# A comment saying the omission is deliberate is fine; an ignore line is not.
pattern: '^[^#]*generated-paths'
allow_empty: true

# ── Hand-written code holds up its end ─────────────────────────────────
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -146,7 +146,14 @@ if [ -n "$APPSVC_BASE" ]; then
else
echo " SKIP GEN-041 — no *ApplicationServiceBase.g.cs in the tree yet"; skip=$((skip+1))
fi
expect_fail_newfile GEN-042 "${SRC_CS%/*}/DirectHandler.cs" "public sealed class DirectHandler : IOrderPlacedHandler { }"
if [ -n "$HANDLER_BASE" ]; then
# The interface beside the base: OrderPlacedHandlerBase.g.cs declares IOrderPlacedHandler.
HANDLER_IFACE="I$(basename "$HANDLER_BASE" .g.cs)"
HANDLER_IFACE="${HANDLER_IFACE%Base}"
expect_fail_newfile GEN-042 "${SRC_CS%/*}/DirectHandler.cs" "public sealed class DirectHandler : $HANDLER_IFACE { }"
else
echo " SKIP GEN-042 — no generated handler interface in the tree yet"; skip=$((skip+1))
fi

echo
echo " $pass ok, $fail missed, $skip skipped"
Expand Down
Loading