@shipfox/api-definitions 12.3.0 → 14.0.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/.turbo/turbo-build.log +11 -11
- package/CHANGELOG.md +45 -0
- package/dist/core/entities/index.d.ts +1 -1
- package/dist/core/entities/index.d.ts.map +1 -1
- package/dist/core/entities/index.js +1 -1
- package/dist/core/entities/index.js.map +1 -1
- package/dist/core/entities/integration-context.d.ts +4 -0
- package/dist/core/entities/integration-context.d.ts.map +1 -1
- package/dist/core/entities/integration-context.js.map +1 -1
- package/dist/core/entities/sync-state.d.ts +10 -4
- package/dist/core/entities/sync-state.d.ts.map +1 -1
- package/dist/core/entities/sync-state.js +26 -7
- package/dist/core/entities/sync-state.js.map +1 -1
- package/dist/core/entities/validation-diagnostic.d.ts +8 -0
- package/dist/core/entities/validation-diagnostic.d.ts.map +1 -0
- package/dist/core/entities/validation-diagnostic.js +3 -0
- package/dist/core/entities/validation-diagnostic.js.map +1 -0
- package/dist/core/entities/workflow-definition.d.ts +2 -0
- package/dist/core/entities/workflow-definition.d.ts.map +1 -1
- package/dist/core/entities/workflow-definition.js.map +1 -1
- package/dist/core/errors.d.ts +10 -0
- package/dist/core/errors.d.ts.map +1 -1
- package/dist/core/errors.js +9 -0
- package/dist/core/errors.js.map +1 -1
- package/dist/core/index.d.ts +2 -1
- package/dist/core/index.d.ts.map +1 -1
- package/dist/core/index.js +2 -1
- package/dist/core/index.js.map +1 -1
- package/dist/core/integrations.d.ts +3 -1
- package/dist/core/integrations.d.ts.map +1 -1
- package/dist/core/integrations.js +10 -2
- package/dist/core/integrations.js.map +1 -1
- package/dist/core/parse-definition.d.ts +4 -4
- package/dist/core/parse-definition.d.ts.map +1 -1
- package/dist/core/parse-definition.js +5 -5
- package/dist/core/parse-definition.js.map +1 -1
- package/dist/core/resolve-definition-at-ref.d.ts +66 -0
- package/dist/core/resolve-definition-at-ref.d.ts.map +1 -0
- package/dist/core/resolve-definition-at-ref.js +374 -0
- package/dist/core/resolve-definition-at-ref.js.map +1 -0
- package/dist/core/sync-definitions.d.ts +2 -2
- package/dist/core/sync-definitions.d.ts.map +1 -1
- package/dist/core/sync-definitions.js +5 -5
- package/dist/core/sync-definitions.js.map +1 -1
- package/dist/core/validate-definition.d.ts +3 -3
- package/dist/core/validate-definition.d.ts.map +1 -1
- package/dist/core/validate-definition.js +17 -12
- package/dist/core/validate-definition.js.map +1 -1
- package/dist/core/workflow-model/cron-trigger.d.ts +1 -1
- package/dist/core/workflow-model/cron-trigger.d.ts.map +1 -1
- package/dist/core/workflow-model/cron-trigger.js +9 -5
- package/dist/core/workflow-model/cron-trigger.js.map +1 -1
- package/dist/core/workflow-model/index.d.ts +1 -1
- package/dist/core/workflow-model/index.d.ts.map +1 -1
- package/dist/core/workflow-model/index.js.map +1 -1
- package/dist/core/workflow-model/invalid-workflow-model-error.d.ts +4 -2
- package/dist/core/workflow-model/invalid-workflow-model-error.d.ts.map +1 -1
- package/dist/core/workflow-model/invalid-workflow-model-error.js.map +1 -1
- package/dist/core/workflow-model/normalize-job-listening.d.ts.map +1 -1
- package/dist/core/workflow-model/normalize-job-listening.js +51 -30
- package/dist/core/workflow-model/normalize-job-listening.js.map +1 -1
- package/dist/core/workflow-model/normalize-triggers.d.ts +1 -1
- package/dist/core/workflow-model/normalize-triggers.d.ts.map +1 -1
- package/dist/core/workflow-model/normalize-triggers.js +48 -18
- package/dist/core/workflow-model/normalize-triggers.js.map +1 -1
- package/dist/core/workflow-model/normalize-workflow-document.d.ts +1 -1
- package/dist/core/workflow-model/normalize-workflow-document.d.ts.map +1 -1
- package/dist/core/workflow-model/normalize-workflow-document.js +3 -3
- package/dist/core/workflow-model/normalize-workflow-document.js.map +1 -1
- package/dist/core/workflow-model/parse-interpolation-field.d.ts.map +1 -1
- package/dist/core/workflow-model/parse-interpolation-field.js +1 -15
- package/dist/core/workflow-model/parse-interpolation-field.js.map +1 -1
- package/dist/core/workflow-model/validate-predicate-expression.d.ts +3 -1
- package/dist/core/workflow-model/validate-predicate-expression.d.ts.map +1 -1
- package/dist/core/workflow-model/validate-predicate-expression.js +3 -0
- package/dist/core/workflow-model/validate-predicate-expression.js.map +1 -1
- package/dist/core/workflow-model/validation-issue.d.ts +2 -1
- package/dist/core/workflow-model/validation-issue.d.ts.map +1 -1
- package/dist/core/workflow-model/validation-issue.js +12 -15
- package/dist/core/workflow-model/validation-issue.js.map +1 -1
- package/dist/db/db.d.ts +196 -4
- package/dist/db/db.d.ts.map +1 -1
- package/dist/db/db.js +3 -1
- package/dist/db/db.js.map +1 -1
- package/dist/db/definition-triggers.js +3 -1
- package/dist/db/definition-triggers.js.map +1 -1
- package/dist/db/definitions.d.ts +17 -0
- package/dist/db/definitions.d.ts.map +1 -1
- package/dist/db/definitions.js +190 -23
- package/dist/db/definitions.js.map +1 -1
- package/dist/db/index.d.ts +2 -1
- package/dist/db/index.d.ts.map +1 -1
- package/dist/db/index.js +2 -1
- package/dist/db/index.js.map +1 -1
- package/dist/db/schema/definitions.d.ts +17 -0
- package/dist/db/schema/definitions.d.ts.map +1 -1
- package/dist/db/schema/definitions.js +8 -0
- package/dist/db/schema/definitions.js.map +1 -1
- package/dist/db/schema/sync-states.d.ts +7 -3
- package/dist/db/schema/sync-states.d.ts.map +1 -1
- package/dist/db/schema/sync-states.js +5 -1
- package/dist/db/schema/sync-states.js.map +1 -1
- package/dist/db/schema/workflows.d.ts +78 -0
- package/dist/db/schema/workflows.d.ts.map +1 -0
- package/dist/db/schema/workflows.js +17 -0
- package/dist/db/schema/workflows.js.map +1 -0
- package/dist/db/sync-states.d.ts +2 -2
- package/dist/db/sync-states.d.ts.map +1 -1
- package/dist/db/sync-states.js +4 -4
- package/dist/db/sync-states.js.map +1 -1
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +5 -1
- package/dist/index.js.map +1 -1
- package/dist/metrics/index.d.ts +2 -0
- package/dist/metrics/index.d.ts.map +1 -0
- package/dist/metrics/index.js +3 -0
- package/dist/metrics/index.js.map +1 -0
- package/dist/metrics/instance.d.ts +4 -0
- package/dist/metrics/instance.d.ts.map +1 -0
- package/dist/metrics/instance.js +19 -0
- package/dist/metrics/instance.js.map +1 -0
- package/dist/presentation/dto/definition.d.ts.map +1 -1
- package/dist/presentation/dto/definition.js +11 -4
- package/dist/presentation/dto/definition.js.map +1 -1
- package/dist/presentation/inter-module.d.ts +9 -1
- package/dist/presentation/inter-module.d.ts.map +1 -1
- package/dist/presentation/inter-module.js +66 -2
- package/dist/presentation/inter-module.js.map +1 -1
- package/dist/presentation/routes/create-definition.d.ts.map +1 -1
- package/dist/presentation/routes/create-definition.js +16 -3
- package/dist/presentation/routes/create-definition.js.map +1 -1
- package/dist/presentation/routes/get-definition.d.ts.map +1 -1
- package/dist/presentation/routes/get-definition.js +18 -4
- package/dist/presentation/routes/get-definition.js.map +1 -1
- package/dist/presentation/routes/project-access.d.ts +1 -0
- package/dist/presentation/routes/project-access.d.ts.map +1 -1
- package/dist/presentation/routes/validate-definition.js +3 -3
- package/dist/presentation/routes/validate-definition.js.map +1 -1
- package/dist/temporal/activities/sync-activities.d.ts +3 -3
- package/dist/temporal/activities/sync-activities.d.ts.map +1 -1
- package/dist/temporal/activities/sync-activities.js +7 -4
- package/dist/temporal/activities/sync-activities.js.map +1 -1
- package/dist/temporal/workflows/definition-sync.js +1 -1
- package/dist/temporal/workflows/definition-sync.js.map +1 -1
- package/dist/temporal/workflows/index.bundle.js +50 -22
- package/dist/tsconfig.test.tsbuildinfo +1 -1
- package/drizzle/0003_nebulous_nemesis.sql +11 -0
- package/drizzle/0004_workflow_ref_lookup.sql +1 -0
- package/drizzle/meta/0003_snapshot.json +627 -0
- package/drizzle/meta/0004_snapshot.json +649 -0
- package/drizzle/meta/_journal.json +14 -0
- package/drizzle.config.ts +1 -0
- package/package.json +7 -7
- package/src/core/entities/index.ts +1 -1
- package/src/core/entities/integration-context.ts +4 -0
- package/src/core/entities/sync-state.test.ts +49 -0
- package/src/core/entities/sync-state.ts +35 -12
- package/src/core/entities/validation-diagnostic.ts +8 -0
- package/src/core/entities/workflow-definition.ts +2 -0
- package/src/core/errors.ts +26 -0
- package/src/core/index.ts +12 -0
- package/src/core/integrations.test.ts +38 -0
- package/src/core/integrations.ts +10 -1
- package/src/core/parse-definition-diagnostics.test.ts +47 -0
- package/src/core/parse-definition.test.ts +29 -5
- package/src/core/parse-definition.ts +7 -7
- package/src/core/resolve-definition-at-ref.test.ts +792 -0
- package/src/core/resolve-definition-at-ref.ts +551 -0
- package/src/core/sync-definitions.test.ts +61 -2
- package/src/core/sync-definitions.ts +7 -7
- package/src/core/validate-definition.test.ts +31 -22
- package/src/core/validate-definition.ts +21 -13
- package/src/core/workflow-model/cron-trigger.ts +6 -2
- package/src/core/workflow-model/index.ts +1 -0
- package/src/core/workflow-model/invalid-workflow-model-error.ts +5 -1
- package/src/core/workflow-model/normalize-job-listening.ts +55 -23
- package/src/core/workflow-model/normalize-triggers.ts +44 -15
- package/src/core/workflow-model/normalize-workflow-document.test.ts +494 -36
- package/src/core/workflow-model/normalize-workflow-document.ts +8 -4
- package/src/core/workflow-model/parse-interpolation-field.ts +1 -23
- package/src/core/workflow-model/validate-predicate-expression.ts +6 -0
- package/src/core/workflow-model/validation-issue.ts +8 -13
- package/src/db/db.ts +7 -1
- package/src/db/definition-triggers.test.ts +44 -0
- package/src/db/definition-triggers.ts +1 -1
- package/src/db/definitions.test.ts +300 -1
- package/src/db/definitions.ts +282 -28
- package/src/db/index.ts +2 -0
- package/src/db/schema/definitions.test.ts +1 -0
- package/src/db/schema/definitions.ts +11 -0
- package/src/db/schema/sync-states.ts +12 -3
- package/src/db/schema/workflows.ts +23 -0
- package/src/db/sync-states.test.ts +87 -18
- package/src/db/sync-states.ts +6 -6
- package/src/db/workflow-lineage-migration.test.ts +158 -0
- package/src/index.ts +3 -1
- package/src/metrics/index.ts +1 -0
- package/src/metrics/instance.test.ts +50 -0
- package/src/metrics/instance.ts +23 -0
- package/src/presentation/dto/definition.test.ts +89 -1
- package/src/presentation/dto/definition.ts +8 -5
- package/src/presentation/inter-module.test.ts +177 -0
- package/src/presentation/inter-module.ts +77 -4
- package/src/presentation/routes/create-definition.test.ts +38 -0
- package/src/presentation/routes/create-definition.ts +20 -3
- package/src/presentation/routes/get-definition.test.ts +125 -11
- package/src/presentation/routes/get-definition.ts +21 -4
- package/src/presentation/routes/list-definitions.test.ts +1 -1
- package/src/presentation/routes/validate-definition.test.ts +1 -1
- package/src/presentation/routes/validate-definition.ts +3 -3
- package/src/presentation/subscribers/on-integration-connection-available.test.ts +3 -0
- package/src/temporal/activities/sync-activities.test.ts +46 -2
- package/src/temporal/activities/sync-activities.ts +9 -7
- package/src/temporal/workflows/definition-sync.ts +1 -1
- package/test/factories/definition.ts +1 -0
- package/test/globalSetup.ts +2 -0
- package/tsconfig.build.tsbuildinfo +1 -1
- package/dist/core/entities/validation-warning.d.ts +0 -6
- package/dist/core/entities/validation-warning.d.ts.map +0 -1
- package/dist/core/entities/validation-warning.js +0 -3
- package/dist/core/entities/validation-warning.js.map +0 -1
- package/src/core/entities/validation-warning.ts +0 -5
- package/src/core/parse-definition-warnings.test.ts +0 -33
|
@@ -0,0 +1,374 @@
|
|
|
1
|
+
import { createWorkflowModelSnapshot } from '@shipfox/api-definitions-dto';
|
|
2
|
+
import { integrationsInterModuleContract } from '@shipfox/api-integration-core-dto/inter-module';
|
|
3
|
+
import { isInterModuleKnownError } from '@shipfox/inter-module';
|
|
4
|
+
import { boundedMap } from '@shipfox/node-module';
|
|
5
|
+
import { definitionTriggersFor } from '#db/definition-triggers.js';
|
|
6
|
+
import { findOrCreateWorkflowLineage } from '#db/definitions.js';
|
|
7
|
+
import { recordDefinitionRefResolution } from '#metrics/index.js';
|
|
8
|
+
import { DefinitionAtRefError, DefinitionParseError } from './errors.js';
|
|
9
|
+
import { hasAgentStepIntegrations } from './has-agent-step-integrations.js';
|
|
10
|
+
import { loadIntegrationValidationContext } from './integrations.js';
|
|
11
|
+
import { parseDefinitionWithDiagnostics } from './parse-definition.js';
|
|
12
|
+
import { DEFAULT_WORKFLOW_PATH, FILE_FETCH_CONCURRENCY, MAX_WORKFLOW_FILE_BYTES, MAX_WORKFLOW_FILES } from './sync-definitions.js';
|
|
13
|
+
/**
|
|
14
|
+
* Resolves a workflow definition file at a git ref without persisting it.
|
|
15
|
+
* The ref is pinned to a commit, the file is fetched at that commit, and the
|
|
16
|
+
* result is validated with the sync pipeline. Only the workflow lineage row is
|
|
17
|
+
* created so the dev run can be numbered; no definition row and no outbox
|
|
18
|
+
* event are written.
|
|
19
|
+
*/ export async function resolveDefinitionAtRef(params) {
|
|
20
|
+
try {
|
|
21
|
+
return await resolveDefinitionAtRefUnsafe(params);
|
|
22
|
+
} catch (error) {
|
|
23
|
+
if (error instanceof DefinitionAtRefError) {
|
|
24
|
+
recordDefinitionRefResolution(error.code);
|
|
25
|
+
}
|
|
26
|
+
throw error;
|
|
27
|
+
}
|
|
28
|
+
}
|
|
29
|
+
async function resolveDefinitionAtRefUnsafe(params) {
|
|
30
|
+
throwIfAborted(params.signal);
|
|
31
|
+
const source = await requireProjectSource(params.projects, params.projectId, params.signal);
|
|
32
|
+
const commit = await resolveRefToCommit({
|
|
33
|
+
integrations: params.integrations,
|
|
34
|
+
source,
|
|
35
|
+
ref: params.ref,
|
|
36
|
+
signal: params.signal
|
|
37
|
+
});
|
|
38
|
+
throwIfAborted(params.signal);
|
|
39
|
+
if (params.expectedCommit !== undefined && commit !== params.expectedCommit) {
|
|
40
|
+
throw new DefinitionAtRefError('ref-moved', `Git ref ${params.ref} no longer resolves to the expected commit`, {
|
|
41
|
+
ref: params.ref,
|
|
42
|
+
expectedCommit: params.expectedCommit
|
|
43
|
+
});
|
|
44
|
+
}
|
|
45
|
+
const snapshot = await fetchFileAtCommit({
|
|
46
|
+
integrations: params.integrations,
|
|
47
|
+
source,
|
|
48
|
+
commit,
|
|
49
|
+
ref: params.ref,
|
|
50
|
+
configPath: params.configPath,
|
|
51
|
+
signal: params.signal
|
|
52
|
+
});
|
|
53
|
+
assertFileSize(snapshot.content, snapshot.path);
|
|
54
|
+
const parsed = await parseDefinitionAtRef({
|
|
55
|
+
content: snapshot.content,
|
|
56
|
+
agent: params.agent,
|
|
57
|
+
integrations: params.integrations,
|
|
58
|
+
source,
|
|
59
|
+
signal: params.signal
|
|
60
|
+
});
|
|
61
|
+
throwIfAborted(params.signal);
|
|
62
|
+
const workflowId = await findOrCreateWorkflowLineage({
|
|
63
|
+
projectId: params.projectId,
|
|
64
|
+
configPath: params.configPath
|
|
65
|
+
});
|
|
66
|
+
recordDefinitionRefResolution('resolved');
|
|
67
|
+
return {
|
|
68
|
+
workflow: {
|
|
69
|
+
id: workflowId,
|
|
70
|
+
configPath: params.configPath
|
|
71
|
+
},
|
|
72
|
+
commit,
|
|
73
|
+
model: createWorkflowModelSnapshot(parsed.model),
|
|
74
|
+
sourceSnapshot: {
|
|
75
|
+
content: snapshot.content,
|
|
76
|
+
format: 'yaml'
|
|
77
|
+
},
|
|
78
|
+
triggers: definitionTriggersFor(parsed.model),
|
|
79
|
+
warnings: warningsFor(parsed.diagnostics)
|
|
80
|
+
};
|
|
81
|
+
}
|
|
82
|
+
/**
|
|
83
|
+
* Lists the workflow files at a git ref with their validation state. Applies
|
|
84
|
+
* the sync limits (100 files, 1 MB per file). One invalid file does not fail
|
|
85
|
+
* the listing; it is reported as invalid.
|
|
86
|
+
*/ export async function listDefinitionsAtRef(params) {
|
|
87
|
+
try {
|
|
88
|
+
return await listDefinitionsAtRefUnsafe(params);
|
|
89
|
+
} catch (error) {
|
|
90
|
+
if (error instanceof DefinitionAtRefError) {
|
|
91
|
+
recordDefinitionRefResolution(error.code);
|
|
92
|
+
}
|
|
93
|
+
throw error;
|
|
94
|
+
}
|
|
95
|
+
}
|
|
96
|
+
async function listDefinitionsAtRefUnsafe(params) {
|
|
97
|
+
throwIfAborted(params.signal);
|
|
98
|
+
const source = await requireProjectSource(params.projects, params.projectId, params.signal);
|
|
99
|
+
const commit = await resolveRefToCommit({
|
|
100
|
+
integrations: params.integrations,
|
|
101
|
+
source,
|
|
102
|
+
ref: params.ref,
|
|
103
|
+
signal: params.signal
|
|
104
|
+
});
|
|
105
|
+
throwIfAborted(params.signal);
|
|
106
|
+
const paths = await listWorkflowFilesAtCommit({
|
|
107
|
+
integrations: params.integrations,
|
|
108
|
+
source,
|
|
109
|
+
commit,
|
|
110
|
+
signal: params.signal
|
|
111
|
+
});
|
|
112
|
+
const fetched = await boundedMap(paths, FILE_FETCH_CONCURRENCY, (path)=>fetchListingFile({
|
|
113
|
+
integrations: params.integrations,
|
|
114
|
+
source,
|
|
115
|
+
commit,
|
|
116
|
+
ref: params.ref,
|
|
117
|
+
path,
|
|
118
|
+
signal: params.signal
|
|
119
|
+
}), {
|
|
120
|
+
stopOnError: true,
|
|
121
|
+
signal: params.signal
|
|
122
|
+
});
|
|
123
|
+
throwIfAborted(params.signal);
|
|
124
|
+
const agentValidationCatalog = await callWithSignal(params.agent.getValidationCatalog, {}, params.signal);
|
|
125
|
+
throwIfAborted(params.signal);
|
|
126
|
+
let entries = fetched.map((entry)=>{
|
|
127
|
+
throwIfAborted(params.signal);
|
|
128
|
+
return parseListingEntry(entry, {
|
|
129
|
+
agentValidationCatalog
|
|
130
|
+
});
|
|
131
|
+
});
|
|
132
|
+
const needsIntegrationContext = entries.some((entry)=>'definition' in entry && hasAgentStepIntegrations(entry.definition.document));
|
|
133
|
+
if (needsIntegrationContext) {
|
|
134
|
+
const integrationValidationContext = await loadAtRefIntegrationValidationContext({
|
|
135
|
+
integrations: params.integrations,
|
|
136
|
+
source,
|
|
137
|
+
signal: params.signal
|
|
138
|
+
});
|
|
139
|
+
entries = entries.map((entry)=>'definition' in entry && hasAgentStepIntegrations(entry.definition.document) ? parseListingEntry({
|
|
140
|
+
path: entry.path,
|
|
141
|
+
content: entry.content
|
|
142
|
+
}, {
|
|
143
|
+
agentValidationCatalog,
|
|
144
|
+
integrationValidationContext
|
|
145
|
+
}) : entry);
|
|
146
|
+
}
|
|
147
|
+
throwIfAborted(params.signal);
|
|
148
|
+
recordDefinitionRefResolution('resolved');
|
|
149
|
+
return {
|
|
150
|
+
commit,
|
|
151
|
+
files: entries.map((entry)=>listingFileFor(entry))
|
|
152
|
+
};
|
|
153
|
+
}
|
|
154
|
+
async function requireProjectSource(projects, projectId, signal) {
|
|
155
|
+
const { project } = await callWithSignal(projects.getProjectById, {
|
|
156
|
+
projectId
|
|
157
|
+
}, signal);
|
|
158
|
+
if (project === null) {
|
|
159
|
+
throw new DefinitionAtRefError('project-not-found', `Project not found: ${projectId}`, {
|
|
160
|
+
projectId
|
|
161
|
+
});
|
|
162
|
+
}
|
|
163
|
+
return {
|
|
164
|
+
workspaceId: project.workspaceId,
|
|
165
|
+
connectionId: project.sourceConnectionId,
|
|
166
|
+
externalRepositoryId: project.sourceExternalRepositoryId
|
|
167
|
+
};
|
|
168
|
+
}
|
|
169
|
+
async function resolveRefToCommit(params) {
|
|
170
|
+
try {
|
|
171
|
+
const resolved = await callWithSignal(params.integrations.resolveSourceRef, {
|
|
172
|
+
workspaceId: params.source.workspaceId,
|
|
173
|
+
connectionId: params.source.connectionId,
|
|
174
|
+
externalRepositoryId: params.source.externalRepositoryId,
|
|
175
|
+
ref: params.ref
|
|
176
|
+
}, params.signal);
|
|
177
|
+
return resolved.commit;
|
|
178
|
+
} catch (error) {
|
|
179
|
+
if (isInterModuleKnownError(integrationsInterModuleContract.methods.resolveSourceRef, error)) {
|
|
180
|
+
if (error.code === 'ref-not-found') {
|
|
181
|
+
throw new DefinitionAtRefError('ref-not-found', `Git ref not found: ${params.ref}`, {
|
|
182
|
+
ref: params.ref
|
|
183
|
+
});
|
|
184
|
+
}
|
|
185
|
+
if (error.code === 'ref-invalid') {
|
|
186
|
+
throw new DefinitionAtRefError('ref-invalid', `Git ref is not a resolvable branch or tag name: ${params.ref}`, {
|
|
187
|
+
ref: params.ref
|
|
188
|
+
});
|
|
189
|
+
}
|
|
190
|
+
throw sourceUnavailable(error, 'The source repository is unavailable');
|
|
191
|
+
}
|
|
192
|
+
throw error;
|
|
193
|
+
}
|
|
194
|
+
}
|
|
195
|
+
async function listWorkflowFilesAtCommit(params) {
|
|
196
|
+
let page;
|
|
197
|
+
try {
|
|
198
|
+
page = await callWithSignal(params.integrations.listSourceFiles, {
|
|
199
|
+
workspaceId: params.source.workspaceId,
|
|
200
|
+
connectionId: params.source.connectionId,
|
|
201
|
+
externalRepositoryId: params.source.externalRepositoryId,
|
|
202
|
+
ref: params.commit,
|
|
203
|
+
prefix: DEFAULT_WORKFLOW_PATH,
|
|
204
|
+
limit: MAX_WORKFLOW_FILES
|
|
205
|
+
}, params.signal);
|
|
206
|
+
} catch (error) {
|
|
207
|
+
throwIfAborted(params.signal);
|
|
208
|
+
throw sourceUnavailable(error, 'The workflow files at the ref could not be listed');
|
|
209
|
+
}
|
|
210
|
+
if (page.nextCursor) {
|
|
211
|
+
throw new DefinitionAtRefError('too-many-files', `More than ${MAX_WORKFLOW_FILES} workflow files were found`);
|
|
212
|
+
}
|
|
213
|
+
return page.files.filter((file)=>file.path.endsWith('.yml') || file.path.endsWith('.yaml')).map((file)=>file.path);
|
|
214
|
+
}
|
|
215
|
+
async function fetchFileAtCommit(params) {
|
|
216
|
+
try {
|
|
217
|
+
return await callWithSignal(params.integrations.fetchSourceFile, {
|
|
218
|
+
workspaceId: params.source.workspaceId,
|
|
219
|
+
connectionId: params.source.connectionId,
|
|
220
|
+
externalRepositoryId: params.source.externalRepositoryId,
|
|
221
|
+
ref: params.commit,
|
|
222
|
+
path: params.configPath
|
|
223
|
+
}, params.signal);
|
|
224
|
+
} catch (error) {
|
|
225
|
+
throwIfAborted(params.signal);
|
|
226
|
+
if (isInterModuleKnownError(integrationsInterModuleContract.methods.fetchSourceFile, error)) {
|
|
227
|
+
if (error.code === 'provider-failure' && error.details.reason === 'file-not-found') {
|
|
228
|
+
throw new DefinitionAtRefError('file-not-found', `Workflow file not found at ${params.ref}: ${params.configPath}`, {
|
|
229
|
+
ref: params.ref,
|
|
230
|
+
configPath: params.configPath
|
|
231
|
+
});
|
|
232
|
+
}
|
|
233
|
+
throw sourceUnavailable(error, 'The workflow file at the ref could not be fetched');
|
|
234
|
+
}
|
|
235
|
+
throw error;
|
|
236
|
+
}
|
|
237
|
+
}
|
|
238
|
+
function assertFileSize(content, path) {
|
|
239
|
+
if (Buffer.byteLength(content, 'utf8') > MAX_WORKFLOW_FILE_BYTES) {
|
|
240
|
+
throw new DefinitionAtRefError('content-too-large', `Workflow file is larger than ${MAX_WORKFLOW_FILE_BYTES} bytes: ${path}`, {
|
|
241
|
+
configPath: path
|
|
242
|
+
});
|
|
243
|
+
}
|
|
244
|
+
}
|
|
245
|
+
async function parseDefinitionAtRef(params) {
|
|
246
|
+
const agentValidationCatalog = await callWithSignal(params.agent.getValidationCatalog, {}, params.signal);
|
|
247
|
+
throwIfAborted(params.signal);
|
|
248
|
+
const firstPass = parseWorkflowDefinition(params.content, {
|
|
249
|
+
agentValidationCatalog
|
|
250
|
+
});
|
|
251
|
+
if (!hasAgentStepIntegrations(firstPass.document)) return firstPass;
|
|
252
|
+
const integrationValidationContext = await loadAtRefIntegrationValidationContext({
|
|
253
|
+
integrations: params.integrations,
|
|
254
|
+
source: params.source,
|
|
255
|
+
signal: params.signal
|
|
256
|
+
});
|
|
257
|
+
return parseWorkflowDefinition(params.content, {
|
|
258
|
+
agentValidationCatalog,
|
|
259
|
+
integrationValidationContext
|
|
260
|
+
});
|
|
261
|
+
}
|
|
262
|
+
function parseWorkflowDefinition(content, options) {
|
|
263
|
+
try {
|
|
264
|
+
return parseDefinitionWithDiagnostics(content, options);
|
|
265
|
+
} catch (error) {
|
|
266
|
+
if (error instanceof DefinitionParseError) {
|
|
267
|
+
throw new DefinitionAtRefError('invalid-definition', `Invalid workflow definition: ${error.message}`, {
|
|
268
|
+
errors: error.details ?? []
|
|
269
|
+
});
|
|
270
|
+
}
|
|
271
|
+
throw error;
|
|
272
|
+
}
|
|
273
|
+
}
|
|
274
|
+
async function fetchListingFile(params) {
|
|
275
|
+
try {
|
|
276
|
+
const snapshot = await fetchFileAtCommit({
|
|
277
|
+
integrations: params.integrations,
|
|
278
|
+
source: params.source,
|
|
279
|
+
commit: params.commit,
|
|
280
|
+
ref: params.ref,
|
|
281
|
+
configPath: params.path,
|
|
282
|
+
signal: params.signal
|
|
283
|
+
});
|
|
284
|
+
assertFileSize(snapshot.content, snapshot.path);
|
|
285
|
+
return {
|
|
286
|
+
path: snapshot.path,
|
|
287
|
+
content: snapshot.content
|
|
288
|
+
};
|
|
289
|
+
} catch (error) {
|
|
290
|
+
if (error instanceof DefinitionAtRefError && isPerFileListingError(error.code)) {
|
|
291
|
+
return {
|
|
292
|
+
path: params.path,
|
|
293
|
+
errors: [
|
|
294
|
+
{
|
|
295
|
+
message: error.message
|
|
296
|
+
}
|
|
297
|
+
]
|
|
298
|
+
};
|
|
299
|
+
}
|
|
300
|
+
throw error;
|
|
301
|
+
}
|
|
302
|
+
}
|
|
303
|
+
function parseListingEntry(entry, options) {
|
|
304
|
+
if ('errors' in entry) return entry;
|
|
305
|
+
try {
|
|
306
|
+
const definition = parseDefinitionWithDiagnostics(entry.content, options);
|
|
307
|
+
return {
|
|
308
|
+
path: entry.path,
|
|
309
|
+
content: entry.content,
|
|
310
|
+
definition
|
|
311
|
+
};
|
|
312
|
+
} catch (error) {
|
|
313
|
+
if (error instanceof DefinitionParseError) {
|
|
314
|
+
return {
|
|
315
|
+
path: entry.path,
|
|
316
|
+
errors: error.details ?? []
|
|
317
|
+
};
|
|
318
|
+
}
|
|
319
|
+
throw error;
|
|
320
|
+
}
|
|
321
|
+
}
|
|
322
|
+
function listingFileFor(entry) {
|
|
323
|
+
if ('definition' in entry) {
|
|
324
|
+
return {
|
|
325
|
+
configPath: entry.path,
|
|
326
|
+
name: entry.definition.document.name,
|
|
327
|
+
valid: true,
|
|
328
|
+
errors: [],
|
|
329
|
+
warnings: warningsFor(entry.definition.diagnostics),
|
|
330
|
+
triggers: definitionTriggersFor(entry.definition.model)
|
|
331
|
+
};
|
|
332
|
+
}
|
|
333
|
+
return {
|
|
334
|
+
configPath: entry.path,
|
|
335
|
+
name: null,
|
|
336
|
+
valid: false,
|
|
337
|
+
errors: entry.errors,
|
|
338
|
+
warnings: [],
|
|
339
|
+
triggers: {}
|
|
340
|
+
};
|
|
341
|
+
}
|
|
342
|
+
function warningsFor(diagnostics) {
|
|
343
|
+
return diagnostics.filter((diagnostic)=>diagnostic.severity === 'warning').map((diagnostic)=>({
|
|
344
|
+
code: diagnostic.code,
|
|
345
|
+
message: diagnostic.message,
|
|
346
|
+
...diagnostic.path === undefined ? {} : {
|
|
347
|
+
path: diagnostic.path
|
|
348
|
+
}
|
|
349
|
+
}));
|
|
350
|
+
}
|
|
351
|
+
async function loadAtRefIntegrationValidationContext(params) {
|
|
352
|
+
try {
|
|
353
|
+
return await loadIntegrationValidationContext(params.integrations, params.source.workspaceId, params.source.connectionId, params.signal);
|
|
354
|
+
} catch (error) {
|
|
355
|
+
throwIfAborted(params.signal);
|
|
356
|
+
throw sourceUnavailable(error, 'Integration validation context is unavailable');
|
|
357
|
+
}
|
|
358
|
+
}
|
|
359
|
+
function isPerFileListingError(code) {
|
|
360
|
+
return code === 'file-not-found' || code === 'content-too-large' || code === 'invalid-definition';
|
|
361
|
+
}
|
|
362
|
+
function callWithSignal(method, input, signal) {
|
|
363
|
+
return signal === undefined ? method(input) : method(input, {
|
|
364
|
+
signal
|
|
365
|
+
});
|
|
366
|
+
}
|
|
367
|
+
function throwIfAborted(signal) {
|
|
368
|
+
if (signal?.aborted) throw signal.reason ?? new Error('Operation aborted');
|
|
369
|
+
}
|
|
370
|
+
function sourceUnavailable(error, message) {
|
|
371
|
+
return new DefinitionAtRefError('source-unavailable', `${message}: ${error instanceof Error ? error.message : String(error)}`);
|
|
372
|
+
}
|
|
373
|
+
|
|
374
|
+
//# sourceMappingURL=resolve-definition-at-ref.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../../src/core/resolve-definition-at-ref.ts"],"sourcesContent":["import type {AgentInterModuleClient} from '@shipfox/api-agent-dto/inter-module';\nimport type {\n TriggerDto,\n WorkflowModelSnapshot,\n WorkflowSourceSnapshot,\n} from '@shipfox/api-definitions-dto';\nimport {createWorkflowModelSnapshot} from '@shipfox/api-definitions-dto';\nimport {\n type IntegrationsModuleClient,\n integrationsInterModuleContract,\n} from '@shipfox/api-integration-core-dto/inter-module';\nimport type {ProjectsModuleClient} from '@shipfox/api-projects-dto/inter-module';\nimport {isInterModuleKnownError} from '@shipfox/inter-module';\nimport {boundedMap} from '@shipfox/node-module';\nimport {definitionTriggersFor} from '#db/definition-triggers.js';\nimport {findOrCreateWorkflowLineage} from '#db/definitions.js';\nimport {recordDefinitionRefResolution} from '#metrics/index.js';\nimport type {ValidationDiagnostic} from './entities/validation-diagnostic.js';\nimport {\n DefinitionAtRefError,\n type DefinitionAtRefErrorCode,\n DefinitionParseError,\n} from './errors.js';\nimport {hasAgentStepIntegrations} from './has-agent-step-integrations.js';\nimport {loadIntegrationValidationContext} from './integrations.js';\nimport type {ParsedDefinition} from './parse-definition.js';\nimport {parseDefinitionWithDiagnostics} from './parse-definition.js';\nimport {\n DEFAULT_WORKFLOW_PATH,\n FILE_FETCH_CONCURRENCY,\n MAX_WORKFLOW_FILE_BYTES,\n MAX_WORKFLOW_FILES,\n} from './sync-definitions.js';\nimport type {ValidationError} from './validate-definition.js';\n\nexport interface ResolveDefinitionAtRefParams {\n projectId: string;\n ref: string;\n configPath: string;\n expectedCommit?: string | undefined;\n projects: ProjectsModuleClient;\n agent: AgentInterModuleClient;\n integrations: IntegrationsModuleClient;\n signal?: AbortSignal;\n}\n\nexport interface ValidationWarning {\n code: string;\n message: string;\n path?: string | undefined;\n}\n\nexport interface ResolvedDefinitionAtRef {\n workflow: {id: string; configPath: string};\n commit: string;\n model: WorkflowModelSnapshot;\n sourceSnapshot: WorkflowSourceSnapshot;\n triggers: Record<string, TriggerDto>;\n warnings: ValidationWarning[];\n}\n\nexport interface ListDefinitionsAtRefParams {\n projectId: string;\n ref: string;\n projects: ProjectsModuleClient;\n agent: AgentInterModuleClient;\n integrations: IntegrationsModuleClient;\n signal?: AbortSignal;\n}\n\nexport interface DefinitionAtRefFile {\n configPath: string;\n name: string | null;\n valid: boolean;\n errors: ValidationError[];\n warnings: ValidationWarning[];\n triggers: Record<string, TriggerDto>;\n}\n\nexport interface DefinitionsAtRefListing {\n commit: string;\n files: DefinitionAtRefFile[];\n}\n\ninterface ResolvedProjectSource {\n workspaceId: string;\n connectionId: string;\n externalRepositoryId: string;\n}\n\n/**\n * Resolves a workflow definition file at a git ref without persisting it.\n * The ref is pinned to a commit, the file is fetched at that commit, and the\n * result is validated with the sync pipeline. Only the workflow lineage row is\n * created so the dev run can be numbered; no definition row and no outbox\n * event are written.\n */\nexport async function resolveDefinitionAtRef(\n params: ResolveDefinitionAtRefParams,\n): Promise<ResolvedDefinitionAtRef> {\n try {\n return await resolveDefinitionAtRefUnsafe(params);\n } catch (error) {\n if (error instanceof DefinitionAtRefError) {\n recordDefinitionRefResolution(error.code);\n }\n throw error;\n }\n}\n\nasync function resolveDefinitionAtRefUnsafe(\n params: ResolveDefinitionAtRefParams,\n): Promise<ResolvedDefinitionAtRef> {\n throwIfAborted(params.signal);\n const source = await requireProjectSource(params.projects, params.projectId, params.signal);\n const commit = await resolveRefToCommit({\n integrations: params.integrations,\n source,\n ref: params.ref,\n signal: params.signal,\n });\n throwIfAborted(params.signal);\n if (params.expectedCommit !== undefined && commit !== params.expectedCommit) {\n throw new DefinitionAtRefError(\n 'ref-moved',\n `Git ref ${params.ref} no longer resolves to the expected commit`,\n {ref: params.ref, expectedCommit: params.expectedCommit},\n );\n }\n\n const snapshot = await fetchFileAtCommit({\n integrations: params.integrations,\n source,\n commit,\n ref: params.ref,\n configPath: params.configPath,\n signal: params.signal,\n });\n assertFileSize(snapshot.content, snapshot.path);\n\n const parsed = await parseDefinitionAtRef({\n content: snapshot.content,\n agent: params.agent,\n integrations: params.integrations,\n source,\n signal: params.signal,\n });\n throwIfAborted(params.signal);\n const workflowId = await findOrCreateWorkflowLineage({\n projectId: params.projectId,\n configPath: params.configPath,\n });\n recordDefinitionRefResolution('resolved');\n\n return {\n workflow: {id: workflowId, configPath: params.configPath},\n commit,\n model: createWorkflowModelSnapshot(parsed.model),\n sourceSnapshot: {content: snapshot.content, format: 'yaml'},\n triggers: definitionTriggersFor(parsed.model),\n warnings: warningsFor(parsed.diagnostics),\n };\n}\n\n/**\n * Lists the workflow files at a git ref with their validation state. Applies\n * the sync limits (100 files, 1 MB per file). One invalid file does not fail\n * the listing; it is reported as invalid.\n */\nexport async function listDefinitionsAtRef(\n params: ListDefinitionsAtRefParams,\n): Promise<DefinitionsAtRefListing> {\n try {\n return await listDefinitionsAtRefUnsafe(params);\n } catch (error) {\n if (error instanceof DefinitionAtRefError) {\n recordDefinitionRefResolution(error.code);\n }\n throw error;\n }\n}\n\ntype ListingEntry =\n | {path: string; content: string; definition: ParsedDefinition}\n | {path: string; errors: ValidationError[]};\n\nasync function listDefinitionsAtRefUnsafe(\n params: ListDefinitionsAtRefParams,\n): Promise<DefinitionsAtRefListing> {\n throwIfAborted(params.signal);\n const source = await requireProjectSource(params.projects, params.projectId, params.signal);\n const commit = await resolveRefToCommit({\n integrations: params.integrations,\n source,\n ref: params.ref,\n signal: params.signal,\n });\n throwIfAborted(params.signal);\n const paths = await listWorkflowFilesAtCommit({\n integrations: params.integrations,\n source,\n commit,\n signal: params.signal,\n });\n\n const fetched = await boundedMap(\n paths,\n FILE_FETCH_CONCURRENCY,\n (path) =>\n fetchListingFile({\n integrations: params.integrations,\n source,\n commit,\n ref: params.ref,\n path,\n signal: params.signal,\n }),\n {stopOnError: true, signal: params.signal},\n );\n throwIfAborted(params.signal);\n const agentValidationCatalog = await callWithSignal(\n params.agent.getValidationCatalog,\n {},\n params.signal,\n );\n throwIfAborted(params.signal);\n let entries = fetched.map((entry) => {\n throwIfAborted(params.signal);\n return parseListingEntry(entry, {agentValidationCatalog});\n });\n\n const needsIntegrationContext = entries.some(\n (entry) => 'definition' in entry && hasAgentStepIntegrations(entry.definition.document),\n );\n if (needsIntegrationContext) {\n const integrationValidationContext = await loadAtRefIntegrationValidationContext({\n integrations: params.integrations,\n source,\n signal: params.signal,\n });\n entries = entries.map((entry) =>\n 'definition' in entry && hasAgentStepIntegrations(entry.definition.document)\n ? parseListingEntry(\n {path: entry.path, content: entry.content},\n {agentValidationCatalog, integrationValidationContext},\n )\n : entry,\n );\n }\n\n throwIfAborted(params.signal);\n recordDefinitionRefResolution('resolved');\n return {commit, files: entries.map((entry) => listingFileFor(entry))};\n}\n\nasync function requireProjectSource(\n projects: ProjectsModuleClient,\n projectId: string,\n signal: AbortSignal | undefined,\n): Promise<ResolvedProjectSource> {\n const {project} = await callWithSignal(projects.getProjectById, {projectId}, signal);\n if (project === null) {\n throw new DefinitionAtRefError('project-not-found', `Project not found: ${projectId}`, {\n projectId,\n });\n }\n return {\n workspaceId: project.workspaceId,\n connectionId: project.sourceConnectionId,\n externalRepositoryId: project.sourceExternalRepositoryId,\n };\n}\n\nasync function resolveRefToCommit(params: {\n integrations: IntegrationsModuleClient;\n source: ResolvedProjectSource;\n ref: string;\n signal: AbortSignal | undefined;\n}): Promise<string> {\n try {\n const resolved = await callWithSignal(\n params.integrations.resolveSourceRef,\n {\n workspaceId: params.source.workspaceId,\n connectionId: params.source.connectionId,\n externalRepositoryId: params.source.externalRepositoryId,\n ref: params.ref,\n },\n params.signal,\n );\n return resolved.commit;\n } catch (error) {\n if (isInterModuleKnownError(integrationsInterModuleContract.methods.resolveSourceRef, error)) {\n if (error.code === 'ref-not-found') {\n throw new DefinitionAtRefError('ref-not-found', `Git ref not found: ${params.ref}`, {\n ref: params.ref,\n });\n }\n if (error.code === 'ref-invalid') {\n throw new DefinitionAtRefError(\n 'ref-invalid',\n `Git ref is not a resolvable branch or tag name: ${params.ref}`,\n {ref: params.ref},\n );\n }\n throw sourceUnavailable(error, 'The source repository is unavailable');\n }\n throw error;\n }\n}\n\nasync function listWorkflowFilesAtCommit(params: {\n integrations: IntegrationsModuleClient;\n source: ResolvedProjectSource;\n commit: string;\n signal: AbortSignal | undefined;\n}): Promise<string[]> {\n let page: Awaited<ReturnType<IntegrationsModuleClient['listSourceFiles']>>;\n try {\n page = await callWithSignal(\n params.integrations.listSourceFiles,\n {\n workspaceId: params.source.workspaceId,\n connectionId: params.source.connectionId,\n externalRepositoryId: params.source.externalRepositoryId,\n ref: params.commit,\n prefix: DEFAULT_WORKFLOW_PATH,\n limit: MAX_WORKFLOW_FILES,\n },\n params.signal,\n );\n } catch (error) {\n throwIfAborted(params.signal);\n throw sourceUnavailable(error, 'The workflow files at the ref could not be listed');\n }\n if (page.nextCursor) {\n throw new DefinitionAtRefError(\n 'too-many-files',\n `More than ${MAX_WORKFLOW_FILES} workflow files were found`,\n );\n }\n return page.files\n .filter((file) => file.path.endsWith('.yml') || file.path.endsWith('.yaml'))\n .map((file) => file.path);\n}\n\nasync function fetchFileAtCommit(params: {\n integrations: IntegrationsModuleClient;\n source: ResolvedProjectSource;\n commit: string;\n ref: string;\n configPath: string;\n signal: AbortSignal | undefined;\n}): Promise<{path: string; content: string}> {\n try {\n return await callWithSignal(\n params.integrations.fetchSourceFile,\n {\n workspaceId: params.source.workspaceId,\n connectionId: params.source.connectionId,\n externalRepositoryId: params.source.externalRepositoryId,\n ref: params.commit,\n path: params.configPath,\n },\n params.signal,\n );\n } catch (error) {\n throwIfAborted(params.signal);\n if (isInterModuleKnownError(integrationsInterModuleContract.methods.fetchSourceFile, error)) {\n if (error.code === 'provider-failure' && error.details.reason === 'file-not-found') {\n throw new DefinitionAtRefError(\n 'file-not-found',\n `Workflow file not found at ${params.ref}: ${params.configPath}`,\n {ref: params.ref, configPath: params.configPath},\n );\n }\n throw sourceUnavailable(error, 'The workflow file at the ref could not be fetched');\n }\n throw error;\n }\n}\n\nfunction assertFileSize(content: string, path: string): void {\n if (Buffer.byteLength(content, 'utf8') > MAX_WORKFLOW_FILE_BYTES) {\n throw new DefinitionAtRefError(\n 'content-too-large',\n `Workflow file is larger than ${MAX_WORKFLOW_FILE_BYTES} bytes: ${path}`,\n {configPath: path},\n );\n }\n}\n\nasync function parseDefinitionAtRef(params: {\n content: string;\n agent: AgentInterModuleClient;\n integrations: IntegrationsModuleClient;\n source: ResolvedProjectSource;\n signal: AbortSignal | undefined;\n}): Promise<ParsedDefinition> {\n const agentValidationCatalog = await callWithSignal(\n params.agent.getValidationCatalog,\n {},\n params.signal,\n );\n throwIfAborted(params.signal);\n const firstPass = parseWorkflowDefinition(params.content, {agentValidationCatalog});\n if (!hasAgentStepIntegrations(firstPass.document)) return firstPass;\n\n const integrationValidationContext = await loadAtRefIntegrationValidationContext({\n integrations: params.integrations,\n source: params.source,\n signal: params.signal,\n });\n return parseWorkflowDefinition(params.content, {\n agentValidationCatalog,\n integrationValidationContext,\n });\n}\n\nfunction parseWorkflowDefinition(\n content: string,\n options: Parameters<typeof parseDefinitionWithDiagnostics>[1],\n): ParsedDefinition {\n try {\n return parseDefinitionWithDiagnostics(content, options);\n } catch (error) {\n if (error instanceof DefinitionParseError) {\n throw new DefinitionAtRefError(\n 'invalid-definition',\n `Invalid workflow definition: ${error.message}`,\n {errors: (error.details ?? []) as ValidationError[]},\n );\n }\n throw error;\n }\n}\n\nasync function fetchListingFile(params: {\n integrations: IntegrationsModuleClient;\n source: ResolvedProjectSource;\n commit: string;\n ref: string;\n path: string;\n signal: AbortSignal | undefined;\n}): Promise<{path: string; content: string} | {path: string; errors: ValidationError[]}> {\n try {\n const snapshot = await fetchFileAtCommit({\n integrations: params.integrations,\n source: params.source,\n commit: params.commit,\n ref: params.ref,\n configPath: params.path,\n signal: params.signal,\n });\n assertFileSize(snapshot.content, snapshot.path);\n return {path: snapshot.path, content: snapshot.content};\n } catch (error) {\n if (error instanceof DefinitionAtRefError && isPerFileListingError(error.code)) {\n return {path: params.path, errors: [{message: error.message}]};\n }\n throw error;\n }\n}\n\nfunction parseListingEntry(\n entry: {path: string; content: string} | {path: string; errors: ValidationError[]},\n options: Parameters<typeof parseDefinitionWithDiagnostics>[1],\n): ListingEntry {\n if ('errors' in entry) return entry;\n try {\n const definition = parseDefinitionWithDiagnostics(entry.content, options);\n return {path: entry.path, content: entry.content, definition};\n } catch (error) {\n if (error instanceof DefinitionParseError) {\n return {path: entry.path, errors: (error.details ?? []) as ValidationError[]};\n }\n throw error;\n }\n}\n\nfunction listingFileFor(entry: ListingEntry): DefinitionAtRefFile {\n if ('definition' in entry) {\n return {\n configPath: entry.path,\n name: entry.definition.document.name,\n valid: true,\n errors: [],\n warnings: warningsFor(entry.definition.diagnostics),\n triggers: definitionTriggersFor(entry.definition.model),\n };\n }\n return {\n configPath: entry.path,\n name: null,\n valid: false,\n errors: entry.errors,\n warnings: [],\n triggers: {},\n };\n}\n\nfunction warningsFor(diagnostics: readonly ValidationDiagnostic[]): ValidationWarning[] {\n return diagnostics\n .filter((diagnostic) => diagnostic.severity === 'warning')\n .map((diagnostic) => ({\n code: diagnostic.code,\n message: diagnostic.message,\n ...(diagnostic.path === undefined ? {} : {path: diagnostic.path}),\n }));\n}\n\nasync function loadAtRefIntegrationValidationContext(params: {\n integrations: IntegrationsModuleClient;\n source: ResolvedProjectSource;\n signal: AbortSignal | undefined;\n}) {\n try {\n return await loadIntegrationValidationContext(\n params.integrations,\n params.source.workspaceId,\n params.source.connectionId,\n params.signal,\n );\n } catch (error) {\n throwIfAborted(params.signal);\n throw sourceUnavailable(error, 'Integration validation context is unavailable');\n }\n}\n\nfunction isPerFileListingError(code: DefinitionAtRefErrorCode): boolean {\n return code === 'file-not-found' || code === 'content-too-large' || code === 'invalid-definition';\n}\n\nfunction callWithSignal<Input, Output>(\n method: (input: Input, options?: {signal?: AbortSignal}) => Promise<Output>,\n input: Input,\n signal: AbortSignal | undefined,\n): Promise<Output> {\n return signal === undefined ? method(input) : method(input, {signal});\n}\n\nfunction throwIfAborted(signal: AbortSignal | undefined): void {\n if (signal?.aborted) throw signal.reason ?? new Error('Operation aborted');\n}\n\nfunction sourceUnavailable(error: unknown, message: string): DefinitionAtRefError {\n return new DefinitionAtRefError(\n 'source-unavailable',\n `${message}: ${error instanceof Error ? error.message : String(error)}`,\n );\n}\n"],"names":["createWorkflowModelSnapshot","integrationsInterModuleContract","isInterModuleKnownError","boundedMap","definitionTriggersFor","findOrCreateWorkflowLineage","recordDefinitionRefResolution","DefinitionAtRefError","DefinitionParseError","hasAgentStepIntegrations","loadIntegrationValidationContext","parseDefinitionWithDiagnostics","DEFAULT_WORKFLOW_PATH","FILE_FETCH_CONCURRENCY","MAX_WORKFLOW_FILE_BYTES","MAX_WORKFLOW_FILES","resolveDefinitionAtRef","params","resolveDefinitionAtRefUnsafe","error","code","throwIfAborted","signal","source","requireProjectSource","projects","projectId","commit","resolveRefToCommit","integrations","ref","expectedCommit","undefined","snapshot","fetchFileAtCommit","configPath","assertFileSize","content","path","parsed","parseDefinitionAtRef","agent","workflowId","workflow","id","model","sourceSnapshot","format","triggers","warnings","warningsFor","diagnostics","listDefinitionsAtRef","listDefinitionsAtRefUnsafe","paths","listWorkflowFilesAtCommit","fetched","fetchListingFile","stopOnError","agentValidationCatalog","callWithSignal","getValidationCatalog","entries","map","entry","parseListingEntry","needsIntegrationContext","some","definition","document","integrationValidationContext","loadAtRefIntegrationValidationContext","files","listingFileFor","project","getProjectById","workspaceId","connectionId","sourceConnectionId","externalRepositoryId","sourceExternalRepositoryId","resolved","resolveSourceRef","methods","sourceUnavailable","page","listSourceFiles","prefix","limit","nextCursor","filter","file","endsWith","fetchSourceFile","details","reason","Buffer","byteLength","firstPass","parseWorkflowDefinition","options","message","errors","isPerFileListingError","name","valid","diagnostic","severity","method","input","aborted","Error","String"],"mappings":"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"}
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import type { AgentValidationCatalog } from '@shipfox/api-agent-dto/inter-module';
|
|
2
2
|
import type { IntegrationValidationContext } from './entities/integration-context.js';
|
|
3
3
|
import type { DefinitionSyncErrorCode } from './entities/sync-state.js';
|
|
4
|
-
import type {
|
|
4
|
+
import type { ValidationDiagnostic } from './entities/validation-diagnostic.js';
|
|
5
5
|
import type { WorkflowDefinitionPayload } from './entities/workflow-definition.js';
|
|
6
6
|
import type { DefinitionsSourceControl } from './integrations.js';
|
|
7
7
|
export declare const DEFAULT_WORKFLOW_PATH = ".shipfox/workflows/";
|
|
@@ -31,7 +31,7 @@ export interface ParsedWorkflow {
|
|
|
31
31
|
name: string;
|
|
32
32
|
definition: WorkflowDefinitionPayload;
|
|
33
33
|
contentHash: string;
|
|
34
|
-
|
|
34
|
+
diagnostics: ValidationDiagnostic[];
|
|
35
35
|
}
|
|
36
36
|
export interface FetchAndParseWorkflowsParams extends SyncSourceContext {
|
|
37
37
|
ref: string;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"sync-definitions.d.ts","sourceRoot":"","sources":["../../src/core/sync-definitions.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAC,sBAAsB,EAAC,MAAM,qCAAqC,CAAC;AAIhF,OAAO,KAAK,EAAC,4BAA4B,EAAC,MAAM,mCAAmC,CAAC;AACpF,OAAO,KAAK,EAAC,uBAAuB,EAAC,MAAM,0BAA0B,CAAC;AACtE,OAAO,KAAK,EAAC,
|
|
1
|
+
{"version":3,"file":"sync-definitions.d.ts","sourceRoot":"","sources":["../../src/core/sync-definitions.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAC,sBAAsB,EAAC,MAAM,qCAAqC,CAAC;AAIhF,OAAO,KAAK,EAAC,4BAA4B,EAAC,MAAM,mCAAmC,CAAC;AACpF,OAAO,KAAK,EAAC,uBAAuB,EAAC,MAAM,0BAA0B,CAAC;AACtE,OAAO,KAAK,EAAC,oBAAoB,EAAC,MAAM,qCAAqC,CAAC;AAC9E,OAAO,KAAK,EAAC,yBAAyB,EAAC,MAAM,mCAAmC,CAAC;AAGjF,OAAO,KAAK,EAAC,wBAAwB,EAAC,MAAM,mBAAmB,CAAC;AAGhE,eAAO,MAAM,qBAAqB,wBAAwB,CAAC;AAC3D,eAAO,MAAM,kBAAkB,MAAM,CAAC;AACtC,eAAO,MAAM,uBAAuB,UAAY,CAAC;AACjD,eAAO,MAAM,sBAAsB,IAAI,CAAC;AACxC,eAAO,MAAM,mBAAmB,mBAAmB,CAAC;AAEpD,MAAM,WAAW,iBAAiB;IAChC,WAAW,EAAE,MAAM,CAAC;IACpB,kBAAkB,EAAE,MAAM,CAAC;IAC3B,0BAA0B,EAAE,MAAM,CAAC;IACnC,aAAa,EAAE,wBAAwB,CAAC;CACzC;AAED,MAAM,WAAW,kBAAkB;IACjC,GAAG,EAAE,MAAM,CAAC;CACb;AAED,wBAAsB,iBAAiB,CAAC,MAAM,EAAE,iBAAiB,GAAG,OAAO,CAAC,kBAAkB,CAAC,CAO9F;AAED,MAAM,WAAW,2BAA4B,SAAQ,iBAAiB;IACpE,GAAG,EAAE,MAAM,CAAC;IACZ,YAAY,CAAC,EAAE,MAAM,GAAG,SAAS,CAAC;CACnC;AAED,wBAAsB,qBAAqB,CACzC,MAAM,EAAE,2BAA2B,GAClC,OAAO,CAAC;IAAC,KAAK,EAAE,MAAM,EAAE,CAAA;CAAC,CAAC,CA4B5B;AAED,MAAM,WAAW,cAAc;IAC7B,IAAI,EAAE,MAAM,CAAC;IACb,IAAI,EAAE,MAAM,CAAC;IACb,UAAU,EAAE,yBAAyB,CAAC;IACtC,WAAW,EAAE,MAAM,CAAC;IACpB,WAAW,EAAE,oBAAoB,EAAE,CAAC;CACrC;AAED,MAAM,WAAW,4BAA6B,SAAQ,iBAAiB;IACrE,GAAG,EAAE,MAAM,CAAC;IACZ,KAAK,EAAE,MAAM,EAAE,CAAC;IAChB,UAAU,CAAC,EAAE,CAAC,CAAC,IAAI,EAAE,MAAM,KAAK,IAAI,CAAC,GAAG,SAAS,CAAC;IAClD,sBAAsB,EAAE,sBAAsB,CAAC;IAC/C,gCAAgC,CAAC,EAAE,CAAC,MAAM,OAAO,CAAC,4BAA4B,CAAC,CAAC,GAAG,SAAS,CAAC;CAC9F;AAED,wBAAsB,sBAAsB,CAC1C,MAAM,EAAE,4BAA4B,GACnC,OAAO,CAAC,cAAc,EAAE,CAAC,CAkD3B;AAqCD,MAAM,WAAW,yBAAyB;IACxC,IAAI,EAAE,uBAAuB,CAAC;IAC9B,OAAO,EAAE,MAAM,CAAC;IAChB,SAAS,EAAE,OAAO,CAAC;CACpB;AAED,wBAAgB,mBAAmB,CAAC,KAAK,EAAE,OAAO,GAAG,yBAAyB,CA+B7E"}
|
|
@@ -4,7 +4,7 @@ import { isInterModuleKnownError } from '@shipfox/inter-module';
|
|
|
4
4
|
import { boundedMap } from '@shipfox/node-module';
|
|
5
5
|
import { DefinitionParseError, DefinitionSyncPermanentError } from './errors.js';
|
|
6
6
|
import { hasAgentStepIntegrations } from './has-agent-step-integrations.js';
|
|
7
|
-
import {
|
|
7
|
+
import { parseDefinitionWithDiagnostics, stripDefinitionDiagnostics } from './parse-definition.js';
|
|
8
8
|
export const DEFAULT_WORKFLOW_PATH = '.shipfox/workflows/';
|
|
9
9
|
export const MAX_WORKFLOW_FILES = 100;
|
|
10
10
|
export const MAX_WORKFLOW_FILE_BYTES = 1_000_000;
|
|
@@ -78,9 +78,9 @@ export async function fetchAndParseWorkflows(params) {
|
|
|
78
78
|
}
|
|
79
79
|
function parseWorkflowSnapshot(params) {
|
|
80
80
|
try {
|
|
81
|
-
const definition = params.integrationValidationContext === undefined ?
|
|
81
|
+
const definition = params.integrationValidationContext === undefined ? parseDefinitionWithDiagnostics(params.content, {
|
|
82
82
|
agentValidationCatalog: params.agentValidationCatalog
|
|
83
|
-
}) :
|
|
83
|
+
}) : parseDefinitionWithDiagnostics(params.content, {
|
|
84
84
|
agentValidationCatalog: params.agentValidationCatalog,
|
|
85
85
|
integrationValidationContext: params.integrationValidationContext
|
|
86
86
|
});
|
|
@@ -88,9 +88,9 @@ function parseWorkflowSnapshot(params) {
|
|
|
88
88
|
return {
|
|
89
89
|
path: params.path,
|
|
90
90
|
name: definition.document.name,
|
|
91
|
-
definition:
|
|
91
|
+
definition: stripDefinitionDiagnostics(definition),
|
|
92
92
|
contentHash,
|
|
93
|
-
|
|
93
|
+
diagnostics: definition.diagnostics
|
|
94
94
|
};
|
|
95
95
|
} catch (error) {
|
|
96
96
|
if (error instanceof DefinitionParseError) {
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../../src/core/sync-definitions.ts"],"sourcesContent":["import {createHash} from 'node:crypto';\nimport type {AgentValidationCatalog} from '@shipfox/api-agent-dto/inter-module';\nimport {integrationsInterModuleContract} from '@shipfox/api-integration-core-dto/inter-module';\nimport {isInterModuleKnownError} from '@shipfox/inter-module';\nimport {boundedMap} from '@shipfox/node-module';\nimport type {IntegrationValidationContext} from './entities/integration-context.js';\nimport type {DefinitionSyncErrorCode} from './entities/sync-state.js';\nimport type {ValidationWarning} from './entities/validation-warning.js';\nimport type {WorkflowDefinitionPayload} from './entities/workflow-definition.js';\nimport {DefinitionParseError, DefinitionSyncPermanentError} from './errors.js';\nimport {hasAgentStepIntegrations} from './has-agent-step-integrations.js';\nimport type {DefinitionsSourceControl} from './integrations.js';\nimport {parseDefinitionWithWarnings, stripDefinitionWarnings} from './parse-definition.js';\n\nexport const DEFAULT_WORKFLOW_PATH = '.shipfox/workflows/';\nexport const MAX_WORKFLOW_FILES = 100;\nexport const MAX_WORKFLOW_FILE_BYTES = 1_000_000;\nexport const FILE_FETCH_CONCURRENCY = 4;\nexport const UNRESOLVED_SYNC_REF = '__unresolved__';\n\nexport interface SyncSourceContext {\n workspaceId: string;\n sourceConnectionId: string;\n sourceExternalRepositoryId: string;\n sourceControl: DefinitionsSourceControl;\n}\n\nexport interface ResolvedSyncSource {\n ref: string;\n}\n\nexport async function resolveSyncSource(params: SyncSourceContext): Promise<ResolvedSyncSource> {\n const source = await params.sourceControl.resolveRepository({\n workspaceId: params.workspaceId,\n connectionId: params.sourceConnectionId,\n externalRepositoryId: params.sourceExternalRepositoryId,\n });\n return {ref: source.repository.defaultBranch};\n}\n\nexport interface DiscoverWorkflowFilesParams extends SyncSourceContext {\n ref: string;\n workflowPath?: string | undefined;\n}\n\nexport async function discoverWorkflowFiles(\n params: DiscoverWorkflowFilesParams,\n): Promise<{paths: string[]}> {\n const workflowPath = params.workflowPath ?? DEFAULT_WORKFLOW_PATH;\n const page = await params.sourceControl.listFiles({\n workspaceId: params.workspaceId,\n connectionId: params.sourceConnectionId,\n externalRepositoryId: params.sourceExternalRepositoryId,\n ref: params.ref,\n prefix: workflowPath,\n limit: MAX_WORKFLOW_FILES,\n });\n if (page.nextCursor) {\n throw new DefinitionSyncPermanentError(\n 'too-many-files',\n `More than ${MAX_WORKFLOW_FILES} workflow files were found`,\n );\n }\n\n const paths = page.files\n .filter((file) => file.path.endsWith('.yml') || file.path.endsWith('.yaml'))\n .map((file) => file.path);\n if (paths.length === 0) {\n throw new DefinitionSyncPermanentError(\n 'no-workflow-files',\n `No workflow files were found under ${workflowPath}`,\n );\n }\n\n return {paths};\n}\n\nexport interface ParsedWorkflow {\n path: string;\n name: string;\n definition: WorkflowDefinitionPayload;\n contentHash: string;\n warnings: ValidationWarning[];\n}\n\nexport interface FetchAndParseWorkflowsParams extends SyncSourceContext {\n ref: string;\n paths: string[];\n onProgress?: ((path: string) => void) | undefined;\n agentValidationCatalog: AgentValidationCatalog;\n loadIntegrationValidationContext?: (() => Promise<IntegrationValidationContext>) | undefined;\n}\n\nexport async function fetchAndParseWorkflows(\n params: FetchAndParseWorkflowsParams,\n): Promise<ParsedWorkflow[]> {\n const parsed = await boundedMap(\n params.paths,\n FILE_FETCH_CONCURRENCY,\n async (path) => {\n params.onProgress?.(path);\n\n const snapshot = await params.sourceControl.fetchFile({\n workspaceId: params.workspaceId,\n connectionId: params.sourceConnectionId,\n externalRepositoryId: params.sourceExternalRepositoryId,\n ref: params.ref,\n path,\n });\n\n if (Buffer.byteLength(snapshot.content, 'utf8') > MAX_WORKFLOW_FILE_BYTES) {\n throw new DefinitionSyncPermanentError(\n 'content-too-large',\n `Workflow file is larger than ${MAX_WORKFLOW_FILE_BYTES} bytes: ${snapshot.path}`,\n );\n }\n\n return {\n ...parseWorkflowSnapshot({\n path: snapshot.path,\n content: snapshot.content,\n agentValidationCatalog: params.agentValidationCatalog,\n }),\n rawContent: snapshot.content,\n };\n },\n {stopOnError: true},\n );\n\n if (\n !params.loadIntegrationValidationContext ||\n !parsed.some((entry) => hasAgentStepIntegrations(entry.definition.document))\n ) {\n return parsed.map(({rawContent: _rawContent, ...entry}) => entry);\n }\n\n const integrationValidationContext = await params.loadIntegrationValidationContext();\n return parsed.map((entry) =>\n parseWorkflowSnapshot({\n path: entry.path,\n content: entry.rawContent,\n agentValidationCatalog: params.agentValidationCatalog,\n integrationValidationContext,\n }),\n );\n}\n\nfunction parseWorkflowSnapshot(params: {\n path: string;\n content: string;\n integrationValidationContext?: IntegrationValidationContext | undefined;\n agentValidationCatalog: AgentValidationCatalog;\n}): ParsedWorkflow {\n try {\n const definition =\n params.integrationValidationContext === undefined\n ? parseDefinitionWithWarnings(params.content, {\n agentValidationCatalog: params.agentValidationCatalog,\n })\n : parseDefinitionWithWarnings(params.content, {\n agentValidationCatalog: params.agentValidationCatalog,\n integrationValidationContext: params.integrationValidationContext,\n });\n const contentHash = sha256Hex(params.content);\n return {\n path: params.path,\n name: definition.document.name,\n definition: stripDefinitionWarnings(definition),\n contentHash,\n warnings: definition.warnings,\n };\n } catch (error) {\n if (error instanceof DefinitionParseError) {\n throw new DefinitionSyncPermanentError(\n 'invalid-definition',\n `Invalid workflow definition at ${params.path}: ${error.message}`,\n );\n }\n throw error;\n }\n}\n\nexport interface SyncFailureClassification {\n code: DefinitionSyncErrorCode;\n message: string;\n retryable: boolean;\n}\n\nexport function classifySyncFailure(error: unknown): SyncFailureClassification {\n if (error instanceof DefinitionSyncPermanentError) {\n return {code: error.code, message: error.message, retryable: false};\n }\n const methods = [\n integrationsInterModuleContract.methods.resolveSourceRepository,\n integrationsInterModuleContract.methods.listSourceFiles,\n integrationsInterModuleContract.methods.fetchSourceFile,\n ] as const;\n for (const method of methods) {\n if (!isInterModuleKnownError(method, error)) continue;\n if (\n error.code === 'connection-not-found' ||\n error.code === 'connection-inactive' ||\n error.code === 'connection-workspace-mismatch'\n ) {\n return {code: 'connection-unavailable', message: error.message, retryable: false};\n }\n if (error.code === 'provider-failure') {\n return {\n code: providerErrorCode(error.details.reason),\n message: error.message,\n retryable: isProviderReasonRetryable(error.details.reason),\n };\n }\n }\n return {\n code: 'unknown',\n message: error instanceof Error ? error.message : String(error),\n retryable: true,\n };\n}\n\nfunction isProviderReasonRetryable(reason: string): boolean {\n return reason === 'rate-limited' || reason === 'timeout' || reason === 'provider-unavailable';\n}\n\nfunction providerErrorCode(reason: string): DefinitionSyncErrorCode {\n if (reason === 'repository-not-found') return 'provider-repository-not-found';\n if (reason === 'file-not-found') return 'provider-file-not-found';\n if (reason === 'access-denied') return 'provider-access-denied';\n if (reason === 'rate-limited') return 'provider-rate-limited';\n if (reason === 'timeout') return 'provider-timeout';\n if (reason === 'provider-unavailable') return 'provider-unavailable';\n if (reason === 'malformed-provider-response') return 'provider-malformed-response';\n if (reason === 'content-too-large') return 'content-too-large';\n if (reason === 'too-many-files') return 'too-many-files';\n return 'unknown';\n}\n\nfunction sha256Hex(content: string): string {\n return createHash('sha256').update(content, 'utf8').digest('hex');\n}\n"],"names":["createHash","integrationsInterModuleContract","isInterModuleKnownError","boundedMap","DefinitionParseError","DefinitionSyncPermanentError","hasAgentStepIntegrations","parseDefinitionWithWarnings","stripDefinitionWarnings","DEFAULT_WORKFLOW_PATH","MAX_WORKFLOW_FILES","MAX_WORKFLOW_FILE_BYTES","FILE_FETCH_CONCURRENCY","UNRESOLVED_SYNC_REF","resolveSyncSource","params","source","sourceControl","resolveRepository","workspaceId","connectionId","sourceConnectionId","externalRepositoryId","sourceExternalRepositoryId","ref","repository","defaultBranch","discoverWorkflowFiles","workflowPath","page","listFiles","prefix","limit","nextCursor","paths","files","filter","file","path","endsWith","map","length","fetchAndParseWorkflows","parsed","onProgress","snapshot","fetchFile","Buffer","byteLength","content","parseWorkflowSnapshot","agentValidationCatalog","rawContent","stopOnError","loadIntegrationValidationContext","some","entry","definition","document","_rawContent","integrationValidationContext","undefined","contentHash","sha256Hex","name","warnings","error","message","classifySyncFailure","code","retryable","methods","resolveSourceRepository","listSourceFiles","fetchSourceFile","method","providerErrorCode","details","reason","isProviderReasonRetryable","Error","String","update","digest"],"mappings":"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"}
|
|
1
|
+
{"version":3,"sources":["../../src/core/sync-definitions.ts"],"sourcesContent":["import {createHash} from 'node:crypto';\nimport type {AgentValidationCatalog} from '@shipfox/api-agent-dto/inter-module';\nimport {integrationsInterModuleContract} from '@shipfox/api-integration-core-dto/inter-module';\nimport {isInterModuleKnownError} from '@shipfox/inter-module';\nimport {boundedMap} from '@shipfox/node-module';\nimport type {IntegrationValidationContext} from './entities/integration-context.js';\nimport type {DefinitionSyncErrorCode} from './entities/sync-state.js';\nimport type {ValidationDiagnostic} from './entities/validation-diagnostic.js';\nimport type {WorkflowDefinitionPayload} from './entities/workflow-definition.js';\nimport {DefinitionParseError, DefinitionSyncPermanentError} from './errors.js';\nimport {hasAgentStepIntegrations} from './has-agent-step-integrations.js';\nimport type {DefinitionsSourceControl} from './integrations.js';\nimport {parseDefinitionWithDiagnostics, stripDefinitionDiagnostics} from './parse-definition.js';\n\nexport const DEFAULT_WORKFLOW_PATH = '.shipfox/workflows/';\nexport const MAX_WORKFLOW_FILES = 100;\nexport const MAX_WORKFLOW_FILE_BYTES = 1_000_000;\nexport const FILE_FETCH_CONCURRENCY = 4;\nexport const UNRESOLVED_SYNC_REF = '__unresolved__';\n\nexport interface SyncSourceContext {\n workspaceId: string;\n sourceConnectionId: string;\n sourceExternalRepositoryId: string;\n sourceControl: DefinitionsSourceControl;\n}\n\nexport interface ResolvedSyncSource {\n ref: string;\n}\n\nexport async function resolveSyncSource(params: SyncSourceContext): Promise<ResolvedSyncSource> {\n const source = await params.sourceControl.resolveRepository({\n workspaceId: params.workspaceId,\n connectionId: params.sourceConnectionId,\n externalRepositoryId: params.sourceExternalRepositoryId,\n });\n return {ref: source.repository.defaultBranch};\n}\n\nexport interface DiscoverWorkflowFilesParams extends SyncSourceContext {\n ref: string;\n workflowPath?: string | undefined;\n}\n\nexport async function discoverWorkflowFiles(\n params: DiscoverWorkflowFilesParams,\n): Promise<{paths: string[]}> {\n const workflowPath = params.workflowPath ?? DEFAULT_WORKFLOW_PATH;\n const page = await params.sourceControl.listFiles({\n workspaceId: params.workspaceId,\n connectionId: params.sourceConnectionId,\n externalRepositoryId: params.sourceExternalRepositoryId,\n ref: params.ref,\n prefix: workflowPath,\n limit: MAX_WORKFLOW_FILES,\n });\n if (page.nextCursor) {\n throw new DefinitionSyncPermanentError(\n 'too-many-files',\n `More than ${MAX_WORKFLOW_FILES} workflow files were found`,\n );\n }\n\n const paths = page.files\n .filter((file) => file.path.endsWith('.yml') || file.path.endsWith('.yaml'))\n .map((file) => file.path);\n if (paths.length === 0) {\n throw new DefinitionSyncPermanentError(\n 'no-workflow-files',\n `No workflow files were found under ${workflowPath}`,\n );\n }\n\n return {paths};\n}\n\nexport interface ParsedWorkflow {\n path: string;\n name: string;\n definition: WorkflowDefinitionPayload;\n contentHash: string;\n diagnostics: ValidationDiagnostic[];\n}\n\nexport interface FetchAndParseWorkflowsParams extends SyncSourceContext {\n ref: string;\n paths: string[];\n onProgress?: ((path: string) => void) | undefined;\n agentValidationCatalog: AgentValidationCatalog;\n loadIntegrationValidationContext?: (() => Promise<IntegrationValidationContext>) | undefined;\n}\n\nexport async function fetchAndParseWorkflows(\n params: FetchAndParseWorkflowsParams,\n): Promise<ParsedWorkflow[]> {\n const parsed = await boundedMap(\n params.paths,\n FILE_FETCH_CONCURRENCY,\n async (path) => {\n params.onProgress?.(path);\n\n const snapshot = await params.sourceControl.fetchFile({\n workspaceId: params.workspaceId,\n connectionId: params.sourceConnectionId,\n externalRepositoryId: params.sourceExternalRepositoryId,\n ref: params.ref,\n path,\n });\n\n if (Buffer.byteLength(snapshot.content, 'utf8') > MAX_WORKFLOW_FILE_BYTES) {\n throw new DefinitionSyncPermanentError(\n 'content-too-large',\n `Workflow file is larger than ${MAX_WORKFLOW_FILE_BYTES} bytes: ${snapshot.path}`,\n );\n }\n\n return {\n ...parseWorkflowSnapshot({\n path: snapshot.path,\n content: snapshot.content,\n agentValidationCatalog: params.agentValidationCatalog,\n }),\n rawContent: snapshot.content,\n };\n },\n {stopOnError: true},\n );\n\n if (\n !params.loadIntegrationValidationContext ||\n !parsed.some((entry) => hasAgentStepIntegrations(entry.definition.document))\n ) {\n return parsed.map(({rawContent: _rawContent, ...entry}) => entry);\n }\n\n const integrationValidationContext = await params.loadIntegrationValidationContext();\n return parsed.map((entry) =>\n parseWorkflowSnapshot({\n path: entry.path,\n content: entry.rawContent,\n agentValidationCatalog: params.agentValidationCatalog,\n integrationValidationContext,\n }),\n );\n}\n\nfunction parseWorkflowSnapshot(params: {\n path: string;\n content: string;\n integrationValidationContext?: IntegrationValidationContext | undefined;\n agentValidationCatalog: AgentValidationCatalog;\n}): ParsedWorkflow {\n try {\n const definition =\n params.integrationValidationContext === undefined\n ? parseDefinitionWithDiagnostics(params.content, {\n agentValidationCatalog: params.agentValidationCatalog,\n })\n : parseDefinitionWithDiagnostics(params.content, {\n agentValidationCatalog: params.agentValidationCatalog,\n integrationValidationContext: params.integrationValidationContext,\n });\n const contentHash = sha256Hex(params.content);\n return {\n path: params.path,\n name: definition.document.name,\n definition: stripDefinitionDiagnostics(definition),\n contentHash,\n diagnostics: definition.diagnostics,\n };\n } catch (error) {\n if (error instanceof DefinitionParseError) {\n throw new DefinitionSyncPermanentError(\n 'invalid-definition',\n `Invalid workflow definition at ${params.path}: ${error.message}`,\n );\n }\n throw error;\n }\n}\n\nexport interface SyncFailureClassification {\n code: DefinitionSyncErrorCode;\n message: string;\n retryable: boolean;\n}\n\nexport function classifySyncFailure(error: unknown): SyncFailureClassification {\n if (error instanceof DefinitionSyncPermanentError) {\n return {code: error.code, message: error.message, retryable: false};\n }\n const methods = [\n integrationsInterModuleContract.methods.resolveSourceRepository,\n integrationsInterModuleContract.methods.listSourceFiles,\n integrationsInterModuleContract.methods.fetchSourceFile,\n ] as const;\n for (const method of methods) {\n if (!isInterModuleKnownError(method, error)) continue;\n if (\n error.code === 'connection-not-found' ||\n error.code === 'connection-inactive' ||\n error.code === 'connection-workspace-mismatch'\n ) {\n return {code: 'connection-unavailable', message: error.message, retryable: false};\n }\n if (error.code === 'provider-failure') {\n return {\n code: providerErrorCode(error.details.reason),\n message: error.message,\n retryable: isProviderReasonRetryable(error.details.reason),\n };\n }\n }\n return {\n code: 'unknown',\n message: error instanceof Error ? error.message : String(error),\n retryable: true,\n };\n}\n\nfunction isProviderReasonRetryable(reason: string): boolean {\n return reason === 'rate-limited' || reason === 'timeout' || reason === 'provider-unavailable';\n}\n\nfunction providerErrorCode(reason: string): DefinitionSyncErrorCode {\n if (reason === 'repository-not-found') return 'provider-repository-not-found';\n if (reason === 'file-not-found') return 'provider-file-not-found';\n if (reason === 'access-denied') return 'provider-access-denied';\n if (reason === 'rate-limited') return 'provider-rate-limited';\n if (reason === 'timeout') return 'provider-timeout';\n if (reason === 'provider-unavailable') return 'provider-unavailable';\n if (reason === 'malformed-provider-response') return 'provider-malformed-response';\n if (reason === 'content-too-large') return 'content-too-large';\n if (reason === 'too-many-files') return 'too-many-files';\n return 'unknown';\n}\n\nfunction sha256Hex(content: string): string {\n return createHash('sha256').update(content, 'utf8').digest('hex');\n}\n"],"names":["createHash","integrationsInterModuleContract","isInterModuleKnownError","boundedMap","DefinitionParseError","DefinitionSyncPermanentError","hasAgentStepIntegrations","parseDefinitionWithDiagnostics","stripDefinitionDiagnostics","DEFAULT_WORKFLOW_PATH","MAX_WORKFLOW_FILES","MAX_WORKFLOW_FILE_BYTES","FILE_FETCH_CONCURRENCY","UNRESOLVED_SYNC_REF","resolveSyncSource","params","source","sourceControl","resolveRepository","workspaceId","connectionId","sourceConnectionId","externalRepositoryId","sourceExternalRepositoryId","ref","repository","defaultBranch","discoverWorkflowFiles","workflowPath","page","listFiles","prefix","limit","nextCursor","paths","files","filter","file","path","endsWith","map","length","fetchAndParseWorkflows","parsed","onProgress","snapshot","fetchFile","Buffer","byteLength","content","parseWorkflowSnapshot","agentValidationCatalog","rawContent","stopOnError","loadIntegrationValidationContext","some","entry","definition","document","_rawContent","integrationValidationContext","undefined","contentHash","sha256Hex","name","diagnostics","error","message","classifySyncFailure","code","retryable","methods","resolveSourceRepository","listSourceFiles","fetchSourceFile","method","providerErrorCode","details","reason","isProviderReasonRetryable","Error","String","update","digest"],"mappings":"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"}
|
|
@@ -1,12 +1,12 @@
|
|
|
1
1
|
import type { AgentValidationCatalog } from '@shipfox/api-agent-dto/inter-module';
|
|
2
2
|
import type { IntegrationValidationContext } from './entities/integration-context.js';
|
|
3
|
-
import type {
|
|
3
|
+
import type { ValidationDiagnostic } from './entities/validation-diagnostic.js';
|
|
4
4
|
import type { WorkflowDefinitionPayload } from './entities/workflow-definition.js';
|
|
5
5
|
export type ValidationError = {
|
|
6
6
|
message: string;
|
|
7
7
|
path?: string | undefined;
|
|
8
8
|
};
|
|
9
|
-
export type {
|
|
9
|
+
export type { ValidationDiagnostic } from './entities/validation-diagnostic.js';
|
|
10
10
|
export interface DefinitionValidationOptions {
|
|
11
11
|
defaultRunnerLabels?: readonly string[];
|
|
12
12
|
agentValidationCatalog: AgentValidationCatalog;
|
|
@@ -15,7 +15,7 @@ export interface DefinitionValidationOptions {
|
|
|
15
15
|
export type ValidationResult = {
|
|
16
16
|
valid: true;
|
|
17
17
|
definition: WorkflowDefinitionPayload;
|
|
18
|
-
|
|
18
|
+
diagnostics: ValidationDiagnostic[];
|
|
19
19
|
} | {
|
|
20
20
|
valid: false;
|
|
21
21
|
errors: ValidationError[];
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"validate-definition.d.ts","sourceRoot":"","sources":["../../src/core/validate-definition.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAC,sBAAsB,EAAC,MAAM,qCAAqC,CAAC;AAGhF,OAAO,KAAK,EAAC,4BAA4B,EAAC,MAAM,mCAAmC,CAAC;AACpF,OAAO,KAAK,EAAC,
|
|
1
|
+
{"version":3,"file":"validate-definition.d.ts","sourceRoot":"","sources":["../../src/core/validate-definition.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAC,sBAAsB,EAAC,MAAM,qCAAqC,CAAC;AAGhF,OAAO,KAAK,EAAC,4BAA4B,EAAC,MAAM,mCAAmC,CAAC;AACpF,OAAO,KAAK,EAAC,oBAAoB,EAAC,MAAM,qCAAqC,CAAC;AAC9E,OAAO,KAAK,EAAC,yBAAyB,EAAC,MAAM,mCAAmC,CAAC;AAQjF,MAAM,MAAM,eAAe,GAAG;IAAC,OAAO,EAAE,MAAM,CAAC;IAAC,IAAI,CAAC,EAAE,MAAM,GAAG,SAAS,CAAA;CAAC,CAAC;AAC3E,YAAY,EAAC,oBAAoB,EAAC,MAAM,qCAAqC,CAAC;AAE9E,MAAM,WAAW,2BAA2B;IAC1C,mBAAmB,CAAC,EAAE,SAAS,MAAM,EAAE,CAAC;IACxC,sBAAsB,EAAE,sBAAsB,CAAC;IAC/C,4BAA4B,CAAC,EAAE,4BAA4B,CAAC;CAC7D;AAED,MAAM,MAAM,gBAAgB,GACxB;IAAC,KAAK,EAAE,IAAI,CAAC;IAAC,UAAU,EAAE,yBAAyB,CAAC;IAAC,WAAW,EAAE,oBAAoB,EAAE,CAAA;CAAC,GACzF;IAAC,KAAK,EAAE,KAAK,CAAC;IAAC,MAAM,EAAE,eAAe,EAAE,CAAA;CAAC,CAAC;AAE9C,wBAAgB,kBAAkB,CAChC,WAAW,EAAE,MAAM,EACnB,OAAO,EAAE,2BAA2B,GACnC,gBAAgB,CAmBlB"}
|