@bedrock-rbx/core 0.1.0-beta.14 → 0.1.0-beta.16
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 +180 -0
- package/dist/cli/run.mjs +135 -37
- package/dist/cli/run.mjs.map +1 -1
- package/dist/config.d.mts +1 -1
- package/dist/{define-config-C2cOtDpP.d.mts → define-config-B4GZRPj-.d.mts} +3 -3
- package/dist/{define-config-C2cOtDpP.d.mts.map → define-config-B4GZRPj-.d.mts.map} +1 -1
- package/dist/index.d.mts +251 -95
- package/dist/index.d.mts.map +1 -1
- package/dist/index.mjs +2 -26
- package/dist/index.mjs.map +1 -1
- package/dist/{migrate-mantle-state-qejWFAR0.mjs → migrate-mantle-state-F4zdhxV4.mjs} +513 -178
- package/dist/migrate-mantle-state-F4zdhxV4.mjs.map +1 -0
- package/package.json +4 -4
- package/dist/migrate-mantle-state-qejWFAR0.mjs.map +0 -1
package/README.md
ADDED
|
@@ -0,0 +1,180 @@
|
|
|
1
|
+
# @bedrock-rbx/core
|
|
2
|
+
|
|
3
|
+
Infrastructure-as-Code for Roblox, with a bundled `bedrock` CLI.
|
|
4
|
+
|
|
5
|
+
[](https://npmx.dev/package/@bedrock-rbx/core)
|
|
6
|
+
[](https://github.com/christopher-buss/bedrock/blob/main/LICENSE)
|
|
7
|
+
[](https://github.com/christopher-buss/bedrock/actions/workflows/ci.yaml)
|
|
8
|
+
|
|
9
|
+
> **Status: 0.1 beta.** The public API is stabilizing. Breaking changes may land in minor releases (0.1 to 0.2) until 1.0.
|
|
10
|
+
|
|
11
|
+
## What is `@bedrock-rbx/core`?
|
|
12
|
+
|
|
13
|
+
Bedrock defines a Roblox experience's setup, including the universe, places, game passes, and developer products, in a single config file you keep alongside your game code. Each deploy diffs that config against the live state in Roblox and applies the create or update operations needed to bring them into sync. Adding a new place (lobby, mini-game, hub world) means editing the config instead of clicking through Creator Hub.
|
|
14
|
+
|
|
15
|
+
It is a spiritual successor to [Mantle](https://github.com/blake-mealey/mantle) (no longer maintained), rebuilt on top of [Roblox Open Cloud](https://create.roblox.com/docs/cloud). That means API-key authentication only, no `ROBLOSECURITY` cookies or legacy endpoints.
|
|
16
|
+
|
|
17
|
+
Bedrock ships two paths to the same engine. The `bedrock` CLI reconciles a config file (TypeScript, JavaScript, YAML, JSON, or Luau) against live Roblox state. The programmatic API exposes the same `deploy()`, `diff()`, and `applyOps()` functions for direct use in TypeScript, so deploys can be triggered from a webhook handler, a chat bot, or any other service in your stack. Both surfaces run identical code below the entry point.
|
|
18
|
+
|
|
19
|
+
## Install
|
|
20
|
+
|
|
21
|
+
```bash
|
|
22
|
+
pnpm add -D @bedrock-rbx/core
|
|
23
|
+
# or: npm install --save-dev @bedrock-rbx/core
|
|
24
|
+
# or: bun add -d @bedrock-rbx/core
|
|
25
|
+
```
|
|
26
|
+
|
|
27
|
+
The `bedrock` binary is then available via your package manager (`pnpm bedrock`, `npx bedrock`, `bunx bedrock`).
|
|
28
|
+
|
|
29
|
+
**Runtime:** Node >= 24.12 or Bun >= 1.3.
|
|
30
|
+
|
|
31
|
+
**Authentication:** bedrock reads two environment variables.
|
|
32
|
+
|
|
33
|
+
| Variable | Purpose | Where to get it |
|
|
34
|
+
|---|---|---|
|
|
35
|
+
| `BEDROCK_API_KEY` | Authenticates Open Cloud calls. | [Creator Hub > Credentials > API Keys](https://create.roblox.com/dashboard/credentials). Needs the scopes for the resources you manage (universe-place, universe-place-config, universe-passes, universe-developer-products, asset-create). |
|
|
36
|
+
| `BEDROCK_GITHUB_TOKEN` | Reads and writes the state gist (the default state backend). | A GitHub personal access token with the `gist` scope. The gist itself starts empty: create one at [gist.github.com](https://gist.github.com), then put its ID in your config's `state.gistId`. |
|
|
37
|
+
|
|
38
|
+
Both can be overridden per environment in your config (or via `--api-key` / `--github-token` flags on the CLI).
|
|
39
|
+
|
|
40
|
+
## Quick start (programmatic)
|
|
41
|
+
|
|
42
|
+
A bedrock config is a plain `Config` object. The `defineConfig` helper is identity at runtime; it exists only to give TypeScript users full type inference and autocomplete.
|
|
43
|
+
|
|
44
|
+
```ts
|
|
45
|
+
// bedrock.config.ts
|
|
46
|
+
import { defineConfig } from "@bedrock-rbx/core/config";
|
|
47
|
+
|
|
48
|
+
export default defineConfig({
|
|
49
|
+
environments: {
|
|
50
|
+
production: { universe: { universeId: 1234567890 } },
|
|
51
|
+
},
|
|
52
|
+
passes: {
|
|
53
|
+
"vip-pass": {
|
|
54
|
+
name: "VIP Pass",
|
|
55
|
+
description: "Grants VIP perks.",
|
|
56
|
+
icon: { "en-us": "assets/vip-icon.png" },
|
|
57
|
+
price: 500,
|
|
58
|
+
},
|
|
59
|
+
},
|
|
60
|
+
places: {
|
|
61
|
+
"start-place": {
|
|
62
|
+
name: "Start Place",
|
|
63
|
+
file: "places/start.rbxl",
|
|
64
|
+
},
|
|
65
|
+
},
|
|
66
|
+
state: { backend: "gist", gistId: "abc123def456" },
|
|
67
|
+
universe: {
|
|
68
|
+
name: "My Game",
|
|
69
|
+
description: "An adventure.",
|
|
70
|
+
},
|
|
71
|
+
});
|
|
72
|
+
```
|
|
73
|
+
|
|
74
|
+
Place your custom deploy orchestration at `.bedrock/deploy.ts`. The `bedrock deploy` CLI auto-discovers and invokes this file when present, and the same exports can be imported from a webhook handler, chat bot, or other service that wants to trigger deploys directly.
|
|
75
|
+
|
|
76
|
+
```ts
|
|
77
|
+
// .bedrock/deploy.ts
|
|
78
|
+
import { deploy } from "@bedrock-rbx/core";
|
|
79
|
+
|
|
80
|
+
/**
|
|
81
|
+
* Triggered from a webhook handler whenever a release tag is pushed.
|
|
82
|
+
* Wraps `deploy` with custom orchestration: structured logging on
|
|
83
|
+
* failure, success reporting back to the caller.
|
|
84
|
+
*
|
|
85
|
+
* @param environment - Target environment from the webhook payload.
|
|
86
|
+
* @returns Whether the deploy completed successfully.
|
|
87
|
+
*/
|
|
88
|
+
export async function deployFromWebhook(environment: string): Promise<boolean> {
|
|
89
|
+
const result = await deploy({ environment });
|
|
90
|
+
if (!result.success) {
|
|
91
|
+
console.error("bedrock deploy failed", { environment, err: result.err });
|
|
92
|
+
return false;
|
|
93
|
+
}
|
|
94
|
+
|
|
95
|
+
console.log("bedrock deploy succeeded", { environment });
|
|
96
|
+
return true;
|
|
97
|
+
}
|
|
98
|
+
```
|
|
99
|
+
|
|
100
|
+
`deploy()` returns a `Result<BedrockState, DeployError>` rather than throwing on failure. `Result` is a discriminated union: `result.success` is `true` with the value on `result.data`, or `false` with the error on `result.err`. `DeployError` is itself stage-tagged (`configLoadFailed`, `stateReadFailed`, `applyFailed`, and similar) so callers can branch on `kind` to distinguish what went wrong without parsing error messages.
|
|
101
|
+
|
|
102
|
+
## Quick start (CLI)
|
|
103
|
+
|
|
104
|
+
Using the same `bedrock.config.ts` from above:
|
|
105
|
+
|
|
106
|
+
```bash
|
|
107
|
+
export BEDROCK_API_KEY=...
|
|
108
|
+
export BEDROCK_GITHUB_TOKEN=...
|
|
109
|
+
|
|
110
|
+
pnpm bedrock deploy --env production
|
|
111
|
+
```
|
|
112
|
+
|
|
113
|
+
`bedrock deploy` discovers `bedrock.config.{ts,js,mjs,yaml,yml,json,luau}` in the current directory, loads it, and runs the same reconcile as the programmatic path. If no config sits at the project root, bedrock also looks inside `.bedrock/` so you can colocate the file with your other `.bedrock/` artifacts; a root-level config always wins on collision. Output is rendered via `@clack/prompts` (interactive progress, summary, and error reporting).
|
|
114
|
+
|
|
115
|
+
`--env` may be repeated to deploy to multiple environments in one invocation; each environment is reconciled with its own merged config and its own state slot.
|
|
116
|
+
|
|
117
|
+
## What bedrock manages today
|
|
118
|
+
|
|
119
|
+
| Kind | Key example | What bedrock manages | Notes |
|
|
120
|
+
|---|---|---|---|
|
|
121
|
+
| `universe` | `"main"` (singleton) | Name, description, social links, age guidelines, opt-in studio access. | Adopted by ID. Bedrock does not create new universes. |
|
|
122
|
+
| `place` | `"start-place"` | Place metadata (name, description, server-fill mode, max-player count), `.rbxl` file uploads. | The root place is adopted; secondary places are provisioned by bedrock. |
|
|
123
|
+
| `gamePass` | `"vip-pass"` | Name, description, icon upload, price, on-sale state. | Provisioned by bedrock; the asset ID is recorded in outputs. |
|
|
124
|
+
| `developerProduct` | `"gem-pack-100"` | Name, description, icon upload, price. | Provisioned by bedrock; the asset ID is recorded in outputs. |
|
|
125
|
+
|
|
126
|
+
Bedrock does not delete resources. Removing an entry from your config leaves the upstream entity in place; delete it from Creator Hub directly if you want it gone. Additional kinds (badges, place settings, more) are on the [roadmap](https://github.com/christopher-buss/bedrock/projects).
|
|
127
|
+
|
|
128
|
+
## CLI reference
|
|
129
|
+
|
|
130
|
+
```text
|
|
131
|
+
bedrock <command> [options]
|
|
132
|
+
```
|
|
133
|
+
|
|
134
|
+
**`bedrock deploy`** - reconciles every configured environment (or only those passed via `--env`) against live Roblox state, writing the new state snapshot on success.
|
|
135
|
+
|
|
136
|
+
Options: `--env <name>` (repeatable), `--config <path>`, `--api-key <value>`, `--github-token <value>`.
|
|
137
|
+
|
|
138
|
+
**`bedrock diff`** - previews the operations a deploy *would* apply, without writing state or hitting any mutating Roblox endpoints. Suitable for code review and CI.
|
|
139
|
+
|
|
140
|
+
Options: same as `deploy`.
|
|
141
|
+
|
|
142
|
+
**`bedrock migrate [stateFilePath]`** - translates a state file from another deployment tool into a bedrock project. Currently supports Mantle (`--from mantle`); other sources will be added as needed. The maintainer-prompt UI walks through naming the project, choosing a backend, and resolving any unrecognized fields.
|
|
143
|
+
|
|
144
|
+
Options: `--from <tool>`.
|
|
145
|
+
|
|
146
|
+
Pass `--help` to any command for the full option list at the version you have installed.
|
|
147
|
+
|
|
148
|
+
## Programmatic API surface
|
|
149
|
+
|
|
150
|
+
The most commonly imported entry points:
|
|
151
|
+
|
|
152
|
+
| Symbol | Module | Role |
|
|
153
|
+
|---|---|---|
|
|
154
|
+
| `deploy()` | `@bedrock-rbx/core` | Full reconcile end-to-end. |
|
|
155
|
+
| `diff()` | `@bedrock-rbx/core` | Pure function from desired and current state to an operation list. |
|
|
156
|
+
| `applyOps()` | `@bedrock-rbx/core` | Dispatch an operation list to its drivers and collect outputs. |
|
|
157
|
+
| `loadConfig()` | `@bedrock-rbx/core` | Discover and load a `bedrock.config.*` file. |
|
|
158
|
+
| `buildDesired()` | `@bedrock-rbx/core` | Compute the desired-state list from a resolved config. |
|
|
159
|
+
| `defineConfig()` | `@bedrock-rbx/core/config` | Type-helper for `bedrock.config.ts`. |
|
|
160
|
+
| `ResourceDriver<K>` | `@bedrock-rbx/core` | Plugin contract for resource kinds. |
|
|
161
|
+
| `StatePort` | `@bedrock-rbx/core` | Plugin contract for state backends. |
|
|
162
|
+
| `ProgressPort` | `@bedrock-rbx/core` | Listener interface for per-resource and aggregate deploy events. |
|
|
163
|
+
|
|
164
|
+
`ResourceDriver<K>`, `StatePort`, and `ProgressPort` are published contracts today; the plugin runtime that lets you register custom implementations against a real deploy ships in v0.3.
|
|
165
|
+
|
|
166
|
+
See the [full reference on the docs site](https://bedrock-livid.vercel.app/) for the complete list of exports.
|
|
167
|
+
|
|
168
|
+
## Status, docs, and contributing
|
|
169
|
+
|
|
170
|
+
Bedrock is in active development ahead of a first public release. Track scope and timing on the [project board](https://github.com/christopher-buss/bedrock/projects).
|
|
171
|
+
|
|
172
|
+
- [Documentation site](https://bedrock-livid.vercel.app/) (work in progress)
|
|
173
|
+
- [Source repository](https://github.com/christopher-buss/bedrock)
|
|
174
|
+
- [Issues](https://github.com/christopher-buss/bedrock/issues) (maintainer-only; external feedback runs through [Discussions](https://github.com/christopher-buss/bedrock/discussions) as prompt requests)
|
|
175
|
+
- [Contributing guide](https://github.com/christopher-buss/bedrock/blob/main/CONTRIBUTING.md)
|
|
176
|
+
- [Security policy](https://github.com/christopher-buss/bedrock/blob/main/SECURITY.md)
|
|
177
|
+
|
|
178
|
+
## License
|
|
179
|
+
|
|
180
|
+
[MIT](https://github.com/christopher-buss/bedrock/blob/main/LICENSE) (c) Christopher Buss.
|
package/dist/cli/run.mjs
CHANGED
|
@@ -1,25 +1,94 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
|
-
import {
|
|
2
|
+
import { $ as renderStateWriteError, G as renderBuildStatePortError, J as renderMigrateParseError, K as renderDeployError, N as createClackProgressAdapter, Q as renderParseError, W as resolveStateConfig, X as renderOverrideDiscoveryError, Y as renderMigrationSummary, Z as renderOverrideError, _ as diff, a as assertAllReconcilable, b as buildCredentialOverrides, d as selectEnvironment, et as createClackPort, f as selectMergedEnvironment, i as loadConfig, k as serializeStateFile, m as flattenConfig, n as serializeConfig, o as buildStatePort, p as collectRedactionAnnotations, q as renderMigrateError, r as deploy, s as buildDesired, t as migrateMantleState, u as extractResourceRedaction, x as createDefaultSpawner, y as dispatchOverride } from "../migrate-mantle-state-F4zdhxV4.mjs";
|
|
3
3
|
import { isCancel, path, select, text } from "@clack/prompts";
|
|
4
4
|
import process from "node:process";
|
|
5
5
|
import { mkdir, readFile, writeFile } from "node:fs/promises";
|
|
6
|
-
import {
|
|
6
|
+
import { statSync } from "node:fs";
|
|
7
|
+
import { dirname, join, resolve } from "node:path";
|
|
7
8
|
import sade from "sade";
|
|
8
9
|
//#region package.json
|
|
9
|
-
var version = "0.1.0-beta.
|
|
10
|
+
var version = "0.1.0-beta.16";
|
|
10
11
|
//#endregion
|
|
11
|
-
//#region src/cli/
|
|
12
|
+
//#region src/cli/build-override-invocation.ts
|
|
12
13
|
/**
|
|
13
|
-
*
|
|
14
|
-
*
|
|
15
|
-
*
|
|
16
|
-
*
|
|
14
|
+
* Translate the deploy command's parsed inputs into a single-environment
|
|
15
|
+
* {@link OverrideInvocation}. Optional flags (`apiKey`, `configFile`,
|
|
16
|
+
* `githubToken`) are *omitted* from the returned object when their parsed
|
|
17
|
+
* value is `undefined`, rather than included with an `undefined` value: the
|
|
18
|
+
* spawn protocol's downstream argv and env-var routing relies on field
|
|
19
|
+
* presence, not just defined-ness.
|
|
20
|
+
* @param inputs - {@link BuildOverrideInvocationInputs}.
|
|
21
|
+
* @returns A single-environment {@link OverrideInvocation}.
|
|
17
22
|
*/
|
|
18
|
-
function
|
|
19
|
-
const
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
+
function buildOverrideInvocation(inputs) {
|
|
24
|
+
const { environment, overridePath, parsed } = inputs;
|
|
25
|
+
return {
|
|
26
|
+
...parsed.apiKey === void 0 ? {} : { apiKey: parsed.apiKey },
|
|
27
|
+
...parsed.configFile === void 0 ? {} : { configFile: parsed.configFile },
|
|
28
|
+
environment,
|
|
29
|
+
...parsed.githubToken === void 0 ? {} : { githubToken: parsed.githubToken },
|
|
30
|
+
overridePath
|
|
31
|
+
};
|
|
32
|
+
}
|
|
33
|
+
//#endregion
|
|
34
|
+
//#region src/cli/discover-override.ts
|
|
35
|
+
const OVERRIDE_DIR_NAME = ".bedrock";
|
|
36
|
+
const OVERRIDE_EXTENSION = ".ts";
|
|
37
|
+
const VALID_COMMAND = /^[a-z][a-z0-9-]*$/;
|
|
38
|
+
/**
|
|
39
|
+
* Stat-injectable variant of {@link discoverOverride}. Exported so tests can
|
|
40
|
+
* drive `EACCES`-class errors and malformed-throw cases that real fs fixtures
|
|
41
|
+
* cannot reliably produce on every supported OS.
|
|
42
|
+
* @param inputs - {@link DiscoverOverrideInputs}.
|
|
43
|
+
* @returns The absolute path to the override file when it exists, otherwise
|
|
44
|
+
* `undefined`.
|
|
45
|
+
*/
|
|
46
|
+
function discoverOverrideWith(inputs) {
|
|
47
|
+
const { command, projectRoot, stat } = inputs;
|
|
48
|
+
if (!VALID_COMMAND.test(command)) return;
|
|
49
|
+
const candidate = resolve(projectRoot, OVERRIDE_DIR_NAME, `${command}${OVERRIDE_EXTENSION}`);
|
|
50
|
+
try {
|
|
51
|
+
return stat(candidate).isFile() ? candidate : void 0;
|
|
52
|
+
} catch (err) {
|
|
53
|
+
if (isAbsenceError(err)) return;
|
|
54
|
+
throw err;
|
|
55
|
+
}
|
|
56
|
+
}
|
|
57
|
+
/**
|
|
58
|
+
* Resolve the path of a user-authored `.bedrock/<command>.ts` override for
|
|
59
|
+
* the given command, or return `undefined` when no such file exists.
|
|
60
|
+
*
|
|
61
|
+
* The CLI uses this primitive to decide whether a subcommand invocation
|
|
62
|
+
* should be handed to an override script or run through the built-in path.
|
|
63
|
+
* `undefined` therefore means "fall through to the built-in implementation",
|
|
64
|
+
* so only absence-style stat failures (`ENOENT`, `ENOTDIR`) are swallowed.
|
|
65
|
+
* Permission and other errors propagate; the dispatcher must refuse to
|
|
66
|
+
* silently route a `deploy` (or any other destructive command) through the
|
|
67
|
+
* built-in path when the override file demonstrably exists but is
|
|
68
|
+
* unreadable.
|
|
69
|
+
*
|
|
70
|
+
* `command` is validated against the subcommand grammar before any path
|
|
71
|
+
* construction. An out-of-shape input cannot be a real subcommand and
|
|
72
|
+
* returns `undefined` without touching the filesystem.
|
|
73
|
+
* @param projectRoot - Absolute path of the directory `bedrock` was invoked
|
|
74
|
+
* from. Relative inputs are resolved against `process.cwd()`.
|
|
75
|
+
* @param command - The CLI subcommand name to look up (`deploy`, `diff`,
|
|
76
|
+
* ...). Must match `/^[a-z][a-z0-9-]*$/`; anything else returns `undefined`.
|
|
77
|
+
* @returns The absolute path to the override file when it exists, otherwise
|
|
78
|
+
* `undefined`.
|
|
79
|
+
* @throws When the stat call fails with anything other than `ENOENT` or
|
|
80
|
+
* `ENOTDIR` (e.g. `EACCES`, `EPERM`).
|
|
81
|
+
*/
|
|
82
|
+
function discoverOverride(projectRoot, command) {
|
|
83
|
+
return discoverOverrideWith({
|
|
84
|
+
command,
|
|
85
|
+
projectRoot,
|
|
86
|
+
stat: statSync
|
|
87
|
+
});
|
|
88
|
+
}
|
|
89
|
+
function isAbsenceError(error) {
|
|
90
|
+
if (!(error instanceof Error) || !("code" in error)) return false;
|
|
91
|
+
return error.code === "ENOENT" || error.code === "ENOTDIR";
|
|
23
92
|
}
|
|
24
93
|
//#endregion
|
|
25
94
|
//#region src/cli/parse-options.ts
|
|
@@ -124,6 +193,14 @@ function pickString(rawOptions, ...keys) {
|
|
|
124
193
|
* `deploy()` for each `--env` value in order. Per-env successes and failures
|
|
125
194
|
* render through clack as a single line each; the aggregated exit code is
|
|
126
195
|
* `EXIT_OK` only when every env succeeded.
|
|
196
|
+
*
|
|
197
|
+
* When a `.bedrock/deploy.ts` override is discovered under the resolved
|
|
198
|
+
* project root, each `--env` is handed to the spawner via
|
|
199
|
+
* {@link dispatchOverride} instead of the in-process `deploy()` call. The
|
|
200
|
+
* aggregation rule is identical: every env still runs and the exit code is
|
|
201
|
+
* `EXIT_OK` only when every spawn returned a zero exit code. Unlike the
|
|
202
|
+
* in-process path, only failures emit a per-env line here; a successful
|
|
203
|
+
* spawn's output comes from the override script's own inherited stdout.
|
|
127
204
|
* @param deps - Dependency overrides; missing slots are default-constructed
|
|
128
205
|
* from real implementations.
|
|
129
206
|
* @returns An async sade action that returns once `deps.exit` was invoked.
|
|
@@ -139,9 +216,12 @@ function resolveDeploy(deps) {
|
|
|
139
216
|
return {
|
|
140
217
|
clack: deps.clack ?? createClackPort(),
|
|
141
218
|
deploy: deps.deploy ?? deploy,
|
|
219
|
+
discoverOverride: deps.discoverOverride ?? discoverOverride,
|
|
142
220
|
exit: deps.exit ?? ((code) => process.exit(code)),
|
|
143
221
|
loadConfig: deps.loadConfig ?? loadConfig,
|
|
144
|
-
progressOverride: deps.progress
|
|
222
|
+
progressOverride: deps.progress,
|
|
223
|
+
projectRoot: deps.projectRoot ?? process.cwd(),
|
|
224
|
+
spawner: deps.spawner ?? createDefaultSpawner()
|
|
145
225
|
};
|
|
146
226
|
}
|
|
147
227
|
function loadOptionsFor$1(parsed) {
|
|
@@ -151,28 +231,30 @@ function cancelAsFailed$1(clack) {
|
|
|
151
231
|
clack.cancel("deploy failed");
|
|
152
232
|
}
|
|
153
233
|
async function dispatchEnvironments$1(inputs) {
|
|
154
|
-
const { config,
|
|
234
|
+
const { config, getEnv, overridePath, parsed, progress, resolved } = inputs;
|
|
155
235
|
const failed = [];
|
|
156
|
-
for (const environment of environments) {
|
|
157
|
-
|
|
236
|
+
for (const environment of parsed.environments) {
|
|
237
|
+
if (overridePath !== void 0) {
|
|
238
|
+
const result = await dispatchOverride(buildOverrideInvocation({
|
|
239
|
+
environment,
|
|
240
|
+
overridePath,
|
|
241
|
+
parsed
|
|
242
|
+
}), resolved.spawner);
|
|
243
|
+
if (!result.success) {
|
|
244
|
+
renderOverrideError({
|
|
245
|
+
environment,
|
|
246
|
+
err: result.err
|
|
247
|
+
}, resolved.clack);
|
|
248
|
+
failed.push(environment);
|
|
249
|
+
}
|
|
250
|
+
continue;
|
|
251
|
+
}
|
|
252
|
+
if (!(await resolved.deploy({
|
|
158
253
|
config,
|
|
159
254
|
environment,
|
|
160
255
|
getEnv,
|
|
161
256
|
progress
|
|
162
|
-
});
|
|
163
|
-
if (result.success) progress.emit({
|
|
164
|
-
environment,
|
|
165
|
-
kind: "deploySuccess",
|
|
166
|
-
resourceCount: result.data.resources.length
|
|
167
|
-
});
|
|
168
|
-
else {
|
|
169
|
-
progress.emit({
|
|
170
|
-
environment,
|
|
171
|
-
error: result.err,
|
|
172
|
-
kind: "deployFailure"
|
|
173
|
-
});
|
|
174
|
-
failed.push(environment);
|
|
175
|
-
}
|
|
257
|
+
})).success) failed.push(environment);
|
|
176
258
|
}
|
|
177
259
|
return failed;
|
|
178
260
|
}
|
|
@@ -181,15 +263,16 @@ function buildGetEnvironment$1(parsed) {
|
|
|
181
263
|
return (name) => overrides[name] ?? process.env[name];
|
|
182
264
|
}
|
|
183
265
|
async function dispatchAndReport(input) {
|
|
184
|
-
const { loaded, parsed, resolved } = input;
|
|
266
|
+
const { loaded, overridePath, parsed, resolved } = input;
|
|
185
267
|
const progress = resolved.progressOverride ?? createClackProgressAdapter({
|
|
186
268
|
clack: resolved.clack,
|
|
187
269
|
config: loaded
|
|
188
270
|
});
|
|
189
271
|
if ((await dispatchEnvironments$1({
|
|
190
272
|
config: loaded,
|
|
191
|
-
environments: parsed.environments,
|
|
192
273
|
getEnv: buildGetEnvironment$1(parsed),
|
|
274
|
+
overridePath,
|
|
275
|
+
parsed,
|
|
193
276
|
progress,
|
|
194
277
|
resolved
|
|
195
278
|
})).length > 0) {
|
|
@@ -199,6 +282,18 @@ async function dispatchAndReport(input) {
|
|
|
199
282
|
resolved.clack.outro("deploy succeeded");
|
|
200
283
|
return 0;
|
|
201
284
|
}
|
|
285
|
+
function discoverOverridePath(resolved) {
|
|
286
|
+
try {
|
|
287
|
+
return {
|
|
288
|
+
kind: "discovered",
|
|
289
|
+
overridePath: resolved.discoverOverride(resolved.projectRoot, "deploy")
|
|
290
|
+
};
|
|
291
|
+
} catch (err) {
|
|
292
|
+
renderOverrideDiscoveryError(err, resolved.clack);
|
|
293
|
+
cancelAsFailed$1(resolved.clack);
|
|
294
|
+
return { kind: "failed" };
|
|
295
|
+
}
|
|
296
|
+
}
|
|
202
297
|
async function runDeploy(rawOptions, resolved) {
|
|
203
298
|
resolved.clack.intro("bedrock deploy");
|
|
204
299
|
const parsed = parseCommonOptions(rawOptions);
|
|
@@ -216,8 +311,11 @@ async function runDeploy(rawOptions, resolved) {
|
|
|
216
311
|
cancelAsFailed$1(resolved.clack);
|
|
217
312
|
return 1;
|
|
218
313
|
}
|
|
314
|
+
const discovery = discoverOverridePath(resolved);
|
|
315
|
+
if (discovery.kind === "failed") return 1;
|
|
219
316
|
return dispatchAndReport({
|
|
220
317
|
loaded: loaded.data,
|
|
318
|
+
overridePath: discovery.overridePath,
|
|
221
319
|
parsed: parsed.data,
|
|
222
320
|
resolved
|
|
223
321
|
});
|
|
@@ -227,7 +325,7 @@ async function runDeploy(rawOptions, resolved) {
|
|
|
227
325
|
/**
|
|
228
326
|
* Compute the operations `deploy` would apply for a target environment
|
|
229
327
|
* without writing state. Default-constructs missing deps from the project
|
|
230
|
-
* config and `
|
|
328
|
+
* config and `BEDROCK_GITHUB_TOKEN`; never reads `process.env` when `statePort`
|
|
231
329
|
* and `config` are both supplied explicitly.
|
|
232
330
|
*
|
|
233
331
|
* @param options - Target environment plus optional overrides.
|
|
@@ -336,7 +434,7 @@ async function runPreview(environment, deps) {
|
|
|
336
434
|
success: false
|
|
337
435
|
};
|
|
338
436
|
const priorResources = prior.data?.resources ?? [];
|
|
339
|
-
const validated =
|
|
437
|
+
const validated = assertAllReconcilable(desired.data, priorResources);
|
|
340
438
|
if (!validated.success) return {
|
|
341
439
|
err: {
|
|
342
440
|
cause: validated.err,
|
|
@@ -1328,8 +1426,8 @@ const PROGRAM_DESCRIBE = "Infrastructure-as-Code deployment tool for Roblox";
|
|
|
1328
1426
|
*/
|
|
1329
1427
|
function createProg(deps = {}) {
|
|
1330
1428
|
const prog = sade(PROGRAM_NAME).describe(PROGRAM_DESCRIBE).version(version);
|
|
1331
|
-
prog.command("deploy").describe("Reconcile a project's resources against the configured environment(s)").option("--env", "Target environment (repeat for multiple)").option("--config", "Config file path (overrides discovery)").option("--api-key", "Override the BEDROCK_API_KEY environment variable").option("--github-token", "Override the
|
|
1332
|
-
prog.command("diff").describe("Preview the operations a deploy would apply, without writing state").option("--env", "Target environment (repeat for multiple)").option("--config", "Config file path (overrides discovery)").option("--api-key", "Override the BEDROCK_API_KEY environment variable").option("--github-token", "Override the
|
|
1429
|
+
prog.command("deploy").describe("Reconcile a project's resources against the configured environment(s)").option("--env", "Target environment (repeat for multiple)").option("--config", "Config file path (overrides discovery)").option("--api-key", "Override the BEDROCK_API_KEY environment variable").option("--github-token", "Override the BEDROCK_GITHUB_TOKEN environment variable").action(deployCommand(deps));
|
|
1430
|
+
prog.command("diff").describe("Preview the operations a deploy would apply, without writing state").option("--env", "Target environment (repeat for multiple)").option("--config", "Config file path (overrides discovery)").option("--api-key", "Override the BEDROCK_API_KEY environment variable").option("--github-token", "Override the BEDROCK_GITHUB_TOKEN environment variable").action(diffCommand(deps));
|
|
1333
1431
|
prog.command("migrate [stateFilePath]").describe("Translate a state file from another tool into a bedrock project").option("--from", "Source format to migrate from (mantle; prompted if omitted)").action(migrateCommand(deps));
|
|
1334
1432
|
return prog;
|
|
1335
1433
|
}
|