Repository navigation
fix(lint): accept an empty composable stack - #230
Conversation
The platform accepts an empty `stack` (`[]`, `{}` or null) for a
composable image, e.g. for static sites, but rejects a non-empty list:
the list form was removed in favor of the `runtimes`/`packages` mapping.
- Allow arrays and null for `stack` in the Flex and Fixed schemas.
- Report a non-empty list with a specific error from CheckTypes, rather
than a JSON schema type error.
- Treat an empty list as an empty stack, and only warn that 'stack'
should be specified for a composable image when it is missing.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
There was a problem hiding this comment.
Note
Reviewed — No blocking findings · 🔵 1 minor point
🔍 Full review · 7 files reviewed
🔵 Minor point
internal/lint/types.go:54— A non-emptystacklist now gets an error fromcheckStackList, but the existing checks still treat it as a real stack, so the same problem is reported twice.isStackEmptyreturns false for a non-empty list. With a non-composable type (e.g.type: php:8.4,stack: [php@8.4]),checkRuntimealso adds the warning "'stack' is only used with a composable image type" (line 47). With an emptytype, line 55 also adds "'type' should be specified (as a composable image) when using 'stack'". In both cases a stack the linter has just rejected as malformed gets a second report.
Verification
- Both schemas use
"type": ["object","array","null"], and Flex app and task stacks both point to the single#/definitions/stack, so only lists and null newly pass the schema. CheckContentreturns on schema errors beforerunChecks, so the non-empty list error only appears once the config passes the schema, as the description says.- The composable warning now fires only when the stack is nil (missing or
stack:);[],{}and{runtimes: [], packages: []}no longer warn. checkStackListruns before thetask.Base == ""guard, so tasks usingbasestill get the list check (covered by the types_teststack_listcase).
The PR adds table cases in internal/lint/linter_test.go, fixed_test.go and types_test.go for empty stacks and stack lists, and updates two existing cases to the mapping form; CI runs them in the make test-go step of .github/workflows/ci.yml. No test covers a non-empty list combined with a non-composable type or a missing type.
Review details
- Commit: c3c54ca
- Model: claude-opus-5-5
Review 1 of 10 for this pull request · View the full run
A non-empty stack list was also treated as a stack by the type checks, adding the 'only used with a composable image' or 'type should be specified' warnings after the list error. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
There was a problem hiding this comment.
Warning
Changes suggested — 🟡 1 warning
🔁 Incremental · 2 files reviewed
Verification
Config.ApplicationsandTasksare maps of struct values, soapp.Stack = checkStackList(...)changes a local copy and does not affect the checks that run after CheckTypes.- For a composable app with a list stack, the empty-map replacement is non-nil, so the extra warning
'stack' should be specifiedno longer appears. - For a classic or docker app with a list stack, the replacement counts as empty for
isStackEmpty, so the list error is not followed by a duplicate warning that'stack' is only used with a composable image type.
The stack_list case in TestCheckTypes (internal/lint/types_test.go) now covers composable, classic, untyped and base-task apps with list stacks. Its expected output includes the extra type cannot be empty error reported in the finding, so the test locks that behaviour in.
Review 2 of 10 for this pull request · View the full run
…k list Replacing the rejected list before the stack-without-type check sent the app to the type check, which reported 'type cannot be empty'. Check the original stack there instead, and only skip the warning. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
upsun lintrejectedstack: []for a composable image (Invalid type. Expected: object, given: array), although the platform accepts an empty stack, e.g. for static sites. The platform no longer accepts a non-empty list:stackmust be a mapping ofruntimesandpackages.stackin the Flex and Fixed schemas.CheckTypeswith a specific error ('stack' must be a mapping of 'runtimes' and 'packages', not a list) instead of a schema type error. As a semantic check, it's only shown once the config passes the schema.stackshould be specified for a composable image when it is missing or null, not when it is deliberately empty ([],{},{runtimes: []}).🤖 Generated with Claude Code