Skip to content

feat(lint): use the schema from meta.upsun.com for Flex and Fixed config - #248

Merged
pjcdawkins merged 4 commits into
mainfrom
claude/canonical-schema-pr-220-8a133e
Oct 16, 2026
Merged

pjcdawkins merged 4 commits into
mainfrom
claude/canonical-schema-pr-220-8a133e

Conversation

@pjcdawkins

@pjcdawkins pjcdawkins commented Oct 16, 2026 •

Copy link
Copy Markdown
Contributor

Since upsun/meta#220, the schema served at https://meta.upsun.com/schema/upsun matches the CLI's copy, so the CLI now takes it from there. Schema changes are made in upsun/meta first.

Flex

  • make update-schema fetches the schema and indents it (internal/lint/schema/gen.go, like the registry's gen.go). make check-schema runs in the non-blocking CI job beside check-registry, renamed lint-upstream.
  • The schema's remote $refs (runtime-versions, service-versions) are replaced with empty schemas when loading, so lint does not fetch them over the network. Types are already checked against the registry by CheckTypes, with clearer messages. A test fails if the schema gains another remote $ref.
  • The schema is otherwise used as is. A non-empty stack list is reported by its maxItems: 0 ("Array must have at most 0 items").

Fixed

The platform validates Fixed and Flex config with the same models, differing only in a few keys. Fixed config is now checked with the same schema, patched by internal/lint/schema/fixed-overlay.json (a JSON Merge Patch), in place of the three platformsh.*.json schemas maintained here, which had fallen behind (e.g. post_start, dynamic_compression, runtime extensions).

  • The overlay adds disk on applications, web, workers and services, an application size and name (required, as on the platform), and build.caches.
  • firewall is rejected in both styles, as it is deprecated in favor of egress.
  • type is now required for Fixed apps with a stack, as on the platform, and a stack list gets the schema's error. checkStackList and the stack-without-type warning are removed.
  • The schema tests (defaults, keywords beside $ref, dot-key patterns) also run on the patched schema.

🤖 Generated with Claude Code

…schema

The Flex config schema now comes from https://meta.upsun.com/schema/upsun
(the upsun/meta repository), which was synced with the CLI's copy in
upsun/meta#220. Schema changes are made there first.

- Add `make update-schema` (internal/lint/schema/gen.go), which fetches the
  schema and indents it, and `make check-schema`, run in the non-blocking
  upstream CI job beside `check-registry` (renamed `lint-upstream`).
- Replace the schema's remote $refs (runtime-versions, service-versions)
  with empty schemas when loading, so lint does not need the network.
  Types are checked against the registry by CheckTypes. A test fails if
  the schema gains another remote $ref.
- Report the schema's "maxItems: 0" error on a stack list with the same
  message as checkStackList.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>

@upsun-dispatch upsun-dispatch Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Warning

Changes suggested — 🟡 1 warning

🔍 Full review · 10 files reviewed

Verification
  • compile registers both remote $ref URLs as {} with AddSchema before Compile, and TestSchemaKeywords fails on any remote $ref not listed in remoteRefs.
  • The array_max_items rewrite in CheckSchemaAt cannot misfire elsewhere: maxItems appears only once in the Flex schema (on definitions.stack), and the Fixed schemas have none.
  • With the stubbed refs, the new type anyOf/allOf branches always pass, so type messages still come only from CheckTypes.
  • check-schema diffs only upsun-config-schema.json after gen.go rewrites it, and the !cancelled() condition lets it run even when check-registry fails.

New coverage: one TestLint_ContainerFeatures case (a task stack list plus a cron timeout error), and an extended TestSchemaKeywords remote-ref assertion, both run by make test-go in the CI test job. Schema freshness is checked by make check-schema in the non-blocking lint-upstream job. No test combines a stack list with a semantic (non-schema) error.

Review details
  • Commit: d59cd29
  • Model: claude-opus-5-5

Review 1 of 10 for this pull request · View the full run

Comment thread internal/lint/schema/upsun-config-schema.json
pjcdawkins and others added 2 commits October 16, 2026 17:18
…ill run

A schema error stops CheckContent before the semantic checks, so reporting
the schema's "maxItems: 0" stack error hid every other error until the
stack was fixed. The schema error is now skipped, and checkStackList
reports the stack list with the other errors, as before.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Use the upstream schema's "maxItems: 0" error for a non-empty stack list,
rather than skipping it for checkStackList, which now only reports stack
lists in Fixed config. As with any schema error, the semantic checks run
once it is fixed.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>

@upsun-dispatch upsun-dispatch Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Note

Reviewed — No blocking findings · 🔵 1 minor point

🔁 Incremental · 2 files reviewed

🔵 Minor point

  • internal/lint/linter_test.go:409 — With the array_max_items skip removed from CheckSchemaAt, a non-empty stack list is now reported differently depending on the config style. A Flex config (stack: ["php@8.4"] in .upsun/) gets the generic schema message applications.app.stack: Array must have at most 0 items, and CheckContent returns before runChecks. The same list in a Fixed .platform.app.yaml passes the Fixed schema, which has no maxItems, and reaches checkStackList in types.go. That prints 'stack' must be a mapping of 'runtimes' and 'packages', not a list (fixed_test.go:167). For Flex configs, checkStackList can no longer see a non-empty list, so its explanatory message is effectively Fixed-only.
Verification
  • The strings import in yaml.go is still used after isStackField is removed (TrimPrefix, HasPrefix, Contains).
  • checkStackList still runs for Fixed configs: the Fixed application schema allows a stack array with no maxItems, so its fixed_test.go expectation still holds.
  • The updated stack list test case expects the raw gojsonschema array_max_items message, which matches what CheckSchemaAt now emits with the skip gone.

Covered by the updated TestLint_ContainerFeatures stack list case in internal/lint/linter_test.go. The test that combined a stack list with a semantic error was removed, so no test now checks how a stack-list error interacts with the semantic checks. The Go test job in .github/workflows/ci.yml runs these tests.

Review details

Review 3 of 10 for this pull request · View the full run

The platform validates Fixed and Flex config with the same models, so
Fixed config is now checked with the upstream Flex schema, patched by
fixed-overlay.json (a JSON Merge Patch), instead of three schemas
maintained here, which had fallen behind (e.g. post_start,
dynamic_compression, runtime extensions).

The overlay adds the keys that only Fixed config accepts: `disk` on
applications, web, workers and services, an application `size` and
`name` (required, as on the platform), and `build.caches`.

Behavior changes for Fixed config, matching Flex and the platform:
- `firewall` is rejected (deprecated in favor of `egress`).
- `type` is required, also with a `stack`.
- A non-empty stack list gets the schema's error, so checkStackList and
  the stack-without-type warning are removed.

The schema tests now also check the patched schema.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
@pjcdawkins pjcdawkins changed the title feat(lint): use the schema from meta.upsun.com as the canonical Flex schema feat(lint): use the schema from meta.upsun.com for Flex and Fixed config Oct 16, 2026

@upsun-dispatch upsun-dispatch Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Warning

Changes suggested — 🟡 1 warning

🔁 Incremental · 12 files reviewed

Verification
  • Every path the overlay patches (applications.additionalProperties, build, web, workers.additionalProperties, services.additionalProperties) is inline in the Flex schema, not a $ref, so the merged keywords take effect.
  • subSchema copies the root definitions and $schema into each Fixed sub-schema, so #/definitions/fixed/* and the Flex #/definitions/stack refs resolve. compile still replaces the remote version refs.
  • The Flex application anyOf requires type, so dropping the stack-without-type branch from CheckTypes can't let an untyped Flex app reach checkRuntime.
  • The Flex services schema already has size and resources, so these Fixed service keys stay valid without an overlay entry.

This push adds table cases to fixed_test.go (Fixed-only keys, firewall, invalid size, stack list, stack without type) and to linter_test.go. schema_test.go now runs the defaults and keyword checks on the patched schema too. These run under make test-go in CI. Nothing compares the overlay with the platform's real Fixed model, so keys accepted there and missing from the overlay go unnoticed.

Review details

Review 4 of 10 for this pull request · View the full run

Comment thread internal/lint/fixed_test.go
@pjcdawkins
pjcdawkins merged commit 88332f9 into main Oct 16, 2026
7 checks passed
@pjcdawkins
pjcdawkins deleted the claude/canonical-schema-pr-220-8a133e branch October 16, 2026 16:47
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