@nitsan-ai/ragsuite-test 0.1.2 → 0.1.4
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 +42 -59
- package/package.json +3 -2
- package/src/commands/doctor.js +17 -13
- package/src/commands/init.js +130 -60
- package/src/commands/start.js +25 -17
- package/src/commands/stop.js +23 -13
- package/src/commands/update.js +84 -51
- package/src/index.js +5 -3
- package/src/utils/args.js +6 -0
- package/src/utils/config.js +11 -5
- package/src/utils/distribution.js +10 -8
- package/src/utils/git-install.js +12 -7
- package/src/utils/global-config.js +61 -0
- package/src/utils/images-install.js +106 -0
- package/src/utils/paths.js +77 -21
- package/src/utils/port.js +1 -1
- package/templates/images/.env.example +76 -0
- package/templates/images/docker-compose.yml +165 -0
- package/templates/images/scripts/docker-doctor-images.sh +48 -0
- package/templates/images/scripts/docker-start-images.sh +107 -0
- package/templates/images/scripts/docker-stop-images.sh +22 -0
package/README.md
CHANGED
|
@@ -1,86 +1,69 @@
|
|
|
1
1
|
# RAGSuite test CLI (`ragsuite-test`)
|
|
2
2
|
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
**One-command public install** (GitHub repo must be public):
|
|
3
|
+
npm-style install: **init once**, then **start / update / stop** — no `--repo-root` every time.
|
|
6
4
|
|
|
7
5
|
```bash
|
|
8
6
|
npm install -g @nitsan-ai/ragsuite-test
|
|
9
|
-
ragsuite-test init
|
|
10
|
-
ragsuite-test start --repo-root ~/ragsuite-test --detach
|
|
11
|
-
```
|
|
12
7
|
|
|
13
|
-
|
|
8
|
+
# First time only
|
|
9
|
+
ragsuite-test init
|
|
10
|
+
# or without app source on disk:
|
|
11
|
+
# ragsuite-test init --from-images
|
|
14
12
|
|
|
15
|
-
-
|
|
16
|
-
|
|
17
|
-
- Web (native): http://localhost:9191
|
|
13
|
+
ragsuite-test start
|
|
14
|
+
# API http://localhost:9090 · Web http://localhost:9091
|
|
18
15
|
|
|
19
|
-
|
|
20
|
-
ragsuite-test stop --repo-root ~/ragsuite-test
|
|
16
|
+
ragsuite-test stop
|
|
21
17
|
```
|
|
22
18
|
|
|
23
|
-
|
|
19
|
+
Active install is remembered in `~/.ragsuite-test/config.json` (default app dir: `~/ragsuite-test`).
|
|
24
20
|
|
|
25
|
-
|
|
26
|
-
|------|-----------|-----|
|
|
27
|
-
| Node.js 18+ | Yes | https://nodejs.org · `brew install node` |
|
|
28
|
-
| git | Yes | `xcode-select --install` · `brew install git` |
|
|
29
|
-
| Docker | No | Optional; without it init uses native (needs Postgres `:5436` + Redis `:6382`) |
|
|
21
|
+
---
|
|
30
22
|
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
## Advanced (optional)
|
|
23
|
+
## Upgrade (keeps data & `.env`)
|
|
34
24
|
|
|
35
25
|
```bash
|
|
36
|
-
|
|
37
|
-
ragsuite-test
|
|
38
|
-
ragsuite-test
|
|
39
|
-
|
|
40
|
-
# Custom install dir
|
|
41
|
-
ragsuite-test init --install-dir ~/my-ragsuite
|
|
42
|
-
|
|
43
|
-
# Existing checkout (CI / developers)
|
|
44
|
-
ragsuite-test init --repo-root /path/to/RAGSUITE
|
|
26
|
+
npm install -g @nitsan-ai/ragsuite-test@latest
|
|
27
|
+
ragsuite-test update
|
|
28
|
+
ragsuite-test start
|
|
45
29
|
```
|
|
46
30
|
|
|
47
|
-
|
|
31
|
+
| Install type | What `update` does |
|
|
32
|
+
|--------------|--------------------|
|
|
33
|
+
| Git (`init`) | `git pull` in `~/ragsuite-test` |
|
|
34
|
+
| Images (`init --from-images`) | `docker compose pull` + recreate containers |
|
|
48
35
|
|
|
49
|
-
|
|
50
|
-
|---------|------|
|
|
51
|
-
| API | 9090 |
|
|
52
|
-
| Web (Docker) | 9091 |
|
|
53
|
-
| Web (native Expo) | 9191 |
|
|
54
|
-
| Postgres | 5436 |
|
|
55
|
-
| Redis | 6382 |
|
|
36
|
+
**Never** run `docker compose down -v` or `init --force` unless you mean to wipe data.
|
|
56
37
|
|
|
57
|
-
|
|
38
|
+
If you already installed and run `init` again → it says **Already installed** and exits OK (does not wipe).
|
|
58
39
|
|
|
59
|
-
|
|
40
|
+
---
|
|
60
41
|
|
|
61
|
-
|
|
62
|
-
|---------|----------|
|
|
63
|
-
| `init` | Clone public repo → `.env` + config (default) |
|
|
64
|
-
| `start` / `stop` | Docker or native scripts |
|
|
65
|
-
| `doctor` | Health / prereq hints |
|
|
66
|
-
| `logs` / `update` / `version` | As before |
|
|
42
|
+
## Which first-time install?
|
|
67
43
|
|
|
68
|
-
|
|
44
|
+
| | **Git source** `init` | **Images** `init --from-images` |
|
|
45
|
+
|--|----------------------|----------------------------------|
|
|
46
|
+
| App code on disk | Yes | No |
|
|
47
|
+
| Docker | Optional (`--mode native`) | Required |
|
|
48
|
+
| Best for | Dev / native | Testers / “just run it” |
|
|
69
49
|
|
|
70
|
-
|
|
50
|
+
---
|
|
71
51
|
|
|
72
|
-
|
|
73
|
-
cd cli && npm run prepublish:check
|
|
74
|
-
# Only when approved:
|
|
75
|
-
RAGSUITE_TEST_ALLOW_PUBLISH=1 npm publish --access public
|
|
76
|
-
```
|
|
52
|
+
## Commands
|
|
77
53
|
|
|
78
|
-
|
|
54
|
+
| Command | Purpose |
|
|
55
|
+
|---------|---------|
|
|
56
|
+
| `init` | First-time install |
|
|
57
|
+
| `start` | Start app (uses saved install path) |
|
|
58
|
+
| `stop` | Stop app (volumes kept) |
|
|
59
|
+
| `update` | Upgrade code/images in place |
|
|
60
|
+
| `doctor` | Health / prereqs |
|
|
61
|
+
| `version` | CLI version |
|
|
79
62
|
|
|
80
|
-
|
|
63
|
+
## Ports
|
|
81
64
|
|
|
82
|
-
|
|
65
|
+
API **9090** · Web **9091** (Docker/images) · Web **9191** (native) · Postgres **5436** · Redis **6382**
|
|
83
66
|
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
67
|
+
## Publish (maintainers)
|
|
68
|
+
|
|
69
|
+
See [PUBLISH.md](./PUBLISH.md). Also publish GHCR images before `--from-images` works for others.
|
package/package.json
CHANGED
|
@@ -1,8 +1,8 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@nitsan-ai/ragsuite-test",
|
|
3
|
-
"version": "0.1.
|
|
3
|
+
"version": "0.1.4",
|
|
4
4
|
"private": false,
|
|
5
|
-
"description": "RAGSuite testing CLI
|
|
5
|
+
"description": "RAGSuite testing CLI — init once, then start/update/stop (npm-style).",
|
|
6
6
|
"main": "src/index.js",
|
|
7
7
|
"bin": {
|
|
8
8
|
"ragsuite-test": "./bin/ragsuite-test.js"
|
|
@@ -10,6 +10,7 @@
|
|
|
10
10
|
"files": [
|
|
11
11
|
"bin/",
|
|
12
12
|
"src/",
|
|
13
|
+
"templates/",
|
|
13
14
|
"package.json",
|
|
14
15
|
"README.md",
|
|
15
16
|
"LICENSE"
|
package/src/commands/doctor.js
CHANGED
|
@@ -2,22 +2,22 @@
|
|
|
2
2
|
|
|
3
3
|
const path = require('path');
|
|
4
4
|
const { resolveMode } = require('../utils/config');
|
|
5
|
-
const { resolveRepoRoot } = require('../utils/paths');
|
|
5
|
+
const { resolveRepoRoot, isImagesInstall } = require('../utils/paths');
|
|
6
6
|
const { runScript } = require('../utils/spawn');
|
|
7
7
|
|
|
8
8
|
const name = 'doctor';
|
|
9
|
-
const summary = 'Run
|
|
9
|
+
const summary = 'Run doctor checks (git or images install)';
|
|
10
10
|
|
|
11
11
|
function help() {
|
|
12
12
|
return `Usage: ragsuite-test doctor [options]
|
|
13
13
|
|
|
14
|
-
|
|
15
|
-
|
|
14
|
+
Git install: scripts/doctor.sh
|
|
15
|
+
Images install: scripts/docker-doctor-images.sh
|
|
16
16
|
|
|
17
17
|
Options:
|
|
18
|
-
--mode <docker|native>
|
|
19
|
-
--repo-root <path>
|
|
20
|
-
--dry-run
|
|
18
|
+
--mode <docker|native> Git install gate
|
|
19
|
+
--repo-root <path>
|
|
20
|
+
--dry-run
|
|
21
21
|
`;
|
|
22
22
|
}
|
|
23
23
|
|
|
@@ -26,12 +26,16 @@ function run(ctx) {
|
|
|
26
26
|
cwd: ctx.cwd,
|
|
27
27
|
repoRootFlag: ctx.globals.repoRoot,
|
|
28
28
|
});
|
|
29
|
-
const
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
29
|
+
const images = isImagesInstall(repoRoot);
|
|
30
|
+
const mode = images
|
|
31
|
+
? 'docker'
|
|
32
|
+
: resolveMode({
|
|
33
|
+
flagMode: ctx.globals.mode,
|
|
34
|
+
repoRoot,
|
|
35
|
+
env: ctx.env,
|
|
36
|
+
});
|
|
37
|
+
const script = images ? 'docker-doctor-images.sh' : 'doctor.sh';
|
|
38
|
+
return runScript(repoRoot, path.join('scripts', script), [], {
|
|
35
39
|
dryRun: ctx.globals.dryRun,
|
|
36
40
|
env: { ...ctx.env, RAGSUITE_MODE: mode },
|
|
37
41
|
});
|
package/src/commands/init.js
CHANGED
|
@@ -1,14 +1,22 @@
|
|
|
1
1
|
'use strict';
|
|
2
2
|
|
|
3
3
|
const path = require('path');
|
|
4
|
-
const { writeConfig, CONFIG_DIR } = require('../utils/config');
|
|
5
|
-
const {
|
|
4
|
+
const { writeConfig, CONFIG_DIR, readConfig } = require('../utils/config');
|
|
5
|
+
const {
|
|
6
|
+
ensureRagsuiteDir,
|
|
7
|
+
resolveRepoRoot,
|
|
8
|
+
isImagesInstall,
|
|
9
|
+
looksLikeRepoRoot,
|
|
10
|
+
isDirEmptyOrMissing,
|
|
11
|
+
} = require('../utils/paths');
|
|
12
|
+
const { setActiveInstall } = require('../utils/global-config');
|
|
6
13
|
const { assertSupportedInstall, installHint } = require('../utils/distribution');
|
|
7
14
|
const {
|
|
8
15
|
DEFAULT_GIT_URL,
|
|
9
16
|
defaultInstallDir,
|
|
10
17
|
cloneGitToInstallDir,
|
|
11
18
|
} = require('../utils/git-install');
|
|
19
|
+
const { materializeImagesInstall } = require('../utils/images-install');
|
|
12
20
|
const { detectOs } = require('../utils/os-detect');
|
|
13
21
|
const {
|
|
14
22
|
printPrereqs,
|
|
@@ -20,57 +28,76 @@ const {
|
|
|
20
28
|
writeInstallEnv,
|
|
21
29
|
} = require('../utils/env-file');
|
|
22
30
|
const { assertPortsFree } = require('../utils/port');
|
|
23
|
-
const { info, error } = require('../utils/log');
|
|
31
|
+
const { info, warn, error } = require('../utils/log');
|
|
24
32
|
|
|
25
33
|
const name = 'init';
|
|
26
|
-
const summary = '
|
|
34
|
+
const summary = 'First-time install (git or images). Safe if already installed.';
|
|
27
35
|
|
|
28
|
-
function printSuccess(repoRoot, mode) {
|
|
36
|
+
function printSuccess(repoRoot, mode, source) {
|
|
29
37
|
info('');
|
|
30
38
|
info('=== Install complete ===');
|
|
31
39
|
info(` Install dir : ${repoRoot}`);
|
|
40
|
+
info(` Source : ${source}`);
|
|
32
41
|
info(` Mode : ${mode}`);
|
|
33
|
-
info(` Config : ${path.join(repoRoot, CONFIG_DIR, 'config.json')}`);
|
|
34
42
|
info('');
|
|
35
43
|
info(' API http://localhost:9090');
|
|
36
|
-
if (mode === '
|
|
37
|
-
info(' Web http://localhost:
|
|
44
|
+
if (source === 'images' || mode === 'docker') {
|
|
45
|
+
info(' Web http://localhost:9091');
|
|
38
46
|
} else {
|
|
39
|
-
info(' Web http://localhost:
|
|
47
|
+
info(' Web http://localhost:9191');
|
|
40
48
|
}
|
|
41
49
|
info('');
|
|
42
|
-
info('Next
|
|
43
|
-
info(
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
} else {
|
|
47
|
-
info(' 2. Open http://localhost:9091 and bootstrap the first admin');
|
|
48
|
-
}
|
|
49
|
-
info(` 3. ragsuite-test doctor --repo-root ${repoRoot}`);
|
|
50
|
+
info('Next (no --repo-root needed):');
|
|
51
|
+
info(' ragsuite-test start');
|
|
52
|
+
info(' ragsuite-test stop');
|
|
53
|
+
info(' ragsuite-test update # later upgrades, keeps data');
|
|
50
54
|
info('');
|
|
51
55
|
info(installHint());
|
|
52
56
|
}
|
|
53
57
|
|
|
58
|
+
function printAlreadyInstalled(repoRoot) {
|
|
59
|
+
const cfg = readConfig(repoRoot);
|
|
60
|
+
setActiveInstall(repoRoot);
|
|
61
|
+
info('');
|
|
62
|
+
info('=== Already installed ===');
|
|
63
|
+
info(` ${repoRoot}`);
|
|
64
|
+
if (cfg) info(` source=${cfg.source} mode=${cfg.mode}`);
|
|
65
|
+
info('');
|
|
66
|
+
info('Use:');
|
|
67
|
+
info(' ragsuite-test start # run the app');
|
|
68
|
+
info(' ragsuite-test update # upgrade code/images (keeps .env + data)');
|
|
69
|
+
info(' ragsuite-test stop');
|
|
70
|
+
info('');
|
|
71
|
+
info('Do NOT run init --force unless you intend to wipe and reinstall.');
|
|
72
|
+
}
|
|
73
|
+
|
|
74
|
+
function isInitializedInstall(dir) {
|
|
75
|
+
return looksLikeRepoRoot(dir) && Boolean(readConfig(dir));
|
|
76
|
+
}
|
|
77
|
+
|
|
54
78
|
function help() {
|
|
55
79
|
return `Usage: ragsuite-test init [options]
|
|
56
80
|
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
--
|
|
71
|
-
--
|
|
72
|
-
--
|
|
73
|
-
--
|
|
81
|
+
First-time setup only (npm-style):
|
|
82
|
+
|
|
83
|
+
ragsuite-test init # git clone → ~/ragsuite-test
|
|
84
|
+
ragsuite-test init --from-images # Docker images only (no app source)
|
|
85
|
+
|
|
86
|
+
If already installed, init exits OK and tells you to start/update.
|
|
87
|
+
|
|
88
|
+
Day-to-day:
|
|
89
|
+
ragsuite-test start
|
|
90
|
+
ragsuite-test update
|
|
91
|
+
ragsuite-test stop
|
|
92
|
+
|
|
93
|
+
Options:
|
|
94
|
+
--from-images Images-only install
|
|
95
|
+
--from-git [url] Clone URL (default public repo)
|
|
96
|
+
--repo-root <path> Point at an existing checkout
|
|
97
|
+
--install-dir <path> Default: ~/ragsuite-test
|
|
98
|
+
--mode <docker|native> Git install only
|
|
99
|
+
--force Wipe install dir and reinstall (destructive)
|
|
100
|
+
--yes, -y Non-interactive
|
|
74
101
|
`;
|
|
75
102
|
}
|
|
76
103
|
|
|
@@ -91,9 +118,10 @@ function resolveLlmOverride(g, env) {
|
|
|
91
118
|
return null;
|
|
92
119
|
}
|
|
93
120
|
|
|
94
|
-
function countSources(fromGit, repoRootFlag) {
|
|
121
|
+
function countSources(fromGit, fromImages, repoRootFlag) {
|
|
95
122
|
let n = 0;
|
|
96
123
|
if (fromGit !== null && fromGit !== undefined) n += 1;
|
|
124
|
+
if (fromImages) n += 1;
|
|
97
125
|
if (repoRootFlag) n += 1;
|
|
98
126
|
return n;
|
|
99
127
|
}
|
|
@@ -103,12 +131,12 @@ async function run(ctx) {
|
|
|
103
131
|
const g = ctx.globals;
|
|
104
132
|
|
|
105
133
|
if (g.fromRelease) {
|
|
106
|
-
error('--from-release is not supported.
|
|
134
|
+
error('--from-release is not supported.');
|
|
107
135
|
return 1;
|
|
108
136
|
}
|
|
109
137
|
|
|
110
|
-
if (countSources(g.fromGit, g.repoRoot) > 1) {
|
|
111
|
-
error('Use only one of --from-git or --repo-root');
|
|
138
|
+
if (countSources(g.fromGit, g.fromImages, g.repoRoot) > 1) {
|
|
139
|
+
error('Use only one of --from-images, --from-git, or --repo-root');
|
|
112
140
|
return 1;
|
|
113
141
|
}
|
|
114
142
|
|
|
@@ -116,20 +144,60 @@ async function run(ctx) {
|
|
|
116
144
|
info(`OS: ${osInfo.label} (${osInfo.platform})`);
|
|
117
145
|
|
|
118
146
|
let fromGit = g.fromGit;
|
|
147
|
+
let fromImages = Boolean(g.fromImages);
|
|
119
148
|
let repoRootFlag = g.repoRoot;
|
|
120
|
-
const installDir = g.installDir || defaultInstallDir();
|
|
149
|
+
const installDir = path.resolve(g.installDir || defaultInstallDir());
|
|
150
|
+
|
|
151
|
+
// Existing configured install → friendly no-op (like other npm CLIs)
|
|
152
|
+
if (!g.force) {
|
|
153
|
+
if (repoRootFlag && isInitializedInstall(path.resolve(repoRootFlag))) {
|
|
154
|
+
printAlreadyInstalled(path.resolve(repoRootFlag));
|
|
155
|
+
return 0;
|
|
156
|
+
}
|
|
157
|
+
if (!repoRootFlag && isInitializedInstall(installDir)) {
|
|
158
|
+
printAlreadyInstalled(installDir);
|
|
159
|
+
return 0;
|
|
160
|
+
}
|
|
161
|
+
}
|
|
121
162
|
|
|
122
|
-
|
|
123
|
-
if (fromGit === null && !repoRootFlag) {
|
|
163
|
+
if (!fromImages && fromGit === null && !repoRootFlag) {
|
|
124
164
|
fromGit = '';
|
|
125
|
-
info(`
|
|
126
|
-
info(`
|
|
165
|
+
info(`First-time install (git): ${DEFAULT_GIT_URL}`);
|
|
166
|
+
info(` → ${installDir}`);
|
|
167
|
+
}
|
|
168
|
+
if (fromImages) {
|
|
169
|
+
info(`First-time install (images, no source): → ${installDir}`);
|
|
127
170
|
}
|
|
128
171
|
|
|
129
|
-
|
|
130
|
-
|
|
172
|
+
// Checkout already on disk but never inited → wire config/.env, do not re-clone
|
|
173
|
+
if (
|
|
174
|
+
!g.force &&
|
|
175
|
+
!repoRootFlag &&
|
|
176
|
+
!fromImages &&
|
|
177
|
+
looksLikeRepoRoot(installDir) &&
|
|
178
|
+
!readConfig(installDir)
|
|
179
|
+
) {
|
|
180
|
+
info(`Found existing source at ${installDir} — finishing setup (no re-clone).`);
|
|
181
|
+
repoRootFlag = installDir;
|
|
182
|
+
fromGit = null;
|
|
183
|
+
}
|
|
184
|
+
|
|
185
|
+
if (!g.force && !isDirEmptyOrMissing(installDir) && !looksLikeRepoRoot(installDir) && !repoRootFlag) {
|
|
186
|
+
error(
|
|
187
|
+
[
|
|
188
|
+
`Directory exists but is not a RAGSuite install: ${installDir}`,
|
|
189
|
+
' Fix leftover files, or:',
|
|
190
|
+
' ragsuite-test init --force # wipe & reinstall (destructive)',
|
|
191
|
+
' ragsuite-test init --install-dir ~/ragsuite-test-2',
|
|
192
|
+
].join('\n'),
|
|
193
|
+
);
|
|
194
|
+
return 1;
|
|
195
|
+
}
|
|
131
196
|
|
|
132
|
-
|
|
197
|
+
let mode = fromImages ? 'docker' : g.mode || resolvePreferredMode(null);
|
|
198
|
+
info(`Run mode: ${mode}`);
|
|
199
|
+
|
|
200
|
+
const needGit = !fromImages && fromGit !== null && fromGit !== undefined;
|
|
133
201
|
if (!printPrereqs(mode, { needGit })) {
|
|
134
202
|
error('Fix prerequisites above and re-run init');
|
|
135
203
|
return 1;
|
|
@@ -137,7 +205,6 @@ async function run(ctx) {
|
|
|
137
205
|
|
|
138
206
|
const jwtSecret = generateJwtSecret();
|
|
139
207
|
info(`JWT_SECRET_KEY will be auto-generated (…${jwtSecret.slice(-8)})`);
|
|
140
|
-
info('SMTP + LLM: from .env.example into .env (no prompts).');
|
|
141
208
|
|
|
142
209
|
const llmKey = resolveLlmOverride(g, ctx.env);
|
|
143
210
|
const smtp = optionalSmtpOverrides(g, ctx.env);
|
|
@@ -155,22 +222,22 @@ async function run(ctx) {
|
|
|
155
222
|
let source = 'checkout';
|
|
156
223
|
|
|
157
224
|
try {
|
|
158
|
-
if (
|
|
225
|
+
if (fromImages) {
|
|
226
|
+
const result = materializeImagesInstall({ installDir, force: g.force });
|
|
227
|
+
repoRoot = result.repoRoot;
|
|
228
|
+
source = 'images';
|
|
229
|
+
} else if (fromGit !== null && fromGit !== undefined) {
|
|
159
230
|
const url = fromGit === '' ? DEFAULT_GIT_URL : fromGit;
|
|
160
|
-
|
|
161
|
-
const result = cloneGitToInstallDir(url, {
|
|
162
|
-
installDir,
|
|
163
|
-
force: g.force,
|
|
164
|
-
});
|
|
231
|
+
const result = cloneGitToInstallDir(url, { installDir, force: g.force });
|
|
165
232
|
repoRoot = result.repoRoot;
|
|
166
233
|
source = 'git';
|
|
167
|
-
info(`Installed app at ${repoRoot}`);
|
|
168
234
|
} else {
|
|
169
235
|
repoRoot = resolveRepoRoot({
|
|
170
236
|
cwd: ctx.cwd,
|
|
171
237
|
repoRootFlag,
|
|
172
238
|
env: ctx.env,
|
|
173
239
|
});
|
|
240
|
+
if (isImagesInstall(repoRoot)) source = 'images';
|
|
174
241
|
}
|
|
175
242
|
} catch (err) {
|
|
176
243
|
error(err.message || String(err));
|
|
@@ -184,6 +251,7 @@ async function run(ctx) {
|
|
|
184
251
|
repoRoot,
|
|
185
252
|
installDir: repoRoot,
|
|
186
253
|
});
|
|
254
|
+
setActiveInstall(repoRoot);
|
|
187
255
|
|
|
188
256
|
try {
|
|
189
257
|
writeInstallEnv(repoRoot, {
|
|
@@ -193,17 +261,19 @@ async function run(ctx) {
|
|
|
193
261
|
smtp,
|
|
194
262
|
});
|
|
195
263
|
} catch (err) {
|
|
196
|
-
if (err.code === 'ENV_EXISTS'
|
|
264
|
+
if (err.code === 'ENV_EXISTS') {
|
|
265
|
+
warn('.env already present — keeping it (use --force only if you want to regenerate).');
|
|
266
|
+
} else if (err.code === 'ENV_INCOMPLETE') {
|
|
197
267
|
error(err.message);
|
|
198
268
|
return 1;
|
|
269
|
+
} else {
|
|
270
|
+
error(err.message || String(err));
|
|
271
|
+
return 1;
|
|
199
272
|
}
|
|
200
|
-
error(err.message || String(err));
|
|
201
|
-
return 1;
|
|
202
273
|
}
|
|
203
274
|
|
|
204
|
-
info(`
|
|
205
|
-
|
|
206
|
-
printSuccess(repoRoot, mode);
|
|
275
|
+
info(`Config: mode=${cfg.mode} source=${cfg.source}`);
|
|
276
|
+
printSuccess(repoRoot, mode, source);
|
|
207
277
|
return 0;
|
|
208
278
|
}
|
|
209
279
|
|
package/src/commands/start.js
CHANGED
|
@@ -2,25 +2,25 @@
|
|
|
2
2
|
|
|
3
3
|
const path = require('path');
|
|
4
4
|
const { resolveMode } = require('../utils/config');
|
|
5
|
-
const { resolveRepoRoot } = require('../utils/paths');
|
|
5
|
+
const { resolveRepoRoot, isImagesInstall } = require('../utils/paths');
|
|
6
6
|
const { runScript } = require('../utils/spawn');
|
|
7
7
|
const { assertApiPortFree } = require('../utils/port');
|
|
8
8
|
const { error } = require('../utils/log');
|
|
9
9
|
|
|
10
10
|
const name = 'start';
|
|
11
|
-
const summary = 'Start stack
|
|
11
|
+
const summary = 'Start stack (git scripts or images pull-only)';
|
|
12
12
|
|
|
13
13
|
function help() {
|
|
14
|
-
return `Usage: ragsuite-test start [options]
|
|
14
|
+
return `Usage: ragsuite-test start [options]
|
|
15
15
|
|
|
16
|
-
|
|
17
|
-
|
|
16
|
+
Git install: scripts/docker-start.sh or native-start.sh
|
|
17
|
+
Images install (--from-images): scripts/docker-start-images.sh (pull, no build)
|
|
18
18
|
|
|
19
19
|
Options:
|
|
20
|
-
--mode <docker|native> Override
|
|
21
|
-
--repo-root <path>
|
|
22
|
-
--dry-run Print
|
|
23
|
-
--detach, -d
|
|
20
|
+
--mode <docker|native> Override (git install; images always docker)
|
|
21
|
+
--repo-root <path> Install root
|
|
22
|
+
--dry-run Print script path and exit 0
|
|
23
|
+
--detach, -d Detached start
|
|
24
24
|
`;
|
|
25
25
|
}
|
|
26
26
|
|
|
@@ -29,14 +29,22 @@ async function run(ctx) {
|
|
|
29
29
|
cwd: ctx.cwd,
|
|
30
30
|
repoRootFlag: ctx.globals.repoRoot,
|
|
31
31
|
});
|
|
32
|
-
const
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
32
|
+
const images = isImagesInstall(repoRoot);
|
|
33
|
+
const mode = images
|
|
34
|
+
? 'docker'
|
|
35
|
+
: resolveMode({
|
|
36
|
+
flagMode: ctx.globals.mode,
|
|
37
|
+
repoRoot,
|
|
38
|
+
env: ctx.env,
|
|
39
|
+
});
|
|
40
|
+
|
|
41
|
+
let scriptName;
|
|
42
|
+
if (images) {
|
|
43
|
+
scriptName = 'docker-start-images.sh';
|
|
44
|
+
} else {
|
|
45
|
+
scriptName = mode === 'native' ? 'native-start.sh' : 'docker-start.sh';
|
|
46
|
+
}
|
|
37
47
|
|
|
38
|
-
const scriptName = mode === 'native' ? 'native-start.sh' : 'docker-start.sh';
|
|
39
|
-
const rel = path.join('scripts', scriptName);
|
|
40
48
|
const forward = normalizeStartArgs(ctx.commandArgs);
|
|
41
49
|
|
|
42
50
|
if (!ctx.globals.dryRun) {
|
|
@@ -48,7 +56,7 @@ async function run(ctx) {
|
|
|
48
56
|
}
|
|
49
57
|
}
|
|
50
58
|
|
|
51
|
-
return runScript(repoRoot,
|
|
59
|
+
return runScript(repoRoot, path.join('scripts', scriptName), forward, {
|
|
52
60
|
dryRun: ctx.globals.dryRun,
|
|
53
61
|
env: { ...ctx.env, RAGSUITE_MODE: mode },
|
|
54
62
|
});
|
package/src/commands/stop.js
CHANGED
|
@@ -2,22 +2,23 @@
|
|
|
2
2
|
|
|
3
3
|
const path = require('path');
|
|
4
4
|
const { resolveMode } = require('../utils/config');
|
|
5
|
-
const { resolveRepoRoot } = require('../utils/paths');
|
|
5
|
+
const { resolveRepoRoot, isImagesInstall } = require('../utils/paths');
|
|
6
6
|
const { runScript } = require('../utils/spawn');
|
|
7
7
|
|
|
8
8
|
const name = 'stop';
|
|
9
|
-
const summary = 'Stop stack
|
|
9
|
+
const summary = 'Stop stack (git scripts or images pull-only)';
|
|
10
10
|
|
|
11
11
|
function help() {
|
|
12
12
|
return `Usage: ragsuite-test stop [options]
|
|
13
13
|
|
|
14
|
-
|
|
15
|
-
|
|
14
|
+
Git install: docker-stop.sh / native-stop.sh
|
|
15
|
+
Images install: docker-stop-images.sh
|
|
16
|
+
Never wipes Docker volumes.
|
|
16
17
|
|
|
17
18
|
Options:
|
|
18
|
-
--mode <docker|native> Override
|
|
19
|
-
--repo-root <path>
|
|
20
|
-
--dry-run Print
|
|
19
|
+
--mode <docker|native> Override (git install)
|
|
20
|
+
--repo-root <path> Install root
|
|
21
|
+
--dry-run Print script path and exit 0
|
|
21
22
|
`;
|
|
22
23
|
}
|
|
23
24
|
|
|
@@ -26,12 +27,21 @@ function run(ctx) {
|
|
|
26
27
|
cwd: ctx.cwd,
|
|
27
28
|
repoRootFlag: ctx.globals.repoRoot,
|
|
28
29
|
});
|
|
29
|
-
const
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
30
|
+
const images = isImagesInstall(repoRoot);
|
|
31
|
+
const mode = images
|
|
32
|
+
? 'docker'
|
|
33
|
+
: resolveMode({
|
|
34
|
+
flagMode: ctx.globals.mode,
|
|
35
|
+
repoRoot,
|
|
36
|
+
env: ctx.env,
|
|
37
|
+
});
|
|
38
|
+
|
|
39
|
+
const scriptName = images
|
|
40
|
+
? 'docker-stop-images.sh'
|
|
41
|
+
: mode === 'native'
|
|
42
|
+
? 'native-stop.sh'
|
|
43
|
+
: 'docker-stop.sh';
|
|
44
|
+
|
|
35
45
|
return runScript(repoRoot, path.join('scripts', scriptName), [], {
|
|
36
46
|
dryRun: ctx.globals.dryRun,
|
|
37
47
|
env: { ...ctx.env, RAGSUITE_MODE: mode },
|