@treeseed/sdk 0.10.19 → 0.10.20
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.
|
@@ -613,9 +613,7 @@ function setRailwaySecretVariable({ cwd, service, environment, key, value, env =
|
|
|
613
613
|
}
|
|
614
614
|
function ensureRailwayProjectExists(service, { env = process.env } = {}) {
|
|
615
615
|
const projectName = typeof service?.projectName === "string" ? service.projectName.trim() : "";
|
|
616
|
-
|
|
617
|
-
throw new Error(`Railway service ${service?.key ?? service?.serviceName ?? service?.serviceId ?? "(unknown)"} is missing a projectName.`);
|
|
618
|
-
}
|
|
616
|
+
const projectId = typeof service?.projectId === "string" ? service.projectId.trim() : "";
|
|
619
617
|
const listed = runRailway(["list", "--json"], {
|
|
620
618
|
cwd: service.rootDir,
|
|
621
619
|
capture: true,
|
|
@@ -623,11 +621,17 @@ function ensureRailwayProjectExists(service, { env = process.env } = {}) {
|
|
|
623
621
|
env
|
|
624
622
|
});
|
|
625
623
|
if (listed.status === 0) {
|
|
626
|
-
const match = normalizeRailwayProjectList(listed.stdout ?? "").find((entry) => entry.name === projectName || entry.id === projectName);
|
|
624
|
+
const match = normalizeRailwayProjectList(listed.stdout ?? "").find((entry) => entry.name === projectName || entry.id === projectName || entry.id === projectId);
|
|
627
625
|
if (match) {
|
|
628
626
|
return match;
|
|
629
627
|
}
|
|
630
628
|
}
|
|
629
|
+
if (!projectName) {
|
|
630
|
+
if (projectId) {
|
|
631
|
+
return { id: projectId, name: "" };
|
|
632
|
+
}
|
|
633
|
+
throw new Error(`Railway service ${service?.key ?? service?.serviceName ?? service?.serviceId ?? "(unknown)"} is missing a projectName.`);
|
|
634
|
+
}
|
|
631
635
|
const args = ["init", "--name", projectName, "--json"];
|
|
632
636
|
const workspace = resolveRailwayWorkspace(env);
|
|
633
637
|
if (workspace) {
|
|
@@ -1758,6 +1762,16 @@ async function ensureRailwayServiceVolumeWithCliFallback({
|
|
|
1758
1762
|
capture: true,
|
|
1759
1763
|
env
|
|
1760
1764
|
};
|
|
1765
|
+
ensureRailwayProjectContext({
|
|
1766
|
+
key: serviceName,
|
|
1767
|
+
projectId,
|
|
1768
|
+
serviceName,
|
|
1769
|
+
rootDir: tenantRoot,
|
|
1770
|
+
railwayEnvironment: environmentName
|
|
1771
|
+
}, {
|
|
1772
|
+
env,
|
|
1773
|
+
capture: true
|
|
1774
|
+
});
|
|
1761
1775
|
const volumeArgs = ["volume", "--service", serviceId, "--environment", environmentId];
|
|
1762
1776
|
const listResult = runRailway([...volumeArgs, "list", "--json"], cliOptions);
|
|
1763
1777
|
const existingVolumes = normalizeRailwayCliVolumeList(parseRailwayJsonOutput(listResult.stdout ?? ""), {
|
|
@@ -47,6 +47,7 @@ import {
|
|
|
47
47
|
getRailwayServiceInstance,
|
|
48
48
|
getRailwayProject,
|
|
49
49
|
listRailwayCustomDomains,
|
|
50
|
+
listRailwayEnvironments,
|
|
50
51
|
listRailwayProjects,
|
|
51
52
|
listRailwayVolumes,
|
|
52
53
|
listRailwayVariables,
|
|
@@ -1395,6 +1396,44 @@ function relativeRailwayRootDir(tenantRoot, serviceRoot) {
|
|
|
1395
1396
|
const resolved = relative(tenantRoot, serviceRoot).replace(/\\/gu, "/");
|
|
1396
1397
|
return !resolved || resolved === "" ? "." : resolved;
|
|
1397
1398
|
}
|
|
1399
|
+
async function ensureRailwayEnvironmentForService({
|
|
1400
|
+
service,
|
|
1401
|
+
project,
|
|
1402
|
+
environmentName,
|
|
1403
|
+
env
|
|
1404
|
+
}) {
|
|
1405
|
+
try {
|
|
1406
|
+
return (await ensureRailwayEnvironment({
|
|
1407
|
+
projectId: project.id,
|
|
1408
|
+
environmentName,
|
|
1409
|
+
env
|
|
1410
|
+
})).environment;
|
|
1411
|
+
} catch (error) {
|
|
1412
|
+
const message = error instanceof Error ? error.message : String(error ?? "");
|
|
1413
|
+
if (!/Problem processing request/iu.test(message)) {
|
|
1414
|
+
throw error;
|
|
1415
|
+
}
|
|
1416
|
+
}
|
|
1417
|
+
ensureRailwayProjectContext({
|
|
1418
|
+
...service,
|
|
1419
|
+
projectId: project.id,
|
|
1420
|
+
projectName: project.name ?? service.projectName,
|
|
1421
|
+
railwayEnvironment: environmentName
|
|
1422
|
+
}, {
|
|
1423
|
+
env,
|
|
1424
|
+
allowFailure: true,
|
|
1425
|
+
capture: true
|
|
1426
|
+
});
|
|
1427
|
+
for (let attempt = 0; attempt < 12; attempt += 1) {
|
|
1428
|
+
const environments = await listRailwayEnvironments({ projectId: project.id, env });
|
|
1429
|
+
const existing = environments.find((environment) => environment.name === environmentName || environment.id === environmentName) ?? null;
|
|
1430
|
+
if (existing) {
|
|
1431
|
+
return existing;
|
|
1432
|
+
}
|
|
1433
|
+
await new Promise((resolve2) => setTimeout(resolve2, 2500));
|
|
1434
|
+
}
|
|
1435
|
+
throw new Error(`Railway environment ${environmentName} was created through the CLI fallback but was not visible through the Railway API.`);
|
|
1436
|
+
}
|
|
1398
1437
|
async function resolveRailwayTopologyForScope(input, scope, {
|
|
1399
1438
|
ensure = false,
|
|
1400
1439
|
refresh = false,
|
|
@@ -1465,11 +1504,12 @@ async function resolveRailwayTopologyForScope(input, scope, {
|
|
|
1465
1504
|
}
|
|
1466
1505
|
let environment = project?.environments.find((entry) => entry.name === service.railwayEnvironment || entry.id === service.railwayEnvironment) ?? null;
|
|
1467
1506
|
if (project && !environment && ensure) {
|
|
1468
|
-
environment =
|
|
1469
|
-
|
|
1507
|
+
environment = await ensureRailwayEnvironmentForService({
|
|
1508
|
+
service,
|
|
1509
|
+
project,
|
|
1470
1510
|
environmentName: service.railwayEnvironment,
|
|
1471
1511
|
env
|
|
1472
|
-
})
|
|
1512
|
+
});
|
|
1473
1513
|
project = {
|
|
1474
1514
|
...project,
|
|
1475
1515
|
environments: [...project.environments.filter((entry) => entry.id !== environment?.id), environment]
|
|
@@ -69,6 +69,7 @@ import {
|
|
|
69
69
|
syncBranchWithOrigin
|
|
70
70
|
} from "../operations/services/git-workflow.js";
|
|
71
71
|
import { resolveGitHubRepositorySlug } from "../operations/services/github-automation.js";
|
|
72
|
+
import { dispatchGitHubWorkflowRun } from "../operations/services/github-api.js";
|
|
72
73
|
import {
|
|
73
74
|
formatGitHubActionsGateFailure,
|
|
74
75
|
inspectGitHubActionsVerification,
|
|
@@ -1168,6 +1169,9 @@ function workflowSessionSnapshot(session) {
|
|
|
1168
1169
|
}))
|
|
1169
1170
|
};
|
|
1170
1171
|
}
|
|
1172
|
+
function sleep(ms) {
|
|
1173
|
+
return new Promise((resolve2) => setTimeout(resolve2, ms));
|
|
1174
|
+
}
|
|
1171
1175
|
function nextPendingJournalStep(journal) {
|
|
1172
1176
|
return journal.steps.find((step) => step.status === "pending") ?? null;
|
|
1173
1177
|
}
|
|
@@ -3127,9 +3131,39 @@ async function workflowSave(helpers, input) {
|
|
|
3127
3131
|
lockfileValidation: repo.lockfileValidation
|
|
3128
3132
|
}))
|
|
3129
3133
|
};
|
|
3130
|
-
const saveWorkflowGates = shouldUseHostedSaveCi(effectiveInput, branch) ? await executeJournalStep(root, workflowRun.runId, "hosted-ci", () => {
|
|
3134
|
+
const saveWorkflowGates = shouldUseHostedSaveCi(effectiveInput, branch) ? await executeJournalStep(root, workflowRun.runId, "hosted-ci", async () => {
|
|
3131
3135
|
if (branch === STAGING_BRANCH) {
|
|
3132
|
-
|
|
3136
|
+
const workflowGates = saveResult?.workflowGates ?? [];
|
|
3137
|
+
if (workflowGates.length > 0 || effectiveInput.verifyDeployedResources !== true || scope === "local" || !savedRootRepo.commitSha) {
|
|
3138
|
+
return { workflowGates };
|
|
3139
|
+
}
|
|
3140
|
+
helpers.write("[save][workflow] Dispatching hosted market deploy gate for deployed resource verification.");
|
|
3141
|
+
const repository = resolveGitHubRepositorySlug(savedRootRepo.path);
|
|
3142
|
+
await dispatchGitHubWorkflowRun(repository, {
|
|
3143
|
+
workflow: "deploy.yml",
|
|
3144
|
+
branch,
|
|
3145
|
+
inputs: {
|
|
3146
|
+
environment: "staging",
|
|
3147
|
+
action_kind: "deploy_web"
|
|
3148
|
+
}
|
|
3149
|
+
});
|
|
3150
|
+
await sleep(5e3);
|
|
3151
|
+
helpers.write("[save][workflow] Waiting for hosted market deploy gate.");
|
|
3152
|
+
const dispatchedGates = await waitForWorkflowGates("save", [
|
|
3153
|
+
hostedDeployGate({
|
|
3154
|
+
name: savedRootRepo.name,
|
|
3155
|
+
repoPath: savedRootRepo.path,
|
|
3156
|
+
repository,
|
|
3157
|
+
workflow: "deploy.yml",
|
|
3158
|
+
branch,
|
|
3159
|
+
headSha: savedRootRepo.commitSha
|
|
3160
|
+
})
|
|
3161
|
+
], "hosted", {
|
|
3162
|
+
root,
|
|
3163
|
+
runId: workflowRun.runId,
|
|
3164
|
+
onProgress: (line, stream) => helpers.write(line, stream)
|
|
3165
|
+
});
|
|
3166
|
+
return { workflowGates: dispatchedGates };
|
|
3133
3167
|
}
|
|
3134
3168
|
helpers.write("[save][workflow] Waiting for hosted save workflow gates.");
|
|
3135
3169
|
return waitForWorkflowGates("save", [
|