rainbo 0.1.10 → 0.1.17
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 +70 -10
- package/package.json +28 -5
- package/packaging/npm/platform.js +16 -0
- package/packaging/npm/postinstall.js +97 -0
- package/packaging/npm/run.js +34 -5
package/README.md
CHANGED
|
@@ -14,16 +14,55 @@ Those platform packages are published under the `@singdata` scope.
|
|
|
14
14
|
|
|
15
15
|
## Install
|
|
16
16
|
|
|
17
|
+
First-time install:
|
|
18
|
+
|
|
17
19
|
```bash
|
|
18
20
|
npm install -g rainbo
|
|
19
21
|
rainbo version
|
|
20
22
|
```
|
|
21
23
|
|
|
24
|
+
The npm package automatically attempts to sync the official Rainbo skills after
|
|
25
|
+
install. If the postinstall sync cannot reach GitLab or `npx skills`, it does
|
|
26
|
+
not fail the npm install; run the same sync manually:
|
|
27
|
+
|
|
28
|
+
```bash
|
|
29
|
+
rainbo update --force
|
|
30
|
+
```
|
|
31
|
+
|
|
32
|
+
Set `RAINBO_NPM_NO_SKILLS_SYNC=1` to skip the automatic postinstall sync in
|
|
33
|
+
scripted environments. If GitLab is unavailable, use the offline package from
|
|
34
|
+
数据校验宝典:
|
|
35
|
+
|
|
36
|
+
```bash
|
|
37
|
+
rainbo update --skills-package /path/to/rainbo-skills.zip
|
|
38
|
+
```
|
|
39
|
+
|
|
40
|
+
Maintainers can regenerate the offline package from the repository root with:
|
|
41
|
+
|
|
42
|
+
```bash
|
|
43
|
+
cd packages/rainbo
|
|
44
|
+
npm run pack:skills
|
|
45
|
+
```
|
|
46
|
+
|
|
47
|
+
This writes `../../skills.zip`, a standard `npx skills` source archive that
|
|
48
|
+
contains `skills/index.json` plus all official Rainbo skill directories.
|
|
49
|
+
|
|
50
|
+
If `rainbo` is already installed, prefer the built-in upgrade flow instead of
|
|
51
|
+
running bare `npm install -g rainbo`:
|
|
52
|
+
|
|
53
|
+
```bash
|
|
54
|
+
rainbo update
|
|
55
|
+
```
|
|
56
|
+
|
|
57
|
+
`rainbo update` upgrades the npm package and syncs official Rainbo skills in
|
|
58
|
+
one step, which avoids `_notice.skills` drift.
|
|
59
|
+
|
|
22
60
|
## Development
|
|
23
61
|
|
|
24
62
|
```bash
|
|
25
63
|
node packaging/npm/run.js version
|
|
26
64
|
node packaging/npm/run.js help
|
|
65
|
+
npm run check:npm
|
|
27
66
|
npm run check:skills
|
|
28
67
|
npm run build:npm:local
|
|
29
68
|
```
|
|
@@ -55,6 +94,7 @@ Errors are written to stderr:
|
|
|
55
94
|
rainbo update --check
|
|
56
95
|
rainbo update
|
|
57
96
|
rainbo update --force
|
|
97
|
+
rainbo update --skills-only
|
|
58
98
|
rainbo update --skills-package /path/to/rainbo-skills.zip
|
|
59
99
|
```
|
|
60
100
|
|
|
@@ -64,6 +104,10 @@ and `_notice.skills` when locally synced skills are out of sync with the
|
|
|
64
104
|
running binary. The update cache refreshes at most every 2 hours. Both notices
|
|
65
105
|
recommend `rainbo update`.
|
|
66
106
|
|
|
107
|
+
`update --skills-only` syncs Rainbo skills without checking npm for newer
|
|
108
|
+
versions or attempting a self-update. It is intended for npm postinstall and
|
|
109
|
+
other bootstrap flows that only need skill synchronization.
|
|
110
|
+
|
|
67
111
|
`update` detects npm installations, runs `npm install -g rainbo@<latest>`
|
|
68
112
|
when auto-update is available, verifies the new binary, and syncs repository
|
|
69
113
|
skills with:
|
|
@@ -79,7 +123,10 @@ available, it falls back to a full install.
|
|
|
79
123
|
When users cannot access the GitLab skills repository, they can use the offline
|
|
80
124
|
skills package from 数据校验宝典 and run `rainbo update --skills-package
|
|
81
125
|
/path/to/rainbo-skills.zip`. The CLI will update Rainbo as usual and sync skills
|
|
82
|
-
from the local package path instead of the GitLab source.
|
|
126
|
+
from the local package path instead of the GitLab source. The offline package is
|
|
127
|
+
installed through the same `npx skills` protocol after Rainbo extracts the zip,
|
|
128
|
+
and `skills-state.json` records the package path for future `_notice.skills`
|
|
129
|
+
version drift checks.
|
|
83
130
|
|
|
84
131
|
If automatic update is unavailable, the JSON action is `manual_required` and
|
|
85
132
|
the response includes release and changelog URLs.
|
|
@@ -102,10 +149,12 @@ permissions for this file.
|
|
|
102
149
|
|
|
103
150
|
Authenticated API commands reuse the session created by `rainbo auth connect`.
|
|
104
151
|
Complex request bodies can be passed with `--data-json`, `--data-file`, or
|
|
105
|
-
`--data @payload.json`.
|
|
152
|
+
`--data @payload.json`. Add `--dry-run` to print the request method, path,
|
|
153
|
+
query, and body without reading auth state or calling Rainbo APIs.
|
|
106
154
|
|
|
107
155
|
```bash
|
|
108
156
|
rainbo data-sync cmt-jobs --data-file cmt-jobs.json
|
|
157
|
+
rainbo data-sync cmt-jobs --data-file cmt-jobs.json --dry-run
|
|
109
158
|
rainbo data-verify lineage-verify-table --data-file verify-table.json
|
|
110
159
|
rainbo toolbox sql-debug --datasource-id 1 --sql "select 1"
|
|
111
160
|
rainbo toolbox lineage-spark --data-file lineage-spark.json
|
|
@@ -145,8 +194,10 @@ npm run publish:npm:local
|
|
|
145
194
|
```
|
|
146
195
|
|
|
147
196
|
The publish script refuses to continue if `package.json` and `rust/Cargo.toml`
|
|
148
|
-
versions differ.
|
|
149
|
-
|
|
197
|
+
versions differ. It also runs `npm run check:npm` to verify npm metadata,
|
|
198
|
+
generated meta-package contents, and platform optional dependencies before
|
|
199
|
+
publishing. After building the current-platform binary, it runs the bundled
|
|
200
|
+
binary and verifies `rainbo version` matches `package.json`.
|
|
150
201
|
The publish script is cross-platform and can be run from macOS shells,
|
|
151
202
|
Windows PowerShell, or Windows CMD.
|
|
152
203
|
|
|
@@ -167,7 +218,7 @@ To build multiple platforms from a machine with the required Rust
|
|
|
167
218
|
targets/toolchains installed, set:
|
|
168
219
|
|
|
169
220
|
```bash
|
|
170
|
-
RAINBO_NPM_BUILD_TARGETS=darwin-arm64,darwin-x64,win32-x64,win32-arm64 npm run publish:npm:local
|
|
221
|
+
RAINBO_NPM_BUILD_TARGETS=linux-x64,linux-arm64,darwin-arm64,darwin-x64,win32-x64,win32-arm64 npm run publish:npm:local
|
|
171
222
|
```
|
|
172
223
|
|
|
173
224
|
The package source lives under the Rainbo GitLab repository as
|
|
@@ -186,13 +237,22 @@ npx skills add git@gitlab.clickzetta-inc.com:ee/rainbo.git -y -g
|
|
|
186
237
|
|
|
187
238
|
`git@gitlab.clickzetta-inc.com:ee/rainbo.git` is the skills repository
|
|
188
239
|
source used by `rainbo update`. The old aggregate `rainbo` skill has
|
|
189
|
-
been removed; current Rainbo skills use focused names such as
|
|
240
|
+
been removed; current Rainbo skills use focused names such as
|
|
241
|
+
`rainbo-shared`, `rainbo-auth`, `rainbo-data-sync`, `rainbo-data-verify`,
|
|
242
|
+
`rainbo-studio`, `rainbo-lineage`, and `rainbo-toolbox`.
|
|
243
|
+
|
|
244
|
+
The repository root `skills/index.json` is the official skill list consumed by
|
|
245
|
+
the standard `npx skills` installer. Keep it in sync with `skills/*/SKILL.md`
|
|
246
|
+
and run `npm run check:skills` before publishing. Do not add agent-specific
|
|
247
|
+
install paths such as Claude or Codex directories to the Rainbo CLI; the
|
|
248
|
+
installer owns host compatibility.
|
|
190
249
|
|
|
191
250
|
New Rainbo skills should follow the style in the repository-level
|
|
192
|
-
`skill-template/`: the top-level
|
|
193
|
-
|
|
194
|
-
|
|
195
|
-
|
|
251
|
+
`skill-template/`: the top-level `SKILL.md` acts as a routing and safety
|
|
252
|
+
rulebook, while detailed command families live in `references/*.md`.
|
|
253
|
+
Business workflow skills should point to `rainbo-shared` first and then
|
|
254
|
+
`rainbo-auth` when they call authenticated APIs instead of duplicating shared
|
|
255
|
+
output, risk, dry-run, session, or secret-handling rules.
|
|
196
256
|
|
|
197
257
|
## Project layout
|
|
198
258
|
|
package/package.json
CHANGED
|
@@ -1,7 +1,24 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "rainbo",
|
|
3
|
-
"version": "0.1.
|
|
3
|
+
"version": "0.1.17",
|
|
4
4
|
"description": "Rainbo command line tools for data migration workflows",
|
|
5
|
+
"keywords": [
|
|
6
|
+
"rainbo",
|
|
7
|
+
"cli",
|
|
8
|
+
"data-migration",
|
|
9
|
+
"data-validation",
|
|
10
|
+
"lineage",
|
|
11
|
+
"ai-agent"
|
|
12
|
+
],
|
|
13
|
+
"homepage": "https://gitlab.clickzetta-inc.com/ee/rainbo#readme",
|
|
14
|
+
"repository": {
|
|
15
|
+
"type": "git",
|
|
16
|
+
"url": "git+ssh://git@gitlab.clickzetta-inc.com/ee/rainbo.git",
|
|
17
|
+
"directory": "packages/rainbo"
|
|
18
|
+
},
|
|
19
|
+
"bugs": {
|
|
20
|
+
"url": "https://gitlab.clickzetta-inc.com/ee/rainbo/-/issues"
|
|
21
|
+
},
|
|
5
22
|
"bin": {
|
|
6
23
|
"rainbo": "packaging/npm/run.js"
|
|
7
24
|
},
|
|
@@ -9,14 +26,20 @@
|
|
|
9
26
|
"node": ">=16"
|
|
10
27
|
},
|
|
11
28
|
"optionalDependencies": {
|
|
12
|
-
"@singdata/rainbo-cli-
|
|
13
|
-
"@singdata/rainbo-cli-
|
|
14
|
-
"@singdata/rainbo-cli-
|
|
15
|
-
"@singdata/rainbo-cli-
|
|
29
|
+
"@singdata/rainbo-cli-linux-x64": "0.1.17",
|
|
30
|
+
"@singdata/rainbo-cli-linux-arm64": "0.1.17",
|
|
31
|
+
"@singdata/rainbo-cli-darwin-x64": "0.1.17",
|
|
32
|
+
"@singdata/rainbo-cli-darwin-arm64": "0.1.17",
|
|
33
|
+
"@singdata/rainbo-cli-win32-x64": "0.1.17",
|
|
34
|
+
"@singdata/rainbo-cli-win32-arm64": "0.1.17"
|
|
16
35
|
},
|
|
17
36
|
"license": "MIT",
|
|
37
|
+
"scripts": {
|
|
38
|
+
"postinstall": "node packaging/npm/postinstall.js"
|
|
39
|
+
},
|
|
18
40
|
"files": [
|
|
19
41
|
"packaging/npm/platform.js",
|
|
42
|
+
"packaging/npm/postinstall.js",
|
|
20
43
|
"packaging/npm/run.js",
|
|
21
44
|
"README.md",
|
|
22
45
|
"LICENSE"
|
|
@@ -1,4 +1,20 @@
|
|
|
1
1
|
const PLATFORM_PACKAGES = {
|
|
2
|
+
"linux-x64": {
|
|
3
|
+
packageName: "@singdata/rainbo-cli-linux-x64",
|
|
4
|
+
target: "x86_64-unknown-linux-gnu",
|
|
5
|
+
binary: "rainbo",
|
|
6
|
+
os: "linux",
|
|
7
|
+
cpu: "x64",
|
|
8
|
+
archiveExt: ".tar.xz",
|
|
9
|
+
},
|
|
10
|
+
"linux-arm64": {
|
|
11
|
+
packageName: "@singdata/rainbo-cli-linux-arm64",
|
|
12
|
+
target: "aarch64-unknown-linux-gnu",
|
|
13
|
+
binary: "rainbo",
|
|
14
|
+
os: "linux",
|
|
15
|
+
cpu: "arm64",
|
|
16
|
+
archiveExt: ".tar.xz",
|
|
17
|
+
},
|
|
2
18
|
"darwin-x64": {
|
|
3
19
|
packageName: "@singdata/rainbo-cli-darwin-x64",
|
|
4
20
|
target: "x86_64-apple-darwin",
|
|
@@ -0,0 +1,97 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
|
|
3
|
+
const { spawnSync } = require("child_process");
|
|
4
|
+
const fs = require("fs");
|
|
5
|
+
const path = require("path");
|
|
6
|
+
|
|
7
|
+
const isTruthy = (value) => value && value !== "0" && value.toLowerCase() !== "false";
|
|
8
|
+
|
|
9
|
+
const sourceManifest = path.join(__dirname, "..", "..", "rust", "Cargo.toml");
|
|
10
|
+
const launcher = path.join(__dirname, "run.js");
|
|
11
|
+
|
|
12
|
+
if (isTruthy(process.env.RAINBO_NPM_NO_INSTALL_HINT) || isTruthy(process.env.RAINBO_NPM_NO_SKILLS_SYNC)) {
|
|
13
|
+
process.exit(0);
|
|
14
|
+
}
|
|
15
|
+
|
|
16
|
+
function writeHint(reason) {
|
|
17
|
+
const reasonLine = reason ? [`Rainbo skills were not synced automatically: ${reason}`] : [];
|
|
18
|
+
const lines = [
|
|
19
|
+
"",
|
|
20
|
+
...reasonLine,
|
|
21
|
+
"To sync the official Rainbo skills, run:",
|
|
22
|
+
" rainbo update --force",
|
|
23
|
+
"If GitLab is unavailable, use an offline skills package:",
|
|
24
|
+
" rainbo update --skills-package <path-to-rainbo-skills.zip>",
|
|
25
|
+
"Set RAINBO_NPM_NO_SKILLS_SYNC=1 to skip automatic postinstall sync.",
|
|
26
|
+
"",
|
|
27
|
+
];
|
|
28
|
+
process.stderr.write(`${lines.join("\n")}\n`);
|
|
29
|
+
}
|
|
30
|
+
|
|
31
|
+
if (fs.existsSync(sourceManifest)) {
|
|
32
|
+
writeHint("source checkout detected");
|
|
33
|
+
process.exit(0);
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
if (!fs.existsSync(launcher)) {
|
|
37
|
+
writeHint("rainbo npm launcher is missing");
|
|
38
|
+
process.exit(0);
|
|
39
|
+
}
|
|
40
|
+
|
|
41
|
+
process.stderr.write("\nrainbo installed. Syncing official Rainbo skills...\n");
|
|
42
|
+
const result = spawnSync(
|
|
43
|
+
process.execPath,
|
|
44
|
+
[launcher, "update", "--skills-only", "--force", "--format", "json"],
|
|
45
|
+
{
|
|
46
|
+
stdio: ["ignore", "pipe", "pipe"],
|
|
47
|
+
encoding: "utf8",
|
|
48
|
+
env: {
|
|
49
|
+
...process.env,
|
|
50
|
+
RAINBO_NPM_POSTINSTALL: "1",
|
|
51
|
+
RAINBO_CLI_NO_UPDATE_NOTIFIER: "1",
|
|
52
|
+
RAINBO_CLI_NO_SKILLS_NOTIFIER: "1",
|
|
53
|
+
},
|
|
54
|
+
},
|
|
55
|
+
);
|
|
56
|
+
|
|
57
|
+
if (result.error) {
|
|
58
|
+
writeHint(result.error.message);
|
|
59
|
+
process.exit(0);
|
|
60
|
+
}
|
|
61
|
+
|
|
62
|
+
if (result.status !== 0) {
|
|
63
|
+
const stderr = String(result.stderr || "").trim();
|
|
64
|
+
if (stderr) process.stderr.write(`${stderr}\n`);
|
|
65
|
+
writeHint(`sync command exited with status ${result.status}`);
|
|
66
|
+
process.exit(0);
|
|
67
|
+
}
|
|
68
|
+
|
|
69
|
+
let output;
|
|
70
|
+
try {
|
|
71
|
+
output = JSON.parse(String(result.stdout || "").trim());
|
|
72
|
+
} catch (err) {
|
|
73
|
+
const stdout = String(result.stdout || "").trim();
|
|
74
|
+
const stderr = String(result.stderr || "").trim();
|
|
75
|
+
if (stdout) process.stderr.write(`${stdout}\n`);
|
|
76
|
+
if (stderr) process.stderr.write(`${stderr}\n`);
|
|
77
|
+
writeHint(`sync command returned non-JSON output: ${err.message}`);
|
|
78
|
+
process.exit(0);
|
|
79
|
+
}
|
|
80
|
+
|
|
81
|
+
const action = output && output.data && output.data.skills_action;
|
|
82
|
+
if (!action) {
|
|
83
|
+
writeHint("sync command did not report skills_action");
|
|
84
|
+
process.exit(0);
|
|
85
|
+
}
|
|
86
|
+
if (action === "failed" || action === "fallback_failed") {
|
|
87
|
+
const warning = output.data.skills_warning || output.data.skills_detail || action;
|
|
88
|
+
writeHint(warning);
|
|
89
|
+
process.exit(0);
|
|
90
|
+
}
|
|
91
|
+
|
|
92
|
+
const lines = [
|
|
93
|
+
"",
|
|
94
|
+
"Rainbo skills synced.",
|
|
95
|
+
"",
|
|
96
|
+
];
|
|
97
|
+
process.stderr.write(`${lines.join("\n")}\n`);
|
package/packaging/npm/run.js
CHANGED
|
@@ -9,6 +9,19 @@ const isWindows = process.platform === "win32";
|
|
|
9
9
|
const repoRoot = path.join(__dirname, "..", "..");
|
|
10
10
|
const sourceManifest = path.join(repoRoot, "rust", "Cargo.toml");
|
|
11
11
|
|
|
12
|
+
function writeError(type, subtype, message, hint) {
|
|
13
|
+
const error = {
|
|
14
|
+
ok: false,
|
|
15
|
+
error: {
|
|
16
|
+
type,
|
|
17
|
+
subtype,
|
|
18
|
+
message,
|
|
19
|
+
},
|
|
20
|
+
};
|
|
21
|
+
if (hint) error.error.hint = hint;
|
|
22
|
+
process.stderr.write(`${JSON.stringify(error)}\n`);
|
|
23
|
+
}
|
|
24
|
+
|
|
12
25
|
function resolveBundledLauncher() {
|
|
13
26
|
const platformPackage = currentPlatformPackage();
|
|
14
27
|
if (!platformPackage) return null;
|
|
@@ -37,9 +50,12 @@ function installIfMissing() {
|
|
|
37
50
|
const packageHint = platformPackage
|
|
38
51
|
? `${platformPackage.packageName} (${currentPlatformKey()})`
|
|
39
52
|
: `unsupported platform ${currentPlatformKey()}`;
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
53
|
+
writeError(
|
|
54
|
+
"internal",
|
|
55
|
+
platformPackage ? "binary_package_missing" : "unsupported_platform",
|
|
56
|
+
`rainbo binary package is missing for ${currentPlatformKey()}`,
|
|
57
|
+
`expected npm binary package: ${packageHint}; reinstall rainbo so npm installs the matching optional dependency`,
|
|
58
|
+
);
|
|
43
59
|
process.exit(1);
|
|
44
60
|
}
|
|
45
61
|
|
|
@@ -55,11 +71,24 @@ const command = useSource ? "cargo" : resolveLauncher();
|
|
|
55
71
|
const args = useSource
|
|
56
72
|
? ["run", "--quiet", "--manifest-path", sourceManifest, "--", ...process.argv.slice(2)]
|
|
57
73
|
: process.argv.slice(2);
|
|
58
|
-
if (!command)
|
|
74
|
+
if (!command) {
|
|
75
|
+
writeError(
|
|
76
|
+
"internal",
|
|
77
|
+
"launcher_missing",
|
|
78
|
+
"rainbo launcher could not resolve a source or bundled binary",
|
|
79
|
+
"reinstall the rainbo npm package",
|
|
80
|
+
);
|
|
81
|
+
process.exit(1);
|
|
82
|
+
}
|
|
59
83
|
const result = spawnSync(command, args, { stdio: "inherit", shell: isWindows });
|
|
60
84
|
|
|
61
85
|
if (result.error) {
|
|
62
|
-
|
|
86
|
+
writeError(
|
|
87
|
+
"internal",
|
|
88
|
+
"launcher_spawn_failed",
|
|
89
|
+
result.error.message,
|
|
90
|
+
`failed to execute ${command}`,
|
|
91
|
+
);
|
|
63
92
|
process.exit(1);
|
|
64
93
|
}
|
|
65
94
|
process.exit(result.status || 0);
|