@treeseed/sdk 0.6.7 → 0.6.9
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/copilot.d.ts +15 -0
- package/dist/copilot.js +75 -0
- package/dist/index.d.ts +2 -0
- package/dist/index.js +18 -0
- package/dist/managed-dependencies.d.ts +56 -0
- package/dist/managed-dependencies.js +668 -0
- package/dist/operations/providers/default.js +30 -1
- package/dist/operations/services/commit-message-provider.d.ts +33 -0
- package/dist/operations/services/commit-message-provider.js +319 -0
- package/dist/operations/services/config-runtime.js +50 -23
- package/dist/operations/services/git-remote-policy.d.ts +9 -0
- package/dist/operations/services/git-remote-policy.js +55 -0
- package/dist/operations/services/git-workflow.js +22 -3
- package/dist/operations/services/github-api.js +9 -4
- package/dist/operations/services/knowledge-coop-launch.js +4 -0
- package/dist/operations/services/local-dev.js +7 -2
- package/dist/operations/services/package-reference-policy.d.ts +70 -0
- package/dist/operations/services/package-reference-policy.js +330 -0
- package/dist/operations/services/project-platform.d.ts +4 -0
- package/dist/operations/services/project-platform.js +28 -4
- package/dist/operations/services/railway-deploy.d.ts +4 -1
- package/dist/operations/services/railway-deploy.js +76 -38
- package/dist/operations/services/repository-save-orchestrator.d.ts +172 -0
- package/dist/operations/services/repository-save-orchestrator.js +1462 -0
- package/dist/operations/services/workspace-dependency-mode.d.ts +70 -0
- package/dist/operations/services/workspace-dependency-mode.js +404 -0
- package/dist/operations/services/workspace-preflight.js +5 -0
- package/dist/operations/services/workspace-save.js +10 -6
- package/dist/operations-registry.js +5 -0
- package/dist/operations-types.d.ts +1 -0
- package/dist/platform/books-data.js +4 -1
- package/dist/platform/env.yaml +6 -3
- package/dist/reconcile/builtin-adapters.js +37 -7
- package/dist/scripts/cleanup-markdown.js +4 -0
- package/dist/scripts/prepare.js +14 -0
- package/dist/scripts/publish-package.js +5 -0
- package/dist/scripts/tenant-workflow-action.js +11 -2
- package/dist/verification.js +46 -13
- package/dist/workflow/operations.d.ts +381 -55
- package/dist/workflow/operations.js +725 -261
- package/dist/workflow-state.d.ts +40 -1
- package/dist/workflow-state.js +220 -17
- package/dist/workflow-support.d.ts +3 -0
- package/dist/workflow-support.js +34 -0
- package/dist/workflow.d.ts +19 -3
- package/dist/workflow.js +3 -3
- package/dist/wrangler-d1.js +6 -1
- package/package.json +17 -1
- package/templates/github/deploy.workflow.yml +59 -14
|
@@ -325,6 +325,31 @@ function ensureCloudflareDnsRecord(env, zoneId, record) {
|
|
|
325
325
|
}
|
|
326
326
|
})?.result ?? null;
|
|
327
327
|
}
|
|
328
|
+
function unquoteDnsTxtContent(value) {
|
|
329
|
+
const trimmed = value.trim();
|
|
330
|
+
return trimmed.length >= 2 && trimmed.startsWith('"') && trimmed.endsWith('"') ? trimmed.slice(1, -1) : trimmed;
|
|
331
|
+
}
|
|
332
|
+
function dnsRecordContentMatches(actual, expected, type) {
|
|
333
|
+
const actualText = String(actual ?? "");
|
|
334
|
+
const expectedText = String(expected ?? "");
|
|
335
|
+
if (String(type ?? "").toUpperCase() === "TXT") {
|
|
336
|
+
return unquoteDnsTxtContent(actualText) === unquoteDnsTxtContent(expectedText);
|
|
337
|
+
}
|
|
338
|
+
return actualText === expectedText;
|
|
339
|
+
}
|
|
340
|
+
function dnsRecordProxiedMatches(actual, expected) {
|
|
341
|
+
return expected.proxied === void 0 || Boolean(actual?.proxied) === Boolean(expected.proxied);
|
|
342
|
+
}
|
|
343
|
+
function dnsRecordIdentityMatches(actual, expected) {
|
|
344
|
+
return actual?.name === expected.name && String(actual?.type ?? "").toUpperCase() === expected.type;
|
|
345
|
+
}
|
|
346
|
+
function dnsRecordMatches(actual, expected) {
|
|
347
|
+
return Boolean(actual) && dnsRecordIdentityMatches(actual, expected) && dnsRecordContentMatches(actual?.content, expected.content, expected.type) && dnsRecordProxiedMatches(actual, expected);
|
|
348
|
+
}
|
|
349
|
+
function dnsRecordsFromCurrentResult(input) {
|
|
350
|
+
const records = input.result?.state?.records;
|
|
351
|
+
return Array.isArray(records) ? records.filter((entry) => Boolean(entry) && typeof entry === "object") : [];
|
|
352
|
+
}
|
|
328
353
|
function getCloudflarePagesDomain(env, projectName, domain) {
|
|
329
354
|
const accountId = env.CLOUDFLARE_ACCOUNT_ID;
|
|
330
355
|
if (!accountId) {
|
|
@@ -1600,7 +1625,7 @@ function observeDnsRecordUnit(input) {
|
|
|
1600
1625
|
(record) => listCloudflareDnsRecords(env, zoneId, record.name).find((entry) => entry?.name === record.name && entry?.type === record.type) ?? null
|
|
1601
1626
|
) : [];
|
|
1602
1627
|
const matches = desiredRecords.length > 0 && liveRecords.every(
|
|
1603
|
-
(entry, index) =>
|
|
1628
|
+
(entry, index) => dnsRecordMatches(entry, desiredRecords[index])
|
|
1604
1629
|
);
|
|
1605
1630
|
return {
|
|
1606
1631
|
exists: desiredRecords.length > 0 && liveRecords.every(Boolean),
|
|
@@ -1673,14 +1698,19 @@ function verifyDnsRecordUnit(input) {
|
|
|
1673
1698
|
]);
|
|
1674
1699
|
}
|
|
1675
1700
|
const checks = desiredRecords.map((record, index) => {
|
|
1676
|
-
const live = listCloudflareDnsRecords(env, zoneId, record.name).find((entry) => entry
|
|
1677
|
-
const
|
|
1701
|
+
const live = listCloudflareDnsRecords(env, zoneId, record.name).find((entry) => dnsRecordIdentityMatches(entry, record)) ?? null;
|
|
1702
|
+
const reconciled = dnsRecordsFromCurrentResult(input).find(
|
|
1703
|
+
(entry) => dnsRecordIdentityMatches(entry, record)
|
|
1704
|
+
) ?? null;
|
|
1705
|
+
const effective = dnsRecordMatches(live, record) ? live : reconciled ?? live;
|
|
1706
|
+
const contentMatches = dnsRecordContentMatches(effective?.content, record.content, record.type);
|
|
1707
|
+
const proxiedMatches = dnsRecordProxiedMatches(effective, record);
|
|
1678
1708
|
return verificationCheck(`dns-record:${index + 1}`, `DNS record ${record.type} ${record.name} matches the desired value`, "api", {
|
|
1679
|
-
exists: Boolean(
|
|
1680
|
-
configured:
|
|
1709
|
+
exists: Boolean(effective?.id),
|
|
1710
|
+
configured: contentMatches && proxiedMatches,
|
|
1681
1711
|
expected: `${record.type} ${record.name} -> ${record.content}${record.proxied === void 0 ? "" : ` proxied=${record.proxied}`}`,
|
|
1682
|
-
observed:
|
|
1683
|
-
issues:
|
|
1712
|
+
observed: effective ? `${effective.type} ${effective.name} -> ${effective.content}${typeof effective.proxied === "boolean" ? ` proxied=${effective.proxied}` : ""}` : null,
|
|
1713
|
+
issues: effective?.id ? contentMatches && proxiedMatches ? [] : [`DNS record ${record.name} does not match the expected value.`] : [`DNS record ${record.type} ${record.name} is missing.`]
|
|
1684
1714
|
});
|
|
1685
1715
|
});
|
|
1686
1716
|
return summarizeVerification(input.unit.unitId, checks);
|
|
@@ -336,6 +336,10 @@ async function runCli(argv = process.argv.slice(2)) {
|
|
|
336
336
|
const mode = args.check ? 'check' : 'write';
|
|
337
337
|
const targets = await collectMarkdownTargets(args.targets);
|
|
338
338
|
if (targets.length === 0) {
|
|
339
|
+
if (mode === 'check') {
|
|
340
|
+
console.log('No Markdown files found for cleanup.');
|
|
341
|
+
return 0;
|
|
342
|
+
}
|
|
339
343
|
console.error('No Markdown files found for cleanup.');
|
|
340
344
|
return 1;
|
|
341
345
|
}
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
|
|
3
|
+
import { spawnSync } from 'node:child_process';
|
|
4
|
+
|
|
5
|
+
if (process.env.TREESEED_SKIP_PACKAGE_PREPARE === '1') {
|
|
6
|
+
process.exit(0);
|
|
7
|
+
}
|
|
8
|
+
|
|
9
|
+
const result = spawnSync('npm', ['run', 'build:dist'], {
|
|
10
|
+
stdio: 'inherit',
|
|
11
|
+
shell: process.platform === 'win32',
|
|
12
|
+
});
|
|
13
|
+
|
|
14
|
+
process.exit(result.status ?? 1);
|
|
@@ -3,6 +3,11 @@ import { resolve } from 'node:path';
|
|
|
3
3
|
import { fileURLToPath } from 'node:url';
|
|
4
4
|
const packageRoot = resolve(fileURLToPath(new URL('..', import.meta.url)));
|
|
5
5
|
const extraArgs = process.argv.slice(2);
|
|
6
|
+
const tagName = process.env.GITHUB_REF_NAME;
|
|
7
|
+
if (tagName && !/^\d+\.\d+\.\d+$/.test(tagName)) {
|
|
8
|
+
console.error(`Refusing to publish @treeseed/sdk from non-stable tag "${tagName}".`);
|
|
9
|
+
process.exit(1);
|
|
10
|
+
}
|
|
6
11
|
const npmArgs = ['publish', '.', '--access', 'public'];
|
|
7
12
|
if (process.env.GITHUB_ACTIONS === 'true') {
|
|
8
13
|
npmArgs.push('--provenance');
|
|
@@ -75,7 +75,16 @@ async function main() {
|
|
|
75
75
|
process.stdout.write(`${JSON.stringify(result, null, 2)}\n`);
|
|
76
76
|
}
|
|
77
77
|
}
|
|
78
|
-
|
|
78
|
+
function isCliEntrypoint() {
|
|
79
|
+
if (!process.argv[1]) {
|
|
80
|
+
return false;
|
|
81
|
+
}
|
|
82
|
+
if (import.meta.url === pathToFileURL(process.argv[1]).href) {
|
|
83
|
+
return true;
|
|
84
|
+
}
|
|
85
|
+
return /(?:^|\/)tenant-workflow-action\.(?:ts|js)$/u.test(process.argv[1]);
|
|
86
|
+
}
|
|
87
|
+
if (isCliEntrypoint()) {
|
|
79
88
|
await main();
|
|
80
89
|
}
|
|
81
|
-
export { parseArgs };
|
|
90
|
+
export { isCliEntrypoint, parseArgs };
|
package/dist/verification.js
CHANGED
|
@@ -3,6 +3,8 @@ import * as childProcess from "node:child_process";
|
|
|
3
3
|
import { basename, relative, resolve } from "node:path";
|
|
4
4
|
import { tmpdir } from "node:os";
|
|
5
5
|
import { fileURLToPath } from "node:url";
|
|
6
|
+
import { createTreeseedManagedToolEnv, resolveTreeseedToolBinary } from "./managed-dependencies.js";
|
|
7
|
+
const defaultActUbuntuLatestImage = "catthehacker/ubuntu:act-latest";
|
|
6
8
|
function defaultWrite(message, stream = "stdout") {
|
|
7
9
|
if (!message) return;
|
|
8
10
|
(stream === "stderr" ? process.stderr : process.stdout).write(`${message}
|
|
@@ -11,7 +13,7 @@ function defaultWrite(message, stream = "stdout") {
|
|
|
11
13
|
function run(command, args, cwd) {
|
|
12
14
|
const result = childProcess.spawnSync(command, args, {
|
|
13
15
|
cwd,
|
|
14
|
-
env: process.env,
|
|
16
|
+
env: createTreeseedManagedToolEnv(process.env),
|
|
15
17
|
stdio: "inherit"
|
|
16
18
|
});
|
|
17
19
|
return result.status ?? 1;
|
|
@@ -19,7 +21,7 @@ function run(command, args, cwd) {
|
|
|
19
21
|
function check(command, args, cwd) {
|
|
20
22
|
const result = childProcess.spawnSync(command, args, {
|
|
21
23
|
cwd,
|
|
22
|
-
env: process.env,
|
|
24
|
+
env: createTreeseedManagedToolEnv(process.env),
|
|
23
25
|
stdio: "pipe",
|
|
24
26
|
encoding: "utf8"
|
|
25
27
|
});
|
|
@@ -39,8 +41,31 @@ function readPackageManifest(packageJsonPath) {
|
|
|
39
41
|
return null;
|
|
40
42
|
}
|
|
41
43
|
}
|
|
44
|
+
function createActArgs(eventName, workflowPath) {
|
|
45
|
+
const image = process.env.TREESEED_VERIFY_ACT_UBUNTU_LATEST_IMAGE?.trim() || defaultActUbuntuLatestImage;
|
|
46
|
+
const args = ["act", eventName, "-W", workflowPath, "-j", "verify"];
|
|
47
|
+
if (image) {
|
|
48
|
+
args.push("-P", `ubuntu-latest=${image}`);
|
|
49
|
+
}
|
|
50
|
+
return args;
|
|
51
|
+
}
|
|
42
52
|
function createWorkspaceActWorkflow(options) {
|
|
43
53
|
const relativePackageRoot = relative(options.workspaceRoot, options.packageRoot).replace(/\\/g, "/");
|
|
54
|
+
const siblingLinkCommands = options.localTreeseedSiblingDependencies.map((packageName) => {
|
|
55
|
+
const [, packageShortName] = packageName.split("/");
|
|
56
|
+
const packageDir = `packages/${packageShortName}`;
|
|
57
|
+
const packageScope = packageName.split("/")[0];
|
|
58
|
+
const linkParent = `node_modules/${packageScope}`;
|
|
59
|
+
const linkTarget = relative(
|
|
60
|
+
resolve(options.packageRoot, linkParent),
|
|
61
|
+
resolve(options.workspaceRoot, packageDir)
|
|
62
|
+
).replace(/\\/g, "/");
|
|
63
|
+
return [
|
|
64
|
+
`mkdir -p ${linkParent}`,
|
|
65
|
+
`rm -rf ${linkParent}/${packageShortName}`,
|
|
66
|
+
`ln -s ${linkTarget} ${linkParent}/${packageShortName}`
|
|
67
|
+
].join("\n");
|
|
68
|
+
}).join("\n");
|
|
44
69
|
const siblingPreparationCommands = options.localTreeseedSiblingDependencies.map((packageName) => {
|
|
45
70
|
const packageDir = `packages/${packageName.split("/")[1]}`;
|
|
46
71
|
const manifest = readPackageManifest(resolve(options.workspaceRoot, packageDir, "package.json"));
|
|
@@ -49,9 +74,9 @@ function createWorkspaceActWorkflow(options) {
|
|
|
49
74
|
}
|
|
50
75
|
const commands = [
|
|
51
76
|
`if test -f ${packageDir}/package-lock.json; then`,
|
|
52
|
-
` npm --prefix ${packageDir} ci`,
|
|
77
|
+
` npm --prefix ${packageDir} ci --workspaces=false`,
|
|
53
78
|
"else",
|
|
54
|
-
` npm --prefix ${packageDir} install --no-audit --no-fund`,
|
|
79
|
+
` npm --prefix ${packageDir} install --workspaces=false --no-audit --no-fund`,
|
|
55
80
|
"fi"
|
|
56
81
|
];
|
|
57
82
|
if (manifest.scripts?.["build:dist"]) {
|
|
@@ -101,20 +126,26 @@ ${siblingPreparationCommands.split("\n").map((line) => ` ${line}`).join
|
|
|
101
126
|
|
|
102
127
|
` : ""} - name: Install dependencies
|
|
103
128
|
run: |
|
|
129
|
+
node -e "const fs = require('fs'); const p = JSON.parse(fs.readFileSync('package.json', 'utf8')); if (p.scripts) delete p.scripts.prepare; fs.writeFileSync('package.json', JSON.stringify(p, null, '\\t') + '\\n');"
|
|
104
130
|
if test -f package-lock.json; then
|
|
105
|
-
npm ci
|
|
131
|
+
npm ci --workspaces=false
|
|
106
132
|
else
|
|
107
|
-
npm install --no-audit --no-fund
|
|
133
|
+
npm install --workspaces=false --no-audit --no-fund
|
|
108
134
|
fi
|
|
135
|
+
git checkout -- package.json || true
|
|
136
|
+
|
|
137
|
+
${siblingLinkCommands ? ` - name: Link local Treeseed dependencies
|
|
138
|
+
run: |
|
|
139
|
+
${siblingLinkCommands.split("\n").map((line) => ` ${line}`).join("\n")}
|
|
109
140
|
|
|
110
|
-
- name: Verify package
|
|
141
|
+
` : ""} - name: Verify package
|
|
111
142
|
run: npm run verify:direct
|
|
112
143
|
`,
|
|
113
144
|
"utf8"
|
|
114
145
|
);
|
|
115
146
|
return {
|
|
116
147
|
cwd: options.workspaceRoot,
|
|
117
|
-
args:
|
|
148
|
+
args: createActArgs(options.eventName, workflowPath)
|
|
118
149
|
};
|
|
119
150
|
}
|
|
120
151
|
function findWorkspaceRoot(packageRoot) {
|
|
@@ -186,7 +217,8 @@ function getTreeseedVerifyDriverStatus(options = {}) {
|
|
|
186
217
|
const workflowPresent = existsSync(workflowPath);
|
|
187
218
|
const workspace = resolveLocalWorkspaceContext(packageRoot);
|
|
188
219
|
const checkCommand = options.checkCommand ?? check;
|
|
189
|
-
const
|
|
220
|
+
const gh = options.checkCommand ? "gh" : resolveTreeseedToolBinary("gh") ?? "gh";
|
|
221
|
+
const ghAct = checkCommand(gh, ["act", "--version"], packageRoot);
|
|
190
222
|
const docker = checkCommand("docker", ["info"], packageRoot);
|
|
191
223
|
const prefersDirectForLocalWorkspace = !inGitHubActions && driver === "auto" && workspace.localTreeseedSiblingDependencies.length > 0;
|
|
192
224
|
return {
|
|
@@ -211,6 +243,7 @@ function runTreeseedVerifyDriver(options = {}) {
|
|
|
211
243
|
const status = getTreeseedVerifyDriverStatus(options);
|
|
212
244
|
const runCommand = options.runCommand ?? run;
|
|
213
245
|
const checkCommand = options.checkCommand ?? check;
|
|
246
|
+
const gh = options.runCommand || options.checkCommand ? "gh" : resolveTreeseedToolBinary("gh") ?? "gh";
|
|
214
247
|
if (status.driver === "direct" || status.inGitHubActions) {
|
|
215
248
|
return runCommand("npm", ["run", "verify:direct"], status.packageRoot);
|
|
216
249
|
}
|
|
@@ -220,7 +253,7 @@ function runTreeseedVerifyDriver(options = {}) {
|
|
|
220
253
|
return 1;
|
|
221
254
|
}
|
|
222
255
|
if (!status.ghActAvailable) {
|
|
223
|
-
const detail = checkCommand(
|
|
256
|
+
const detail = checkCommand(gh, ["act", "--version"], status.packageRoot).detail;
|
|
224
257
|
write(detail || "Treeseed verify requires `gh act` when TREESEED_VERIFY_DRIVER=act.", "stderr");
|
|
225
258
|
return 1;
|
|
226
259
|
}
|
|
@@ -236,15 +269,15 @@ function runTreeseedVerifyDriver(options = {}) {
|
|
|
236
269
|
eventName: status.eventName,
|
|
237
270
|
localTreeseedSiblingDependencies: status.localTreeseedSiblingDependencies
|
|
238
271
|
});
|
|
239
|
-
return runCommand(
|
|
272
|
+
return runCommand(gh, workspaceAct.args, workspaceAct.cwd);
|
|
240
273
|
}
|
|
241
|
-
return runCommand(
|
|
274
|
+
return runCommand(gh, createActArgs(status.eventName, ".github/workflows/verify.yml"), status.packageRoot);
|
|
242
275
|
}
|
|
243
276
|
if (status.prefersDirectForLocalWorkspace) {
|
|
244
277
|
return runCommand("npm", ["run", "verify:direct"], status.packageRoot);
|
|
245
278
|
}
|
|
246
279
|
if (status.canUseAct) {
|
|
247
|
-
return runCommand(
|
|
280
|
+
return runCommand(gh, createActArgs(status.eventName, ".github/workflows/verify.yml"), status.packageRoot);
|
|
248
281
|
}
|
|
249
282
|
if (!status.workflowPresent) {
|
|
250
283
|
write("Treeseed verify warning: package-local verify workflow is missing; falling back to verify:direct.", "stderr");
|