Skip to content

Create abstract client steps infrastracture to externalize the ap modules client configurations#6965

Open
alfonso-noriega wants to merge 1 commit into03-10-clean_up_module_outputfile_calculation_and_move_it_to_the_specificationsfrom
03-10-create_abstract_client_steps_infrastracture_to_externalize_the_ap_modules_client_configurations
Open

Create abstract client steps infrastracture to externalize the ap modules client configurations#6965
alfonso-noriega wants to merge 1 commit into03-10-clean_up_module_outputfile_calculation_and_move_it_to_the_specificationsfrom
03-10-create_abstract_client_steps_infrastracture_to_externalize_the_ap_modules_client_configurations

Conversation

@alfonso-noriega
Copy link
Contributor

@alfonso-noriega alfonso-noriega commented Mar 10, 2026

WHY are these changes introduced?

This introduces a new client-side build pipeline system to replace the existing buildConfig approach for extensions. The current system is limited and doesn't provide enough flexibility for complex build scenarios.

WHAT is this pull request doing?

  • Adds a new ClientSteps interface that defines build steps as configuration objects with execution handled separately
  • Introduces BuildContext to pass data through the step pipeline and store results
  • Implements step executors for build_function, build_theme, bundle_theme, and bundle_ui operations
  • Adds an include_assets step type with support for pattern-based and config-key-based file inclusions
  • Updates ExtensionSpecification to include optional clientSteps field alongside existing buildConfig
  • Modifies buildForBundle method to handle app config extensions differently by using the extension UID as the output path
  • Adds null coalescing operators to prevent undefined errors when filePatterns and ignoredFilePatterns are not defined
  • Includes comprehensive test coverage for the new client steps system

How to test your changes?

  1. Create an extension that uses the new clientSteps configuration
  2. Run the build process and verify that steps execute in sequence
  3. Test the include_assets step with both pattern and configKey inclusion types
  4. Verify that error handling works correctly with continueOnError flag
  5. Ensure existing extensions using buildConfig continue to work unchanged

Measuring impact

How do we know this change was effective? Please choose one:

  • n/a - this doesn't need measurement, e.g. a linting rule or a bug-fix

Checklist

  • I've considered possible cross-platform impacts (Mac, Linux, Windows)
  • I've considered possible documentation changes

Copy link
Contributor Author

alfonso-noriega commented Mar 10, 2026

@alfonso-noriega alfonso-noriega marked this pull request as ready for review March 10, 2026 08:34
@alfonso-noriega alfonso-noriega requested a review from a team as a code owner March 10, 2026 08:34
@github-actions
Copy link
Contributor

We detected some changes at packages/*/src and there are no updates in the .changeset.
If the changes are user-facing, run pnpm changeset add to track your changes and include them in the next release CHANGELOG.

Caution

DO NOT create changesets for features which you do not wish to be included in the public changelog of the next CLI release.

FlattenedRemoteSpecification

// Not all the specs are moved to remote definition yet
merged.clientSteps ??= localSpec.clientSteps ?? []
Copy link
Contributor

Choose a reason for hiding this comment

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

Is this necessary? :thinking_face:
when merging in the previous step, is remoteSpec setting this to undefined? or is it preserving the localSpec value?

Comment on lines +63 to +69
interface StepResult {
readonly id: string
readonly success: boolean
readonly duration: number
readonly output?: unknown
readonly error?: Error
}
Copy link
Contributor

Choose a reason for hiding this comment

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

We should be more strict with this type:

type StepResult = StepError | StepSuccess

interface StepResultMetadata {
  readonly id: string
  readonly duration: number
}
type StepError = StepResultMetadata & {
  readonly success: false
  readonly error: Error
}

type StepSuccess = StepResultMetadata & {
  readonly success: true
  readonly output: unknown
}

Which can also me simplified into:

type StepResult = {
  readonly id: string
  readonly duration: number
} & ({
    readonly success: false
    readonly error: Error
} | {
    readonly success: true
    readonly output: unknown
})

* The full client steps configuration for an extension.
* Replaces the old buildConfig contract.
*/
export type ClientSteps = ReadonlyArray<ClientLifecycleGroup>
Copy link
Contributor

Choose a reason for hiding this comment

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

is a bit weird that ClientSteps is not array of ClientStep, but an array of ClientLifecycleGroupthat then contains an array of ClientStep :thinking_face:

Not sure if we should find a different name for either ClientSteps or ClientStep

Comment on lines +57 to +63
type BuildMode = 'copy_files' | 'theme' | 'function' | 'ui' | 'tax_calculation' | 'hosted_app_home' | 'none'

interface BuildConfig {
mode: BuildMode
filePatterns?: string[]
ignoredFilePatterns?: string[]
}
Copy link
Contributor

Choose a reason for hiding this comment

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

Why this change? is it necessary? it is technically wrong to express the type like this (with optional patterns for every mode)

@alfonso-noriega alfonso-noriega force-pushed the 03-10-create_abstract_client_steps_infrastracture_to_externalize_the_ap_modules_client_configurations branch from 16768f3 to 59f0139 Compare March 10, 2026 09:59
@alfonso-noriega alfonso-noriega changed the base branch from main to graphite-base/6965 March 10, 2026 11:07
@alfonso-noriega alfonso-noriega force-pushed the 03-10-create_abstract_client_steps_infrastracture_to_externalize_the_ap_modules_client_configurations branch from 59f0139 to f9f9e63 Compare March 10, 2026 11:07
@alfonso-noriega alfonso-noriega changed the base branch from graphite-base/6965 to 03-10-clean_up_module_outputfile_calculation_and_move_it_to_the_specifications March 10, 2026 11:07
@alfonso-noriega alfonso-noriega force-pushed the 03-10-clean_up_module_outputfile_calculation_and_move_it_to_the_specifications branch from 7b68eb7 to c3ee349 Compare March 10, 2026 11:24
@alfonso-noriega alfonso-noriega force-pushed the 03-10-create_abstract_client_steps_infrastracture_to_externalize_the_ap_modules_client_configurations branch from f9f9e63 to 59dcaa7 Compare March 10, 2026 11:24
case 'validate':
case 'transform':
case 'custom':
throw new Error(`Build step type "${step.type}" is not yet implemented.`)

Choose a reason for hiding this comment

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

Step router makes all step types unusable (always throws)

executeStepByType explicitly throws for every declared step type (including include_assets, bundle_ui, bundle_theme, etc.), so the new ClientSteps pipeline cannot execute any step successfully.

Evidence:

case 'include_assets':
...
  throw new Error(`Build step type "${step.type}" is not yet implemented.`)

Impact:

  • Any runtime path using clientSteps will fail during build/deploy.
  • CI/build pipelines will error; deploys could be blocked broadly once enabled.

@binks-code-reviewer
Copy link

⚠️ Findings outside the diff

These findings are in files not modified by this PR and cannot be posted as inline comments.


packages/app/src/cli/services/build/client-steps.integration.test.ts:168Integration tests assert copying behavior but no implementation exists

The integration test calls executeStep with type: 'include_assets' and asserts files were copied into outputDir, but the router currently throws “not yet implemented” for include_assets, so this test should fail consistently.

Evidence:

await executeStep({ ..., type: 'include_assets', ... }, context)
...
expect(await fileExists(joinPath(outputDir, 'logo.png'))).toBe(true)

Impact:

  • PR should fail CI (or indicates these tests aren’t running).
  • Confirms the core feature is incomplete.

success: true,
duration: Date.now() - startTime,
output,
}

Choose a reason for hiding this comment

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

BuildContext.stepResults is never written to, despite being part of the contract

BuildContext includes stepResults: Map<string, StepResult> and ClientStep.id is described as the “key in the stepResults map”, but executeStep never stores the produced result into context.stepResults. This breaks intended pipeline behavior (later steps can’t inspect prior outputs/errors) and can cause subtle bugs once steps depend on previous results.

@binks-code-reviewer
Copy link

binks-code-reviewer bot commented Mar 10, 2026

🤖 Code Review · #projects-dev-ai for questions
React with 👍/👎 or reply — all feedback helps improve the agent.

Complete - No issues

📋 History

❌ Failed → ❌ Failed → ❌ Failed → ✅ 2 findings → ✅ No issues → ❌ Failed → ❌ Failed → ✅ No issues → ✅ No issues

@alfonso-noriega alfonso-noriega force-pushed the 03-10-create_abstract_client_steps_infrastracture_to_externalize_the_ap_modules_client_configurations branch from 59dcaa7 to fb4c01d Compare March 10, 2026 11:35
@binks-code-reviewer
Copy link

⚠️ Findings outside the diff

These findings are in files not modified by this PR and cannot be posted as inline comments.


packages/app/src/cli/models/extensions/extension-instance.ts:369New build mode 'hosted_app_home' is added to the type but not handled in build switch

BuildConfig.mode includes 'hosted_app_home', but ExtensionInstance.build() does not handle it. The extension may not be built, producing missing artifacts.

Impact: Specs setting mode=hosted_app_home can lead to deploy failures or missing runtime resources.

@alfonso-noriega alfonso-noriega force-pushed the 03-10-create_abstract_client_steps_infrastracture_to_externalize_the_ap_modules_client_configurations branch from fb4c01d to 68f4751 Compare March 10, 2026 12:15
@alfonso-noriega alfonso-noriega force-pushed the 03-10-clean_up_module_outputfile_calculation_and_move_it_to_the_specifications branch 2 times, most recently from 24fb214 to ecf7d0f Compare March 10, 2026 12:41
@alfonso-noriega alfonso-noriega force-pushed the 03-10-create_abstract_client_steps_infrastracture_to_externalize_the_ap_modules_client_configurations branch 4 times, most recently from 9257821 to 596be94 Compare March 10, 2026 14:45
@alfonso-noriega alfonso-noriega force-pushed the 03-10-create_abstract_client_steps_infrastracture_to_externalize_the_ap_modules_client_configurations branch from 596be94 to e088f88 Compare March 10, 2026 14:52
@github-actions
Copy link
Contributor

github-actions bot commented Mar 10, 2026

Coverage report

St.
Category Percentage Covered / Total
🟡 Statements 78.83% 14491/18383
🟡 Branches 73% 7201/9864
🟡 Functions 79.07% 3703/4683
🟡 Lines 79.17% 13690/17292

Test suite run success

3795 tests passing in 1452 suites.

Report generated by 🧪jest coverage report action from b42a87b

@alfonso-noriega alfonso-noriega force-pushed the 03-10-create_abstract_client_steps_infrastracture_to_externalize_the_ap_modules_client_configurations branch from e088f88 to b42a87b Compare March 10, 2026 15:18
export function createConfigExtensionSpecification<TConfiguration extends BaseConfigType = BaseConfigType>(spec: {
identifier: string
schema: ZodSchemaType<TConfiguration>
clientSteps?: ClientSteps
Copy link
Contributor

Choose a reason for hiding this comment

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

is clientSteps meant to eventually replace buildconfig or are we intending to support both?

readonly extension: ExtensionInstance
readonly options: ExtensionBuildOptions
readonly stepResults: Map<string, StepResult>
[key: string]: unknown
Copy link
Contributor

Choose a reason for hiding this comment

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

ideally outputs are not unknown if there is a finite amount of valid steps

* Context passed through the step pipeline.
* Each step can read from and write to the context.
*/
export interface BuildContext {
Copy link
Contributor

Choose a reason for hiding this comment

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

i'm unclear on why an additional stateful context is necessary. can we not iterate through the steps just using the data already available and the step i/o?

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.

3 participants