@fabrika/provider-zerops 0.0.4 → 0.0.6

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/src/control.ts CHANGED
@@ -6,6 +6,7 @@ import type {
6
6
  ProviderDeploymentNamespace,
7
7
  ProviderEnvelope,
8
8
  ProviderEnvironment,
9
+ ProviderReconcileInput,
9
10
  ProviderReconcileOutcome,
10
11
  ProviderRegistration,
11
12
  ProviderRegistrationInput,
@@ -14,12 +15,29 @@ import type {
14
15
  RuntimeProviderRun,
15
16
  SchemaReconciler,
16
17
  } from '@fabrika/provider-contract'
17
- import { createZeropsApi, ZEROPS_ACTIVE, ZEROPS_TERMINAL, type ZeropsApi } from './api'
18
+ import {
19
+ createZeropsApi,
20
+ ZEROPS_ACTIVE,
21
+ ZEROPS_PROCESS_FINISHED,
22
+ ZEROPS_PROCESS_TERMINAL,
23
+ ZEROPS_TERMINAL,
24
+ type ZeropsApi,
25
+ ZeropsApiError,
26
+ type ZeropsAppVersion,
27
+ type ZeropsProcess,
28
+ } from './api'
18
29
  import { defaultSleep, defaultZeropsCollaborators, type Sleeper } from './collaborators'
19
- import { type FabrikaManifest, parseFabrikaManifest, renderFabrikaProvisioningYaml, zeropsArtifactCodec } from './manifest'
30
+ import {
31
+ type FabrikaManifest,
32
+ parseFabrikaManifest,
33
+ renderFabrikaProvisioningYaml,
34
+ verifyZeropsArtifactSourceDescriptor,
35
+ zeropsArtifactCodec,
36
+ } from './manifest'
20
37
  import { createZeropsNamespaceCapabilities, type ZeropsNamespaceTarget, zeropsNamespaceTargetCodec } from './namespace'
21
38
  import { createZeropsProvider } from './provider'
22
- import type { ZeropsRuntimeTarget } from './types'
39
+ import { normalizeZeropsSourceRepository, type ZeropsSourceClient } from './source'
40
+ import type { ZeropsRunState, ZeropsRuntimeTarget } from './types'
23
41
 
24
42
  /** Provider coordinates that are safe to persist. Credentials are composed only for a live run. */
25
43
  export interface ZeropsStoredTarget {
@@ -91,8 +109,10 @@ export interface ZeropsControlProviderOptions {
91
109
  readonly propustkaUrl?: string
92
110
  readonly adminKey?: string
93
111
  readonly api?: ZeropsApi
112
+ readonly source: ZeropsSourceClient
94
113
  readonly reconcileSchema?: SchemaReconciler
95
114
  readonly sleep?: Sleeper
115
+ readonly sourceCancelSleep?: Sleeper
96
116
  readonly execute: ZeropsProviderExecutor
97
117
  readonly beforeDeploy?: ZeropsBeforeDeploy
98
118
  readonly namespaces?: {
@@ -185,6 +205,52 @@ const normalizeRegistration = (input: ProviderRegistrationInput): ProviderRegist
185
205
 
186
206
  const abortSignal = (): AbortSignal => new AbortController().signal
187
207
 
208
+ const IMMUTABLE_GIT_OBJECT = /^(?:[a-f0-9]{40}|[a-f0-9]{64})$/
209
+ const BUILD_TRIGGER_CONSISTENCY_MS = 10_000
210
+ const SOURCE_CANCEL_TIMEOUT_MS = 5000
211
+
212
+ const parseRunState = (value: JsonValue | undefined, externalId: string): ZeropsRunState => {
213
+ if (typeof value !== 'object' || value === null || Array.isArray(value)) {
214
+ throw new Error('Zerops run state must be an object')
215
+ }
216
+ const appVersionId = value['appVersionId']
217
+ const phase = value['phase']
218
+ if (typeof appVersionId !== 'string' || appVersionId === '' || appVersionId !== externalId) {
219
+ throw new Error('Zerops run state appVersionId must match the external id')
220
+ }
221
+ if (phase === 'version_created' || phase === 'source_uploaded' || phase === 'build_trigger_requested') {
222
+ if (Object.keys(value).some((key) => key !== 'appVersionId' && key !== 'phase')) {
223
+ throw new Error('Zerops run state contains an unknown field')
224
+ }
225
+ return { appVersionId, phase }
226
+ }
227
+ if (phase !== 'build_triggered') {
228
+ throw new Error('Zerops run state phase is invalid')
229
+ }
230
+ if (Object.keys(value).some((key) => key !== 'appVersionId' && key !== 'phase' && key !== 'processId')) {
231
+ throw new Error('Zerops run state contains an unknown field')
232
+ }
233
+ const processId = value['processId']
234
+ if (processId !== undefined && (typeof processId !== 'string' || processId === '')) {
235
+ throw new Error('Zerops run state processId must be a non-empty string when present')
236
+ }
237
+ return { appVersionId, phase, ...(processId === undefined ? {} : { processId }) }
238
+ }
239
+
240
+ const runState = (
241
+ appVersionId: string,
242
+ phase: Exclude<ZeropsRunState['phase'], 'build_triggered'>,
243
+ ): Exclude<ZeropsRunState, { phase: 'build_triggered' }> => ({ appVersionId, phase })
244
+
245
+ const buildTriggeredState = (
246
+ appVersionId: string,
247
+ processId?: string,
248
+ ): Extract<ZeropsRunState, { phase: 'build_triggered' }> => ({
249
+ appVersionId,
250
+ phase: 'build_triggered',
251
+ ...(processId === undefined ? {} : { processId }),
252
+ })
253
+
188
254
  /** Build the complete Zerops lifecycle bundle without importing control-plane persistence. */
189
255
  export const createZeropsControlProvider = (options: ZeropsControlProviderOptions): ControlProvider => {
190
256
  if (options.accessToken === '') {
@@ -195,6 +261,8 @@ export const createZeropsControlProvider = (options: ZeropsControlProviderOption
195
261
  const defaults = defaultZeropsCollaborators(target)
196
262
  return {
197
263
  api,
264
+ source: options.source,
265
+ ...(options.sourceCancelSleep === undefined ? {} : { sourceCancelSleep: options.sourceCancelSleep }),
198
266
  reconcileSchema: options.reconcileSchema ?? defaults.reconcileSchema,
199
267
  sleep: options.sleep ?? defaultSleep,
200
268
  }
@@ -207,9 +275,108 @@ export const createZeropsControlProvider = (options: ZeropsControlProviderOption
207
275
  ...(options.sleep !== undefined ? { sleep: options.sleep } : {}),
208
276
  })
209
277
 
278
+ const artifactFor = (environment: ProviderEnvironment): FabrikaManifest =>
279
+ parseFabrikaManifest(
280
+ decodeEnvelope('artifact', environment.artifact, zeropsArtifactCodec),
281
+ { appId: environment.appId, env: environment.env },
282
+ )
283
+
284
+ const cancelSourceBestEffort = async (runId: string, appVersionId: string): Promise<void> => {
285
+ const sourceController = new AbortController()
286
+ const timeoutController = new AbortController()
287
+ const cancel = Promise.resolve()
288
+ .then(() => options.source.cancel({ runId, appVersionId, signal: sourceController.signal }))
289
+ .catch(() => {})
290
+ const timeout = Promise.resolve()
291
+ .then(() => (options.sourceCancelSleep ?? defaultSleep)(SOURCE_CANCEL_TIMEOUT_MS, timeoutController.signal))
292
+ .then(() => sourceController.abort())
293
+ .catch(() => {})
294
+ await Promise.race([cancel, timeout])
295
+ timeoutController.abort()
296
+ sourceController.abort()
297
+ }
298
+
299
+ const reconcileActiveSchema = async (
300
+ input: ProviderReconcileInput,
301
+ placement: ReturnType<typeof resolvedEnvironment>,
302
+ signal: AbortSignal,
303
+ ): Promise<void> => {
304
+ const artifact = artifactFor(input.environment)
305
+ if (artifact.app.schema === undefined || options.propustkaUrl === undefined) return
306
+ const runtimeTarget: ZeropsRuntimeTarget = {
307
+ projectId: placement.projectId,
308
+ serviceId: placement.target.serviceId,
309
+ accessToken: options.accessToken,
310
+ ...(options.apiBaseUrl !== undefined ? { apiBaseUrl: options.apiBaseUrl } : {}),
311
+ propustkaUrl: options.propustkaUrl,
312
+ ...(options.adminKey !== undefined ? { adminKey: options.adminKey } : {}),
313
+ }
314
+ const reconcileSchema = options.reconcileSchema ?? defaultZeropsCollaborators(runtimeTarget).reconcileSchema
315
+ await reconcileSchema({
316
+ url: options.propustkaUrl,
317
+ app: artifact.app.id,
318
+ schema: artifact.app.schema,
319
+ ...(input.returnOrigins === undefined || input.returnOrigins.length === 0 ? {} : { returnOrigins: input.returnOrigins }),
320
+ adminKey: options.adminKey,
321
+ signal,
322
+ })
323
+ }
324
+
325
+ const reconcileTriggered = async (
326
+ input: ProviderReconcileInput,
327
+ state: Extract<ZeropsRunState, { phase: 'build_triggered' }>,
328
+ placement: ReturnType<typeof resolvedEnvironment>,
329
+ signal: AbortSignal,
330
+ ): Promise<ProviderReconcileOutcome> => {
331
+ if (state.processId !== undefined) {
332
+ const process = await api.getProcess({ processId: state.processId, signal })
333
+ if (process.id !== state.processId) throw new Error('Zerops process response has different coordinates')
334
+ if (
335
+ process.status !== undefined
336
+ && ZEROPS_PROCESS_TERMINAL.has(process.status)
337
+ && process.status !== ZEROPS_PROCESS_FINISHED
338
+ ) {
339
+ return { state: 'failed' }
340
+ }
341
+ }
342
+ const version = await api.getAppVersion({ appVersionId: state.appVersionId, signal })
343
+ if (version.id !== state.appVersionId) throw new Error('Zerops app-version response has different coordinates')
344
+ if (version.status === ZEROPS_ACTIVE) {
345
+ await reconcileActiveSchema(input, placement, signal)
346
+ return { state: 'succeeded' }
347
+ }
348
+ if (version.status !== undefined && ZEROPS_TERMINAL.has(version.status)) return { state: 'failed' }
349
+ return { state: 'running' }
350
+ }
351
+
210
352
  return {
211
353
  id: 'zerops',
212
354
  normalizeRegistration,
355
+ resolveSource: async (input) => {
356
+ const registration = normalizeRegistration({ app: input.app, environment: input.environment })
357
+ const artifact = decodeEnvelope('artifact', registration.environment.artifact, zeropsArtifactCodec)
358
+ await verifyZeropsArtifactSourceDescriptor(artifact.target.sourceDescriptor)
359
+ const repository = normalizeZeropsSourceRepository(registration.app.source.repoUrl)
360
+ const result = await options.source.resolve({
361
+ runId: input.runId,
362
+ repository,
363
+ requestedRef: registration.app.source.ref,
364
+ ...(input.expectedCommitSha === undefined ? {} : { expectedCommitSha: input.expectedCommitSha }),
365
+ ...(registration.app.source.githubInstallationId === undefined
366
+ ? {}
367
+ : { githubInstallationId: registration.app.source.githubInstallationId }),
368
+ descriptorSha256: artifact.target.sourceDescriptor.sha256,
369
+ signal: input.signal,
370
+ })
371
+ if (
372
+ result.runId !== input.runId
373
+ || result.descriptorSha256 !== artifact.target.sourceDescriptor.sha256
374
+ || (input.expectedCommitSha !== undefined && result.commitSha !== input.expectedCommitSha)
375
+ ) {
376
+ throw new Error('Zerops source resolution returned different coordinates')
377
+ }
378
+ return { commitSha: result.commitSha }
379
+ },
213
380
  deploy: async (input: ProviderDeployInput): Promise<ProviderTerminalOutcome> => {
214
381
  const registration = normalizeRegistration({ app: input.app, environment: input.environment })
215
382
  const placement = resolvedEnvironment(registration.environment, { requireReady: true })
@@ -218,19 +385,36 @@ export const createZeropsControlProvider = (options: ZeropsControlProviderOption
218
385
  throw new Error(`Zerops deployment namespace \`${placement.namespace.id}\` has no proxy service id`)
219
386
  }
220
387
  const artifact = decodeEnvelope('artifact', registration.environment.artifact, zeropsArtifactCodec)
221
- await options.beforeDeploy?.({
222
- appId: input.app.id,
223
- env: input.environment.env,
224
- namespaceId: placement.namespace.id,
225
- target: {
226
- serviceId: placement.target.serviceId,
227
- projectId: placement.projectId,
228
- proxyServiceId,
229
- },
230
- artifact,
231
- api,
232
- signal: input.signal,
233
- })
388
+ await verifyZeropsArtifactSourceDescriptor(artifact.target.sourceDescriptor)
389
+ let source: ZeropsRuntimeTarget['source']
390
+ if (!input.dryRun) {
391
+ if (!IMMUTABLE_GIT_OBJECT.test(input.app.source.ref)) {
392
+ throw new Error('Zerops deploy source must be an exact lowercase Git object id')
393
+ }
394
+ source = {
395
+ runId: input.runId,
396
+ repository: normalizeZeropsSourceRepository(input.app.source.repoUrl),
397
+ commitSha: input.app.source.ref,
398
+ ...(input.app.source.githubInstallationId === undefined
399
+ ? {}
400
+ : { githubInstallationId: input.app.source.githubInstallationId }),
401
+ }
402
+ }
403
+ if (!input.dryRun) {
404
+ await options.beforeDeploy?.({
405
+ appId: input.app.id,
406
+ env: input.environment.env,
407
+ namespaceId: placement.namespace.id,
408
+ target: {
409
+ serviceId: placement.target.serviceId,
410
+ projectId: placement.projectId,
411
+ proxyServiceId,
412
+ },
413
+ artifact,
414
+ api,
415
+ signal: input.signal,
416
+ })
417
+ }
234
418
  const managedEnvironment = input.managedEnvironment
235
419
  const managedEntries = Object.entries(managedEnvironment).sort(([left], [right]) => left.localeCompare(right))
236
420
  const managedNames = managedEntries.map(([name]) => name)
@@ -264,6 +448,7 @@ export const createZeropsControlProvider = (options: ZeropsControlProviderOption
264
448
  projectId: placement.projectId,
265
449
  serviceId: placement.target.serviceId,
266
450
  accessToken: options.accessToken,
451
+ ...(source === undefined ? {} : { source }),
267
452
  ...(options.apiBaseUrl !== undefined ? { apiBaseUrl: options.apiBaseUrl } : {}),
268
453
  ...(options.propustkaUrl !== undefined ? { propustkaUrl: options.propustkaUrl } : {}),
269
454
  ...(options.adminKey !== undefined ? { adminKey: options.adminKey } : {}),
@@ -286,42 +471,116 @@ export const createZeropsControlProvider = (options: ZeropsControlProviderOption
286
471
  },
287
472
  cancel: async (input) => {
288
473
  resolvedEnvironment(input.environment, { requireReady: false })
289
- await api.cancelBuild({ appVersionId: input.externalId, signal: abortSignal() })
474
+ const state = parseRunState(input.providerState, input.externalId)
475
+ await cancelSourceBestEffort(input.runId, state.appVersionId)
476
+ if (state.phase === 'build_triggered') {
477
+ await api.cancelBuild({ appVersionId: state.appVersionId, signal: abortSignal() })
478
+ return
479
+ }
480
+ if (state.phase === 'build_trigger_requested') {
481
+ await (options.sleep ?? defaultSleep)(BUILD_TRIGGER_CONSISTENCY_MS, abortSignal())
482
+ const version = await api.getAppVersion({ appVersionId: state.appVersionId, signal: abortSignal() })
483
+ if (version.id !== state.appVersionId) throw new Error('Zerops app-version response has different coordinates')
484
+ if (version.status === undefined) {
485
+ throw new Error('Zerops app-version status is not observable yet')
486
+ }
487
+ if (version.status !== 'UPLOADING') {
488
+ await api.cancelBuild({ appVersionId: state.appVersionId, signal: abortSignal() })
489
+ return
490
+ }
491
+ }
492
+ await api.deleteAppVersion({ appVersionId: state.appVersionId, signal: abortSignal() })
290
493
  },
291
494
  reconcile: async (input): Promise<ProviderReconcileOutcome> => {
292
495
  const signal = abortSignal()
293
496
  const placement = resolvedEnvironment(input.environment, { requireReady: false })
294
- const version = await api.getAppVersion({ appVersionId: input.externalId, signal })
295
- if (version.status === ZEROPS_ACTIVE) {
296
- const artifact = parseFabrikaManifest(
297
- decodeEnvelope('artifact', input.environment.artifact, zeropsArtifactCodec),
298
- { appId: input.environment.appId, env: input.environment.env },
299
- )
300
- if (artifact.app.schema !== undefined && options.propustkaUrl !== undefined) {
301
- const runtimeTarget: ZeropsRuntimeTarget = {
302
- projectId: placement.projectId,
303
- serviceId: placement.target.serviceId,
304
- accessToken: options.accessToken,
305
- ...(options.apiBaseUrl !== undefined ? { apiBaseUrl: options.apiBaseUrl } : {}),
306
- propustkaUrl: options.propustkaUrl,
307
- ...(options.adminKey !== undefined ? { adminKey: options.adminKey } : {}),
308
- }
309
- const reconcileSchema = options.reconcileSchema ?? defaultZeropsCollaborators(runtimeTarget).reconcileSchema
310
- await reconcileSchema({
311
- url: options.propustkaUrl,
312
- app: artifact.app.id,
313
- schema: artifact.app.schema,
314
- ...(input.returnOrigins === undefined || input.returnOrigins.length === 0 ? {} : { returnOrigins: input.returnOrigins }),
315
- adminKey: options.adminKey,
497
+ const state = parseRunState(input.providerState, input.externalId)
498
+ if (state.phase === 'version_created') {
499
+ await cancelSourceBestEffort(input.runId, state.appVersionId)
500
+ await api.deleteAppVersion({ appVersionId: state.appVersionId, signal: abortSignal() })
501
+ return { state: 'failed' }
502
+ }
503
+ if (state.phase === 'source_uploaded') {
504
+ let artifact: FabrikaManifest
505
+ try {
506
+ artifact = artifactFor(input.environment)
507
+ await verifyZeropsArtifactSourceDescriptor(artifact.target.sourceDescriptor)
508
+ } catch {
509
+ await cancelSourceBestEffort(input.runId, state.appVersionId)
510
+ await api.deleteAppVersion({ appVersionId: state.appVersionId, signal: abortSignal() })
511
+ return { state: 'failed' }
512
+ }
513
+ try {
514
+ await input.checkpoint(runState(state.appVersionId, 'build_trigger_requested'))
515
+ } catch {
516
+ return { state: 'running' }
517
+ }
518
+ let process: ZeropsProcess
519
+ try {
520
+ process = await api.buildAndDeployAppVersion({
521
+ appVersionId: state.appVersionId,
522
+ zeropsYaml: artifact.target.sourceDescriptor.contents,
523
+ ...(artifact.target.zeropsSetup === undefined ? {} : { zeropsYamlSetup: artifact.target.zeropsSetup }),
316
524
  signal,
317
525
  })
526
+ } catch (error) {
527
+ if (error instanceof ZeropsApiError && error.status >= 400 && error.status < 500) {
528
+ await cancelSourceBestEffort(input.runId, state.appVersionId)
529
+ await api.deleteAppVersion({ appVersionId: state.appVersionId, signal: abortSignal() })
530
+ return { state: 'failed' }
531
+ }
532
+ let observed: ZeropsAppVersion
533
+ try {
534
+ await (options.sleep ?? defaultSleep)(BUILD_TRIGGER_CONSISTENCY_MS, signal)
535
+ observed = await api.getAppVersion({ appVersionId: state.appVersionId, signal })
536
+ } catch {
537
+ return { state: 'running' }
538
+ }
539
+ if (observed.id !== state.appVersionId || observed.status === undefined) return { state: 'running' }
540
+ if (observed.status === 'UPLOADING') {
541
+ await cancelSourceBestEffort(input.runId, state.appVersionId)
542
+ await api.deleteAppVersion({ appVersionId: state.appVersionId, signal: abortSignal() })
543
+ return { state: 'failed' }
544
+ }
545
+ const triggered = buildTriggeredState(state.appVersionId)
546
+ try {
547
+ await input.checkpoint(triggered)
548
+ } catch {
549
+ return { state: 'running' }
550
+ }
551
+ return reconcileTriggered(input, triggered, placement, signal)
552
+ }
553
+ const triggered = buildTriggeredState(state.appVersionId, process.id)
554
+ try {
555
+ await input.checkpoint(triggered)
556
+ } catch {
557
+ return { state: 'running' }
318
558
  }
319
- return { state: 'succeeded' }
559
+ return reconcileTriggered(input, triggered, placement, signal)
320
560
  }
321
- if (version.status !== undefined && ZEROPS_TERMINAL.has(version.status)) {
322
- return { state: 'failed' }
561
+ if (state.phase === 'build_trigger_requested') {
562
+ let version: ZeropsAppVersion
563
+ try {
564
+ await (options.sleep ?? defaultSleep)(BUILD_TRIGGER_CONSISTENCY_MS, signal)
565
+ version = await api.getAppVersion({ appVersionId: state.appVersionId, signal })
566
+ } catch {
567
+ return { state: 'running' }
568
+ }
569
+ if (version.id !== state.appVersionId || version.status === undefined) return { state: 'running' }
570
+ if (version.status === 'UPLOADING') {
571
+ await cancelSourceBestEffort(input.runId, state.appVersionId)
572
+ await api.deleteAppVersion({ appVersionId: state.appVersionId, signal: abortSignal() })
573
+ return { state: 'failed' }
574
+ }
575
+ const triggered = buildTriggeredState(state.appVersionId)
576
+ try {
577
+ await input.checkpoint(triggered)
578
+ } catch {
579
+ return { state: 'running' }
580
+ }
581
+ return reconcileTriggered(input, triggered, placement, signal)
323
582
  }
324
- return { state: 'running' }
583
+ return reconcileTriggered(input, state, placement, signal)
325
584
  },
326
585
  secrets: {
327
586
  put: async (input) => {
package/src/index.ts CHANGED
@@ -16,6 +16,7 @@ export type {
16
16
  ZeropsApiOptions,
17
17
  ZeropsAppVersion,
18
18
  ZeropsAppVersionStatus,
19
+ ZeropsAppVersionUpload,
19
20
  ZeropsImportedService,
20
21
  ZeropsImportResult,
21
22
  ZeropsIntegrationToken,
@@ -53,14 +54,17 @@ export { createZeropsControlProvider, zeropsStoredTargetCodec } from './control'
53
54
  export type { ZeropsBeforeDeploy, ZeropsBeforeDeployInput, ZeropsControlProviderOptions, ZeropsProviderExecutor, ZeropsStoredTarget } from './control'
54
55
  export {
55
56
  compileFabrikaManifest,
57
+ createZeropsArtifactSourceDescriptor,
56
58
  FABRIKA_MANIFEST_VERSION,
57
59
  manifestServiceHostnames,
58
60
  parseFabrikaManifest,
59
61
  renderFabrikaImportYaml,
62
+ verifyZeropsArtifactSourceDescriptor,
60
63
  ZEROPS_SERVICE_HOSTNAME_PATTERN,
64
+ ZEROPS_SOURCE_DESCRIPTOR_MAX_BYTES,
61
65
  zeropsArtifactCodec,
62
66
  } from './manifest'
63
- export type { FabrikaImportDocument, FabrikaManifest, ManifestExpectation } from './manifest'
67
+ export type { FabrikaImportDocument, FabrikaManifest, ManifestExpectation, ZeropsArtifactSourceDescriptor } from './manifest'
64
68
  export {
65
69
  compileZeropsNamespaceTopology,
66
70
  createZeropsNamespaceCapabilities,
@@ -90,6 +94,118 @@ export type { ZeropsJobSpec, ZeropsPlan, ZeropsStepKind } from './plan'
90
94
  export { CANCELLED, createZeropsProvider, interpolateManifest, zeropsProvider } from './provider'
91
95
  export type { ZeropsProvider } from './provider'
92
96
  export type * from './schema.generated'
97
+ export {
98
+ buildZeropsSourceCancelRequest,
99
+ buildZeropsSourceCancelResponse,
100
+ buildZeropsSourceCredentialActivateRequest,
101
+ buildZeropsSourceCredentialActivateResponse,
102
+ buildZeropsSourceCredentialBundle,
103
+ buildZeropsSourceCredentialStatusRequest,
104
+ buildZeropsSourceCredentialStatusResponse,
105
+ buildZeropsSourceErrorEnvelope,
106
+ buildZeropsSourceInstallationsVerifyRequest,
107
+ buildZeropsSourceInstallationsVerifyResponse,
108
+ buildZeropsSourceResolveInstallationRequest,
109
+ buildZeropsSourceResolveInstallationResponse,
110
+ buildZeropsSourceResolveRequest,
111
+ buildZeropsSourceResolveResponse,
112
+ buildZeropsSourceUploadRequest,
113
+ buildZeropsSourceUploadResponse,
114
+ buildZeropsSourceWebhookConfigureRequest,
115
+ buildZeropsSourceWebhookConfigureResponse,
116
+ decodeZeropsSourceCancelRequest,
117
+ decodeZeropsSourceCancelResponse,
118
+ decodeZeropsSourceCredentialActivateRequest,
119
+ decodeZeropsSourceCredentialActivateResponse,
120
+ decodeZeropsSourceCredentialBundle,
121
+ decodeZeropsSourceCredentialStatusRequest,
122
+ decodeZeropsSourceCredentialStatusResponse,
123
+ decodeZeropsSourceErrorEnvelope,
124
+ decodeZeropsSourceInstallationsVerifyRequest,
125
+ decodeZeropsSourceInstallationsVerifyResponse,
126
+ decodeZeropsSourceResolveInstallationRequest,
127
+ decodeZeropsSourceResolveInstallationResponse,
128
+ decodeZeropsSourceResolveRequest,
129
+ decodeZeropsSourceResolveResponse,
130
+ decodeZeropsSourceUploadRequest,
131
+ decodeZeropsSourceUploadResponse,
132
+ decodeZeropsSourceWebhookConfigureRequest,
133
+ decodeZeropsSourceWebhookConfigureResponse,
134
+ normalizeZeropsSourceRepository,
135
+ serializeZeropsSourceCredentialBundle,
136
+ sha256ZeropsSourceCredentialBundle,
137
+ ZEROPS_SOURCE_CANCEL_PATH,
138
+ ZEROPS_SOURCE_CREDENTIAL_ACTIVATE_PATH,
139
+ ZEROPS_SOURCE_CREDENTIAL_BUNDLE_VERSION,
140
+ ZEROPS_SOURCE_CREDENTIAL_STATUS_PATH,
141
+ ZEROPS_SOURCE_ERROR_CODES,
142
+ ZEROPS_SOURCE_ERROR_STAGES,
143
+ ZEROPS_SOURCE_INSTALLATIONS_VERIFY_PATH,
144
+ ZEROPS_SOURCE_PROTOCOL_VERSION,
145
+ ZEROPS_SOURCE_RESOLVE_INSTALLATION_PATH,
146
+ ZEROPS_SOURCE_RESOLVE_PATH,
147
+ ZEROPS_SOURCE_UPLOAD_PATH,
148
+ ZEROPS_SOURCE_WEBHOOK_CONFIGURE_PATH,
149
+ } from './source'
150
+ export type {
151
+ ZeropsSourceCancelInput,
152
+ ZeropsSourceCancelRequestV1,
153
+ ZeropsSourceCancelResponseV1,
154
+ ZeropsSourceCancelResult,
155
+ ZeropsSourceClient,
156
+ ZeropsSourceCredentialActivateInput,
157
+ ZeropsSourceCredentialActivateRequestV1,
158
+ ZeropsSourceCredentialActivateResponseV1,
159
+ ZeropsSourceCredentialActiveStatusResponseV1,
160
+ ZeropsSourceCredentialAnonymousStatusResponseV1,
161
+ ZeropsSourceCredentialBundleV1,
162
+ ZeropsSourceCredentialManager,
163
+ ZeropsSourceCredentialStatusInput,
164
+ ZeropsSourceCredentialStatusRequestV1,
165
+ ZeropsSourceCredentialStatusResponseV1,
166
+ ZeropsSourceDescriptor,
167
+ ZeropsSourceErrorCode,
168
+ ZeropsSourceErrorEnvelope,
169
+ ZeropsSourceErrorStage,
170
+ ZeropsSourceGitHubAppIdentityV1,
171
+ ZeropsSourceInstallationScopeV1,
172
+ ZeropsSourceInstallationsVerifyInput,
173
+ ZeropsSourceInstallationsVerifyRequestV1,
174
+ ZeropsSourceInstallationsVerifyResponseV1,
175
+ ZeropsSourceInstallationVerificationV1,
176
+ ZeropsSourceRepository,
177
+ ZeropsSourceResolveInput,
178
+ ZeropsSourceResolveInstallationRequestV1,
179
+ ZeropsSourceResolveInstallationResponseV1,
180
+ ZeropsSourceResolveRequestV1,
181
+ ZeropsSourceResolveResponseV1,
182
+ ZeropsSourceResolveResult,
183
+ ZeropsSourceUploadInput,
184
+ ZeropsSourceUploadRequestV1,
185
+ ZeropsSourceUploadResponseV1,
186
+ ZeropsSourceUploadResult,
187
+ ZeropsSourceWebhookConfigureInput,
188
+ ZeropsSourceWebhookConfigureRequestV1,
189
+ ZeropsSourceWebhookConfigureResponseV1,
190
+ } from './source'
191
+ export {
192
+ createZeropsSourceConnectionAdmin,
193
+ SourceConnectionAdminError,
194
+ ZEROPS_SOURCE_CREDENTIAL_ENV,
195
+ ZEROPS_SOURCE_LEGACY_APP_ID_ENV,
196
+ ZEROPS_SOURCE_LEGACY_PRIVATE_KEY_ENV,
197
+ } from './source-connection'
198
+ export type {
199
+ SourceConnectionActivateInput,
200
+ SourceConnectionAdmin,
201
+ SourceConnectionAdminErrorCode,
202
+ SourceConnectionAdoptExistingInput,
203
+ SourceConnectionInspection,
204
+ SourceConnectionStatus,
205
+ SourceConnectionStatusInput,
206
+ SourceConnectionZeropsApi,
207
+ ZeropsSourceConnectionAdminOptions,
208
+ } from './source-connection'
93
209
  export type {
94
210
  ZeropsAppConfig,
95
211
  ZeropsCompilerOwnedProjectField,
@@ -101,6 +217,8 @@ export type {
101
217
  ZeropsProxySpec,
102
218
  ZeropsReadinessCheckSpec,
103
219
  ZeropsResourceContext,
220
+ ZeropsRunState,
221
+ ZeropsRuntimeSource,
104
222
  ZeropsRuntimeTarget,
105
223
  ZeropsServiceSpec,
106
224
  ZeropsSharedPostgresBinding,