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
3 changes: 2 additions & 1 deletion CONTRIBUTING.md
Original file line number Diff line number Diff line change
Expand Up @@ -83,7 +83,8 @@ a PR, so nothing red leaves your machine:
```bash
scripts/ci-local.sh # full parity: hygiene.yml's leak-scan, all-port
# conformance, the java reactor, the drift/mutation
# gates, + integration-tests.yml's docker suite
# gates, the showcase current in all five ports, +
# integration-tests.yml's docker suite
scripts/ci-local.sh --quick # hygiene.yml in full + the TypeScript half of
# conformance.yml; skips the C#/Java/Kotlin/Python
# ports, the java reactor and the docker suite
Expand Down
6 changes: 3 additions & 3 deletions examples/showcase/.metaobjects/.gen-state/.hashes.json
Original file line number Diff line number Diff line change
@@ -1,16 +1,16 @@
{
"generated/csharp/AppDbContext.g.cs": "314c6078030ba151687430b37e6b6ea936238bb5df02df238e4acce2f95a430d",
"generated/csharp/Subscriber.g.cs": "3ca160941378fbb8b6ad6acf080ff85573f463931e21b8756873a4476e5dd163",
"generated/csharp/SubscriberBlurbPayload.g.cs": "6b1ce5b5a4018c647586d86125718c4764ae5d6eeb94e9545e8006a7ec2b2b6f",
"generated/csharp/SubscriberBlurbPayload.g.cs": "30ae31959c0cd98ba4ab12b2e827fa48f3bf59a05aa34974ebc4a1fe930378be",
"generated/csharp/SubscriberFilterAllowlist.g.cs": "7428d47f6ccb64bb315266ee0564fa3803736623a34ab491435c042848c5d472",
"generated/csharp/SubscriberNames.g.cs": "91f6eba78657b31fceef7021c6ca6bd799524dcb5120acbc8fcbe18786787174",
"generated/csharp/SubscriberRoutes.g.cs": "a14815f7870e309102d57a0227555191b3f32a4012e04fb213ef17abe12ab3f4",
"generated/csharp/SubscriberRoutes.g.cs": "e98387adf0d9fd5c2743409e5820d72400373ca6a758176cba76112fa1efc02a",
"generated/python/Subscriber.py": "9dd4c0acea47f99d1daf79930f9de2e400f30780ebce6c63f023be528a72b762",
"generated/python/SubscriberBlurbPayload.py": "a5ef8a08e63efbe0f73e39a21a368cff5150c68cc8beeea6e8aab0c755f8bbdd",
"generated/python/__init__.py": "daa04cec586768866d0996c779f62073e6773fe63750ff668327991fac2fd0f5",
"generated/python/subscriber_filter_allowlist.py": "b0414cc95ff3982c80a0e1a06839f090c0b423e41f5a94275df93426cea09df5",
"generated/python/subscriber_names.py": "269637a02bf9b46f55658b58cb42f83196c03a877e1e2101337847fd406c1561",
"generated/python/subscriber_router.py": "734f9c91aa1ea475ac8014e9f5db47fe54c8f5e35a25d1ae64c1dc3276ad2546",
"generated/python/subscriber_router.py": "9c2393da6c055bd7a76b81cbc1492fccc44bae257cab5755830ab58f59f522c7",
"generated/ts/Subscriber.queries.ts": "9f1a459c57fafc98bf074b4443b506d4a1e7023ed188f293021ae89c298d4562",
"generated/ts/Subscriber.routes.ts": "147d32ae658f985e024c3de6e8894ca7359f767eeaa765cec70756802e3bd300",
"generated/ts/Subscriber.ts": "a78c17f915222ee108290c28468313d77f77b5cff438f485324409302e389a96",
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@ public class SubscriberBlurbPayload
{
public enum SubscriberBlurbPayloadStatus { active, paused, cancelled }
[JsonPropertyName("name")]
[JsonIgnore(Condition = JsonIgnoreCondition.WhenWritingNull)]
public string? Name { get; set; }
[JsonPropertyName("status")]
public SubscriberBlurbPayloadStatus Status { get; set; }
Expand Down
Original file line number Diff line number Diff line change
@@ -1,8 +1,10 @@
package acme;

import jakarta.validation.constraints.*;
import com.fasterxml.jackson.annotation.JsonInclude;

/** GENERATED — value object SubscriberBlurbPayload. Do not hand-edit; regenerated from metadata. */
@JsonInclude(JsonInclude.Include.NON_NULL)
public record SubscriberBlurbPayload(
String name,
@NotNull Status status
Expand Down
Original file line number Diff line number Diff line change
@@ -1,12 +1,14 @@
package acme

import com.fasterxml.jackson.`annotation`.JsonInclude
import jakarta.validation.constraints.NotNull
import kotlin.String
import kotlin.jvm.JvmStatic

/**
* GENERATED — do not hand-edit. Regenerated from metadata.
*/
@JsonInclude(JsonInclude.Include.NON_NULL)
public data class SubscriberBlurbPayload(
public val name: String? = null,
@field:NotNull
Expand Down
11 changes: 9 additions & 2 deletions examples/showcase/generated/python/subscriber_router.py
Original file line number Diff line number Diff line change
Expand Up @@ -75,6 +75,9 @@ class _SortClause(BaseModel):
_DECIMAL_LIMITS: dict[str, tuple[int, int]] = {}


_NESTED_DECIMALS: dict[str, Any] = {}


async def _json_body(request: Request) -> dict[str, Any] | None:
"""GENERATED — the request body as a JSON object (non-integer numbers are exact `Decimal`s), or None."""
try:
Expand Down Expand Up @@ -182,7 +185,9 @@ def create_subscriber(
): # the body was not a JSON object: the cross-port 400, not FastAPI's 422
return JSONResponse(status_code=400, content={"error": "validation"})
try:
dto = coerce_decimal_fields(dto, _DECIMAL_FIELDS, _DECIMAL_LIMITS)
dto = coerce_decimal_fields(
dto, _DECIMAL_FIELDS, _DECIMAL_LIMITS, _NESTED_DECIMALS
)
except ValueError:
return JSONResponse(status_code=400, content={"error": "validation"})
# FR-036: run the generated field constraints (length / pattern /
Expand Down Expand Up @@ -215,7 +220,9 @@ def update_subscriber(
): # the body was not a JSON object: the cross-port 400, not FastAPI's 422
return JSONResponse(status_code=400, content={"error": "validation"})
try:
dto = coerce_decimal_fields(dto, _DECIMAL_FIELDS, _DECIMAL_LIMITS)
dto = coerce_decimal_fields(
dto, _DECIMAL_FIELDS, _DECIMAL_LIMITS, _NESTED_DECIMALS
)
except ValueError:
return JSONResponse(status_code=400, content={"error": "validation"})
# FR-035 PATCH-2: an explicit null on a @required field is a 400 —
Expand Down
28 changes: 26 additions & 2 deletions scripts/ci-local.sh
Original file line number Diff line number Diff line change
Expand Up @@ -399,10 +399,22 @@ gate_no_api_prefix() { bun scripts/check-no-api-prefix.ts; }
#
# Deliberately does NOT run the other four ports: that shells out to mvn/dotnet/uv,
# and this lane is `step_if bun` — guarded on bun alone and included in `--quick`, the
# documented pre-PR command. The release preflight runs `--check --all-ports`, which
# refuses to leave a port out.
# documented pre-PR command. The other four ports are checked by `gate_showcase_all_ports`
# in the heavy tier of the flagless run, and again by the release preflight
# (`--check --all-ports`); both refuse to leave a port out.
gate_site_payload() { bun_install && bun test scripts/site && bun scripts/build-site-payload.ts --check; }

# ── the showcase is current in EVERY port, not just ts+sql ────────────────────
# `gate_site_payload` can only afford `--bun-only`, so a change to the python, csharp,
# java or kotlin emitter left the committed showcase stale while the full run stayed
# green, and the first thing to notice was the release preflight (`--check --all-ports`)
# refusing the release cut (#447/#448 value-object null omission). No single CI lane has
# mvn, dotnet and uv together, so this runs in the flagless full run only, which is the
# one place all three coexist; it is absent from `--quick` (bun-only by design) and from
# every `--only` lane. It needs the workspace built (`gate_ts_build_typecheck` earlier in
# the same run) for the reason given above `gate_site_payload`.
gate_showcase_all_ports() { bun_install && bun scripts/regen-showcase.ts --check --all-ports; }

# ── the published metamodel reference tracks the registry ─────────────────────
# site-reference/ is rendered HTML the site COPIES at deploy — the deploy has no install
# step for this repo, so the rendering happens here and the release tag carries the pages.
Expand Down Expand Up @@ -924,6 +936,18 @@ else
if want python; then step_if uv "conformance: python" gate_conf_python; fi
if want_any java java-fast; then step_if mvn "conformance: kotlin" gate_conf_kotlin; fi
if want_any java java-slow; then step_if mvn "java-reactor (install)" gate_java_reactor; fi
# Needs all three toolchains at once, which no single --only lane has: flagless run only.
if [ -z "$ONLY" ] && [ "$INTEG_ONLY" -eq 0 ]; then
if have mvn && have dotnet && have uv; then
step "showcase current in all ports" gate_showcase_all_ports
elif [ "$STRICT" -eq 1 ]; then
echo ""; echo " ✖ showcase current in all ports — needs mvn, dotnet and uv (strict-toolchains)" >&2
FAIL+=("showcase current in all ports (missing toolchain, strict)")
else
echo ""; echo "── ⊘ showcase current in all ports — SKIPPED (needs mvn, dotnet and uv) ──" >&2
SKIP+=("showcase current in all ports (needs mvn+dotnet+uv)")
fi
fi
# Docker integration — full suite when no --only, per-port otherwise.
# --no-integration drops this whole half; --integration-only keeps ONLY it, which is
# why it asks in_lane / in_lane_any (selection) where the checks above ask want.
Expand Down
Loading