Skip to content

feat(config): generalize the task run-arg table into a named action set #61

Description

@AbysmalBiscuit

A task's run entry is either a plain string or exactly one table shape, { split = "...", on = "..." }. RunArg in crates/devkit-config/src/lib.rs hardcodes that table as the table an entry can be, so split is not one action among several, it is the only one the type admits. Adding a second means bolting on another untagged variant and hoping the key sets stay disjoint, and the derived JSON Schema gains another anonymous anyOf branch with no shared name for "an action entry".

Generalize the type so split becomes one member of a named action set.

Shape

#[serde(untagged, deny_unknown_fields)]
pub enum Arg {
    Scalar(String),
    Split { split: String, on: String },
    // room for join, default, optional
}

Constraints that carry over:

  • Untagged plus deny_unknown_fields, for the reason already recorded on the derive: without it a misspelled key beside a well-formed pair deserializes silently and the typo changes nothing the author can see. With more variants in the union this matters more, not less.
  • template() stays the one accessor for the minijinja source, so port scanning and variable discovery never learn the variant list.
  • The schema is derived, so devkit schema picks the new shape up on its own. schema/devkit-config.json is regenerated with DEVKIT_UPDATE_SCHEMA=1 cargo test, and the drift test keeps it honest.

Fields

tasks.<name>.run is the only field typed on this entry today, so it is the only one that changes. If the type has been accepted anywhere else by the time this lands, every such field moves with it rather than being left on the old shape.

Call sites

  • crates/devkit-ports/src/task.rs: resolution, argv assembly, and the two shape checks (the program must be a plain string; a split must be last or followed only by splits).
  • crates/devkit-ports/src/guard/mod.rs: configured_task, which reads a task's leading static words by finding the first non-scalar entry.
  • crates/devkit-ports/src/guard/tasks.rs: template collection.
  • docs/configuration.md: the task run section, which documents the split table and its shape rules.

Guard and resolution both match on the variant rather than on the rendered template, so every new action is a compile error at each site. That is the design, keep it: no _ => arm.

Not in this change

Implementing join, default or optional. They are what motivates the shape, but each one is its own semantics question. This issue is the change that makes them cheap to add.

Activity

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions