@treeseed/sdk 0.6.1 → 0.6.2
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/dist/operations/services/bootstrap-runner.d.ts +33 -0
- package/dist/operations/services/bootstrap-runner.js +136 -0
- package/dist/operations/services/config-runtime.d.ts +27 -8
- package/dist/operations/services/config-runtime.js +297 -124
- package/dist/operations/services/github-api.d.ts +33 -0
- package/dist/operations/services/github-api.js +118 -4
- package/dist/operations/services/github-automation.d.ts +30 -0
- package/dist/operations/services/github-automation.js +107 -1
- package/dist/operations/services/project-platform.d.ts +38 -2
- package/dist/operations/services/project-platform.js +281 -9
- package/dist/operations/services/railway-deploy.d.ts +6 -2
- package/dist/operations/services/railway-deploy.js +26 -18
- package/dist/operations/services/runtime-tools.d.ts +0 -2
- package/dist/operations/services/runtime-tools.js +0 -2
- package/dist/platform/env.yaml +68 -96
- package/dist/platform/environment.js +51 -0
- package/dist/reconcile/bootstrap-systems.d.ts +32 -0
- package/dist/reconcile/bootstrap-systems.js +175 -0
- package/dist/reconcile/builtin-adapters.js +1 -9
- package/dist/reconcile/desired-state.js +16 -14
- package/dist/reconcile/engine.d.ts +9 -4
- package/dist/reconcile/engine.js +57 -14
- package/dist/reconcile/index.d.ts +1 -0
- package/dist/reconcile/index.js +1 -0
- package/dist/scripts/config-treeseed.js +30 -0
- package/dist/scripts/package-tools.js +0 -2
- package/dist/scripts/tenant-deploy.js +16 -36
- package/dist/scripts/test-cloudflare-local.js +0 -2
- package/dist/workflow/operations.js +23 -4
- package/dist/workflow.d.ts +5 -0
- package/package.json +1 -1
- package/templates/github/deploy.workflow.yml +15 -15
|
@@ -27,11 +27,23 @@ function parseGitHubRepositorySlug(value) {
|
|
|
27
27
|
name: rest.join("/")
|
|
28
28
|
};
|
|
29
29
|
}
|
|
30
|
-
function
|
|
30
|
+
function createGitHubRequestSignal(timeoutMs = DEFAULT_GITHUB_API_TIMEOUT_MS, upstreamSignal) {
|
|
31
31
|
if (typeof AbortSignal !== "undefined" && typeof AbortSignal.timeout === "function") {
|
|
32
|
-
|
|
32
|
+
const timeoutSignal = AbortSignal.timeout(timeoutMs);
|
|
33
|
+
if (upstreamSignal) {
|
|
34
|
+
const abortSignalAny = AbortSignal.any;
|
|
35
|
+
return typeof abortSignalAny === "function" ? abortSignalAny([upstreamSignal, timeoutSignal]) : timeoutSignal;
|
|
36
|
+
}
|
|
37
|
+
return timeoutSignal;
|
|
33
38
|
}
|
|
34
|
-
return void 0;
|
|
39
|
+
return upstreamSignal ?? void 0;
|
|
40
|
+
}
|
|
41
|
+
function createGitHubTimeoutFetch(timeoutMs = DEFAULT_GITHUB_API_TIMEOUT_MS) {
|
|
42
|
+
const baseFetch = globalThis.fetch.bind(globalThis);
|
|
43
|
+
return ((input, init) => {
|
|
44
|
+
const signal = createGitHubRequestSignal(timeoutMs, init?.signal ?? null);
|
|
45
|
+
return baseFetch(input, signal ? { ...init, signal } : init);
|
|
46
|
+
});
|
|
35
47
|
}
|
|
36
48
|
function normalizeGitHubApiError(error, context) {
|
|
37
49
|
if (error && typeof error === "object") {
|
|
@@ -100,7 +112,7 @@ function createGitHubApiClient({
|
|
|
100
112
|
return new Octokit({
|
|
101
113
|
auth: token,
|
|
102
114
|
request: {
|
|
103
|
-
|
|
115
|
+
fetch: createGitHubTimeoutFetch(timeoutMs)
|
|
104
116
|
}
|
|
105
117
|
});
|
|
106
118
|
}
|
|
@@ -208,6 +220,50 @@ async function listGitHubRepositoryVariableNames(repository, { client = createGi
|
|
|
208
220
|
throw normalizeGitHubApiError(error, `Unable to list GitHub variables for ${owner}/${name}`);
|
|
209
221
|
}
|
|
210
222
|
}
|
|
223
|
+
async function ensureGitHubActionsEnvironment(repository, environmentName, { client = createGitHubApiClient() } = {}) {
|
|
224
|
+
const { owner, name: repo } = typeof repository === "string" ? parseGitHubRepositorySlug(repository) : repository;
|
|
225
|
+
try {
|
|
226
|
+
await withGitHubApiRetries(() => client.request("PUT /repos/{owner}/{repo}/environments/{environment_name}", {
|
|
227
|
+
owner,
|
|
228
|
+
repo,
|
|
229
|
+
environment_name: environmentName
|
|
230
|
+
}));
|
|
231
|
+
return { repository: `${owner}/${repo}`, environment: environmentName };
|
|
232
|
+
} catch (error) {
|
|
233
|
+
throw normalizeGitHubApiError(error, `Unable to ensure GitHub environment ${environmentName} for ${owner}/${repo}`);
|
|
234
|
+
}
|
|
235
|
+
}
|
|
236
|
+
async function paginateGitHubEnvironmentNames(client, route, params) {
|
|
237
|
+
const paginate = client.paginate;
|
|
238
|
+
return await paginateNames(() => paginate(route, {
|
|
239
|
+
...params,
|
|
240
|
+
per_page: 100
|
|
241
|
+
}));
|
|
242
|
+
}
|
|
243
|
+
async function listGitHubEnvironmentSecretNames(repository, environmentName, { client = createGitHubApiClient() } = {}) {
|
|
244
|
+
const { owner, name } = typeof repository === "string" ? parseGitHubRepositorySlug(repository) : repository;
|
|
245
|
+
try {
|
|
246
|
+
return await paginateGitHubEnvironmentNames(
|
|
247
|
+
client,
|
|
248
|
+
"GET /repos/{owner}/{repo}/environments/{environment_name}/secrets",
|
|
249
|
+
{ owner, repo: name, environment_name: environmentName }
|
|
250
|
+
);
|
|
251
|
+
} catch (error) {
|
|
252
|
+
throw normalizeGitHubApiError(error, `Unable to list GitHub environment secrets for ${owner}/${name}:${environmentName}`);
|
|
253
|
+
}
|
|
254
|
+
}
|
|
255
|
+
async function listGitHubEnvironmentVariableNames(repository, environmentName, { client = createGitHubApiClient() } = {}) {
|
|
256
|
+
const { owner, name } = typeof repository === "string" ? parseGitHubRepositorySlug(repository) : repository;
|
|
257
|
+
try {
|
|
258
|
+
return await paginateGitHubEnvironmentNames(
|
|
259
|
+
client,
|
|
260
|
+
"GET /repos/{owner}/{repo}/environments/{environment_name}/variables",
|
|
261
|
+
{ owner, repo: name, environment_name: environmentName }
|
|
262
|
+
);
|
|
263
|
+
} catch (error) {
|
|
264
|
+
throw normalizeGitHubApiError(error, `Unable to list GitHub environment variables for ${owner}/${name}:${environmentName}`);
|
|
265
|
+
}
|
|
266
|
+
}
|
|
211
267
|
async function encryptGitHubSecret(secret, key) {
|
|
212
268
|
await sodium.ready;
|
|
213
269
|
const messageBytes = Buffer.from(secret);
|
|
@@ -233,6 +289,27 @@ async function upsertGitHubRepositorySecret(repository, name, value, { client =
|
|
|
233
289
|
throw normalizeGitHubApiError(error, `Unable to upsert GitHub secret ${name} for ${owner}/${repo}`);
|
|
234
290
|
}
|
|
235
291
|
}
|
|
292
|
+
async function upsertGitHubEnvironmentSecret(repository, environmentName, name, value, { client = createGitHubApiClient() } = {}) {
|
|
293
|
+
const { owner, name: repo } = typeof repository === "string" ? parseGitHubRepositorySlug(repository) : repository;
|
|
294
|
+
try {
|
|
295
|
+
const key = await client.request("GET /repos/{owner}/{repo}/environments/{environment_name}/secrets/public-key", {
|
|
296
|
+
owner,
|
|
297
|
+
repo,
|
|
298
|
+
environment_name: environmentName
|
|
299
|
+
});
|
|
300
|
+
const encryptedValue = await encryptGitHubSecret(value, String(key.data.key ?? ""));
|
|
301
|
+
await withGitHubApiRetries(() => client.request("PUT /repos/{owner}/{repo}/environments/{environment_name}/secrets/{secret_name}", {
|
|
302
|
+
owner,
|
|
303
|
+
repo,
|
|
304
|
+
environment_name: environmentName,
|
|
305
|
+
secret_name: name,
|
|
306
|
+
encrypted_value: encryptedValue,
|
|
307
|
+
key_id: String(key.data.key_id ?? "")
|
|
308
|
+
}));
|
|
309
|
+
} catch (error) {
|
|
310
|
+
throw normalizeGitHubApiError(error, `Unable to upsert GitHub environment secret ${name} for ${owner}/${repo}:${environmentName}`);
|
|
311
|
+
}
|
|
312
|
+
}
|
|
236
313
|
async function upsertGitHubRepositoryVariable(repository, name, value, { client = createGitHubApiClient() } = {}) {
|
|
237
314
|
const { owner, name: repo } = typeof repository === "string" ? parseGitHubRepositorySlug(repository) : repository;
|
|
238
315
|
try {
|
|
@@ -273,6 +350,38 @@ async function upsertGitHubRepositoryVariable(repository, name, value, { client
|
|
|
273
350
|
throw normalizeGitHubApiError(error, `Unable to upsert GitHub variable ${name} for ${owner}/${repo}`);
|
|
274
351
|
}
|
|
275
352
|
}
|
|
353
|
+
async function upsertGitHubEnvironmentVariable(repository, environmentName, name, value, { client = createGitHubApiClient() } = {}) {
|
|
354
|
+
const { owner, name: repo } = typeof repository === "string" ? parseGitHubRepositorySlug(repository) : repository;
|
|
355
|
+
try {
|
|
356
|
+
await withGitHubApiRetries(async () => {
|
|
357
|
+
try {
|
|
358
|
+
await client.request("POST /repos/{owner}/{repo}/environments/{environment_name}/variables", {
|
|
359
|
+
owner,
|
|
360
|
+
repo,
|
|
361
|
+
environment_name: environmentName,
|
|
362
|
+
name,
|
|
363
|
+
value
|
|
364
|
+
});
|
|
365
|
+
return;
|
|
366
|
+
} catch (error) {
|
|
367
|
+
const status = typeof error?.status === "number" ? Number(error.status) : null;
|
|
368
|
+
const message = error instanceof Error ? error.message : String(error ?? "");
|
|
369
|
+
if (status !== 409 && status !== 422 && !/already exists/iu.test(message)) {
|
|
370
|
+
throw error;
|
|
371
|
+
}
|
|
372
|
+
}
|
|
373
|
+
await client.request("PATCH /repos/{owner}/{repo}/environments/{environment_name}/variables/{name}", {
|
|
374
|
+
owner,
|
|
375
|
+
repo,
|
|
376
|
+
environment_name: environmentName,
|
|
377
|
+
name,
|
|
378
|
+
value
|
|
379
|
+
});
|
|
380
|
+
});
|
|
381
|
+
} catch (error) {
|
|
382
|
+
throw normalizeGitHubApiError(error, `Unable to upsert GitHub environment variable ${name} for ${owner}/${repo}:${environmentName}`);
|
|
383
|
+
}
|
|
384
|
+
}
|
|
276
385
|
function upsertGitHubRepositoryVariableWithGhCli(repository, name, value, {
|
|
277
386
|
env = process.env
|
|
278
387
|
} = {}) {
|
|
@@ -440,14 +549,19 @@ async function ensureGitHubBranchFromBase(repository, branch, {
|
|
|
440
549
|
}
|
|
441
550
|
export {
|
|
442
551
|
createGitHubApiClient,
|
|
552
|
+
ensureGitHubActionsEnvironment,
|
|
443
553
|
ensureGitHubBranchFromBase,
|
|
444
554
|
ensureGitHubRepository,
|
|
445
555
|
getGitHubRepository,
|
|
556
|
+
listGitHubEnvironmentSecretNames,
|
|
557
|
+
listGitHubEnvironmentVariableNames,
|
|
446
558
|
listGitHubRepositorySecretNames,
|
|
447
559
|
listGitHubRepositoryVariableNames,
|
|
448
560
|
maybeGetGitHubRepository,
|
|
449
561
|
parseGitHubRepositorySlug,
|
|
450
562
|
resolveGitHubApiToken,
|
|
563
|
+
upsertGitHubEnvironmentSecret,
|
|
564
|
+
upsertGitHubEnvironmentVariable,
|
|
451
565
|
upsertGitHubRepositorySecret,
|
|
452
566
|
upsertGitHubRepositoryVariable,
|
|
453
567
|
upsertGitHubRepositoryVariableWithGhCli,
|
|
@@ -16,11 +16,41 @@ export interface GitHubProvisionedRepository {
|
|
|
16
16
|
visibility: 'private' | 'public' | 'internal';
|
|
17
17
|
defaultBranch: string;
|
|
18
18
|
}
|
|
19
|
+
export interface TreeseedGitHubRepositoryTarget {
|
|
20
|
+
owner: string;
|
|
21
|
+
name: string;
|
|
22
|
+
visibility: 'private' | 'public' | 'internal';
|
|
23
|
+
source: 'config' | 'origin' | 'default';
|
|
24
|
+
}
|
|
19
25
|
export declare function getGitHubAutomationMode(): "stub" | "real";
|
|
20
26
|
export declare function parseGitHubRepositoryFromRemote(remoteUrl: any): string | null;
|
|
21
27
|
export declare function resolveGitHubRepositorySlug(tenantRoot: any): string;
|
|
22
28
|
export declare function maybeResolveGitHubRepositorySlug(tenantRoot: any): string | null;
|
|
23
29
|
export declare function resolveDefaultGitHubOwner(): string;
|
|
30
|
+
export declare function resolveGitHubRepositoryTarget(tenantRoot: string, { values, defaultName, }?: {
|
|
31
|
+
values?: Record<string, string | undefined>;
|
|
32
|
+
defaultName?: string;
|
|
33
|
+
}): TreeseedGitHubRepositoryTarget;
|
|
34
|
+
export declare function ensureGitHubBootstrapRepository(tenantRoot: string, { values, defaultName, onProgress, }?: {
|
|
35
|
+
values?: Record<string, string | undefined>;
|
|
36
|
+
defaultName?: string;
|
|
37
|
+
onProgress?: (message: string) => void;
|
|
38
|
+
}): Promise<{
|
|
39
|
+
repository: string;
|
|
40
|
+
target: TreeseedGitHubRepositoryTarget;
|
|
41
|
+
created: boolean;
|
|
42
|
+
remote: {
|
|
43
|
+
changed: boolean;
|
|
44
|
+
previous: null;
|
|
45
|
+
next: string;
|
|
46
|
+
} | {
|
|
47
|
+
changed: boolean;
|
|
48
|
+
previous: string;
|
|
49
|
+
next: string;
|
|
50
|
+
};
|
|
51
|
+
pushed: boolean;
|
|
52
|
+
mode: string;
|
|
53
|
+
}>;
|
|
24
54
|
export declare function createGitHubRepository(input: any): Promise<import("./github-api.ts").GitHubRepositorySummary | {
|
|
25
55
|
visibility: any;
|
|
26
56
|
defaultBranch: string;
|
|
@@ -6,6 +6,8 @@ import { packageRoot, loadCliDeployConfig } from "./runtime-tools.js";
|
|
|
6
6
|
import {
|
|
7
7
|
createGitHubApiClient,
|
|
8
8
|
ensureGitHubRepository,
|
|
9
|
+
maybeGetGitHubRepository,
|
|
10
|
+
parseGitHubRepositorySlug,
|
|
9
11
|
listGitHubRepositorySecretNames,
|
|
10
12
|
listGitHubRepositoryVariableNames,
|
|
11
13
|
upsertGitHubRepositorySecret,
|
|
@@ -97,7 +99,7 @@ function maybeResolveGitHubRepositorySlug(tenantRoot) {
|
|
|
97
99
|
}
|
|
98
100
|
}
|
|
99
101
|
function resolveDefaultGitHubOwner() {
|
|
100
|
-
const explicit = envOrNull("
|
|
102
|
+
const explicit = envOrNull("TREESEED_GITHUB_OWNER");
|
|
101
103
|
if (explicit) {
|
|
102
104
|
return explicit;
|
|
103
105
|
}
|
|
@@ -110,6 +112,108 @@ function resolveDefaultGitHubOwner() {
|
|
|
110
112
|
}
|
|
111
113
|
return "treeseed-ai";
|
|
112
114
|
}
|
|
115
|
+
function normalizeGitHubVisibility(value) {
|
|
116
|
+
const normalized = String(value ?? "").trim().toLowerCase();
|
|
117
|
+
return normalized === "public" || normalized === "internal" || normalized === "private" ? normalized : "private";
|
|
118
|
+
}
|
|
119
|
+
function configuredValue(values, key) {
|
|
120
|
+
const value = values?.[key] ?? process.env[key];
|
|
121
|
+
return typeof value === "string" && value.trim().length > 0 ? value.trim() : "";
|
|
122
|
+
}
|
|
123
|
+
function resolveGitHubRepositoryTarget(tenantRoot, {
|
|
124
|
+
values = {},
|
|
125
|
+
defaultName
|
|
126
|
+
} = {}) {
|
|
127
|
+
const origin = maybeResolveGitHubRepositorySlug(tenantRoot);
|
|
128
|
+
const parsedOrigin = origin ? parseGitHubRepositorySlug(origin) : null;
|
|
129
|
+
const owner = configuredValue(values, "TREESEED_GITHUB_OWNER") || parsedOrigin?.owner || "";
|
|
130
|
+
const name = configuredValue(values, "TREESEED_GITHUB_REPOSITORY_NAME") || parsedOrigin?.name || defaultName || "project";
|
|
131
|
+
if (!owner) {
|
|
132
|
+
throw new Error("Configure TREESEED_GITHUB_OWNER before GitHub repository bootstrap.");
|
|
133
|
+
}
|
|
134
|
+
return {
|
|
135
|
+
owner: slugifySegment(owner, "owner"),
|
|
136
|
+
name: slugifySegment(name, "project"),
|
|
137
|
+
visibility: normalizeGitHubVisibility(configuredValue(values, "TREESEED_GITHUB_REPOSITORY_VISIBILITY")),
|
|
138
|
+
source: configuredValue(values, "TREESEED_GITHUB_OWNER") || configuredValue(values, "TREESEED_GITHUB_REPOSITORY_NAME") ? "config" : parsedOrigin ? "origin" : "default"
|
|
139
|
+
};
|
|
140
|
+
}
|
|
141
|
+
function ensureGitRepositoryInitialized(cwd, defaultBranch) {
|
|
142
|
+
const insideWorkTree = runGit(["rev-parse", "--is-inside-work-tree"], { cwd, allowFailure: true }).stdout?.trim() === "true";
|
|
143
|
+
if (!insideWorkTree) {
|
|
144
|
+
runGit(["init", "-b", defaultBranch], { cwd });
|
|
145
|
+
}
|
|
146
|
+
ensureGitIdentity(cwd);
|
|
147
|
+
}
|
|
148
|
+
function ensureOriginRemote(cwd, repository, remoteName = "origin") {
|
|
149
|
+
const currentRemote = runGit(["remote", "get-url", remoteName], { cwd, allowFailure: true }).stdout?.trim() ?? "";
|
|
150
|
+
if (!currentRemote) {
|
|
151
|
+
runGit(["remote", "add", remoteName, repository.sshUrl], { cwd });
|
|
152
|
+
return { changed: true, previous: null, next: repository.sshUrl };
|
|
153
|
+
}
|
|
154
|
+
if (currentRemote !== repository.sshUrl && currentRemote !== repository.httpsUrl) {
|
|
155
|
+
runGit(["remote", "set-url", remoteName, repository.sshUrl], { cwd });
|
|
156
|
+
return { changed: true, previous: currentRemote, next: repository.sshUrl };
|
|
157
|
+
}
|
|
158
|
+
return { changed: false, previous: currentRemote, next: currentRemote };
|
|
159
|
+
}
|
|
160
|
+
function pushAllGitHubRefs(cwd, remoteName = "origin") {
|
|
161
|
+
runGit(["push", "-u", remoteName, "--all"], { cwd, capture: false });
|
|
162
|
+
runGit(["push", remoteName, "--tags"], { cwd, capture: false });
|
|
163
|
+
}
|
|
164
|
+
async function ensureGitHubBootstrapRepository(tenantRoot, {
|
|
165
|
+
values = {},
|
|
166
|
+
defaultName,
|
|
167
|
+
onProgress
|
|
168
|
+
} = {}) {
|
|
169
|
+
const target = resolveGitHubRepositoryTarget(tenantRoot, { values, defaultName });
|
|
170
|
+
const remotes = resolveGitHubRemoteUrls(target.owner, target.name);
|
|
171
|
+
const slug = remotes.slug;
|
|
172
|
+
onProgress?.(`[local][github][repo] Preparing ${slug} from ${target.source}...`);
|
|
173
|
+
if (isGitHubAutomationStubbed()) {
|
|
174
|
+
onProgress?.(`[local][github][repo] Stubbed GitHub automation; repository ${slug} not changed.`);
|
|
175
|
+
return {
|
|
176
|
+
repository: slug,
|
|
177
|
+
target,
|
|
178
|
+
created: false,
|
|
179
|
+
remote: { changed: false, previous: null, next: remotes.sshUrl },
|
|
180
|
+
pushed: false,
|
|
181
|
+
mode: "stub"
|
|
182
|
+
};
|
|
183
|
+
}
|
|
184
|
+
const client = createGitHubApiClient({
|
|
185
|
+
env: {
|
|
186
|
+
GH_TOKEN: configuredValue(values, "GH_TOKEN") || configuredValue(values, "GITHUB_TOKEN"),
|
|
187
|
+
GITHUB_TOKEN: configuredValue(values, "GH_TOKEN") || configuredValue(values, "GITHUB_TOKEN")
|
|
188
|
+
}
|
|
189
|
+
});
|
|
190
|
+
const existing = await maybeGetGitHubRepository({ owner: target.owner, name: target.name }, { client });
|
|
191
|
+
const repository = existing ?? await ensureGitHubRepository({
|
|
192
|
+
owner: target.owner,
|
|
193
|
+
name: target.name,
|
|
194
|
+
visibility: target.visibility
|
|
195
|
+
}, { client });
|
|
196
|
+
const created = !existing;
|
|
197
|
+
onProgress?.(`[local][github][repo] ${created ? "Created" : "Verified"} ${repository.slug}.`);
|
|
198
|
+
ensureGitRepositoryInitialized(tenantRoot, repository.defaultBranch || "main");
|
|
199
|
+
const remote = ensureOriginRemote(tenantRoot, repository);
|
|
200
|
+
if (remote.changed) {
|
|
201
|
+
onProgress?.(`[local][github][repo] Updated origin remote to ${repository.slug}.`);
|
|
202
|
+
}
|
|
203
|
+
if (created) {
|
|
204
|
+
onProgress?.(`[local][github][repo] Pushing all local branches and tags to ${repository.slug}...`);
|
|
205
|
+
pushAllGitHubRefs(tenantRoot);
|
|
206
|
+
onProgress?.(`[local][github][repo] Pushed all local branches and tags to ${repository.slug}.`);
|
|
207
|
+
}
|
|
208
|
+
return {
|
|
209
|
+
repository: repository.slug,
|
|
210
|
+
target,
|
|
211
|
+
created,
|
|
212
|
+
remote,
|
|
213
|
+
pushed: created,
|
|
214
|
+
mode: "real"
|
|
215
|
+
};
|
|
216
|
+
}
|
|
113
217
|
async function createGitHubRepository(input) {
|
|
114
218
|
const visibility = input.visibility ?? "private";
|
|
115
219
|
const remotes = resolveGitHubRemoteUrls(input.owner, input.name);
|
|
@@ -422,6 +526,7 @@ async function waitForGitHubWorkflowCompletion(tenantRoot, {
|
|
|
422
526
|
export {
|
|
423
527
|
createGitHubRepository,
|
|
424
528
|
ensureDeployWorkflow,
|
|
529
|
+
ensureGitHubBootstrapRepository,
|
|
425
530
|
ensureGitHubDeployAutomation,
|
|
426
531
|
ensureGitHubEnvironment,
|
|
427
532
|
ensureGitHubSecrets,
|
|
@@ -440,6 +545,7 @@ export {
|
|
|
440
545
|
requiredGitHubSecrets,
|
|
441
546
|
resolveDefaultGitHubOwner,
|
|
442
547
|
resolveGitHubRepositorySlug,
|
|
548
|
+
resolveGitHubRepositoryTarget,
|
|
443
549
|
resolveGitRepositoryRoot,
|
|
444
550
|
waitForGitHubWorkflowCompletion
|
|
445
551
|
};
|
|
@@ -1,4 +1,6 @@
|
|
|
1
1
|
import { type ControlPlaneReporter } from '../../control-plane.ts';
|
|
2
|
+
import type { TreeseedRunnableBootstrapSystem } from '../../reconcile/index.ts';
|
|
3
|
+
import { type TreeseedBootstrapExecution, type TreeseedBootstrapWriter } from './bootstrap-runner.ts';
|
|
2
4
|
export type ProjectPlatformScope = 'local' | 'staging' | 'prod';
|
|
3
5
|
export type ProjectPlatformAction = 'provision' | 'deploy_code' | 'publish_content' | 'monitor';
|
|
4
6
|
export interface ProjectPlatformActionOptions {
|
|
@@ -9,9 +11,43 @@ export interface ProjectPlatformActionOptions {
|
|
|
9
11
|
dryRun?: boolean;
|
|
10
12
|
reporter?: ControlPlaneReporter;
|
|
11
13
|
skipProvision?: boolean;
|
|
14
|
+
bootstrapSystems?: TreeseedRunnableBootstrapSystem[];
|
|
15
|
+
bootstrapExecution?: TreeseedBootstrapExecution;
|
|
16
|
+
write?: TreeseedBootstrapWriter;
|
|
17
|
+
env?: NodeJS.ProcessEnv | Record<string, string | undefined>;
|
|
12
18
|
}
|
|
13
19
|
export declare function inferEnvironmentFromBranch(tenantRoot: string): "staging" | "prod";
|
|
14
20
|
export declare function resolveScope(environment: string | null): ProjectPlatformScope;
|
|
21
|
+
export type TenantCloudflareDeployContext = {
|
|
22
|
+
tenantRoot: string;
|
|
23
|
+
scope: ProjectPlatformScope;
|
|
24
|
+
target: any;
|
|
25
|
+
dryRun?: boolean;
|
|
26
|
+
wranglerPath: string;
|
|
27
|
+
databaseName: string;
|
|
28
|
+
pagesProjectName: string | null;
|
|
29
|
+
pagesBranchName: string | null;
|
|
30
|
+
env: NodeJS.ProcessEnv | Record<string, string | undefined>;
|
|
31
|
+
write?: TreeseedBootstrapWriter;
|
|
32
|
+
};
|
|
33
|
+
export declare function prepareTenantCloudflareDeploy({ tenantRoot, scope, target: explicitTarget, dryRun, write, env, }: {
|
|
34
|
+
tenantRoot: string;
|
|
35
|
+
scope: ProjectPlatformScope;
|
|
36
|
+
target?: any;
|
|
37
|
+
dryRun?: boolean;
|
|
38
|
+
write?: TreeseedBootstrapWriter;
|
|
39
|
+
env?: NodeJS.ProcessEnv | Record<string, string | undefined>;
|
|
40
|
+
}): TenantCloudflareDeployContext;
|
|
41
|
+
export declare function runTenantDataMigration(context: TenantCloudflareDeployContext): Promise<{
|
|
42
|
+
databaseName: string;
|
|
43
|
+
dryRun: boolean;
|
|
44
|
+
}>;
|
|
45
|
+
export declare function runTenantWebBuild(context: Pick<TenantCloudflareDeployContext, 'tenantRoot' | 'scope' | 'dryRun' | 'env' | 'write'>): Promise<{
|
|
46
|
+
dryRun: boolean;
|
|
47
|
+
}>;
|
|
48
|
+
export declare function runTenantWebPublish(context: TenantCloudflareDeployContext): Promise<{
|
|
49
|
+
dryRun: boolean;
|
|
50
|
+
}>;
|
|
15
51
|
export declare function provisionProjectPlatform(options: ProjectPlatformActionOptions): Promise<{
|
|
16
52
|
ok: boolean;
|
|
17
53
|
scope: ProjectPlatformScope;
|
|
@@ -209,7 +245,7 @@ export declare function deployProjectPlatform(options: ProjectPlatformActionOpti
|
|
|
209
245
|
healthcheckTimeoutSeconds: number | null;
|
|
210
246
|
runtimeMode: string | null;
|
|
211
247
|
} | null;
|
|
212
|
-
})[];
|
|
248
|
+
} | undefined)[];
|
|
213
249
|
}>;
|
|
214
250
|
export declare function publishProjectContent(options: ProjectPlatformActionOptions): Promise<{
|
|
215
251
|
ok: boolean;
|
|
@@ -698,5 +734,5 @@ export declare function runProjectPlatformAction(action: ProjectPlatformAction,
|
|
|
698
734
|
healthcheckTimeoutSeconds: number | null;
|
|
699
735
|
runtimeMode: string | null;
|
|
700
736
|
} | null;
|
|
701
|
-
})[];
|
|
737
|
+
} | undefined)[];
|
|
702
738
|
}>;
|