feat(module-ci): apply output types before modules - #17
Merged
Merged
Conversation
A modules repository now carries the output types its modules exchange, at
outputs/{namespace}/{name}.yaml. CI had no step for them.
The order is not a preference. A module names its output type by reference and
the control plane refuses a module upload whose type it does not already hold
("Output @ns/name not found"), so the types are applied first in both preview
and publish mode.
Preview and publish are not the same operation at different strengths, because
an output type is global and unversioned: the control plane keys it on name and
namespace alone, with no stage and no version, and a write replaces it for
every module at once. There is no slot to hold a proposed change and nothing to
roll back to.
- preview (pull request): `raptor create output-type -f FILE --if-absent`. A
type the control plane has never seen is created — it has no consumers, so
the write is safe, and it is the only way a pull request that adds a module
together with its new type can validate its own module. A type that already
exists is only reported in the PR comment.
- publish (push): the full apply. raptor still refuses a removal or a retype
while some module uses the type.
- cleanup (PR close): nothing. CI never deletes an output type — there is no
preview slot to restore one from, and a type carries no provenance, so there
is no ownership check like the module cleanup relies on.
The PR comment is now assembled in the upsert step rather than in the module
step, because a pull request can touch output types only, modules only, or
both, and the marker must appear exactly once in the final body.
New input `apply-output-types` (default true) turns the whole thing off for a
repository whose types are managed elsewhere.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Why
A modules repository now carries two trees: the modules at
modules/{intent}/{flavor}/{version}/and the output types they exchange atoutputs/{namespace}/{name}.yaml. CI had no step for the second.The ordering is forced, not chosen. A module names its output type by reference, and the control plane refuses a module upload whose type it does not already hold (
Output @ns/name not found). So the action applies output types first, in both preview and publish mode.Preview ≠ publish, for a real reason
An output type is global and unversioned: the control plane keys it on
name+namespacealone — no stage, no version — and a write replaces it for every module and every environment at once. There is no slot to hold a proposed change and nothing to roll back to.raptor create output-type -f FILE --if-absent. A type the control plane has never seen is created — zero consumers, so the write is safe, and it is the only way a PR that adds a module and its new type can validate its own module. An existing type is only reported in the PR comment.Never deletes. Removing a file from
outputs/leaves the type in place. Two reasons: a delete on PR-close would break every module reading it with no preview slot to restore from, and a type carries no provenance fields, so there is no ownership check like the one module cleanup relies on. The README says so and points atraptor module delete-output-type.Changes
apply-output-types(defaulttrue) for a repo whose types are managed elsewhere.all-modules: truenow also sweeps every definition underoutputs/.[ -f "$f" ] || continue).<!-- facets-module-ci:preview -->marker must appear exactly once in the final body. The upsert condition widened todirs != '' || output_files != '', so a types-only PR still gets a comment.Testing
Not run against a live repository.
action.ymlparses as YAML, every embedded script passesbash -n, and the three new/changed scripts areshellcheckclean at--severity=warning.Safe to merge before any repository has an
outputs/tree: the detection step finds nothing and every new step no-ops.Merge order
This is second of three, and must not be tagged
v1until raptor ships:Facets-cloud/raptor#442 → merge and tag a release. This action callscreate output-type -f DIR --if-absent; an older raptor rejects both, and control-plane-bootstrapped repos pinmodule-ci-action@v1.v1alias.Facets-cloud/control-plane— export output types in the modules-repo bootstrap and sync. It must land last: the moment it ships, bootstrap and sync start writingoutputs/trees whose CI needs both of the above already live.🤖 Generated with Claude Code