Preserve structured app validation issues internally#7066
Preserve structured app validation issues internally#7066
Conversation
This stack of pull requests is managed by Graphite. Learn more about stacking. |
Coverage report
Test suite run success4001 tests passing in 1529 suites. Report generated by 🧪jest coverage report action from a7602f8 |
59c4766 to
efd8c3d
Compare
b6ee50f to
113bc0e
Compare
efd8c3d to
a078db7
Compare
113bc0e to
3c313f8
Compare
3c313f8 to
0158180
Compare
a078db7 to
d22a6e8
Compare
0158180 to
9d58583
Compare
Differences in type declarationsWe detected differences in the type declarations generated by Typescript for this branch compared to the baseline ('main' branch). Please, review them to ensure they are backward-compatible. Here are some important things to keep in mind:
New type declarationsWe found no new type declarations in this PR Existing type declarationspackages/cli-kit/dist/private/node/constants.d.ts@@ -8,7 +8,6 @@ export declare const environmentVariables: {
env: string;
firstPartyDev: string;
noAnalytics: string;
- cliToken: string;
partnersToken: string;
runAsUser: string;
serviceEnv: string;
packages/cli-kit/dist/public/node/environment.d.ts@@ -10,12 +10,17 @@
*/
export declare function getEnvironmentVariables(): NodeJS.ProcessEnv;
/**
- * Returns the value of the SHOPIFY_CLI_TOKEN environment variable,
- * falling back to the deprecated SHOPIFY_CLI_PARTNERS_TOKEN.
+ * Returns the value of the SHOPIFY_CLI_PARTNERS_TOKEN environment variable.
*
- * @returns The CLI token value, or undefined if neither env var is set.
+ * @returns Current process environment variables.
+ */
+export declare function getPartnersToken(): string | undefined;
+/**
+ * Check if the current proccess is running using the partners token.
+ *
+ * @returns True if the current proccess is running using the partners token.
*/
-export declare function getCliToken(): string | undefined;
+export declare function usePartnersToken(): boolean;
/**
* Returns the value of the organization id from the environment variables.
*
packages/cli-kit/dist/private/node/session/exchange.d.ts@@ -25,7 +25,7 @@ export declare function exchangeAccessForApplicationTokens(identityToken: Identi
*/
export declare function refreshAccessToken(currentToken: IdentityToken): Promise<IdentityToken>;
/**
- * Given a custom CLI token passed as ENV variable, request a valid Partners API token.
+ * Given a custom CLI token passed as ENV variable, request a valid Partners API token
* This token does not accept extra scopes, just the cli one.
* @param token - The CLI token passed as ENV variable
* @returns An instance with the application access tokens.
@@ -35,7 +35,7 @@ export declare function exchangeCustomPartnerToken(token: string): Promise<{
userId: string;
}>;
/**
- * Given a custom CLI token passed as ENV variable, request a valid App Management API token.
+ * Given a custom CLI token passed as ENV variable, request a valid App Management API token
* @param token - The CLI token passed as ENV variable
* @returns An instance with the application access tokens.
*/
@@ -44,7 +44,7 @@ export declare function exchangeCliTokenForAppManagementAccessToken(token: strin
userId: string;
}>;
/**
- * Given a custom CLI token passed as ENV variable, request a valid Business Platform API token.
+ * Given a custom CLI token passed as ENV variable, request a valid Business Platform API token
* @param token - The CLI token passed as ENV variable
* @returns An instance with the application access tokens.
*/
|
d22a6e8 to
5828af2
Compare
9d58583 to
46515e4
Compare
5828af2 to
7a4c5d2
Compare
46515e4 to
365b143
Compare
7a4c5d2 to
bcfb6e3
Compare
15b52cf to
964455a
Compare
bcfb6e3 to
b9064bc
Compare
|
We detected some changes at Caution DO NOT create changesets for features which you do not wish to be included in the public changelog of the next CLI release. |
ryancbahan
left a comment
There was a problem hiding this comment.
can we chat about path forward? I just removed the app loader's mode and have been working on a stack to untangle error handling.
|
Thanks, I somehow missed your changes. I'm refactoring now, I'll put the PR back into draft. |
123cec3 to
30acf6b
Compare
There was a problem hiding this comment.
Pull request overview
This PR updates the app-loading validation pipeline to retain structured Zod validation issue metadata (file/path-aware) internally while keeping existing human-readable CLI output behavior unchanged.
Changes:
- Added structured issue parsing (
parseStructuredErrors) alongside the existing human-readable formatter. - Introduced
LocalConfigErrorand updatedConfigurationError/loader code paths to carry structured issues through the loader boundary. - Updated
AppErrorsto store both rendered messages and structured issues, with new accessors and structured export.
Reviewed changes
Copilot reviewed 5 out of 5 changed files in this pull request and generated 3 comments.
Show a summary per file
| File | Description |
|---|---|
| packages/app/src/cli/models/app/local-config-error.ts | Introduces a shared local configuration error that carries configuration path + structured issues. |
| packages/app/src/cli/models/app/loader.ts | Threads structured issues through configuration parsing and error aggregation (AppErrors). |
| packages/app/src/cli/models/app/loader.test.ts | Adds coverage for structured issues on thrown configuration errors and AppErrors behavior. |
| packages/app/src/cli/models/app/error-parsing.ts | Adds structured issue shaping (AppValidationIssue / parseStructuredErrors) and shared path formatting helpers. |
| packages/app/src/cli/models/app/error-parsing.test.ts | Adds unit tests for parseStructuredErrors, including union handling. |
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
| const fallbackIssues = issue.unionErrors.flatMap((unionError) => unionError.issues ?? []) | ||
| if (fallbackIssues.length > 0) { | ||
| // Preserve any concrete nested issues we were able to recover before | ||
| // falling back to a synthetic root issue. This structured path is still | ||
| // internal, and retaining leaf issues is more actionable than erasing | ||
| // them behind a generic union failure. | ||
| return fallbackIssues.map((nestedIssue) => toStructuredIssue(filePath, nestedIssue)) | ||
| } | ||
|
|
There was a problem hiding this comment.
parseStructuredErrors contains a fallback branch that appears unreachable with the current findBestMatchingVariant implementation: if any union variant has non-empty issues, findBestMatchingVariant will always return a variant with issues.length > 0, so this fallbackIssues path will never execute. Consider either removing this dead code, or updating findBestMatchingVariant to return null when it can’t confidently pick a single variant (so the fallback becomes meaningful).
| const fallbackIssues = issue.unionErrors.flatMap((unionError) => unionError.issues ?? []) | |
| if (fallbackIssues.length > 0) { | |
| // Preserve any concrete nested issues we were able to recover before | |
| // falling back to a synthetic root issue. This structured path is still | |
| // internal, and retaining leaf issues is more actionable than erasing | |
| // them behind a generic union failure. | |
| return fallbackIssues.map((nestedIssue) => toStructuredIssue(filePath, nestedIssue)) | |
| } |
| export interface AppValidationFileIssues { | ||
| filePath: string | ||
| message: OutputMessage | ||
| issues: AppValidationIssue[] | ||
| } |
There was a problem hiding this comment.
AppValidationFileIssues.message is typed as OutputMessage (which can be a TokenizedString). If this structure is intended to be JSON-serialized (as the name suggests), TokenizedString will serialize as an object ({"value": ...}) rather than the rendered string. Consider changing message to a plain string (produced via stringifyMessage) or renaming this type/method to avoid implying JSON-safe output.
| function setupParsing(errorObj: zod.ZodIssue | {}, webhookConfigOverrides: WebhooksConfig) { | ||
| const toParse = getWebhookConfig(webhookConfigOverrides) | ||
| try { | ||
| const parsedConfiguration = parseConfigurationObject(WebhooksSchema, 'tmp', toParse) |
There was a problem hiding this comment.
setupParsing takes an errorObj argument but never uses it. This makes the test helper signature misleading and keeps a lot of unused error objects in the tests. Consider removing the parameter (and updating call sites) or asserting against result.error using the provided errorObj to validate the expected Zod issue details.
30acf6b to
a7602f8
Compare

What
Preserve structured app validation issues internally during app loading.
This keeps the current CLI behavior the same while retaining structured issue metadata alongside rendered validation messages.
Why
app config validate --jsonneeds file-oriented issue data, but the validation pipeline still flattens schema issues into strings too early.To support repair loops and future automation work, the CLI needs to retain structured validation details before deciding how to render them publicly.
How
AppErrorsto retain both rendered messages and structured issuesLocalConfigErroras a shared lower-layer local configuration error