@treeseed/sdk 0.4.5 → 0.4.7
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/fixture-support.d.ts +1 -1
- package/dist/fixture-support.js +5 -5
- package/dist/operations/services/config-runtime.js +1 -1
- package/dist/operations/services/railway-deploy.js +1 -1
- package/dist/operations/services/runtime-tools.d.ts +0 -1
- package/dist/operations/services/runtime-tools.js +1 -3
- package/dist/operations/services/template-registry.d.ts +2 -0
- package/dist/operations/services/template-registry.js +55 -6
- package/dist/scripts/test-scaffold.js +5 -21
- package/dist/scripts/treeseed-release-verify.js +3 -3
- package/dist/sdk-types.d.ts +1 -0
- package/dist/template-catalog.js +1 -0
- package/dist/workflow/operations.d.ts +241 -169
- package/dist/workflow/operations.js +245 -111
- package/dist/workflow/policy.d.ts +12 -0
- package/dist/workflow/policy.js +58 -0
- package/dist/workflow-state.d.ts +19 -1
- package/dist/workflow-state.js +57 -39
- package/dist/workflow.d.ts +3 -0
- package/dist/workflow.js +2 -1
- package/package.json +1 -1
package/dist/workflow-state.js
CHANGED
|
@@ -6,30 +6,14 @@ import {
|
|
|
6
6
|
createPersistentDeployTarget,
|
|
7
7
|
loadDeployState
|
|
8
8
|
} from "./operations/services/deploy.js";
|
|
9
|
-
import { PRODUCTION_BRANCH, STAGING_BRANCH } from "./operations/services/git-workflow.js";
|
|
10
9
|
import { loadCliDeployConfig } from "./operations/services/runtime-tools.js";
|
|
11
10
|
import { collectCliPreflight } from "./operations/services/workspace-preflight.js";
|
|
12
|
-
import {
|
|
11
|
+
import { gitStatusPorcelain } from "./operations/services/workspace-save.js";
|
|
13
12
|
import { isWorkspaceRoot } from "./operations/services/workspace-tools.js";
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
return null;
|
|
19
|
-
}
|
|
20
|
-
}
|
|
21
|
-
function branchRoleFor(branchName) {
|
|
22
|
-
if (!branchName) return "none";
|
|
23
|
-
if (branchName === STAGING_BRANCH) return "staging";
|
|
24
|
-
if (branchName === PRODUCTION_BRANCH) return "main";
|
|
25
|
-
return "feature";
|
|
26
|
-
}
|
|
27
|
-
function environmentForBranchRole(branchRole) {
|
|
28
|
-
if (branchRole === "staging") return "staging";
|
|
29
|
-
if (branchRole === "main") return "prod";
|
|
30
|
-
if (branchRole === "feature") return "local";
|
|
31
|
-
return "none";
|
|
32
|
-
}
|
|
13
|
+
import {
|
|
14
|
+
resolveTreeseedWorkflowPaths,
|
|
15
|
+
workflowEnvironmentForBranchRole
|
|
16
|
+
} from "./workflow/policy.js";
|
|
33
17
|
function emptyPersistentEnvironments() {
|
|
34
18
|
return {
|
|
35
19
|
local: { initialized: false, lastValidatedAt: null, lastDeploymentTimestamp: null, lastDeployedUrl: null },
|
|
@@ -37,25 +21,54 @@ function emptyPersistentEnvironments() {
|
|
|
37
21
|
prod: { initialized: false, lastValidatedAt: null, lastDeploymentTimestamp: null, lastDeployedUrl: null }
|
|
38
22
|
};
|
|
39
23
|
}
|
|
24
|
+
function readinessForEnvironment(state, scope) {
|
|
25
|
+
const blockers = [];
|
|
26
|
+
const warnings = [];
|
|
27
|
+
if (!state.deployConfigPresent) {
|
|
28
|
+
blockers.push("Missing treeseed.site.yaml.");
|
|
29
|
+
}
|
|
30
|
+
if (!state.files.machineConfig) {
|
|
31
|
+
blockers.push("Missing Treeseed machine config.");
|
|
32
|
+
}
|
|
33
|
+
if (scope === "local") {
|
|
34
|
+
if (!state.files.envLocal) {
|
|
35
|
+
blockers.push("Missing .env.local.");
|
|
36
|
+
}
|
|
37
|
+
if (!state.files.devVars) {
|
|
38
|
+
warnings.push("Missing .dev.vars.");
|
|
39
|
+
}
|
|
40
|
+
} else {
|
|
41
|
+
if (!state.persistentEnvironments[scope].initialized) {
|
|
42
|
+
blockers.push(`Environment ${scope} is not initialized.`);
|
|
43
|
+
}
|
|
44
|
+
}
|
|
45
|
+
return {
|
|
46
|
+
ready: blockers.length === 0,
|
|
47
|
+
blockers,
|
|
48
|
+
warnings
|
|
49
|
+
};
|
|
50
|
+
}
|
|
40
51
|
function resolveTreeseedWorkflowState(cwd) {
|
|
41
|
-
const
|
|
42
|
-
const
|
|
52
|
+
const resolved = resolveTreeseedWorkflowPaths(cwd);
|
|
53
|
+
const effectiveCwd = resolved.cwd;
|
|
54
|
+
const workspaceRoot = isWorkspaceRoot(effectiveCwd);
|
|
55
|
+
const treeseedConfigPath = resolve(effectiveCwd, "treeseed.site.yaml");
|
|
43
56
|
const tenantRoot = existsSync(treeseedConfigPath);
|
|
44
|
-
const root =
|
|
45
|
-
const branchName =
|
|
46
|
-
const branchRole =
|
|
57
|
+
const root = resolved.repoRoot;
|
|
58
|
+
const branchName = resolved.branchName;
|
|
59
|
+
const branchRole = resolved.branchRole;
|
|
47
60
|
const dirtyWorktree = root ? gitStatusPorcelain(root).length > 0 : false;
|
|
48
|
-
const preflight = collectCliPreflight({ cwd, requireAuth: false });
|
|
49
|
-
const { configPath, keyPath } = getTreeseedMachineConfigPaths(
|
|
61
|
+
const preflight = collectCliPreflight({ cwd: effectiveCwd, requireAuth: false });
|
|
62
|
+
const { configPath, keyPath } = getTreeseedMachineConfigPaths(effectiveCwd);
|
|
50
63
|
const state = {
|
|
51
|
-
cwd,
|
|
64
|
+
cwd: effectiveCwd,
|
|
52
65
|
workspaceRoot,
|
|
53
66
|
tenantRoot,
|
|
54
67
|
deployConfigPresent: tenantRoot,
|
|
55
68
|
repoRoot: root,
|
|
56
69
|
branchName,
|
|
57
70
|
branchRole,
|
|
58
|
-
environment:
|
|
71
|
+
environment: workflowEnvironmentForBranchRole(branchRole),
|
|
59
72
|
dirtyWorktree,
|
|
60
73
|
preview: {
|
|
61
74
|
enabled: false,
|
|
@@ -86,14 +99,19 @@ function resolveTreeseedWorkflowState(cwd) {
|
|
|
86
99
|
devVars: existsSync(resolve(cwd, ".dev.vars"))
|
|
87
100
|
},
|
|
88
101
|
releaseReady: branchRole === "staging" && !dirtyWorktree,
|
|
102
|
+
readiness: {
|
|
103
|
+
local: { ready: false, blockers: [], warnings: [] },
|
|
104
|
+
staging: { ready: false, blockers: [], warnings: [] },
|
|
105
|
+
prod: { ready: false, blockers: [], warnings: [] }
|
|
106
|
+
},
|
|
89
107
|
rollbackCandidates: [],
|
|
90
108
|
recommendations: []
|
|
91
109
|
};
|
|
92
110
|
if (tenantRoot) {
|
|
93
111
|
try {
|
|
94
|
-
const deployConfig = loadCliDeployConfig(
|
|
112
|
+
const deployConfig = loadCliDeployConfig(effectiveCwd);
|
|
95
113
|
for (const scope of ["local", "staging", "prod"]) {
|
|
96
|
-
const deployState = loadDeployState(
|
|
114
|
+
const deployState = loadDeployState(effectiveCwd, deployConfig, { target: createPersistentDeployTarget(scope) });
|
|
97
115
|
state.persistentEnvironments[scope] = {
|
|
98
116
|
initialized: deployState.readiness?.initialized === true || scope === "local",
|
|
99
117
|
lastValidatedAt: deployState.readiness?.lastValidatedAt ?? deployState.readiness?.initializedAt ?? null,
|
|
@@ -123,7 +141,7 @@ function resolveTreeseedWorkflowState(cwd) {
|
|
|
123
141
|
}
|
|
124
142
|
}
|
|
125
143
|
if (branchRole === "feature" && branchName) {
|
|
126
|
-
const previewState = loadDeployState(
|
|
144
|
+
const previewState = loadDeployState(effectiveCwd, deployConfig, { target: createBranchPreviewDeployTarget(branchName) });
|
|
127
145
|
state.preview = {
|
|
128
146
|
enabled: previewState.previewEnabled === true || previewState.readiness?.initialized === true,
|
|
129
147
|
url: previewState.lastDeployedUrl ?? null,
|
|
@@ -133,6 +151,9 @@ function resolveTreeseedWorkflowState(cwd) {
|
|
|
133
151
|
} catch {
|
|
134
152
|
}
|
|
135
153
|
}
|
|
154
|
+
state.readiness.local = readinessForEnvironment(state, "local");
|
|
155
|
+
state.readiness.staging = readinessForEnvironment(state, "staging");
|
|
156
|
+
state.readiness.prod = readinessForEnvironment(state, "prod");
|
|
136
157
|
state.recommendations = recommendTreeseedNextSteps(state);
|
|
137
158
|
return state;
|
|
138
159
|
}
|
|
@@ -150,13 +171,10 @@ function recommendTreeseedNextSteps(state) {
|
|
|
150
171
|
return recommendations;
|
|
151
172
|
}
|
|
152
173
|
if (state.branchRole === "feature") {
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
} else {
|
|
156
|
-
recommendations.push({ operation: "stage", reason: "Merge this task branch into staging and clean up branch artifacts.", input: { message: "describe the resolution" } });
|
|
157
|
-
}
|
|
174
|
+
recommendations.push({ operation: "stage", reason: "Merge this task branch into staging and clean up branch artifacts.", input: { message: "describe the resolution" } });
|
|
175
|
+
recommendations.push({ operation: "save", reason: "Persist, verify, and push the current task branch before or independently of staging it.", input: { message: "describe your change" } });
|
|
158
176
|
if (state.preview.enabled && state.branchName) {
|
|
159
|
-
recommendations.push({ operation: "save", reason: "Save refreshes the branch preview deployment when one is enabled.", input: { message: "describe your change" } });
|
|
177
|
+
recommendations.push({ operation: "save", reason: "Save refreshes the branch preview deployment when one is enabled.", input: { message: "describe your change", preview: true } });
|
|
160
178
|
} else {
|
|
161
179
|
recommendations.push({ operation: "dev", reason: "Use the local environment for iterative work on this feature branch." });
|
|
162
180
|
}
|
package/dist/workflow.d.ts
CHANGED
|
@@ -35,18 +35,21 @@ export type TreeseedSaveInput = {
|
|
|
35
35
|
hotfix?: boolean;
|
|
36
36
|
verify?: boolean;
|
|
37
37
|
refreshPreview?: boolean;
|
|
38
|
+
preview?: boolean;
|
|
38
39
|
rebase?: boolean;
|
|
39
40
|
};
|
|
40
41
|
export type TreeseedCloseInput = {
|
|
41
42
|
message: string;
|
|
42
43
|
deletePreview?: boolean;
|
|
43
44
|
deleteBranch?: boolean;
|
|
45
|
+
autoSave?: boolean;
|
|
44
46
|
};
|
|
45
47
|
export type TreeseedStageInput = {
|
|
46
48
|
message: string;
|
|
47
49
|
waitForStaging?: boolean;
|
|
48
50
|
deletePreview?: boolean;
|
|
49
51
|
deleteBranch?: boolean;
|
|
52
|
+
autoSave?: boolean;
|
|
50
53
|
};
|
|
51
54
|
export type TreeseedSwitchInput = {
|
|
52
55
|
branch?: string;
|
package/dist/workflow.js
CHANGED
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import { resolveTreeseedWorkflowPaths } from "./workflow/policy.js";
|
|
1
2
|
import {
|
|
2
3
|
TreeseedWorkflowError,
|
|
3
4
|
workflowClose,
|
|
@@ -28,7 +29,7 @@ class TreeseedWorkflowSdk {
|
|
|
28
29
|
};
|
|
29
30
|
return {
|
|
30
31
|
context,
|
|
31
|
-
cwd: () => context.cwd ?? process.cwd(),
|
|
32
|
+
cwd: () => resolveTreeseedWorkflowPaths(context.cwd ?? process.cwd()).cwd,
|
|
32
33
|
write: context.write ?? defaultWrite,
|
|
33
34
|
runStatus: async () => this.status(),
|
|
34
35
|
runTasks: async () => this.tasks()
|