kradle 0.6.6 → 0.6.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/README.md +9 -8
- package/dist/commands/challenge/build.d.ts +4 -2
- package/dist/commands/challenge/build.js +40 -9
- package/dist/lib/challenge.d.ts +12 -0
- package/dist/lib/challenge.js +29 -18
- package/dist/lib/validator.js +2 -0
- package/oclif.manifest.json +17 -13
- package/package.json +1 -1
- package/static/ai_docs/LLM_CLI_REFERENCE.md +17 -10
package/README.md
CHANGED
|
@@ -81,23 +81,24 @@ This creates a `challenges/<challenge-name>/` folder with:
|
|
|
81
81
|
|
|
82
82
|
### Build Challenge
|
|
83
83
|
|
|
84
|
-
Build
|
|
84
|
+
Build and validate challenge datapacks locally, with optional upload:
|
|
85
85
|
|
|
86
86
|
```bash
|
|
87
87
|
kradle challenge build <challenge-name>
|
|
88
|
+
kradle challenge build <challenge-name> --no-upload # Build locally only (no cloud upload)
|
|
88
89
|
kradle challenge build <challenge-name> --no-validate # Skip validation
|
|
89
90
|
kradle challenge build <challenge-name> --public # Upload as public
|
|
90
91
|
kradle challenge build --all # Build all local challenges
|
|
91
92
|
```
|
|
92
93
|
|
|
93
94
|
This command:
|
|
94
|
-
1.
|
|
95
|
-
2.
|
|
96
|
-
3.
|
|
97
|
-
4.
|
|
98
|
-
5. Uploads the datapack to GCS
|
|
95
|
+
1. Builds the datapack by executing `challenge.ts`
|
|
96
|
+
2. Validates the datapack using Spyglass (unless `--no-validate`)
|
|
97
|
+
3. If upload is enabled (default), creates the challenge in the cloud if needed
|
|
98
|
+
4. If upload is enabled (default), uploads `config.ts` and datapack
|
|
99
99
|
|
|
100
|
-
|
|
100
|
+
Use `--no-upload` to build locally only. Use `--no-validate` to skip validation.
|
|
101
|
+
`--public` is only valid when upload is enabled (default).
|
|
101
102
|
|
|
102
103
|
### Delete Challenge
|
|
103
104
|
|
|
@@ -478,7 +479,7 @@ Each challenge is a folder in `challenges/<slug>/` containing:
|
|
|
478
479
|
1. `kradle challenge create <slug>` creates the folder with `challenge.ts`
|
|
479
480
|
2. The create command automatically builds, uploads, and downloads the config from the cloud API
|
|
480
481
|
3. The downloaded JSON is converted into a typed TypeScript `config.ts` file
|
|
481
|
-
4. `kradle challenge build <slug>`
|
|
482
|
+
4. `kradle challenge build <slug>` builds datapacks locally and uploads `config.ts` + datapack by default (use `--no-upload` for local-only build)
|
|
482
483
|
5. You can modify `config.ts` locally and run `build` to sync changes to the cloud
|
|
483
484
|
|
|
484
485
|
## Architecture
|
|
@@ -6,13 +6,15 @@ export default class Build extends Command {
|
|
|
6
6
|
challengeSlug: import("@oclif/core/interfaces").Arg<string | undefined>;
|
|
7
7
|
};
|
|
8
8
|
static flags: {
|
|
9
|
-
"api-key": import("@oclif/core/interfaces").OptionFlag<string, import("@oclif/core/interfaces").CustomOptions>;
|
|
10
|
-
"api-url": import("@oclif/core/interfaces").OptionFlag<string, import("@oclif/core/interfaces").CustomOptions>;
|
|
11
9
|
"challenges-path": import("@oclif/core/interfaces").OptionFlag<string, import("@oclif/core/interfaces").CustomOptions>;
|
|
12
10
|
all: import("@oclif/core/interfaces").BooleanFlag<boolean>;
|
|
13
11
|
public: import("@oclif/core/interfaces").BooleanFlag<boolean>;
|
|
14
12
|
"no-validate": import("@oclif/core/interfaces").BooleanFlag<boolean>;
|
|
13
|
+
"no-upload": import("@oclif/core/interfaces").BooleanFlag<boolean>;
|
|
14
|
+
"api-url": import("@oclif/core/interfaces").OptionFlag<string, import("@oclif/core/interfaces").CustomOptions>;
|
|
15
|
+
"api-key": import("@oclif/core/interfaces").OptionFlag<string | undefined, import("@oclif/core/interfaces").CustomOptions>;
|
|
15
16
|
};
|
|
16
17
|
static strict: boolean;
|
|
17
18
|
run(): Promise<void>;
|
|
19
|
+
private requireApiKey;
|
|
18
20
|
}
|
|
@@ -5,7 +5,7 @@ import { extractShortSlug, getChallengeSlugArgument } from "../../lib/arguments.
|
|
|
5
5
|
import { Challenge } from "../../lib/challenge.js";
|
|
6
6
|
import { getConfigFlags } from "../../lib/flags.js";
|
|
7
7
|
export default class Build extends Command {
|
|
8
|
-
static description = "Build
|
|
8
|
+
static description = "Build challenge datapack locally, with optional upload";
|
|
9
9
|
static examples = [
|
|
10
10
|
"<%= config.bin %> <%= command.id %> my-challenge",
|
|
11
11
|
"<%= config.bin %> <%= command.id %> my-challenge my-other-challenge",
|
|
@@ -13,7 +13,7 @@ export default class Build extends Command {
|
|
|
13
13
|
];
|
|
14
14
|
static args = {
|
|
15
15
|
challengeSlug: getChallengeSlugArgument({
|
|
16
|
-
description: "Challenge slug to build
|
|
16
|
+
description: "Challenge slug to build. Can be used multiple times to build multiple challenges at once. Incompatible with --all flag.",
|
|
17
17
|
required: false,
|
|
18
18
|
}),
|
|
19
19
|
};
|
|
@@ -21,10 +21,23 @@ export default class Build extends Command {
|
|
|
21
21
|
all: Flags.boolean({ char: "a", description: "Build all challenges in the challenges directory", default: false }),
|
|
22
22
|
public: Flags.boolean({ char: "p", description: "Upload challenges as public.", default: false }),
|
|
23
23
|
"no-validate": Flags.boolean({
|
|
24
|
-
description: "Skip datapack validation
|
|
24
|
+
description: "Skip datapack validation",
|
|
25
25
|
default: false,
|
|
26
26
|
}),
|
|
27
|
-
|
|
27
|
+
"no-upload": Flags.boolean({
|
|
28
|
+
description: "Build datapack locally only (skip cloud config/datapack upload)",
|
|
29
|
+
default: false,
|
|
30
|
+
}),
|
|
31
|
+
"api-url": Flags.string({
|
|
32
|
+
description: "Kradle Web API URL",
|
|
33
|
+
env: "KRADLE_API_URL",
|
|
34
|
+
default: "https://api.kradle.ai/v0",
|
|
35
|
+
}),
|
|
36
|
+
"api-key": Flags.string({
|
|
37
|
+
description: "Kradle API key",
|
|
38
|
+
env: "KRADLE_API_KEY",
|
|
39
|
+
}),
|
|
40
|
+
...getConfigFlags("challenges-path"),
|
|
28
41
|
};
|
|
29
42
|
static strict = false;
|
|
30
43
|
async run() {
|
|
@@ -32,6 +45,9 @@ export default class Build extends Command {
|
|
|
32
45
|
if (flags.all && argv.length > 0) {
|
|
33
46
|
this.error(pc.red("Cannot use --all flag with challenge slugs"));
|
|
34
47
|
}
|
|
48
|
+
if (flags["no-upload"] && flags.public) {
|
|
49
|
+
this.error(pc.red("Cannot use --public with --no-upload"));
|
|
50
|
+
}
|
|
35
51
|
if (!flags.all && argv.length === 0) {
|
|
36
52
|
// Show help if no challenge slugs are provided - https://github.com/oclif/oclif/issues/183#issuecomment-1933104981
|
|
37
53
|
await new (await loadHelpClass(this.config))(this.config).showHelp([Build.id]);
|
|
@@ -41,7 +57,8 @@ export default class Build extends Command {
|
|
|
41
57
|
this.log(pc.blue("Building all challenges"));
|
|
42
58
|
}
|
|
43
59
|
const challengeSlugs = flags.all ? await Challenge.getLocalChallenges() : argv;
|
|
44
|
-
const
|
|
60
|
+
const shouldUpload = !flags["no-upload"];
|
|
61
|
+
const api = shouldUpload ? new ApiClient(flags["api-url"], this.requireApiKey(flags["api-key"])) : null;
|
|
45
62
|
for (const challengeSlug of challengeSlugs) {
|
|
46
63
|
// Validate that the challenge exists locally
|
|
47
64
|
const validation = await Challenge.validateForLocalOperation(challengeSlug, flags["challenges-path"]);
|
|
@@ -51,10 +68,17 @@ export default class Build extends Command {
|
|
|
51
68
|
const challenge = new Challenge(extractShortSlug(challengeSlug), flags["challenges-path"]);
|
|
52
69
|
this.log(pc.blue(`==== Building challenge: ${challenge.shortSlug} ====`));
|
|
53
70
|
try {
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
71
|
+
if (shouldUpload && api) {
|
|
72
|
+
await challenge.buildAndUpload(api, {
|
|
73
|
+
asPublic: flags.public,
|
|
74
|
+
validate: !flags["no-validate"],
|
|
75
|
+
});
|
|
76
|
+
}
|
|
77
|
+
else {
|
|
78
|
+
await challenge.buildLocal({
|
|
79
|
+
validate: !flags["no-validate"],
|
|
80
|
+
});
|
|
81
|
+
}
|
|
58
82
|
}
|
|
59
83
|
catch (error) {
|
|
60
84
|
this.error(pc.red(`Build failed: ${error instanceof Error ? error.message : String(error)}`));
|
|
@@ -62,4 +86,11 @@ export default class Build extends Command {
|
|
|
62
86
|
this.log();
|
|
63
87
|
}
|
|
64
88
|
}
|
|
89
|
+
requireApiKey(apiKey) {
|
|
90
|
+
if (apiKey) {
|
|
91
|
+
return apiKey;
|
|
92
|
+
}
|
|
93
|
+
this.error(pc.red("Missing required flag --api-key (or KRADLE_API_KEY) unless using --no-upload"));
|
|
94
|
+
throw new Error("Unreachable");
|
|
95
|
+
}
|
|
65
96
|
}
|
package/dist/lib/challenge.d.ts
CHANGED
|
@@ -51,6 +51,18 @@ export declare class Challenge {
|
|
|
51
51
|
*/
|
|
52
52
|
build(silent?: boolean, config?: ChallengeConfigSchemaType): Promise<void>;
|
|
53
53
|
loadConfig(): Promise<ChallengeConfigSchemaType>;
|
|
54
|
+
/**
|
|
55
|
+
* Build the challenge datapack locally.
|
|
56
|
+
* @param options - Build options
|
|
57
|
+
* @param options.validate - Whether to validate the datapack after build (default: true).
|
|
58
|
+
* @returns The loaded config and datapack hash.
|
|
59
|
+
*/
|
|
60
|
+
buildLocal(options?: {
|
|
61
|
+
validate?: boolean;
|
|
62
|
+
}): Promise<{
|
|
63
|
+
config: ChallengeConfigSchemaType;
|
|
64
|
+
datapackHash: string;
|
|
65
|
+
}>;
|
|
54
66
|
/**
|
|
55
67
|
* Build the challenge datapack and upload it to the cloud.
|
|
56
68
|
* @param api - The API client to use.
|
package/dist/lib/challenge.js
CHANGED
|
@@ -162,17 +162,15 @@ export class Challenge {
|
|
|
162
162
|
}
|
|
163
163
|
}
|
|
164
164
|
/**
|
|
165
|
-
* Build the challenge datapack
|
|
166
|
-
* @param api - The API client to use.
|
|
165
|
+
* Build the challenge datapack locally.
|
|
167
166
|
* @param options - Build options
|
|
168
|
-
* @param options.
|
|
169
|
-
* @
|
|
170
|
-
* @returns The config and datapack hash.
|
|
167
|
+
* @param options.validate - Whether to validate the datapack after build (default: true).
|
|
168
|
+
* @returns The loaded config and datapack hash.
|
|
171
169
|
*/
|
|
172
|
-
async
|
|
173
|
-
const {
|
|
170
|
+
async buildLocal(options = { validate: true }) {
|
|
171
|
+
const { validate = true } = options;
|
|
174
172
|
// Start validation service initialization in parallel with build (if validation enabled)
|
|
175
|
-
// This overlaps the
|
|
173
|
+
// This overlaps the init time with the build process.
|
|
176
174
|
let validationService = null;
|
|
177
175
|
if (validate) {
|
|
178
176
|
validationService = ValidationService.create(this.builtDatapackPath);
|
|
@@ -182,19 +180,12 @@ export class Challenge {
|
|
|
182
180
|
await validationService?.close();
|
|
183
181
|
throw new Error(`Challenge "${this.shortSlug}" does not exist locally. Make sure both the challenge.ts file and the config.ts file exist.`);
|
|
184
182
|
}
|
|
185
|
-
// Ensure challenge exists in the cloud
|
|
186
|
-
if (!(await api.challengeExists(this.shortSlug))) {
|
|
187
|
-
console.log(pc.yellow(`Challenge not found in cloud: ${this.shortSlug}`));
|
|
188
|
-
console.log(pc.yellow(`Creating challenge: ${this.shortSlug}`));
|
|
189
|
-
await api.createChallenge(this.shortSlug);
|
|
190
|
-
console.log(pc.green(`✓ Challenge created in cloud`));
|
|
191
|
-
}
|
|
192
183
|
const config = await this.loadConfig();
|
|
193
184
|
// Build datapack (validation service initializes in parallel)
|
|
194
185
|
console.log(pc.blue(`>> Building datapack: ${this.shortSlug}`));
|
|
195
186
|
await this.build(false, config);
|
|
196
187
|
console.log(pc.green(`✓ Datapack built\n`));
|
|
197
|
-
// Validate datapack
|
|
188
|
+
// Validate datapack after building (if enabled)
|
|
198
189
|
if (validate && validationService) {
|
|
199
190
|
console.log(pc.blue(`>> Validating datapack: ${this.shortSlug}`));
|
|
200
191
|
try {
|
|
@@ -202,13 +193,34 @@ export class Challenge {
|
|
|
202
193
|
console.log(formatValidationResult(validationResult));
|
|
203
194
|
console.log();
|
|
204
195
|
if (validationResult.hasErrors) {
|
|
205
|
-
throw new Error(`Validation failed with ${validationResult.errors.length} error(s).
|
|
196
|
+
throw new Error(`Validation failed with ${validationResult.errors.length} error(s). Build aborted.`);
|
|
206
197
|
}
|
|
207
198
|
}
|
|
208
199
|
finally {
|
|
209
200
|
await validationService.close();
|
|
210
201
|
}
|
|
211
202
|
}
|
|
203
|
+
const datapackHash = await this.getDatapackHash();
|
|
204
|
+
return { config, datapackHash };
|
|
205
|
+
}
|
|
206
|
+
/**
|
|
207
|
+
* Build the challenge datapack and upload it to the cloud.
|
|
208
|
+
* @param api - The API client to use.
|
|
209
|
+
* @param options - Build options
|
|
210
|
+
* @param options.asPublic - Whether the challenge should be uploaded as public.
|
|
211
|
+
* @param options.validate - Whether to validate the datapack before upload (default: true).
|
|
212
|
+
* @returns The config and datapack hash.
|
|
213
|
+
*/
|
|
214
|
+
async buildAndUpload(api, options = { asPublic: false, validate: true }) {
|
|
215
|
+
const { asPublic, validate = true } = options;
|
|
216
|
+
const { config, datapackHash } = await this.buildLocal({ validate });
|
|
217
|
+
// Ensure challenge exists in the cloud
|
|
218
|
+
if (!(await api.challengeExists(this.shortSlug))) {
|
|
219
|
+
console.log(pc.yellow(`Challenge not found in cloud: ${this.shortSlug}`));
|
|
220
|
+
console.log(pc.yellow(`Creating challenge: ${this.shortSlug}`));
|
|
221
|
+
await api.createChallenge(this.shortSlug);
|
|
222
|
+
console.log(pc.green(`✓ Challenge created in cloud`));
|
|
223
|
+
}
|
|
212
224
|
// Ensure challenge's visibility is set to private - else, temporarily set it to private
|
|
213
225
|
const cloudChallengeVisibility = (await api.getChallenge(this.shortSlug, ["visibility"])).visibility;
|
|
214
226
|
if (cloudChallengeVisibility === "public") {
|
|
@@ -230,7 +242,6 @@ export class Challenge {
|
|
|
230
242
|
await api.updateChallengeVisibility(this.shortSlug, "public");
|
|
231
243
|
console.log(pc.green(`✓ Challenge visibility set to public\n`));
|
|
232
244
|
}
|
|
233
|
-
const datapackHash = await this.getDatapackHash();
|
|
234
245
|
return { config, datapackHash };
|
|
235
246
|
}
|
|
236
247
|
/**
|
package/dist/lib/validator.js
CHANGED
|
@@ -12,6 +12,8 @@ import pc from "picocolors";
|
|
|
12
12
|
*/
|
|
13
13
|
const FILTERED_ERROR_MESSAGES = [
|
|
14
14
|
"Fake names cannot be longer than 40 characters", // Actually they can be longer
|
|
15
|
+
"Objective names cannot be longer than 16 characters", // Actually they can be longer
|
|
16
|
+
"Player names cannot be longer than 16 characters", // Actually they can be longer
|
|
15
17
|
];
|
|
16
18
|
/**
|
|
17
19
|
* Get a human-readable severity label with color
|
package/oclif.manifest.json
CHANGED
|
@@ -215,12 +215,12 @@
|
|
|
215
215
|
"aliases": [],
|
|
216
216
|
"args": {
|
|
217
217
|
"challengeSlug": {
|
|
218
|
-
"description": "Challenge slug to build
|
|
218
|
+
"description": "Challenge slug to build. Can be used multiple times to build multiple challenges at once. Incompatible with --all flag.",
|
|
219
219
|
"name": "challengeSlug",
|
|
220
220
|
"required": false
|
|
221
221
|
}
|
|
222
222
|
},
|
|
223
|
-
"description": "Build
|
|
223
|
+
"description": "Build challenge datapack locally, with optional upload",
|
|
224
224
|
"examples": [
|
|
225
225
|
"<%= config.bin %> <%= command.id %> my-challenge",
|
|
226
226
|
"<%= config.bin %> <%= command.id %> my-challenge my-other-challenge",
|
|
@@ -242,30 +242,34 @@
|
|
|
242
242
|
"type": "boolean"
|
|
243
243
|
},
|
|
244
244
|
"no-validate": {
|
|
245
|
-
"description": "Skip datapack validation
|
|
245
|
+
"description": "Skip datapack validation",
|
|
246
246
|
"name": "no-validate",
|
|
247
247
|
"allowNo": false,
|
|
248
248
|
"type": "boolean"
|
|
249
249
|
},
|
|
250
|
-
"
|
|
251
|
-
"description": "
|
|
252
|
-
"
|
|
253
|
-
"
|
|
254
|
-
"
|
|
255
|
-
"hasDynamicHelp": false,
|
|
256
|
-
"multiple": false,
|
|
257
|
-
"type": "option"
|
|
250
|
+
"no-upload": {
|
|
251
|
+
"description": "Build datapack locally only (skip cloud config/datapack upload)",
|
|
252
|
+
"name": "no-upload",
|
|
253
|
+
"allowNo": false,
|
|
254
|
+
"type": "boolean"
|
|
258
255
|
},
|
|
259
256
|
"api-url": {
|
|
260
257
|
"description": "Kradle Web API URL",
|
|
261
258
|
"env": "KRADLE_API_URL",
|
|
262
259
|
"name": "api-url",
|
|
263
|
-
"required": true,
|
|
264
260
|
"default": "https://api.kradle.ai/v0",
|
|
265
261
|
"hasDynamicHelp": false,
|
|
266
262
|
"multiple": false,
|
|
267
263
|
"type": "option"
|
|
268
264
|
},
|
|
265
|
+
"api-key": {
|
|
266
|
+
"description": "Kradle API key",
|
|
267
|
+
"env": "KRADLE_API_KEY",
|
|
268
|
+
"name": "api-key",
|
|
269
|
+
"hasDynamicHelp": false,
|
|
270
|
+
"multiple": false,
|
|
271
|
+
"type": "option"
|
|
272
|
+
},
|
|
269
273
|
"challenges-path": {
|
|
270
274
|
"description": "Absolute path to the challenges directory",
|
|
271
275
|
"env": "KRADLE_CHALLENGES_PATH",
|
|
@@ -1524,5 +1528,5 @@
|
|
|
1524
1528
|
]
|
|
1525
1529
|
}
|
|
1526
1530
|
},
|
|
1527
|
-
"version": "0.6.
|
|
1531
|
+
"version": "0.6.7"
|
|
1528
1532
|
}
|
package/package.json
CHANGED
|
@@ -119,11 +119,12 @@ kradle challenge create my-first-challenge
|
|
|
119
119
|
|
|
120
120
|
### `kradle challenge build <name>`
|
|
121
121
|
|
|
122
|
-
Builds a challenge datapack, validates it, and uploads
|
|
122
|
+
Builds a challenge datapack locally, validates it, and optionally uploads to the cloud.
|
|
123
123
|
|
|
124
124
|
**Usage:**
|
|
125
125
|
```bash
|
|
126
126
|
kradle challenge build <challenge-name>
|
|
127
|
+
kradle challenge build <challenge-name> --no-upload
|
|
127
128
|
kradle challenge build <challenge-name> --public
|
|
128
129
|
kradle challenge build <challenge-name> --no-validate
|
|
129
130
|
kradle challenge build --all
|
|
@@ -140,21 +141,24 @@ kradle challenge build --all --public
|
|
|
140
141
|
|------|-------|-------------|---------|
|
|
141
142
|
| `--all` | `-a` | Build all local challenges | false |
|
|
142
143
|
| `--public` | `-p` | Set visibility to public after upload | false |
|
|
143
|
-
| `--no-validate` | | Skip datapack validation
|
|
144
|
+
| `--no-validate` | | Skip datapack validation | false |
|
|
145
|
+
| `--no-upload` | | Build locally only (skip cloud config/datapack upload) | false |
|
|
146
|
+
|
|
147
|
+
`--public` is incompatible with `--no-upload`.
|
|
144
148
|
|
|
145
149
|
**What it does:**
|
|
146
|
-
1.
|
|
147
|
-
2. Executes `challenge.ts` to generate the datapack
|
|
150
|
+
1. Executes `challenge.ts` to generate the datapack
|
|
148
151
|
- Passes `KRADLE_CHALLENGE_END_STATES` env var containing a JSON array of end state keys from `config.endStates` (e.g., `["victory", "defeat"]`)
|
|
149
152
|
- Passes `KRADLE_CHALLENGE_ROLES` env var containing a JSON array of role names from `config.roles` (e.g., `["attacker", "defender"]`)
|
|
150
153
|
- Passes `KRADLE_CHALLENGE_LOCATIONS` env var containing a JSON array of location keys from `config.challengeConfig.locations` (e.g., `["spawn", "goal"]`)
|
|
151
154
|
- The `@kradle/challenges-sdk` uses these to register valid end states, roles, and locations at build time
|
|
152
|
-
|
|
155
|
+
2. Validates the datapack using Spyglass engine (unless `--no-validate`)
|
|
153
156
|
- Checks `.mcfunction` files for syntax errors, invalid commands, JSON text components
|
|
154
|
-
- **Errors block
|
|
157
|
+
- **Errors block command completion** - fix them before the build can finish
|
|
155
158
|
- Auto-detects Minecraft version from `pack.mcmeta` `pack_format`
|
|
156
|
-
|
|
157
|
-
|
|
159
|
+
3. If upload is enabled (default), creates challenge in cloud if needed
|
|
160
|
+
4. If upload is enabled (default), uploads `config.ts` metadata to cloud
|
|
161
|
+
5. If upload is enabled (default), compresses and uploads datapack to cloud storage
|
|
158
162
|
|
|
159
163
|
**Validation Output:**
|
|
160
164
|
```
|
|
@@ -164,7 +168,7 @@ data/kradle/functions/init.mcfunction:5:1 warning: Unused objective
|
|
|
164
168
|
|
|
165
169
|
Found 1 error, 1 warning
|
|
166
170
|
|
|
167
|
-
Error: Validation failed with 1 error(s).
|
|
171
|
+
Error: Validation failed with 1 error(s). Build aborted.
|
|
168
172
|
```
|
|
169
173
|
|
|
170
174
|
**Examples:**
|
|
@@ -172,6 +176,9 @@ Error: Validation failed with 1 error(s). Upload aborted.
|
|
|
172
176
|
# Build single challenge (with validation)
|
|
173
177
|
kradle challenge build my-challenge
|
|
174
178
|
|
|
179
|
+
# Build local datapack only (no cloud upload)
|
|
180
|
+
kradle challenge build my-challenge --no-upload
|
|
181
|
+
|
|
175
182
|
# Build and make public
|
|
176
183
|
kradle challenge build my-challenge --public
|
|
177
184
|
|
|
@@ -1274,7 +1281,7 @@ kradle challenge build --all --public
|
|
|
1274
1281
|
|---------|-------------|
|
|
1275
1282
|
| `kradle init` | Initialize new project |
|
|
1276
1283
|
| `kradle challenge create <name>` | Create new challenge |
|
|
1277
|
-
| `kradle challenge build <name>` | Build
|
|
1284
|
+
| `kradle challenge build <name>` | Build challenge (uploads by default) |
|
|
1278
1285
|
| `kradle challenge build --all` | Build all challenges |
|
|
1279
1286
|
| `kradle challenge delete <name>` | Delete challenge |
|
|
1280
1287
|
| `kradle challenge list` | List all challenges |
|