dataiku-sdk 2.0.0 → 3.1.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.
- package/LICENSE +107 -17
- package/README.md +144 -17
- package/dist/build-metadata.json +1 -1
- package/dist/packages/types/src/index.d.ts +39 -4
- package/dist/packages/types/src/index.js +31 -2
- package/dist/src/cli/commands/api-service.js +62 -16
- package/dist/src/cli/commands/bundle.js +49 -15
- package/dist/src/cli/commands/code-env.js +210 -49
- package/dist/src/cli/commands/code.d.ts +19 -0
- package/dist/src/cli/commands/code.js +87 -15
- package/dist/src/cli/commands/dataset.js +8 -3
- package/dist/src/cli/commands/flow-zone.js +33 -5
- package/dist/src/cli/commands/notebook.js +72 -41
- package/dist/src/cli/commands/project-git.js +8 -5
- package/dist/src/cli/commands/project-library.d.ts +21 -0
- package/dist/src/cli/commands/project-library.js +121 -50
- package/dist/src/cli/commands/project.js +16 -2
- package/dist/src/cli/commands/recipe.js +37 -12
- package/dist/src/cli/commands/sql.d.ts +10 -0
- package/dist/src/cli/commands/sql.js +39 -17
- package/dist/src/cli/commands/webapp.js +67 -13
- package/dist/src/cli/contract.d.ts +15 -0
- package/dist/src/cli/contract.js +870 -107
- package/dist/src/cli/env.d.ts +9 -0
- package/dist/src/cli/env.js +20 -2
- package/dist/src/cli/flags.js +9 -0
- package/dist/src/cli/helpers/cleanup.js +104 -3
- package/dist/src/cli/helpers/flow-zone.d.ts +3 -0
- package/dist/src/cli/helpers/flow-zone.js +33 -3
- package/dist/src/cli/helpers/recipe.d.ts +20 -0
- package/dist/src/cli/helpers/recipe.js +158 -3
- package/dist/src/cli/output.d.ts +2 -0
- package/dist/src/cli/output.js +33 -6
- package/dist/src/cli/runtime.d.ts +35 -1
- package/dist/src/cli/runtime.js +125 -18
- package/dist/src/cli/types.d.ts +7 -0
- package/dist/src/cli.js +135 -28
- package/dist/src/client.d.ts +60 -0
- package/dist/src/client.js +237 -42
- package/dist/src/errors.d.ts +8 -2
- package/dist/src/errors.js +40 -0
- package/dist/src/index.d.ts +4 -3
- package/dist/src/index.js +2 -1
- package/dist/src/resources/api-services.d.ts +48 -6
- package/dist/src/resources/api-services.js +54 -8
- package/dist/src/resources/bundles.d.ts +51 -6
- package/dist/src/resources/bundles.js +39 -9
- package/dist/src/resources/code-envs.d.ts +25 -3
- package/dist/src/resources/code-envs.js +104 -2
- package/dist/src/resources/datasets.d.ts +20 -0
- package/dist/src/resources/datasets.js +232 -52
- package/dist/src/resources/jobs.d.ts +35 -10
- package/dist/src/resources/jobs.js +92 -17
- package/dist/src/resources/notebooks.d.ts +77 -7
- package/dist/src/resources/notebooks.js +143 -19
- package/dist/src/resources/project-git.d.ts +12 -0
- package/dist/src/resources/project-git.js +39 -8
- package/dist/src/resources/project-library.d.ts +122 -7
- package/dist/src/resources/project-library.js +494 -25
- package/dist/src/resources/projects.d.ts +5 -2
- package/dist/src/resources/projects.js +18 -2
- package/dist/src/resources/scenarios.d.ts +30 -0
- package/dist/src/resources/scenarios.js +73 -27
- package/dist/src/resources/sql.d.ts +6 -0
- package/dist/src/resources/sql.js +22 -2
- package/dist/src/resources/webapps.d.ts +35 -4
- package/dist/src/resources/webapps.js +54 -5
- package/dist/src/schemas.d.ts +2 -2
- package/dist/src/schemas.js +1 -1
- package/dist/src/skill.d.ts +9 -0
- package/dist/src/skill.js +37 -4
- package/dist/src/utils/flow-analysis.d.ts +53 -0
- package/dist/src/utils/flow-analysis.js +382 -0
- package/dist/src/utils/project-archive.d.ts +41 -2
- package/dist/src/utils/project-archive.js +159 -16
- package/package.json +5 -5
- package/packages/types/dist/index.d.ts +39 -4
- package/packages/types/dist/index.js +31 -2
- package/plugin.json +2 -2
- package/skills/dataiku-dss/SKILL.md +75 -48
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import { json, parseBooleanOption, } from "../coerce.js";
|
|
1
2
|
import { requireArgs, UsageError, } from "../usage.js";
|
|
2
3
|
export const bundleCommands = {
|
|
3
4
|
"list-exported": {
|
|
@@ -8,13 +9,24 @@ export const bundleCommands = {
|
|
|
8
9
|
},
|
|
9
10
|
export: {
|
|
10
11
|
handler: async (c, a, f) => {
|
|
11
|
-
|
|
12
|
-
|
|
12
|
+
const usage = "dss bundle export <bundleId> [--release-notes TEXT] [--evaluate-standards-checks true|false] [--project-key KEY]";
|
|
13
|
+
requireArgs(a, 1, usage);
|
|
14
|
+
await c.bundles.exportBundle(a[0], f["project-key"], {
|
|
15
|
+
...(typeof f["release-notes"] === "string" ? { releaseNotes: f["release-notes"], } : {}),
|
|
16
|
+
...(f["evaluate-standards-checks"] !== undefined
|
|
17
|
+
? {
|
|
18
|
+
evaluateProjectStandardsChecks: parseBooleanOption(f["evaluate-standards-checks"], "--evaluate-standards-checks") ?? true,
|
|
19
|
+
}
|
|
20
|
+
: {}),
|
|
21
|
+
});
|
|
13
22
|
return { exported: a[0], };
|
|
14
23
|
},
|
|
15
|
-
usage: "dss bundle export <bundleId> [--project-key KEY]",
|
|
16
|
-
description: "Create (or overwrite) an exported Design-node bundle.",
|
|
17
|
-
examples: [
|
|
24
|
+
usage: "dss bundle export <bundleId> [--release-notes TEXT] [--evaluate-standards-checks true|false] [--project-key KEY]",
|
|
25
|
+
description: "Create (or overwrite) an exported Design-node bundle. --release-notes forwards the documented releaseNotes parameter; --evaluate-standards-checks toggles the documented Project Standards Checks evaluation (default true).",
|
|
26
|
+
examples: [
|
|
27
|
+
"dss bundle export v1",
|
|
28
|
+
"dss bundle export v1 --release-notes='Adds churn model' --evaluate-standards-checks=false",
|
|
29
|
+
],
|
|
18
30
|
},
|
|
19
31
|
"delete-exported": {
|
|
20
32
|
handler: async (c, a, f) => {
|
|
@@ -45,12 +57,18 @@ export const bundleCommands = {
|
|
|
45
57
|
},
|
|
46
58
|
publish: {
|
|
47
59
|
handler: (c, a, f) => {
|
|
48
|
-
|
|
49
|
-
|
|
60
|
+
const usage = "dss bundle publish <bundleId> [--published-project-key KEY] [--project-key KEY]";
|
|
61
|
+
requireArgs(a, 1, usage);
|
|
62
|
+
return c.bundles.publish(a[0], f["project-key"], typeof f["published-project-key"] === "string"
|
|
63
|
+
? { publishedProjectKey: f["published-project-key"], }
|
|
64
|
+
: {});
|
|
50
65
|
},
|
|
51
|
-
usage: "dss bundle publish <bundleId> [--project-key KEY]",
|
|
52
|
-
description: "Publish a Design-node bundle to the Project Deployer.",
|
|
53
|
-
examples: [
|
|
66
|
+
usage: "dss bundle publish <bundleId> [--published-project-key KEY] [--project-key KEY]",
|
|
67
|
+
description: "Publish a Design-node bundle to the Project Deployer; --published-project-key forwards the documented publishedProjectKey query parameter (a new published project is created when no match exists; the source project's key is the server-side default).",
|
|
68
|
+
examples: [
|
|
69
|
+
"dss bundle publish v1",
|
|
70
|
+
"dss bundle publish v1 --published-project-key=PROD-CHURN",
|
|
71
|
+
],
|
|
54
72
|
},
|
|
55
73
|
"list-imported": {
|
|
56
74
|
handler: (c, _a, f) => c.bundles.listImported(f["project-key"]),
|
|
@@ -79,12 +97,28 @@ export const bundleCommands = {
|
|
|
79
97
|
},
|
|
80
98
|
activate: {
|
|
81
99
|
handler: (c, a, f) => {
|
|
82
|
-
|
|
83
|
-
|
|
100
|
+
const usage = "dss bundle activate <bundleId> [--scenarios JSON] [--project-key KEY]";
|
|
101
|
+
requireArgs(a, 1, usage);
|
|
102
|
+
const rawScenarios = f["scenarios"];
|
|
103
|
+
let scenariosToEnable;
|
|
104
|
+
if (rawScenarios !== undefined && rawScenarios !== false) {
|
|
105
|
+
const parsed = json(rawScenarios);
|
|
106
|
+
if (typeof parsed !== "object"
|
|
107
|
+
|| parsed === null
|
|
108
|
+
|| Array.isArray(parsed)
|
|
109
|
+
|| !Object.values(parsed).every((value) => typeof value === "boolean")) {
|
|
110
|
+
throw new UsageError("--scenarios must be a JSON object mapping scenario IDs to true|false. Usage: dss bundle activate <bundleId> --scenarios '{\"daily_build\":true}'");
|
|
111
|
+
}
|
|
112
|
+
scenariosToEnable = parsed;
|
|
113
|
+
}
|
|
114
|
+
return c.bundles.activate(a[0], f["project-key"], scenariosToEnable !== undefined ? { scenariosToEnable, } : {});
|
|
84
115
|
},
|
|
85
|
-
usage: "dss bundle activate <bundleId> [--project-key KEY]",
|
|
86
|
-
description: "Activate an imported Automation-node bundle.",
|
|
87
|
-
examples: [
|
|
116
|
+
usage: "dss bundle activate <bundleId> [--scenarios JSON] [--project-key KEY]",
|
|
117
|
+
description: "Activate an imported Automation-node bundle; --scenarios forwards the documented scenario-ID-to-enabled dict as the scenariosActiveOnActivation body.",
|
|
118
|
+
examples: [
|
|
119
|
+
"dss bundle activate v1",
|
|
120
|
+
'dss bundle activate v1 --scenarios=\'{"daily_build":true,"hourly_retrain":false}\'',
|
|
121
|
+
],
|
|
88
122
|
},
|
|
89
123
|
preload: {
|
|
90
124
|
handler: (c, a, f) => {
|
|
@@ -1,7 +1,33 @@
|
|
|
1
|
-
import { readFileSync, } from "node:fs";
|
|
2
|
-
import {
|
|
3
|
-
import {
|
|
1
|
+
import { readFileSync, writeFileSync, } from "node:fs";
|
|
2
|
+
import { ClientValidationError, } from "../../errors.js";
|
|
3
|
+
import { stableHash, } from "../../utils/stable-hash.js";
|
|
4
|
+
import { json, jsonInput, num, numFlag, parseBooleanOption, } from "../coerce.js";
|
|
5
|
+
import { enqueueCliWarning, isNotFoundError, readIfExists, skipResult, } from "../output.js";
|
|
4
6
|
import { requireArgs, UsageError, } from "../usage.js";
|
|
7
|
+
const CODE_ENV_LANGS = ["PYTHON", "R",];
|
|
8
|
+
/** Validate a positional `<lang>` argument: required, must be PYTHON or R. */
|
|
9
|
+
function requireEnvLang(value, usage) {
|
|
10
|
+
if (value !== "PYTHON" && value !== "R") {
|
|
11
|
+
throw new UsageError(`env language must be one of ${CODE_ENV_LANGS.join(", ")}. Usage: ${usage}`, "invalid_enum", undefined, { value, allowed: CODE_ENV_LANGS, });
|
|
12
|
+
}
|
|
13
|
+
return value;
|
|
14
|
+
}
|
|
15
|
+
function definitionHashMismatch(envLang, envName, expected, current) {
|
|
16
|
+
return new ClientValidationError(`Code env ${envLang}/${envName} changed since the expected definition hash was captured; refusing to overwrite it.`, "validation_failed", "Re-read the definition with dss code-env get-definition (definitionHash comes from code-env get), review the diff, and retry with the fresh hash.", {
|
|
17
|
+
envLang,
|
|
18
|
+
envName,
|
|
19
|
+
expectedDefinitionHash: expected,
|
|
20
|
+
...(current !== undefined ? { currentDefinitionHash: current, } : {}),
|
|
21
|
+
});
|
|
22
|
+
}
|
|
23
|
+
function validateExpectHash(value) {
|
|
24
|
+
if (value === undefined || value === false)
|
|
25
|
+
return undefined;
|
|
26
|
+
if (typeof value !== "string" || !/^[0-9a-fA-F]{64}$/.test(value)) {
|
|
27
|
+
throw new ClientValidationError("Expected code env definition hash must be a 64-character SHA-256 hex digest.", "validation_failed", "Use the definitionHash value returned by dss code-env get.");
|
|
28
|
+
}
|
|
29
|
+
return value;
|
|
30
|
+
}
|
|
5
31
|
function codeEnvWait(flags) {
|
|
6
32
|
return flags["no-wait"] !== true;
|
|
7
33
|
}
|
|
@@ -33,34 +59,116 @@ function codeEnvPackageList(flags) {
|
|
|
33
59
|
}
|
|
34
60
|
export const codeEnvCommands = {
|
|
35
61
|
list: {
|
|
36
|
-
handler: (c, _a, f) =>
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
62
|
+
handler: (c, _a, f) => {
|
|
63
|
+
const usage = "dss code-env list [--lang PYTHON|R]";
|
|
64
|
+
const lang = f["lang"];
|
|
65
|
+
return c.codeEnvs.list({
|
|
66
|
+
envLang: typeof lang === "string"
|
|
67
|
+
? requireEnvLang(lang, usage)
|
|
68
|
+
: undefined,
|
|
69
|
+
});
|
|
70
|
+
},
|
|
71
|
+
usage: "dss code-env list [--lang PYTHON|R]",
|
|
72
|
+
description: "List code environments, optionally filtered to one language.",
|
|
41
73
|
examples: ["dss code-env list", "dss code-env list --lang PYTHON",],
|
|
42
74
|
},
|
|
43
75
|
get: {
|
|
44
76
|
handler: (c, a) => {
|
|
45
|
-
|
|
46
|
-
|
|
77
|
+
const usage = "dss code-env get <lang> <name>";
|
|
78
|
+
requireArgs(a, 2, usage);
|
|
79
|
+
const envLang = requireEnvLang(a[0], usage);
|
|
80
|
+
return c.codeEnvs.get(envLang, a[1]);
|
|
47
81
|
},
|
|
48
82
|
usage: "dss code-env get <lang> <name>",
|
|
49
|
-
description: "Get code environment details.",
|
|
83
|
+
description: "Get code environment details: requested vs installed packages, Python interpreter, deployment mode, and the stable definition hash (definitionHash) used by set-definition --expect-hash.",
|
|
50
84
|
examples: ["dss code-env get PYTHON my_env",],
|
|
51
85
|
},
|
|
52
86
|
"get-definition": {
|
|
53
87
|
handler: (c, a) => {
|
|
54
|
-
|
|
55
|
-
|
|
88
|
+
const usage = "dss code-env get-definition <lang> <name>";
|
|
89
|
+
requireArgs(a, 2, usage);
|
|
90
|
+
const envLang = requireEnvLang(a[0], usage);
|
|
91
|
+
return c.codeEnvs.getDefinition(envLang, a[1]);
|
|
56
92
|
},
|
|
57
93
|
usage: "dss code-env get-definition <lang> <name>",
|
|
58
|
-
description: "Get raw code environment definition.",
|
|
94
|
+
description: "Get the raw code environment definition exactly as DSS stores it; capture its hash (definitionHash from code-env get) before replacing it with set-definition --expect-hash.",
|
|
59
95
|
examples: ["dss code-env get-definition PYTHON my_env",],
|
|
60
96
|
},
|
|
97
|
+
"list-logs": {
|
|
98
|
+
handler: (c, a) => {
|
|
99
|
+
const usage = "dss code-env list-logs <lang> <name>";
|
|
100
|
+
requireArgs(a, 2, usage);
|
|
101
|
+
const envLang = requireEnvLang(a[0], usage);
|
|
102
|
+
return c.codeEnvs.listLogs(envLang, a[1]);
|
|
103
|
+
},
|
|
104
|
+
usage: "dss code-env list-logs <lang> <name>",
|
|
105
|
+
description: "List the build log files DSS keeps for a code environment.",
|
|
106
|
+
examples: ["dss code-env list-logs PYTHON my_env",],
|
|
107
|
+
},
|
|
108
|
+
"get-log": {
|
|
109
|
+
handler: async (c, a, f) => {
|
|
110
|
+
const usage = "dss code-env get-log <lang> <name> <logName> [--max-lines N|--max-log-lines N] [--max-log-bytes N] [--output PATH]";
|
|
111
|
+
requireArgs(a, 3, usage);
|
|
112
|
+
const envLang = requireEnvLang(a[0], usage);
|
|
113
|
+
const maxLines = numFlag(f, ["max-lines", "max-log-lines",]);
|
|
114
|
+
const maxBytes = num(f["max-log-bytes"], "--max-log-bytes");
|
|
115
|
+
const result = await c.codeEnvs.getLog(envLang, a[1], a[2], {
|
|
116
|
+
...(maxLines !== undefined ? { maxLines, } : {}),
|
|
117
|
+
...(maxBytes !== undefined ? { maxBytes, } : {}),
|
|
118
|
+
});
|
|
119
|
+
const output = f["output"];
|
|
120
|
+
if (typeof output === "string" && output.trim().length > 0) {
|
|
121
|
+
writeFileSync(output, result.log, "utf-8");
|
|
122
|
+
if (result.truncated || result.tailed) {
|
|
123
|
+
const limits = [
|
|
124
|
+
result.tailed ? `tail limited to ${maxLines ?? 500} lines` : undefined,
|
|
125
|
+
result.truncated ? "byte cap reached" : undefined,
|
|
126
|
+
].filter((part) => part !== undefined);
|
|
127
|
+
enqueueCliWarning({
|
|
128
|
+
code: "code_env_log_truncated",
|
|
129
|
+
message: `Code env ${envLang}/${a[1]} log '${a[2]}' was truncated (${limits.join("; ")},). Pass --max-log-bytes 0 and --max-lines 0 for the full log, or refetch with higher limits.`,
|
|
130
|
+
envLang,
|
|
131
|
+
envName: a[1],
|
|
132
|
+
logName: a[2],
|
|
133
|
+
truncated: result.truncated,
|
|
134
|
+
tailed: result.tailed,
|
|
135
|
+
});
|
|
136
|
+
}
|
|
137
|
+
return {
|
|
138
|
+
path: output,
|
|
139
|
+
bytes: result.bytes,
|
|
140
|
+
truncated: result.truncated,
|
|
141
|
+
tailed: result.tailed,
|
|
142
|
+
envLang,
|
|
143
|
+
envName: a[1],
|
|
144
|
+
logName: a[2],
|
|
145
|
+
};
|
|
146
|
+
}
|
|
147
|
+
return { ...result, envLang, envName: a[1], logName: a[2], };
|
|
148
|
+
},
|
|
149
|
+
usage: "dss code-env get-log <lang> <name> <logName> [--max-lines N|--max-log-lines N] [--max-log-bytes N] [--output PATH]",
|
|
150
|
+
description: "Fetch one code-env build log, bounded for safe output: the last --max-lines lines (default 500, 0 for all) and at most --max-log-bytes bytes (default 10 MiB, 0 for all). --output PATH writes the kept content to a file; stdout then carries the path metadata. A truncation warning names which cap hit.",
|
|
151
|
+
examples: [
|
|
152
|
+
"dss code-env get-log PYTHON my_env install.log --max-lines 200",
|
|
153
|
+
"dss code-env get-log PYTHON my_env install.log --output ./install.log --max-log-bytes 0",
|
|
154
|
+
],
|
|
155
|
+
},
|
|
156
|
+
version: {
|
|
157
|
+
handler: (c, a) => {
|
|
158
|
+
const usage = "dss code-env version <lang> <name> <projectKey>";
|
|
159
|
+
requireArgs(a, 3, usage);
|
|
160
|
+
const envLang = requireEnvLang(a[0], usage);
|
|
161
|
+
return c.codeEnvs.getVersionForProject(envLang, a[1], a[2]);
|
|
162
|
+
},
|
|
163
|
+
usage: "dss code-env version <lang> <name> <projectKey>",
|
|
164
|
+
description: "Resolve the code environment version a project uses (versioned automation environments); empty version for unversioned environments.",
|
|
165
|
+
examples: ["dss code-env version PYTHON my_env MY_PROJ",],
|
|
166
|
+
},
|
|
61
167
|
create: {
|
|
62
168
|
handler: async (c, a, f) => {
|
|
63
|
-
|
|
169
|
+
const usage = "dss code-env create <lang> <name> --deployment-mode MODE";
|
|
170
|
+
requireArgs(a, 2, usage);
|
|
171
|
+
const envLang = requireEnvLang(a[0], usage);
|
|
64
172
|
const deploymentMode = f["deployment-mode"];
|
|
65
173
|
if (!deploymentMode) {
|
|
66
174
|
throw new UsageError("--deployment-mode is required. Usage: dss code-env create <lang> <name> --deployment-mode MODE");
|
|
@@ -68,38 +176,38 @@ export const codeEnvCommands = {
|
|
|
68
176
|
const params = codeEnvParams(f);
|
|
69
177
|
const wait = codeEnvWait(f);
|
|
70
178
|
if (f["if-not-exists"] === true || f["dry-run"] === true) {
|
|
71
|
-
const existing = (await c.codeEnvs.list({ envLang
|
|
179
|
+
const existing = (await c.codeEnvs.list({ envLang, }))
|
|
72
180
|
.find((env) => env.envName === a[1]);
|
|
73
181
|
if (existing && f["if-not-exists"] === true && f["dry-run"] !== true) {
|
|
74
|
-
return skipResult("code-env", a[1], "exists", { envLang
|
|
182
|
+
return skipResult("code-env", a[1], "exists", { envLang, current: existing, });
|
|
75
183
|
}
|
|
76
184
|
if (f["dry-run"] === true) {
|
|
77
185
|
return {
|
|
78
186
|
dryRun: true,
|
|
79
187
|
action: "create",
|
|
80
188
|
resource: "code-env",
|
|
81
|
-
envLang
|
|
189
|
+
envLang,
|
|
82
190
|
envName: a[1],
|
|
83
191
|
payload: {
|
|
84
192
|
deploymentMode,
|
|
85
193
|
params,
|
|
86
|
-
wait,
|
|
87
194
|
},
|
|
195
|
+
wait,
|
|
88
196
|
...(existing ? { current: existing, } : {}),
|
|
89
197
|
};
|
|
90
198
|
}
|
|
91
199
|
}
|
|
92
200
|
const created = await c.codeEnvs.create({
|
|
93
|
-
envLang
|
|
201
|
+
envLang,
|
|
94
202
|
envName: a[1],
|
|
95
203
|
deploymentMode,
|
|
96
204
|
params,
|
|
97
205
|
wait,
|
|
98
206
|
});
|
|
99
|
-
return { created: a[1], resource: "code-env", envLang
|
|
207
|
+
return { created: a[1], resource: "code-env", envLang, ...created, };
|
|
100
208
|
},
|
|
101
209
|
usage: "dss code-env create <lang> <name> --deployment-mode MODE [--params JSON|--data JSON|--data-file PATH|--stdin] [--python-interpreter PYTHON311] [--no-wait] [--if-not-exists] [--dry-run]",
|
|
102
|
-
description: "Create a code environment.",
|
|
210
|
+
description: "Create a code environment; --no-wait hands back a DSS future payload you can settle with dss future wait.",
|
|
103
211
|
examples: [
|
|
104
212
|
"dss code-env create PYTHON my_env --deployment-mode DESIGN_MANAGED --python-interpreter PYTHON311",
|
|
105
213
|
'dss code-env create PYTHON my_env --deployment-mode DESIGN_MANAGED --params \'{"pythonInterpreter":"PYTHON311"}\' --dry-run',
|
|
@@ -107,47 +215,67 @@ export const codeEnvCommands = {
|
|
|
107
215
|
},
|
|
108
216
|
"set-definition": {
|
|
109
217
|
handler: async (c, a, f) => {
|
|
110
|
-
|
|
218
|
+
const usage = "dss code-env set-definition <lang> <name> (--data JSON|--data-file PATH|--stdin) [--expect-hash SHA256]";
|
|
219
|
+
requireArgs(a, 2, usage);
|
|
220
|
+
const envLang = requireEnvLang(a[0], usage);
|
|
111
221
|
const definition = jsonInput(f);
|
|
112
222
|
if (!definition) {
|
|
113
223
|
throw new UsageError("--data, --data-file, or --stdin is required. Usage: dss code-env set-definition <lang> <name> --data JSON");
|
|
114
224
|
}
|
|
225
|
+
const expectHash = validateExpectHash(f["expect-hash"]);
|
|
226
|
+
const definitionHash = stableHash(definition);
|
|
115
227
|
if (f["dry-run"] === true) {
|
|
228
|
+
const current = await readIfExists(() => c.codeEnvs.getDefinition(envLang, a[1]));
|
|
229
|
+
const currentHash = current ? stableHash(current) : undefined;
|
|
230
|
+
if (expectHash !== undefined && currentHash !== expectHash) {
|
|
231
|
+
throw definitionHashMismatch(envLang, a[1], expectHash, currentHash);
|
|
232
|
+
}
|
|
116
233
|
return {
|
|
117
234
|
dryRun: true,
|
|
118
235
|
action: "set-definition",
|
|
119
236
|
resource: "code-env",
|
|
120
|
-
envLang
|
|
237
|
+
envLang,
|
|
121
238
|
envName: a[1],
|
|
122
239
|
definition,
|
|
240
|
+
definitionHash,
|
|
241
|
+
...(currentHash !== undefined
|
|
242
|
+
? { currentDefinitionHash: currentHash, changed: currentHash !== definitionHash, }
|
|
243
|
+
: {}),
|
|
244
|
+
...(expectHash !== undefined ? { expectHash, provenanceVerified: true, } : {}),
|
|
123
245
|
};
|
|
124
246
|
}
|
|
125
|
-
return c.codeEnvs.setDefinition(
|
|
247
|
+
return c.codeEnvs.setDefinition(envLang, a[1], definition, { expectHash, });
|
|
126
248
|
},
|
|
127
|
-
usage: "dss code-env set-definition <lang> <name> (--data JSON|--data-file PATH|--stdin) [--dry-run]",
|
|
128
|
-
description: "Replace a code environment definition previously fetched from DSS.",
|
|
129
|
-
examples: [
|
|
249
|
+
usage: "dss code-env set-definition <lang> <name> (--data JSON|--data-file PATH|--stdin) [--expect-hash SHA256] [--dry-run]",
|
|
250
|
+
description: "Replace a code environment definition previously fetched from DSS (get-definition). --expect-hash SHA256 refuses the PUT unless the current definition still hashes to the hash captured with code-env get, so concurrent edits are never clobbered; --dry-run also fetches the current definition and reports both hashes plus a changed flag.",
|
|
251
|
+
examples: [
|
|
252
|
+
"dss code-env set-definition PYTHON my_env --data-file code-env.json --expect-hash $HASH --dry-run",
|
|
253
|
+
],
|
|
130
254
|
},
|
|
131
255
|
"set-packages": {
|
|
132
256
|
handler: async (c, a, f) => {
|
|
133
|
-
|
|
257
|
+
const usage = "dss code-env set-packages <lang> <name> (--packages PKGS|--package PKG|--file PATH)";
|
|
258
|
+
requireArgs(a, 2, usage);
|
|
259
|
+
const envLang = requireEnvLang(a[0], usage);
|
|
134
260
|
const packages = codeEnvPackageList(f);
|
|
135
261
|
const installCorePackages = parseBooleanOption(f["install-core-packages"], "--install-core-packages");
|
|
262
|
+
const expectHash = validateExpectHash(f["expect-hash"]);
|
|
136
263
|
if (f["dry-run"] === true) {
|
|
137
264
|
return {
|
|
138
265
|
dryRun: true,
|
|
139
266
|
action: "set-packages",
|
|
140
267
|
resource: "code-env",
|
|
141
|
-
envLang
|
|
268
|
+
envLang,
|
|
142
269
|
envName: a[1],
|
|
143
270
|
packages,
|
|
144
271
|
installCorePackages,
|
|
272
|
+
...(expectHash !== undefined ? { expectHash, } : {}),
|
|
145
273
|
};
|
|
146
274
|
}
|
|
147
|
-
return c.codeEnvs.setPackages(
|
|
275
|
+
return c.codeEnvs.setPackages(envLang, a[1], packages, { installCorePackages, expectHash, });
|
|
148
276
|
},
|
|
149
|
-
usage: "dss code-env set-packages <lang> <name> (--packages PKGS|--package PKG|--file PATH) [--install-core-packages true|false] [--dry-run]",
|
|
150
|
-
description: "
|
|
277
|
+
usage: "dss code-env set-packages <lang> <name> (--packages PKGS|--package PKG|--file PATH) [--install-core-packages true|false] [--expect-hash SHA256] [--dry-run]",
|
|
278
|
+
description: "Fetch the current definition, merge the requested package specs (and --install-core-packages) into it, then PUT the merged definition, so fields outside the package list are never dropped; --expect-hash refuses the merge when DSS changed since the hash was captured.",
|
|
151
279
|
examples: [
|
|
152
280
|
"dss code-env set-packages PYTHON my_env --packages 'tabulate\\nnameparser' --dry-run",
|
|
153
281
|
"dss code-env set-packages PYTHON my_env --file requirements.txt",
|
|
@@ -155,7 +283,9 @@ export const codeEnvCommands = {
|
|
|
155
283
|
},
|
|
156
284
|
"update-packages": {
|
|
157
285
|
handler: async (c, a, f) => {
|
|
158
|
-
|
|
286
|
+
const usage = "dss code-env update-packages <lang> <name>";
|
|
287
|
+
requireArgs(a, 2, usage);
|
|
288
|
+
const envLang = requireEnvLang(a[0], usage);
|
|
159
289
|
const wait = codeEnvWait(f);
|
|
160
290
|
const versionToUpdate = typeof f["env-version"] === "string"
|
|
161
291
|
? f["env-version"]
|
|
@@ -172,20 +302,49 @@ export const codeEnvCommands = {
|
|
|
172
302
|
dryRun: true,
|
|
173
303
|
action: "update-packages",
|
|
174
304
|
resource: "code-env",
|
|
175
|
-
envLang
|
|
305
|
+
envLang,
|
|
176
306
|
envName: a[1],
|
|
177
307
|
...opts,
|
|
178
308
|
};
|
|
179
309
|
}
|
|
180
|
-
return c.codeEnvs.updatePackages(
|
|
310
|
+
return c.codeEnvs.updatePackages(envLang, a[1], opts);
|
|
181
311
|
},
|
|
182
312
|
usage: "dss code-env update-packages <lang> <name> [--force-rebuild] [--env-version VERSION] [--no-wait] [--dry-run]",
|
|
183
|
-
description: "Rebuild or update code environment packages to match the requested specs.",
|
|
313
|
+
description: "Rebuild or update code environment packages to match the requested specs; --no-wait hands back a DSS future payload you can settle with dss future wait.",
|
|
184
314
|
examples: ["dss code-env update-packages PYTHON my_env --force-rebuild --dry-run",],
|
|
185
315
|
},
|
|
316
|
+
"update-images": {
|
|
317
|
+
handler: async (c, a, f) => {
|
|
318
|
+
const usage = "dss code-env update-images <lang> <name>";
|
|
319
|
+
requireArgs(a, 2, usage);
|
|
320
|
+
const envLang = requireEnvLang(a[0], usage);
|
|
321
|
+
const wait = codeEnvWait(f);
|
|
322
|
+
const envVersion = typeof f["env-version"] === "string" ? f["env-version"] : undefined;
|
|
323
|
+
if (f["dry-run"] === true) {
|
|
324
|
+
return {
|
|
325
|
+
dryRun: true,
|
|
326
|
+
action: "update-images",
|
|
327
|
+
resource: "code-env",
|
|
328
|
+
envLang,
|
|
329
|
+
envName: a[1],
|
|
330
|
+
envVersion,
|
|
331
|
+
wait,
|
|
332
|
+
};
|
|
333
|
+
}
|
|
334
|
+
return c.codeEnvs.updateImages(envLang, a[1], { envVersion, wait, });
|
|
335
|
+
},
|
|
336
|
+
usage: "dss code-env update-images <lang> <name> [--env-version VERSION] [--no-wait] [--dry-run]",
|
|
337
|
+
description: "Rebuild the Docker image(s) of a code environment to match its settings; --env-version targets one version of a versioned environment and --no-wait hands back a DSS future payload you can settle with dss future wait.",
|
|
338
|
+
examples: [
|
|
339
|
+
"dss code-env update-images PYTHON my_env --dry-run",
|
|
340
|
+
"dss code-env update-images PYTHON my_env --env-version v3 --no-wait",
|
|
341
|
+
],
|
|
342
|
+
},
|
|
186
343
|
"set-jupyter": {
|
|
187
344
|
handler: async (c, a, f) => {
|
|
188
|
-
|
|
345
|
+
const usage = "dss code-env set-jupyter <lang> <name> --active true|false";
|
|
346
|
+
requireArgs(a, 2, usage);
|
|
347
|
+
const envLang = requireEnvLang(a[0], usage);
|
|
189
348
|
const active = parseBooleanOption(f["active"], "--active");
|
|
190
349
|
if (active === undefined) {
|
|
191
350
|
throw new UsageError("--active is required. Usage: dss code-env set-jupyter <lang> <name> --active true|false");
|
|
@@ -196,48 +355,50 @@ export const codeEnvCommands = {
|
|
|
196
355
|
dryRun: true,
|
|
197
356
|
action: "set-jupyter",
|
|
198
357
|
resource: "code-env",
|
|
199
|
-
envLang
|
|
358
|
+
envLang,
|
|
200
359
|
envName: a[1],
|
|
201
360
|
active,
|
|
202
361
|
wait,
|
|
203
362
|
};
|
|
204
363
|
}
|
|
205
|
-
return c.codeEnvs.setJupyterSupport(
|
|
364
|
+
return c.codeEnvs.setJupyterSupport(envLang, a[1], active, { wait, });
|
|
206
365
|
},
|
|
207
366
|
usage: "dss code-env set-jupyter <lang> <name> --active true|false [--no-wait] [--dry-run]",
|
|
208
|
-
description: "Enable or disable Jupyter support for a code environment.",
|
|
367
|
+
description: "Enable or disable Jupyter support for a code environment; --no-wait hands back a DSS future payload you can settle with dss future wait.",
|
|
209
368
|
examples: ["dss code-env set-jupyter PYTHON my_env --active true --dry-run",],
|
|
210
369
|
},
|
|
211
370
|
delete: {
|
|
212
371
|
handler: async (c, a, f) => {
|
|
213
|
-
|
|
372
|
+
const usage = "dss code-env delete <lang> <name>";
|
|
373
|
+
requireArgs(a, 2, usage);
|
|
374
|
+
const envLang = requireEnvLang(a[0], usage);
|
|
214
375
|
const wait = codeEnvWait(f);
|
|
215
376
|
if (f["dry-run"] === true) {
|
|
216
|
-
const current = await readIfExists(() => c.codeEnvs.get(
|
|
377
|
+
const current = await readIfExists(() => c.codeEnvs.get(envLang, a[1]));
|
|
217
378
|
if (!current)
|
|
218
|
-
return skipResult("code-env", a[1], "missing", { envLang
|
|
379
|
+
return skipResult("code-env", a[1], "missing", { envLang, });
|
|
219
380
|
return {
|
|
220
381
|
dryRun: true,
|
|
221
382
|
action: "delete",
|
|
222
383
|
resource: "code-env",
|
|
223
|
-
envLang
|
|
384
|
+
envLang,
|
|
224
385
|
envName: a[1],
|
|
225
386
|
wait,
|
|
226
387
|
current,
|
|
227
388
|
};
|
|
228
389
|
}
|
|
229
390
|
if (f["if-exists"] === true) {
|
|
230
|
-
return await c.codeEnvs.delete(
|
|
391
|
+
return await c.codeEnvs.delete(envLang, a[1], { wait, }).catch((error) => {
|
|
231
392
|
if (isNotFoundError(error)) {
|
|
232
|
-
return skipResult("code-env", a[1], "missing", { envLang
|
|
393
|
+
return skipResult("code-env", a[1], "missing", { envLang, });
|
|
233
394
|
}
|
|
234
395
|
throw error;
|
|
235
396
|
});
|
|
236
397
|
}
|
|
237
|
-
return c.codeEnvs.delete(
|
|
398
|
+
return c.codeEnvs.delete(envLang, a[1], { wait, });
|
|
238
399
|
},
|
|
239
400
|
usage: "dss code-env delete <lang> <name> [--no-wait] [--if-exists] [--dry-run]",
|
|
240
|
-
description: "Delete a code environment.",
|
|
401
|
+
description: "Delete a code environment; --no-wait hands back a DSS future payload you can settle with dss future wait.",
|
|
241
402
|
examples: ["dss code-env delete PYTHON my_env --dry-run",],
|
|
242
403
|
},
|
|
243
404
|
usages: {
|
|
@@ -1,2 +1,21 @@
|
|
|
1
1
|
import type { CommandMeta } from "../types.js";
|
|
2
|
+
export interface CodeInputSource {
|
|
3
|
+
kind: "file" | "stdin";
|
|
4
|
+
path?: string;
|
|
5
|
+
}
|
|
6
|
+
export interface ResolvedCodeInput {
|
|
7
|
+
script: string;
|
|
8
|
+
source: CodeInputSource;
|
|
9
|
+
}
|
|
10
|
+
/**
|
|
11
|
+
* Canonical validation of `code run` input: rejects positional args and
|
|
12
|
+
* conflicting sources, reads the chosen source, strips a UTF-8 BOM, and
|
|
13
|
+
* rejects empty scripts. Returns the script plus source metadata so plan or
|
|
14
|
+
* replay payloads can hash the script and reference the source without
|
|
15
|
+
* embedding its contents.
|
|
16
|
+
*/
|
|
17
|
+
export declare function resolveCodeInputWithSource(args: string[], flags: Record<string, string | boolean>): ResolvedCodeInput;
|
|
18
|
+
export declare function resolveCodeInput(args: string[], flags: Record<string, string | boolean>): string;
|
|
19
|
+
/** Parse an integer flag value, rejecting negative and fractional values before any DSS request. */
|
|
20
|
+
export declare function parseCodeRunIntegerFlag(value: string | boolean | undefined, flagName: string): number | undefined;
|
|
2
21
|
export declare const codeCommands: Record<string, CommandMeta>;
|