@treeseed/sdk 0.1.1 → 0.3.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.
Files changed (228) hide show
  1. package/README.md +97 -494
  2. package/dist/{src/cli-tools.d.ts → cli-tools.d.ts} +1 -1
  3. package/dist/cli-tools.js +5 -3
  4. package/dist/{src/content-store.d.ts → content-store.d.ts} +3 -2
  5. package/dist/content-store.js +52 -20
  6. package/dist/{src/d1-store.d.ts → d1-store.d.ts} +62 -1
  7. package/dist/d1-store.js +625 -65
  8. package/dist/field-aliases.d.ts +11 -0
  9. package/dist/field-aliases.js +41 -0
  10. package/dist/graph/build.d.ts +19 -0
  11. package/dist/graph/build.js +949 -0
  12. package/dist/graph/dsl.d.ts +2 -0
  13. package/dist/graph/dsl.js +243 -0
  14. package/dist/graph/query.d.ts +47 -0
  15. package/dist/graph/query.js +447 -0
  16. package/dist/graph/ranking.d.ts +3 -0
  17. package/dist/graph/ranking.js +483 -0
  18. package/dist/graph/schema.d.ts +142 -0
  19. package/dist/graph/schema.js +133 -0
  20. package/dist/graph.d.ts +52 -0
  21. package/dist/graph.js +133 -0
  22. package/dist/index.d.ts +27 -0
  23. package/dist/index.js +90 -2
  24. package/dist/model-registry.d.ts +8 -0
  25. package/dist/model-registry.js +351 -25
  26. package/dist/operations/providers/default.d.ts +10 -0
  27. package/dist/operations/providers/default.js +514 -0
  28. package/dist/operations/runtime.d.ts +7 -0
  29. package/dist/operations/runtime.js +60 -0
  30. package/dist/operations/services/config-runtime.d.ts +269 -0
  31. package/dist/operations/services/config-runtime.js +1397 -0
  32. package/dist/operations/services/d1-migration.d.ts +6 -0
  33. package/dist/operations/services/d1-migration.js +89 -0
  34. package/dist/operations/services/deploy.d.ts +371 -0
  35. package/dist/operations/services/deploy.js +981 -0
  36. package/dist/operations/services/git-workflow.d.ts +49 -0
  37. package/dist/operations/services/git-workflow.js +218 -0
  38. package/dist/operations/services/github-automation.d.ts +156 -0
  39. package/dist/operations/services/github-automation.js +256 -0
  40. package/dist/operations/services/local-dev.d.ts +9 -0
  41. package/dist/operations/services/local-dev.js +106 -0
  42. package/dist/operations/services/mailpit-runtime.d.ts +4 -0
  43. package/dist/operations/services/mailpit-runtime.js +59 -0
  44. package/dist/operations/services/railway-deploy.d.ts +53 -0
  45. package/dist/operations/services/railway-deploy.js +123 -0
  46. package/dist/operations/services/runtime-paths.d.ts +19 -0
  47. package/dist/operations/services/runtime-paths.js +54 -0
  48. package/dist/operations/services/runtime-tools.d.ts +117 -0
  49. package/dist/operations/services/runtime-tools.js +358 -0
  50. package/dist/operations/services/save-deploy-preflight.d.ts +34 -0
  51. package/dist/operations/services/save-deploy-preflight.js +76 -0
  52. package/dist/operations/services/template-registry.d.ts +88 -0
  53. package/dist/operations/services/template-registry.js +407 -0
  54. package/dist/operations/services/watch-dev.d.ts +21 -0
  55. package/dist/operations/services/watch-dev.js +284 -0
  56. package/dist/operations/services/workspace-preflight.d.ts +40 -0
  57. package/dist/operations/services/workspace-preflight.js +165 -0
  58. package/dist/operations/services/workspace-save.d.ts +42 -0
  59. package/dist/operations/services/workspace-save.js +235 -0
  60. package/dist/operations/services/workspace-tools.d.ts +16 -0
  61. package/dist/operations/services/workspace-tools.js +270 -0
  62. package/dist/operations-registry.d.ts +5 -0
  63. package/dist/operations-registry.js +68 -0
  64. package/dist/operations-types.d.ts +71 -0
  65. package/dist/operations-types.js +17 -0
  66. package/dist/operations.d.ts +6 -0
  67. package/dist/operations.js +16 -0
  68. package/dist/platform/books-data.d.ts +1 -0
  69. package/dist/platform/books-data.js +1 -0
  70. package/dist/platform/contracts.d.ts +158 -0
  71. package/dist/platform/contracts.js +0 -0
  72. package/dist/platform/deploy/config.d.ts +4 -0
  73. package/dist/platform/deploy/config.js +222 -0
  74. package/dist/platform/deploy-config.d.ts +1 -0
  75. package/dist/platform/deploy-config.js +1 -0
  76. package/dist/platform/env.yaml +394 -0
  77. package/dist/platform/environment.d.ts +130 -0
  78. package/dist/platform/environment.js +331 -0
  79. package/dist/platform/plugin.d.ts +2 -0
  80. package/dist/platform/plugin.js +4 -0
  81. package/dist/platform/plugins/constants.d.ts +22 -0
  82. package/dist/platform/plugins/constants.js +29 -0
  83. package/dist/platform/plugins/plugin.d.ts +51 -0
  84. package/dist/platform/plugins/plugin.js +6 -0
  85. package/dist/platform/plugins/runtime.d.ts +35 -0
  86. package/dist/platform/plugins/runtime.js +142 -0
  87. package/dist/platform/plugins.d.ts +5 -0
  88. package/dist/platform/plugins.js +16 -0
  89. package/dist/platform/site-config-schema.js +1 -0
  90. package/dist/platform/tenant/config.d.ts +9 -0
  91. package/dist/platform/tenant/config.js +154 -0
  92. package/dist/platform/tenant/runtime-config.d.ts +4 -0
  93. package/dist/platform/tenant/runtime-config.js +20 -0
  94. package/dist/platform/tenant-config.d.ts +1 -0
  95. package/dist/platform/tenant-config.js +1 -0
  96. package/dist/platform/utils/books-data.d.ts +29 -0
  97. package/dist/platform/utils/books-data.js +82 -0
  98. package/dist/platform/utils/site-config-schema.js +321 -0
  99. package/dist/remote.d.ts +175 -0
  100. package/dist/remote.js +202 -0
  101. package/dist/runtime.js +50 -3
  102. package/dist/scripts/aggregate-book.js +121 -0
  103. package/dist/scripts/build-dist.js +57 -13
  104. package/dist/scripts/build-tenant-worker.js +36 -0
  105. package/dist/scripts/cleanup-markdown.js +373 -0
  106. package/dist/scripts/cli-test-fixtures.js +48 -0
  107. package/dist/scripts/config-treeseed.js +95 -0
  108. package/dist/scripts/ensure-mailpit.js +29 -0
  109. package/dist/scripts/local-dev.js +129 -0
  110. package/dist/scripts/logs-mailpit.js +2 -0
  111. package/dist/scripts/patch-starlight-content-path.js +172 -0
  112. package/dist/scripts/release-verify.js +34 -5
  113. package/dist/scripts/run-fixture-astro-command.js +18 -0
  114. package/dist/scripts/scaffold-site.js +65 -0
  115. package/dist/scripts/stop-mailpit.js +5 -0
  116. package/dist/scripts/sync-dev-vars.js +6 -0
  117. package/dist/scripts/sync-template.js +20 -0
  118. package/dist/scripts/template-catalog.test.js +100 -0
  119. package/dist/scripts/template-command.js +31 -0
  120. package/dist/scripts/tenant-astro-command.js +3 -0
  121. package/dist/scripts/tenant-build.js +16 -0
  122. package/dist/scripts/tenant-check.js +7 -0
  123. package/dist/scripts/tenant-d1-migrate-local.js +11 -0
  124. package/dist/scripts/tenant-deploy.js +180 -0
  125. package/dist/scripts/tenant-destroy.js +104 -0
  126. package/dist/scripts/tenant-dev.js +171 -0
  127. package/dist/scripts/tenant-lint.js +4 -0
  128. package/dist/scripts/tenant-test.js +4 -0
  129. package/dist/scripts/test-cloudflare-local.js +212 -0
  130. package/dist/scripts/test-scaffold.js +314 -0
  131. package/dist/scripts/test-smoke.js +71 -13
  132. package/dist/scripts/treeseed-assert-release-tag-version.js +21 -0
  133. package/dist/scripts/treeseed-build-dist.js +134 -0
  134. package/dist/scripts/treeseed-publish-package.js +19 -0
  135. package/dist/scripts/treeseed-release-verify.js +131 -0
  136. package/dist/scripts/treeseed-run-ts.js +45 -0
  137. package/dist/scripts/validate-templates.js +6 -0
  138. package/dist/scripts/verify-driver.js +29 -0
  139. package/dist/scripts/workflow-commands.test.js +39 -0
  140. package/dist/scripts/workspace-close.js +24 -0
  141. package/dist/scripts/workspace-command-e2e.js +718 -0
  142. package/dist/scripts/workspace-lint.js +9 -0
  143. package/dist/scripts/workspace-preflight.js +22 -0
  144. package/dist/scripts/workspace-publish-changed-packages.js +16 -0
  145. package/dist/scripts/workspace-release-verify.js +81 -0
  146. package/dist/scripts/workspace-release.js +42 -0
  147. package/dist/scripts/workspace-save.js +124 -0
  148. package/dist/scripts/workspace-start-warning.js +3 -0
  149. package/dist/scripts/workspace-start.js +71 -0
  150. package/dist/scripts/workspace-test-unit.js +4 -0
  151. package/dist/scripts/workspace-test.js +11 -0
  152. package/dist/sdk-fields.d.ts +11 -0
  153. package/dist/sdk-fields.js +169 -0
  154. package/dist/sdk-filters.d.ts +4 -0
  155. package/dist/sdk-filters.js +12 -15
  156. package/dist/sdk-types.d.ts +796 -0
  157. package/dist/sdk-types.js +7 -1
  158. package/dist/sdk-version.d.ts +2 -0
  159. package/dist/sdk-version.js +42 -0
  160. package/dist/sdk.d.ts +215 -0
  161. package/dist/sdk.js +235 -11
  162. package/dist/stores/cursor-store.js +9 -3
  163. package/dist/stores/lease-store.js +8 -2
  164. package/dist/{src/stores → stores}/message-store.d.ts +1 -1
  165. package/dist/stores/message-store.js +27 -3
  166. package/dist/stores/operational-store.d.ts +24 -0
  167. package/dist/stores/operational-store.js +279 -0
  168. package/dist/stores/run-store.js +8 -1
  169. package/dist/stores/subscription-store.js +7 -5
  170. package/dist/template-catalog.d.ts +13 -0
  171. package/dist/template-catalog.js +141 -0
  172. package/dist/treeseed/services/compose.yml +7 -0
  173. package/dist/treeseed/template-catalog/catalog.fixture.json +55 -0
  174. package/dist/treeseed/template-catalog/templates/starter-basic/template/astro.config.d.ts +2 -0
  175. package/dist/treeseed/template-catalog/templates/starter-basic/template/astro.config.ts +3 -0
  176. package/dist/treeseed/template-catalog/templates/starter-basic/template/package.json +32 -0
  177. package/dist/treeseed/template-catalog/templates/starter-basic/template/src/config.yaml +40 -0
  178. package/dist/treeseed/template-catalog/templates/starter-basic/template/src/content/empty/.gitkeep +1 -0
  179. package/dist/treeseed/template-catalog/templates/starter-basic/template/src/content/knowledge/handbook/index.mdx +11 -0
  180. package/dist/treeseed/template-catalog/templates/starter-basic/template/src/content/pages/welcome.mdx +11 -0
  181. package/dist/treeseed/template-catalog/templates/starter-basic/template/src/content.config.d.ts +1 -0
  182. package/dist/treeseed/template-catalog/templates/starter-basic/template/src/content.config.ts +3 -0
  183. package/dist/treeseed/template-catalog/templates/starter-basic/template/src/env.yaml +1 -0
  184. package/dist/treeseed/template-catalog/templates/starter-basic/template/src/manifest.yaml +19 -0
  185. package/dist/treeseed/template-catalog/templates/starter-basic/template/treeseed.site.yaml +26 -0
  186. package/dist/treeseed/template-catalog/templates/starter-basic/template/tsconfig.json +9 -0
  187. package/dist/treeseed/template-catalog/templates/starter-basic/template.config.json +90 -0
  188. package/dist/verification.d.ts +20 -0
  189. package/dist/verification.js +98 -0
  190. package/dist/workflow/operations.d.ts +396 -0
  191. package/dist/workflow/operations.js +841 -0
  192. package/dist/workflow-state.d.ts +56 -0
  193. package/dist/workflow-state.js +195 -0
  194. package/dist/workflow-support.d.ts +9 -0
  195. package/dist/workflow-support.js +176 -0
  196. package/dist/workflow.d.ts +111 -0
  197. package/dist/workflow.js +97 -0
  198. package/package.json +97 -5
  199. package/scripts/verify-driver.mjs +29 -0
  200. package/dist/scripts/.ts-run-1775616845195-odh4xzphk3l.js +0 -22
  201. package/dist/scripts/.ts-run-1775616848931-9386s6kwrl.js +0 -126
  202. package/dist/scripts/assert-release-tag-version.d.ts +0 -1
  203. package/dist/scripts/build-dist.d.ts +0 -1
  204. package/dist/scripts/package-tools.d.ts +0 -15
  205. package/dist/scripts/publish-package.d.ts +0 -1
  206. package/dist/scripts/release-verify.d.ts +0 -1
  207. package/dist/scripts/test-smoke.d.ts +0 -1
  208. package/dist/src/index.d.ts +0 -6
  209. package/dist/src/model-registry.d.ts +0 -4
  210. package/dist/src/sdk-filters.d.ts +0 -4
  211. package/dist/src/sdk-types.d.ts +0 -285
  212. package/dist/src/sdk.d.ts +0 -109
  213. package/dist/test/test-fixture.d.ts +0 -1
  214. package/dist/test/utils/envelopes.test.d.ts +0 -1
  215. package/dist/test/utils/sdk.test.d.ts +0 -1
  216. package/dist/vitest.config.d.ts +0 -2
  217. /package/dist/{src/frontmatter.d.ts → frontmatter.d.ts} +0 -0
  218. /package/dist/{src/git-runtime.d.ts → git-runtime.d.ts} +0 -0
  219. /package/dist/{src/runtime.d.ts → runtime.d.ts} +0 -0
  220. /package/dist/{src/stores → stores}/cursor-store.d.ts +0 -0
  221. /package/dist/{src/stores → stores}/envelopes.d.ts +0 -0
  222. /package/dist/{src/stores → stores}/helpers.d.ts +0 -0
  223. /package/dist/{src/stores → stores}/lease-store.d.ts +0 -0
  224. /package/dist/{src/stores → stores}/run-store.d.ts +0 -0
  225. /package/dist/{src/stores → stores}/subscription-store.d.ts +0 -0
  226. /package/dist/{src/types → types}/agents.d.ts +0 -0
  227. /package/dist/{src/types → types}/cloudflare.d.ts +0 -0
  228. /package/dist/{src/wrangler-d1.d.ts → wrangler-d1.d.ts} +0 -0
@@ -0,0 +1,49 @@
1
+ export declare const STAGING_BRANCH = "staging";
2
+ export declare const PRODUCTION_BRANCH = "main";
3
+ export declare function gitWorkflowRoot(cwd?: any): string;
4
+ export declare function assertCleanWorktree(cwd?: any): string;
5
+ export declare function branchExists(repoDir: any, branchName: any): boolean;
6
+ export declare function remoteBranchExists(repoDir: any, branchName: any): boolean;
7
+ export declare function fetchOrigin(repoDir: any): void;
8
+ export declare function ensureLocalBranchTracking(repoDir: any, branchName: any): void;
9
+ export declare function checkoutBranch(repoDir: any, branchName: any): void;
10
+ export declare function syncBranchWithOrigin(repoDir: any, branchName: any): void;
11
+ export declare function createFeatureBranchFromStaging(cwd: any, branchName: any): {
12
+ repoDir: string;
13
+ baseBranch: string;
14
+ branchName: any;
15
+ };
16
+ export declare function pushBranch(repoDir: any, branchName: any, { setUpstream }?: {
17
+ setUpstream?: boolean | undefined;
18
+ }): void;
19
+ export declare function deleteLocalBranch(repoDir: any, branchName: any): void;
20
+ export declare function deleteRemoteBranch(repoDir: any, branchName: any): boolean;
21
+ export declare function mergeCurrentBranchIntoStaging(cwd: any, featureBranch: any): string;
22
+ export declare function currentManagedBranch(cwd?: any): string;
23
+ export declare function isTaskBranch(branchName: any): boolean;
24
+ export declare function assertFeatureBranch(cwd?: any): string;
25
+ export declare function listTaskBranches(repoDir: any): {
26
+ name: string;
27
+ head: string;
28
+ lastCommitDate: string;
29
+ lastCommitSubject: string;
30
+ local: boolean;
31
+ remote: boolean;
32
+ current: boolean;
33
+ }[];
34
+ export declare function taskTagSlug(branchName: any): string;
35
+ export declare function createDeprecatedTaskTag(repoDir: any, branchName: any, message: any): {
36
+ tagName: string;
37
+ head: string;
38
+ };
39
+ export declare function waitForStagingAutomation(repoDir: any): {
40
+ status: string;
41
+ reason: string;
42
+ branch?: undefined;
43
+ } | {
44
+ status: string;
45
+ branch: string;
46
+ reason?: undefined;
47
+ };
48
+ export declare function prepareReleaseBranches(cwd?: any): string;
49
+ export declare function mergeStagingIntoMain(cwd?: any): string;
@@ -0,0 +1,218 @@
1
+ import { run, workspaceRoot } from "./workspace-tools.js";
2
+ import { currentBranch, gitStatusPorcelain, repoRoot } from "./workspace-save.js";
3
+ const STAGING_BRANCH = "staging";
4
+ const PRODUCTION_BRANCH = "main";
5
+ const RESERVED_BRANCHES = /* @__PURE__ */ new Set([STAGING_BRANCH, PRODUCTION_BRANCH]);
6
+ function runGit(args, { cwd, capture = false } = {}) {
7
+ return run("git", args, { cwd, capture });
8
+ }
9
+ function gitWorkflowRoot(cwd = workspaceRoot()) {
10
+ return repoRoot(cwd);
11
+ }
12
+ function assertCleanWorktree(cwd = workspaceRoot()) {
13
+ const root = gitWorkflowRoot(cwd);
14
+ if (gitStatusPorcelain(root).length > 0) {
15
+ throw new Error("Treeseed requires a clean git worktree before changing branches.");
16
+ }
17
+ return root;
18
+ }
19
+ function branchExists(repoDir, branchName) {
20
+ try {
21
+ runGit(["show-ref", "--verify", "--quiet", `refs/heads/${branchName}`], { cwd: repoDir });
22
+ return true;
23
+ } catch {
24
+ return false;
25
+ }
26
+ }
27
+ function remoteBranchExists(repoDir, branchName) {
28
+ try {
29
+ const output = runGit(["ls-remote", "--heads", "origin", branchName], { cwd: repoDir, capture: true });
30
+ return output.trim().length > 0;
31
+ } catch {
32
+ return false;
33
+ }
34
+ }
35
+ function fetchOrigin(repoDir) {
36
+ runGit(["fetch", "origin"], { cwd: repoDir });
37
+ }
38
+ function ensureLocalBranchTracking(repoDir, branchName) {
39
+ if (branchExists(repoDir, branchName)) {
40
+ return;
41
+ }
42
+ if (remoteBranchExists(repoDir, branchName)) {
43
+ runGit(["checkout", "-b", branchName, `origin/${branchName}`], { cwd: repoDir });
44
+ return;
45
+ }
46
+ runGit(["checkout", "--orphan", branchName], { cwd: repoDir });
47
+ }
48
+ function checkoutBranch(repoDir, branchName) {
49
+ runGit(["checkout", branchName], { cwd: repoDir });
50
+ }
51
+ function syncBranchWithOrigin(repoDir, branchName) {
52
+ fetchOrigin(repoDir);
53
+ if (!branchExists(repoDir, branchName) && remoteBranchExists(repoDir, branchName)) {
54
+ runGit(["checkout", "-b", branchName, `origin/${branchName}`], { cwd: repoDir });
55
+ } else {
56
+ checkoutBranch(repoDir, branchName);
57
+ }
58
+ if (remoteBranchExists(repoDir, branchName)) {
59
+ runGit(["pull", "--rebase", "origin", branchName], { cwd: repoDir });
60
+ }
61
+ }
62
+ function createFeatureBranchFromStaging(cwd, branchName) {
63
+ const repoDir = assertCleanWorktree(cwd);
64
+ fetchOrigin(repoDir);
65
+ if (branchExists(repoDir, branchName) || remoteBranchExists(repoDir, branchName)) {
66
+ throw new Error(`Branch "${branchName}" already exists locally or on origin.`);
67
+ }
68
+ syncBranchWithOrigin(repoDir, STAGING_BRANCH);
69
+ runGit(["checkout", "-b", branchName], { cwd: repoDir });
70
+ return {
71
+ repoDir,
72
+ baseBranch: STAGING_BRANCH,
73
+ branchName
74
+ };
75
+ }
76
+ function pushBranch(repoDir, branchName, { setUpstream = false } = {}) {
77
+ const args = setUpstream ? ["push", "-u", "origin", branchName] : ["push", "origin", branchName];
78
+ runGit(args, { cwd: repoDir });
79
+ }
80
+ function deleteLocalBranch(repoDir, branchName) {
81
+ if (!branchExists(repoDir, branchName)) {
82
+ return;
83
+ }
84
+ runGit(["branch", "-D", branchName], { cwd: repoDir });
85
+ }
86
+ function deleteRemoteBranch(repoDir, branchName) {
87
+ if (!remoteBranchExists(repoDir, branchName)) {
88
+ return false;
89
+ }
90
+ runGit(["push", "origin", "--delete", branchName], { cwd: repoDir });
91
+ return true;
92
+ }
93
+ function mergeCurrentBranchIntoStaging(cwd, featureBranch) {
94
+ const repoDir = assertCleanWorktree(cwd);
95
+ fetchOrigin(repoDir);
96
+ syncBranchWithOrigin(repoDir, STAGING_BRANCH);
97
+ runGit(["merge", "--no-ff", featureBranch, "-m", `merge: ${featureBranch} -> ${STAGING_BRANCH}`], { cwd: repoDir });
98
+ pushBranch(repoDir, STAGING_BRANCH);
99
+ return repoDir;
100
+ }
101
+ function currentManagedBranch(cwd = workspaceRoot()) {
102
+ return currentBranch(gitWorkflowRoot(cwd));
103
+ }
104
+ function isTaskBranch(branchName) {
105
+ return Boolean(branchName) && !RESERVED_BRANCHES.has(branchName) && !branchName.startsWith("deprecated/");
106
+ }
107
+ function assertFeatureBranch(cwd = workspaceRoot()) {
108
+ const branchName = currentManagedBranch(cwd);
109
+ if (!branchName) {
110
+ throw new Error("Unable to determine the current git branch.");
111
+ }
112
+ if (!isTaskBranch(branchName)) {
113
+ throw new Error(`Treeseed task commands only work on task branches. Current branch: ${branchName}`);
114
+ }
115
+ return branchName;
116
+ }
117
+ function gitLines(repoDir, args) {
118
+ return runGit(args, { cwd: repoDir, capture: true }).split("\n").map((line) => line.trim()).filter(Boolean);
119
+ }
120
+ function listTaskBranches(repoDir) {
121
+ try {
122
+ runGit(["fetch", "origin"], { cwd: repoDir, capture: true });
123
+ } catch {
124
+ }
125
+ const local = new Set(
126
+ gitLines(repoDir, ["for-each-ref", "--format=%(refname:short)", "refs/heads"]).filter(isTaskBranch)
127
+ );
128
+ const remote = new Set(
129
+ gitLines(repoDir, ["for-each-ref", "--format=%(refname:short)", "refs/remotes/origin"]).map((branchName) => branchName.replace(/^origin\//, "")).filter(isTaskBranch)
130
+ );
131
+ const current = currentBranch(repoDir);
132
+ const branches = [.../* @__PURE__ */ new Set([...local, ...remote])].sort((left, right) => left.localeCompare(right));
133
+ return branches.map((branchName) => {
134
+ const ref = local.has(branchName) ? branchName : `origin/${branchName}`;
135
+ return {
136
+ name: branchName,
137
+ head: runGit(["rev-parse", ref], { cwd: repoDir, capture: true }).trim(),
138
+ lastCommitDate: runGit(["log", "-1", "--format=%cI", ref], { cwd: repoDir, capture: true }).trim(),
139
+ lastCommitSubject: runGit(["log", "-1", "--format=%s", ref], { cwd: repoDir, capture: true }).trim(),
140
+ local: local.has(branchName),
141
+ remote: remote.has(branchName),
142
+ current: branchName === current
143
+ };
144
+ });
145
+ }
146
+ function taskTagSlug(branchName) {
147
+ return String(branchName).trim().replaceAll("\\", "/").replace(/[^A-Za-z0-9._/-]+/g, "-").replace(/\/+/g, "-").replace(/^-+|-+$/g, "") || "task";
148
+ }
149
+ function createDeprecatedTaskTag(repoDir, branchName, message) {
150
+ const head = runGit(["rev-parse", branchName], { cwd: repoDir, capture: true }).trim();
151
+ const shortSha = head.slice(0, 12);
152
+ const tagName = `deprecated/${taskTagSlug(branchName)}/${shortSha}`;
153
+ runGit(["tag", "-a", tagName, head, "-m", message], { cwd: repoDir });
154
+ runGit(["push", "origin", tagName], { cwd: repoDir, capture: true });
155
+ return { tagName, head };
156
+ }
157
+ function waitForStagingAutomation(repoDir) {
158
+ if (process.env.TREESEED_STAGE_WAIT_MODE === "skip" || process.env.TREESEED_GITHUB_AUTOMATION_MODE === "stub") {
159
+ return { status: "skipped", reason: "stubbed" };
160
+ }
161
+ try {
162
+ run("gh", ["run", "watch", "--branch", STAGING_BRANCH, "--exit-status"], { cwd: repoDir });
163
+ return { status: "completed", branch: STAGING_BRANCH };
164
+ } catch (error) {
165
+ throw new Error([
166
+ "Treeseed stage could not confirm the staging deploy/checks completed.",
167
+ error instanceof Error ? error.message : String(error),
168
+ "Inspect GitHub Actions with `gh run list --branch staging` or your deployment provider logs."
169
+ ].join("\n"));
170
+ }
171
+ }
172
+ function prepareReleaseBranches(cwd = workspaceRoot()) {
173
+ const repoDir = assertCleanWorktree(cwd);
174
+ fetchOrigin(repoDir);
175
+ syncBranchWithOrigin(repoDir, STAGING_BRANCH);
176
+ if (remoteBranchExists(repoDir, PRODUCTION_BRANCH) || branchExists(repoDir, PRODUCTION_BRANCH)) {
177
+ syncBranchWithOrigin(repoDir, PRODUCTION_BRANCH);
178
+ syncBranchWithOrigin(repoDir, STAGING_BRANCH);
179
+ }
180
+ return repoDir;
181
+ }
182
+ function mergeStagingIntoMain(cwd = workspaceRoot()) {
183
+ const repoDir = prepareReleaseBranches(cwd);
184
+ checkoutBranch(repoDir, PRODUCTION_BRANCH);
185
+ if (remoteBranchExists(repoDir, PRODUCTION_BRANCH)) {
186
+ runGit(["pull", "--rebase", "origin", PRODUCTION_BRANCH], { cwd: repoDir });
187
+ }
188
+ runGit(["merge", "--no-ff", STAGING_BRANCH, "-m", `release: ${STAGING_BRANCH} -> ${PRODUCTION_BRANCH}`], { cwd: repoDir });
189
+ pushBranch(repoDir, STAGING_BRANCH);
190
+ pushBranch(repoDir, PRODUCTION_BRANCH);
191
+ return repoDir;
192
+ }
193
+ export {
194
+ PRODUCTION_BRANCH,
195
+ STAGING_BRANCH,
196
+ assertCleanWorktree,
197
+ assertFeatureBranch,
198
+ branchExists,
199
+ checkoutBranch,
200
+ createDeprecatedTaskTag,
201
+ createFeatureBranchFromStaging,
202
+ currentManagedBranch,
203
+ deleteLocalBranch,
204
+ deleteRemoteBranch,
205
+ ensureLocalBranchTracking,
206
+ fetchOrigin,
207
+ gitWorkflowRoot,
208
+ isTaskBranch,
209
+ listTaskBranches,
210
+ mergeCurrentBranchIntoStaging,
211
+ mergeStagingIntoMain,
212
+ prepareReleaseBranches,
213
+ pushBranch,
214
+ remoteBranchExists,
215
+ syncBranchWithOrigin,
216
+ taskTagSlug,
217
+ waitForStagingAutomation
218
+ };
@@ -0,0 +1,156 @@
1
+ export declare function getGitHubAutomationMode(): "stub" | "real";
2
+ export declare function parseGitHubRepositoryFromRemote(remoteUrl: any): string | null;
3
+ export declare function resolveGitHubRepositorySlug(tenantRoot: any): string;
4
+ export declare function maybeResolveGitHubRepositorySlug(tenantRoot: any): string | null;
5
+ export declare function resolveGitRepositoryRoot(tenantRoot: any): any;
6
+ export declare function requiredGitHubEnvironment(tenantRoot: any, { scope, purpose }?: {
7
+ scope?: string | undefined;
8
+ purpose?: string | undefined;
9
+ }): {
10
+ secrets: string[];
11
+ variables: string[];
12
+ };
13
+ export declare function requiredGitHubSecrets(tenantRoot: any): string[];
14
+ export declare function renderDeployWorkflow({ workingDirectory }: {
15
+ workingDirectory: any;
16
+ }): string;
17
+ export declare function ensureDeployWorkflow(tenantRoot: any): {
18
+ workflowPath: string;
19
+ changed: boolean;
20
+ workingDirectory: string;
21
+ mode: string;
22
+ } | {
23
+ workflowPath: string;
24
+ changed: boolean;
25
+ workingDirectory: string;
26
+ mode?: undefined;
27
+ };
28
+ export declare function listGitHubSecretNames(repository: any, tenantRoot: any): Set<unknown>;
29
+ export declare function listGitHubVariableNames(repository: any, tenantRoot: any): Set<unknown>;
30
+ export declare function formatMissingSecretsReport(repository: any, missingSecrets: any, reason?: string): string;
31
+ export declare function ensureGitHubSecrets(tenantRoot: any, { dryRun }?: {
32
+ dryRun?: boolean | undefined;
33
+ }): {
34
+ existing: never[];
35
+ created: never[];
36
+ } | {
37
+ existing: never[];
38
+ created: never[];
39
+ } | {
40
+ existing: string[];
41
+ created: string[];
42
+ };
43
+ export declare function ensureGitHubEnvironment(tenantRoot: any, { dryRun, scope, purpose }?: {
44
+ dryRun?: boolean | undefined;
45
+ scope?: string | undefined;
46
+ purpose?: string | undefined;
47
+ }): {
48
+ repository: string | null;
49
+ secrets: {
50
+ existing: never[];
51
+ created: never[];
52
+ };
53
+ variables: {
54
+ existing: never[];
55
+ created: never[];
56
+ };
57
+ skipped: string;
58
+ mode: string;
59
+ } | {
60
+ repository: null;
61
+ secrets: {
62
+ existing: never[];
63
+ created: never[];
64
+ };
65
+ variables: {
66
+ existing: never[];
67
+ created: never[];
68
+ };
69
+ skipped: string;
70
+ mode?: undefined;
71
+ } | {
72
+ repository: string;
73
+ secrets: {
74
+ existing: string[];
75
+ created: string[];
76
+ };
77
+ variables: {
78
+ existing: string[];
79
+ created: string[];
80
+ };
81
+ skipped?: undefined;
82
+ mode?: undefined;
83
+ };
84
+ export declare function ensureGitHubDeployAutomation(tenantRoot: any, { dryRun }?: {
85
+ dryRun?: boolean | undefined;
86
+ }): {
87
+ mode: string;
88
+ workflow: {
89
+ workflowPath: string;
90
+ changed: boolean;
91
+ workingDirectory: string;
92
+ mode: string;
93
+ } | {
94
+ workflowPath: string;
95
+ changed: boolean;
96
+ workingDirectory: string;
97
+ mode?: undefined;
98
+ };
99
+ secrets: {
100
+ existing: never[];
101
+ created: never[];
102
+ } | {
103
+ existing: never[];
104
+ created: never[];
105
+ } | {
106
+ existing: string[];
107
+ created: string[];
108
+ };
109
+ variables: {
110
+ existing: never[];
111
+ created: never[];
112
+ } | {
113
+ existing: never[];
114
+ created: never[];
115
+ } | {
116
+ existing: string[];
117
+ created: string[];
118
+ };
119
+ environment: {
120
+ repository: string | null;
121
+ secrets: {
122
+ existing: never[];
123
+ created: never[];
124
+ };
125
+ variables: {
126
+ existing: never[];
127
+ created: never[];
128
+ };
129
+ skipped: string;
130
+ mode: string;
131
+ } | {
132
+ repository: null;
133
+ secrets: {
134
+ existing: never[];
135
+ created: never[];
136
+ };
137
+ variables: {
138
+ existing: never[];
139
+ created: never[];
140
+ };
141
+ skipped: string;
142
+ mode?: undefined;
143
+ } | {
144
+ repository: string;
145
+ secrets: {
146
+ existing: string[];
147
+ created: string[];
148
+ };
149
+ variables: {
150
+ existing: string[];
151
+ created: string[];
152
+ };
153
+ skipped?: undefined;
154
+ mode?: undefined;
155
+ };
156
+ };
@@ -0,0 +1,256 @@
1
+ import { existsSync, mkdirSync, readFileSync, writeFileSync } from "node:fs";
2
+ import { dirname, relative, resolve } from "node:path";
3
+ import { spawnSync } from "node:child_process";
4
+ import { resolveTreeseedEnvironmentRegistry } from "../../platform/environment.js";
5
+ import { corePackageRoot, loadCliDeployConfig } from "./runtime-tools.js";
6
+ function envOrNull(key) {
7
+ const value = process.env[key];
8
+ return typeof value === "string" && value.length > 0 ? value : null;
9
+ }
10
+ function getGitHubAutomationMode() {
11
+ return process.env.TREESEED_GITHUB_AUTOMATION_MODE === "stub" ? "stub" : "real";
12
+ }
13
+ function isGitHubAutomationStubbed() {
14
+ return getGitHubAutomationMode() === "stub";
15
+ }
16
+ function parseGitHubRepositoryFromRemote(remoteUrl) {
17
+ if (!remoteUrl) {
18
+ return null;
19
+ }
20
+ const sshMatch = remoteUrl.match(/^git@github\.com:([^/]+)\/(.+?)(?:\.git)?$/);
21
+ if (sshMatch) {
22
+ return `${sshMatch[1]}/${sshMatch[2]}`;
23
+ }
24
+ const httpsMatch = remoteUrl.match(/^https:\/\/github\.com\/([^/]+)\/(.+?)(?:\.git)?$/);
25
+ if (httpsMatch) {
26
+ return `${httpsMatch[1]}/${httpsMatch[2]}`;
27
+ }
28
+ return null;
29
+ }
30
+ function runGit(args, { cwd, allowFailure = false, capture = true } = {}) {
31
+ const result = spawnSync("git", args, {
32
+ cwd,
33
+ stdio: capture ? "pipe" : "inherit",
34
+ encoding: "utf8"
35
+ });
36
+ if (result.status !== 0 && !allowFailure) {
37
+ throw new Error(result.stderr?.trim() || result.stdout?.trim() || `git ${args.join(" ")} failed`);
38
+ }
39
+ return result;
40
+ }
41
+ function runGh(args, { cwd, allowFailure = false, capture = true, input } = {}) {
42
+ const result = spawnSync("gh", args, {
43
+ cwd,
44
+ stdio: capture || input !== void 0 ? ["pipe", "pipe", "pipe"] : "inherit",
45
+ encoding: "utf8",
46
+ input
47
+ });
48
+ if (result.error && result.error.code === "ENOENT") {
49
+ throw new Error("GitHub CLI `gh` is required for Treeseed GitHub automation.");
50
+ }
51
+ if (result.status !== 0 && !allowFailure) {
52
+ throw new Error(result.stderr?.trim() || result.stdout?.trim() || `gh ${args.join(" ")} failed`);
53
+ }
54
+ return result;
55
+ }
56
+ function resolveGitHubRepositorySlug(tenantRoot) {
57
+ const remoteResult = runGit(["remote", "get-url", "origin"], { cwd: tenantRoot });
58
+ const remoteUrl = remoteResult.stdout?.trim() ?? "";
59
+ const repository = parseGitHubRepositoryFromRemote(remoteUrl);
60
+ if (!repository) {
61
+ throw new Error(`Unable to determine GitHub repository from origin remote "${remoteUrl}".`);
62
+ }
63
+ return repository;
64
+ }
65
+ function maybeResolveGitHubRepositorySlug(tenantRoot) {
66
+ try {
67
+ return resolveGitHubRepositorySlug(tenantRoot);
68
+ } catch {
69
+ return null;
70
+ }
71
+ }
72
+ function resolveGitRepositoryRoot(tenantRoot) {
73
+ const result = runGit(["rev-parse", "--show-toplevel"], { cwd: tenantRoot, allowFailure: true });
74
+ return result.status === 0 ? result.stdout.trim() : tenantRoot;
75
+ }
76
+ function requiredGitHubEnvironment(tenantRoot, { scope = "prod", purpose = "save" } = {}) {
77
+ const deployConfig = loadCliDeployConfig(tenantRoot);
78
+ const registry = resolveTreeseedEnvironmentRegistry({ deployConfig });
79
+ const relevant = registry.entries.filter(
80
+ (entry) => entry.scopes.includes(scope) && entry.purposes.includes(purpose) && (!entry.isRelevant || entry.isRelevant(registry.context, scope, purpose))
81
+ );
82
+ return {
83
+ secrets: [...new Set(relevant.filter((entry) => entry.targets.includes("github-secret")).map((entry) => entry.id))],
84
+ variables: [...new Set(relevant.filter((entry) => entry.targets.includes("github-variable")).map((entry) => entry.id))]
85
+ };
86
+ }
87
+ function requiredGitHubSecrets(tenantRoot) {
88
+ return requiredGitHubEnvironment(tenantRoot).secrets;
89
+ }
90
+ function renderDeployWorkflow({ workingDirectory }) {
91
+ const normalizedWorkingDirectory = workingDirectory && workingDirectory !== "." ? workingDirectory : ".";
92
+ const workingDirectoryLine = normalizedWorkingDirectory === "." ? "" : ` defaults:
93
+ run:
94
+ working-directory: ${normalizedWorkingDirectory}
95
+ `;
96
+ const templatePath = resolve(corePackageRoot, "templates", "github", "deploy.workflow.yml");
97
+ const template = readFileSync(templatePath, "utf8");
98
+ return template.replace("__WORKING_DIRECTORY_BLOCK__", workingDirectoryLine).replace(
99
+ "__CACHE_DEPENDENCY_PATH__",
100
+ normalizedWorkingDirectory === "." ? "package-lock.json" : `${normalizedWorkingDirectory}/package-lock.json`
101
+ );
102
+ }
103
+ function ensureDeployWorkflow(tenantRoot) {
104
+ if (isGitHubAutomationStubbed()) {
105
+ return {
106
+ workflowPath: resolve(tenantRoot, ".github", "workflows", "deploy.yml"),
107
+ changed: false,
108
+ workingDirectory: ".",
109
+ mode: "stub"
110
+ };
111
+ }
112
+ const repositoryRoot = resolveGitRepositoryRoot(tenantRoot);
113
+ const workflowPath = resolve(tenantRoot, ".github", "workflows", "deploy.yml");
114
+ const workingDirectory = relative(repositoryRoot, tenantRoot).replaceAll("\\", "/") || ".";
115
+ const expected = renderDeployWorkflow({ workingDirectory });
116
+ const current = existsSync(workflowPath) ? readFileSync(workflowPath, "utf8") : null;
117
+ if (current === expected) {
118
+ return { workflowPath, changed: false, workingDirectory };
119
+ }
120
+ mkdirSync(dirname(workflowPath), { recursive: true });
121
+ writeFileSync(workflowPath, expected, "utf8");
122
+ return { workflowPath, changed: true, workingDirectory };
123
+ }
124
+ function listGitHubSecretNames(repository, tenantRoot) {
125
+ const result = runGh(["secret", "list", "--repo", repository, "--json", "name"], {
126
+ cwd: tenantRoot
127
+ });
128
+ return new Set(
129
+ JSON.parse(result.stdout || "[]").map((entry) => entry?.name).filter((value) => typeof value === "string" && value.length > 0)
130
+ );
131
+ }
132
+ function listGitHubVariableNames(repository, tenantRoot) {
133
+ const result = runGh(["variable", "list", "--repo", repository, "--json", "name"], {
134
+ cwd: tenantRoot
135
+ });
136
+ return new Set(
137
+ JSON.parse(result.stdout || "[]").map((entry) => entry?.name).filter((value) => typeof value === "string" && value.length > 0)
138
+ );
139
+ }
140
+ function formatMissingSecretsReport(repository, missingSecrets, reason = "missing_local_env") {
141
+ const lines = [
142
+ "Treeseed GitHub secret sync failed.",
143
+ `Repository: ${repository}`,
144
+ `Reason: ${reason}`,
145
+ "Missing secrets:"
146
+ ];
147
+ for (const secret of missingSecrets) {
148
+ lines.push(`- ${secret.name}: localEnv=${secret.localEnvPresent ? "present" : "missing"} remote=${secret.remotePresent ? "present" : "missing"}`);
149
+ }
150
+ return lines.join("\n");
151
+ }
152
+ function ensureGitHubSecrets(tenantRoot, { dryRun = false } = {}) {
153
+ return ensureGitHubEnvironment(tenantRoot, { dryRun }).secrets;
154
+ }
155
+ function ensureGitHubEnvironment(tenantRoot, { dryRun = false, scope = "prod", purpose = "save" } = {}) {
156
+ if (isGitHubAutomationStubbed()) {
157
+ return {
158
+ repository: maybeResolveGitHubRepositorySlug(tenantRoot),
159
+ secrets: {
160
+ existing: [],
161
+ created: []
162
+ },
163
+ variables: {
164
+ existing: [],
165
+ created: []
166
+ },
167
+ skipped: "stubbed",
168
+ mode: "stub"
169
+ };
170
+ }
171
+ const repository = maybeResolveGitHubRepositorySlug(tenantRoot);
172
+ if (!repository) {
173
+ if (dryRun) {
174
+ return {
175
+ repository: null,
176
+ secrets: { existing: [], created: [] },
177
+ variables: { existing: [], created: [] },
178
+ skipped: "missing_repository"
179
+ };
180
+ }
181
+ throw new Error("Unable to determine GitHub repository from the current tenant. Configure an origin remote before syncing GitHub secrets.");
182
+ }
183
+ const required = requiredGitHubEnvironment(tenantRoot, { scope, purpose });
184
+ const requiredSecrets = required.secrets;
185
+ const requiredVariables = required.variables;
186
+ const existingSecrets = listGitHubSecretNames(repository, tenantRoot);
187
+ const existingVariables = listGitHubVariableNames(repository, tenantRoot);
188
+ const missingRemote = requiredSecrets.filter((name) => !existingSecrets.has(name));
189
+ const missingRemoteVariables = requiredVariables.filter((name) => !existingVariables.has(name));
190
+ const missingLocal = missingRemote.filter((name) => !envOrNull(name)).map((name) => ({ name, localEnvPresent: false, remotePresent: false }));
191
+ const missingLocalVariables = missingRemoteVariables.filter((name) => !envOrNull(name)).map((name) => ({ name, localEnvPresent: false, remotePresent: false }));
192
+ if (missingLocal.length > 0 || missingLocalVariables.length > 0) {
193
+ throw new Error(formatMissingSecretsReport(repository, [...missingLocal, ...missingLocalVariables]));
194
+ }
195
+ const createdSecrets = [];
196
+ for (const name of missingRemote) {
197
+ if (dryRun) {
198
+ createdSecrets.push(name);
199
+ continue;
200
+ }
201
+ runGh(["secret", "set", name, "--repo", repository, "--body", envOrNull(name) ?? ""], {
202
+ cwd: tenantRoot
203
+ });
204
+ createdSecrets.push(name);
205
+ }
206
+ const createdVariables = [];
207
+ for (const name of missingRemoteVariables) {
208
+ if (dryRun) {
209
+ createdVariables.push(name);
210
+ continue;
211
+ }
212
+ runGh(["variable", "set", name, "--repo", repository, "--body", envOrNull(name) ?? ""], {
213
+ cwd: tenantRoot
214
+ });
215
+ createdVariables.push(name);
216
+ }
217
+ return {
218
+ repository,
219
+ secrets: {
220
+ existing: requiredSecrets.filter((name) => existingSecrets.has(name)),
221
+ created: createdSecrets
222
+ },
223
+ variables: {
224
+ existing: requiredVariables.filter((name) => existingVariables.has(name)),
225
+ created: createdVariables
226
+ }
227
+ };
228
+ }
229
+ function ensureGitHubDeployAutomation(tenantRoot, { dryRun = false } = {}) {
230
+ const workflow = ensureDeployWorkflow(tenantRoot);
231
+ const environment = ensureGitHubEnvironment(tenantRoot, { dryRun });
232
+ return {
233
+ mode: getGitHubAutomationMode(),
234
+ workflow,
235
+ secrets: environment.secrets,
236
+ variables: environment.variables,
237
+ environment
238
+ };
239
+ }
240
+ export {
241
+ ensureDeployWorkflow,
242
+ ensureGitHubDeployAutomation,
243
+ ensureGitHubEnvironment,
244
+ ensureGitHubSecrets,
245
+ formatMissingSecretsReport,
246
+ getGitHubAutomationMode,
247
+ listGitHubSecretNames,
248
+ listGitHubVariableNames,
249
+ maybeResolveGitHubRepositorySlug,
250
+ parseGitHubRepositoryFromRemote,
251
+ renderDeployWorkflow,
252
+ requiredGitHubEnvironment,
253
+ requiredGitHubSecrets,
254
+ resolveGitHubRepositorySlug,
255
+ resolveGitRepositoryRoot
256
+ };
@@ -0,0 +1,9 @@
1
+ export declare function runStep(command: any, args: any, options?: {}): void;
2
+ export declare function runNodeScript(scriptRelativePath: any, args?: never[], options?: {}): void;
3
+ export declare function spawnProcess(command: any, args: any, options?: {}): import("child_process").ChildProcessWithoutNullStreams;
4
+ export declare function syncDevVars(overrides?: {}): void;
5
+ export declare function runLocalD1Migration(persistTo: any): void;
6
+ export declare function prepareCloudflareLocalRuntime({ envOverrides, persistTo, outDir }?: {
7
+ envOverrides?: {} | undefined;
8
+ }): void;
9
+ export declare function startWranglerDev(args?: never[], options?: {}): import("child_process").ChildProcessWithoutNullStreams;