Skip to content

Conversation

MikeCarbone
Copy link

@MikeCarbone MikeCarbone commented Sep 9, 2025

Description

Added support for reusable steps in the CLI. This implementation includes:

  • Core functionality for reading, writing, and processing reusable step data
  • Helpers for validating and managing reusable step directories
  • Support for extracting and inlining content from reusable steps
  • Integration with the existing marshal system

The implementation follows the same pattern as other resource types (workflows, partials, etc.) with specialized handlers for the reusable step structure. It includes the necessary types, processors, and utilities to manage reusable steps both individually and in bulk.

Tasks

KNO-1234

Copy link

linear bot commented Sep 9, 2025

Copy link
Author

This stack of pull requests is managed by Graphite. Learn more about stacking.

@MikeCarbone MikeCarbone changed the title mike-kno-9713-cli-add-reusable-step-marhsal-logic Add reusable step support to CLI Sep 9, 2025
@MikeCarbone MikeCarbone changed the title Add reusable step support to CLI feat(kno-9713): add reusable step marshalling support to CLI Sep 9, 2025
@MikeCarbone MikeCarbone marked this pull request as ready for review September 9, 2025 16:45
@MikeCarbone MikeCarbone force-pushed the 09-09-mike-kno-9713-cli-add-reusable-step-marhsal-logic branch 3 times, most recently from 9267071 to eec0f18 Compare September 9, 2025 17:05
@MikeCarbone MikeCarbone force-pushed the 09-09-mike-kno-9713-cli-add-reusable-step-marhsal-logic branch from eec0f18 to 08e117d Compare September 9, 2025 17:13
@@ -91,7 +91,8 @@
"postpack": "shx rm -f oclif.manifest.json",
"prepack": "yarn build && oclif manifest && oclif readme",
"test": "mocha --forbid-only \"test/**/*.test.ts\"",
"version": "oclif readme && git add README.md"
"version": "oclif readme && git add README.md",
"check": "yarn run lint && yarn run format.check && yarn run type.check"
Copy link
Author

Choose a reason for hiding this comment

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

tests kept failing in the PR for various reasons here, I prefer them to fail locally so I can quick fix. Running the individual commands was cumbersome, added this to check everything before I submit the PR

@@ -53,7 +53,7 @@ const remoteMessageType: MessageTypeData<WithAnnotation> = {
},
};

describe("lib/marshal/message-typel/processor", () => {
describe("lib/marshal/message-type/processor", () => {
Copy link
Author

Choose a reason for hiding this comment

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

noticed this, small fix

@@ -3,7 +3,7 @@ import type { ResourceType } from "./run-context";
// TODO Remove this once hidden option is removed from message types / guides
export type NonHiddenResourceType = Exclude<
ResourceType,
"message_type" | "guide"
"message_type" | "guide" | "reusable_step"
Copy link
Author

Choose a reason for hiding this comment

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

we'll hide it for now before release

Comment on lines +6 to +7
// TODO: update with actual shape from mAPI
export type ReusableStepData<A extends MaybeWithAnnotation = unknown> = A & {
Copy link
Author

Choose a reason for hiding this comment

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

wasn't sure which keys belonged here — need to dig into this when I add the resource to mAPI

Copy link
Contributor

Choose a reason for hiding this comment

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

Check Control.Marshal.Schemas.ReusableStep.ReusableStepSchema, in particular the dump/2 function.

@@ -0,0 +1,220 @@
import path from "node:path";
Copy link
Author

Choose a reason for hiding this comment

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

a lot of these files are copy / pasted from other resources. I'm not entirely sure about the whats & whys of what's going on, but I think I included the bare minimum, just what we needed before adding to mAPI. Please lmk if there is something here that does not belong here yet

| ReusableStepDirTarget
| ReusableStepsIndexDirTarget;

export const ensureValidCommandTarget = async (
Copy link
Contributor

Choose a reason for hiding this comment

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

Not used anywhere?

export * from "./processor.isomorphic";
export * from "./reader";
export * from "./types";
export * from "./writer";
Copy link
Contributor

Choose a reason for hiding this comment

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

The reader and writer modules are not really used anywhere? They are typically needed for the pull and push commands, and I don't think we have any commands for reusable steps.

If this PR is for dashboard to show commit diffs, you just need the buildReusableStepDirBundle helper, and here's an example of only those changes: #498

Comment on lines +6 to +7
// TODO: update with actual shape from mAPI
export type ReusableStepData<A extends MaybeWithAnnotation = unknown> = A & {
Copy link
Contributor

Choose a reason for hiding this comment

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

Check Control.Marshal.Schemas.ReusableStep.ReusableStepSchema, in particular the dump/2 function.

id: string;
key: string;
/** The step content for this reusable step's current version. Currently only HttpFetch is supported. */
step: HttpFetchStepData;
Copy link
Contributor

Choose a reason for hiding this comment

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

Continuing from above -

For example, I don't think there is a step field, because we flatten the object in dump/2, so the data payload you get for a reusable step is:

step object
- ref
+ key, type, environment, created_at, updated_at, sha

https://github.com/knocklabs/control/blob/75aba3b0d50b2ec37e35608d2a0d2659f3c984eb/backend/lib/control/marshal/schemas/reusable_step/reusable_step_schema.ex#L30-L50

import { prepareResourceJson } from "../shared/helpers.isomorphic";
import { ReusableStepData } from "./types";

export const REUSABLE_STEP_JSON = "reusable-step.json";
Copy link
Contributor

Choose a reason for hiding this comment

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

Suggested change
export const REUSABLE_STEP_JSON = "reusable-step.json";
export const REUSABLE_STEP_JSON = "reusable_step.json";

@@ -19,7 +20,8 @@ type ResourceData<A extends WithAnnotation> =
| PartialData<A>
| WorkflowData<A>
| MessageTypeData<A>
| GuideData<A>;
| GuideData<A>
| ReusableStepData<A>;
Copy link
Contributor

Choose a reason for hiding this comment

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

* its file content. It includes the extractable fields, which are extracted out
* and added to the bundle as separate files.
*/
export const buildReusableStepDirBundle = (
Copy link
Contributor

Choose a reason for hiding this comment

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

This probably works for a http fetch step which I believe is the only step type we support with reusable steps, but
one caveat to flag here is that this will likely break once you start supporting other step types.

The proper way to do this would be to refactor the buildWorkflowDirBundle helper, and extract out the part that handles a single step. In ReusableStepSchema, the step field is technically WorkflowStepSchema which can be any step type. But that's more work to refactor.

I'm okay duplicating code and shipping what can work for http steps only - but it will be easy to forget this if/when we ever support additional step types for resuable steps.

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.

2 participants