Skip to content

Commit 78d6c4f

Browse files
committed
fix(sentry): Defer daemon metadata enrichment post-listen
Move Xcode and AXe metadata collection out of pre-listen startup so\ndaemon readiness cannot be blocked by external command execution.\n\nKeep Sentry hardening behavior by setting fast runtime context early\nand enriching metadata asynchronously after the daemon is listening.\n\nCo-Authored-By: Claude <noreply@anthropic.com>
1 parent d364ad6 commit 78d6c4f

1 file changed

Lines changed: 42 additions & 26 deletions

File tree

src/daemon.ts

Lines changed: 42 additions & 26 deletions
Original file line numberDiff line numberDiff line change
@@ -193,28 +193,13 @@ async function main(): Promise<void> {
193193
(workflowId) => !excludedWorkflows.includes(workflowId),
194194
);
195195
const xcodeIdeWorkflowEnabled = daemonWorkflows.includes('xcode-ide');
196-
const commandExecutor = getDefaultCommandExecutor();
197-
const xcodeVersion = await getXcodeVersionMetadata(async (command) => {
198-
const result = await commandExecutor(command, 'Get Xcode Version');
199-
return { success: result.success, output: result.output };
200-
});
201-
const xcodeAvailable = Boolean(
202-
xcodeVersion.version ||
203-
xcodeVersion.buildVersion ||
204-
xcodeVersion.developerDir ||
205-
xcodeVersion.xcodebuildPath,
206-
);
207196
const axeBinary = resolveAxeBinary();
208197
const axeAvailable = axeBinary !== null;
209-
const axeSource = axeBinary?.source ?? 'unavailable';
198+
const axeSource: 'env' | 'bundled' | 'path' | 'unavailable' = axeBinary?.source ?? 'unavailable';
210199
const xcodemakeAvailable = isXcodemakeBinaryAvailable();
211-
const axeVersion = await getAxeVersionMetadata(async (command) => {
212-
const result = await commandExecutor(command, 'Get AXe Version');
213-
return { success: result.success, output: result.output };
214-
}, axeBinary?.path);
215-
setSentryRuntimeContext({
216-
mode: 'cli-daemon',
217-
xcodeAvailable,
200+
const xcodemakeEnabled = isXcodemakeEnabled();
201+
const baseSentryRuntimeContext = {
202+
mode: 'cli-daemon' as const,
218203
enabledWorkflows: daemonWorkflows,
219204
disableSessionDefaults: result.runtime.config.disableSessionDefaults,
220205
disableXcodeAutoSync: result.runtime.config.disableXcodeAutoSync,
@@ -224,14 +209,38 @@ async function main(): Promise<void> {
224209
xcodeIdeWorkflowEnabled,
225210
axeAvailable,
226211
axeSource,
227-
axeVersion,
228-
xcodeDeveloperDir: xcodeVersion.developerDir,
229-
xcodebuildPath: xcodeVersion.xcodebuildPath,
230212
xcodemakeAvailable,
231-
xcodemakeEnabled: isXcodemakeEnabled(),
232-
xcodeVersion: xcodeVersion.version,
233-
xcodeBuildVersion: xcodeVersion.buildVersion,
234-
});
213+
xcodemakeEnabled,
214+
};
215+
setSentryRuntimeContext(baseSentryRuntimeContext);
216+
217+
const enrichSentryMetadata = async (): Promise<void> => {
218+
const commandExecutor = getDefaultCommandExecutor();
219+
const xcodeVersion = await getXcodeVersionMetadata(async (command) => {
220+
const result = await commandExecutor(command, 'Get Xcode Version');
221+
return { success: result.success, output: result.output };
222+
});
223+
const xcodeAvailable = Boolean(
224+
xcodeVersion.version ||
225+
xcodeVersion.buildVersion ||
226+
xcodeVersion.developerDir ||
227+
xcodeVersion.xcodebuildPath,
228+
);
229+
const axeVersion = await getAxeVersionMetadata(async (command) => {
230+
const result = await commandExecutor(command, 'Get AXe Version');
231+
return { success: result.success, output: result.output };
232+
}, axeBinary?.path);
233+
234+
setSentryRuntimeContext({
235+
...baseSentryRuntimeContext,
236+
xcodeAvailable,
237+
axeVersion,
238+
xcodeDeveloperDir: xcodeVersion.developerDir,
239+
xcodebuildPath: xcodeVersion.xcodebuildPath,
240+
xcodeVersion: xcodeVersion.version,
241+
xcodeBuildVersion: xcodeVersion.buildVersion,
242+
});
243+
};
235244

236245
const catalog = await buildDaemonToolCatalogFromManifest({
237246
excludeWorkflows: excludedWorkflows,
@@ -391,6 +400,13 @@ async function main(): Promise<void> {
391400
writeLine(`Socket: ${socketPath}`);
392401
writeLine(`Tools: ${catalog.tools.length}`);
393402
recordBootstrapDurationMetric('cli-daemon', Date.now() - daemonBootstrapStart);
403+
404+
setImmediate(() => {
405+
void enrichSentryMetadata().catch((error) => {
406+
const message = error instanceof Error ? error.message : String(error);
407+
log('warning', `[Daemon] Failed to enrich Sentry metadata: ${message}`);
408+
});
409+
});
394410
});
395411

396412
process.on('SIGTERM', shutdown);

0 commit comments

Comments
 (0)