@scalebun/cli 1.0.0 → 1.4.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/lib/api/client.d.ts +8 -0
- package/lib/api/client.d.ts.map +1 -1
- package/lib/api/client.js +70 -2
- package/lib/api/client.js.map +1 -1
- package/lib/commands/ci-init.d.ts +0 -6
- package/lib/commands/ci-init.d.ts.map +1 -1
- package/lib/commands/ci-init.js +172 -28
- package/lib/commands/ci-init.js.map +1 -1
- package/lib/commands/doctor.d.ts +8 -0
- package/lib/commands/doctor.d.ts.map +1 -0
- package/lib/commands/doctor.js +252 -0
- package/lib/commands/doctor.js.map +1 -0
- package/lib/commands/login.d.ts +28 -4
- package/lib/commands/login.d.ts.map +1 -1
- package/lib/commands/login.js +132 -51
- package/lib/commands/login.js.map +1 -1
- package/lib/commands/ota-bundle.d.ts.map +1 -1
- package/lib/commands/ota-bundle.js +2 -0
- package/lib/commands/ota-bundle.js.map +1 -1
- package/lib/commands/ota-delete-bundle.d.ts +8 -0
- package/lib/commands/ota-delete-bundle.d.ts.map +1 -1
- package/lib/commands/ota-delete-bundle.js +60 -0
- package/lib/commands/ota-delete-bundle.js.map +1 -1
- package/lib/commands/ota-keys.d.ts +14 -0
- package/lib/commands/ota-keys.d.ts.map +1 -0
- package/lib/commands/ota-keys.js +200 -0
- package/lib/commands/ota-keys.js.map +1 -0
- package/lib/commands/ota-publish.d.ts +10 -0
- package/lib/commands/ota-publish.d.ts.map +1 -1
- package/lib/commands/ota-publish.js +251 -34
- package/lib/commands/ota-publish.js.map +1 -1
- package/lib/commands/ota-rollout.d.ts +3 -0
- package/lib/commands/ota-rollout.d.ts.map +1 -0
- package/lib/commands/ota-rollout.js +235 -0
- package/lib/commands/ota-rollout.js.map +1 -0
- package/lib/commands/quickstart.d.ts +4 -0
- package/lib/commands/quickstart.d.ts.map +1 -0
- package/lib/commands/quickstart.js +274 -0
- package/lib/commands/quickstart.js.map +1 -0
- package/lib/index.js +20 -1
- package/lib/index.js.map +1 -1
- package/lib/utils/bundle.d.ts +86 -0
- package/lib/utils/bundle.d.ts.map +1 -1
- package/lib/utils/bundle.js +244 -14
- package/lib/utils/bundle.js.map +1 -1
- package/lib/utils/credentials.d.ts +12 -1
- package/lib/utils/credentials.d.ts.map +1 -1
- package/lib/utils/credentials.js +40 -1
- package/lib/utils/credentials.js.map +1 -1
- package/lib/utils/transportSecurity.d.ts +36 -0
- package/lib/utils/transportSecurity.d.ts.map +1 -0
- package/lib/utils/transportSecurity.js +74 -0
- package/lib/utils/transportSecurity.js.map +1 -0
- package/lib/utils/ui.d.ts.map +1 -1
- package/lib/utils/ui.js +2 -0
- package/lib/utils/ui.js.map +1 -1
- package/package.json +1 -1
package/lib/api/client.d.ts
CHANGED
|
@@ -12,8 +12,16 @@ export declare class ApiClient {
|
|
|
12
12
|
get<T = unknown>(path: string): Promise<T>;
|
|
13
13
|
/** POST request — sends JSON body, returns parsed JSON. */
|
|
14
14
|
post<T = unknown>(path: string, body?: unknown): Promise<T>;
|
|
15
|
+
/** PATCH request — sends JSON body, returns parsed JSON. */
|
|
16
|
+
patch<T = unknown>(path: string, body?: unknown): Promise<T>;
|
|
15
17
|
/** DELETE request — returns parsed JSON. */
|
|
16
18
|
delete<T = unknown>(path: string): Promise<T>;
|
|
19
|
+
/**
|
|
20
|
+
* Multipart POST to a backend path with extra headers (symbol uploads).
|
|
21
|
+
* Bearer auth is still attached; endpoint-specific headers (e.g. the SDK
|
|
22
|
+
* secret key) ride alongside it.
|
|
23
|
+
*/
|
|
24
|
+
postMultipart(path: string, body: Buffer, contentType: string, extraHeaders?: Record<string, string>): Promise<unknown>;
|
|
17
25
|
/** Upload raw bytes via PUT to an arbitrary URL (presigned S3/R2). */
|
|
18
26
|
putBytes(url: string, data: Buffer, contentType: string): Promise<void>;
|
|
19
27
|
private request;
|
package/lib/api/client.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"client.d.ts","sourceRoot":"","sources":["../../src/api/client.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,sBAAsB,CAAC;
|
|
1
|
+
{"version":3,"file":"client.d.ts","sourceRoot":"","sources":["../../src/api/client.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,sBAAsB,CAAC;AAGxD;;;;GAIG;AACH,qBAAa,SAAS;IACpB,OAAO,CAAC,QAAQ,CAAC,MAAM,CAAS;IAChC,OAAO,CAAC,QAAQ,CAAC,KAAK,CAAS;gBAEnB,KAAK,EAAE,WAAW;IAU9B,yCAAyC;IACnC,GAAG,CAAC,CAAC,GAAG,OAAO,EAAE,IAAI,EAAE,MAAM,GAAG,OAAO,CAAC,CAAC,CAAC;IAIhD,2DAA2D;IACrD,IAAI,CAAC,CAAC,GAAG,OAAO,EAAE,IAAI,EAAE,MAAM,EAAE,IAAI,CAAC,EAAE,OAAO,GAAG,OAAO,CAAC,CAAC,CAAC;IAIjE,4DAA4D;IACtD,KAAK,CAAC,CAAC,GAAG,OAAO,EAAE,IAAI,EAAE,MAAM,EAAE,IAAI,CAAC,EAAE,OAAO,GAAG,OAAO,CAAC,CAAC,CAAC;IAIlE,4CAA4C;IACtC,MAAM,CAAC,CAAC,GAAG,OAAO,EAAE,IAAI,EAAE,MAAM,GAAG,OAAO,CAAC,CAAC,CAAC;IAInD;;;;OAIG;IACG,aAAa,CACjB,IAAI,EAAE,MAAM,EACZ,IAAI,EAAE,MAAM,EACZ,WAAW,EAAE,MAAM,EACnB,YAAY,GAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAM,GACxC,OAAO,CAAC,OAAO,CAAC;IA8CnB,sEAAsE;IAChE,QAAQ,CAAC,GAAG,EAAE,MAAM,EAAE,IAAI,EAAE,MAAM,EAAE,WAAW,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC;YA6C/D,OAAO;CAuEtB"}
|
package/lib/api/client.js
CHANGED
|
@@ -36,6 +36,7 @@ Object.defineProperty(exports, "__esModule", { value: true });
|
|
|
36
36
|
exports.ApiClient = void 0;
|
|
37
37
|
const https = __importStar(require("https"));
|
|
38
38
|
const http = __importStar(require("http"));
|
|
39
|
+
const transportSecurity_1 = require("../utils/transportSecurity");
|
|
39
40
|
/**
|
|
40
41
|
* Minimal HTTP client for the Scalebun backend API.
|
|
41
42
|
* Uses PAT-based auth (Authorization: Bearer <token>).
|
|
@@ -43,8 +44,12 @@ const http = __importStar(require("http"));
|
|
|
43
44
|
*/
|
|
44
45
|
class ApiClient {
|
|
45
46
|
constructor(creds) {
|
|
46
|
-
//
|
|
47
|
-
|
|
47
|
+
// Every request below attaches `Authorization: Bearer <token>`, so the
|
|
48
|
+
// scheme is a security decision, not a formatting one. Refuse a plaintext
|
|
49
|
+
// endpoint here — at construction, before any socket is opened — rather
|
|
50
|
+
// than at each call site, so no future method can quietly skip the check.
|
|
51
|
+
// Loopback is exempt; see transportSecurity.ts.
|
|
52
|
+
this.apiUrl = (0, transportSecurity_1.assertSecureApiUrl)(creds.apiUrl);
|
|
48
53
|
this.token = creds.token;
|
|
49
54
|
}
|
|
50
55
|
/** GET request — returns parsed JSON. */
|
|
@@ -55,10 +60,63 @@ class ApiClient {
|
|
|
55
60
|
async post(path, body) {
|
|
56
61
|
return this.request('POST', path, body);
|
|
57
62
|
}
|
|
63
|
+
/** PATCH request — sends JSON body, returns parsed JSON. */
|
|
64
|
+
async patch(path, body) {
|
|
65
|
+
return this.request('PATCH', path, body);
|
|
66
|
+
}
|
|
58
67
|
/** DELETE request — returns parsed JSON. */
|
|
59
68
|
async delete(path) {
|
|
60
69
|
return this.request('DELETE', path);
|
|
61
70
|
}
|
|
71
|
+
/**
|
|
72
|
+
* Multipart POST to a backend path with extra headers (symbol uploads).
|
|
73
|
+
* Bearer auth is still attached; endpoint-specific headers (e.g. the SDK
|
|
74
|
+
* secret key) ride alongside it.
|
|
75
|
+
*/
|
|
76
|
+
async postMultipart(path, body, contentType, extraHeaders = {}) {
|
|
77
|
+
return new Promise((resolve, reject) => {
|
|
78
|
+
const parsed = new URL(`${this.apiUrl}${path}`);
|
|
79
|
+
const transport = parsed.protocol === 'https:' ? https : http;
|
|
80
|
+
const req = transport.request({
|
|
81
|
+
hostname: parsed.hostname,
|
|
82
|
+
port: parsed.port || undefined,
|
|
83
|
+
path: parsed.pathname + parsed.search,
|
|
84
|
+
method: 'POST',
|
|
85
|
+
headers: {
|
|
86
|
+
Authorization: `Bearer ${this.token}`,
|
|
87
|
+
Accept: 'application/json',
|
|
88
|
+
'Content-Type': contentType,
|
|
89
|
+
'Content-Length': body.length,
|
|
90
|
+
...extraHeaders,
|
|
91
|
+
},
|
|
92
|
+
timeout: 120000,
|
|
93
|
+
}, (res) => {
|
|
94
|
+
const chunks = [];
|
|
95
|
+
res.on('data', (c) => chunks.push(c));
|
|
96
|
+
res.on('end', () => {
|
|
97
|
+
const raw = Buffer.concat(chunks).toString('utf-8');
|
|
98
|
+
if (res.statusCode && res.statusCode >= 200 && res.statusCode < 300) {
|
|
99
|
+
try {
|
|
100
|
+
resolve(JSON.parse(raw));
|
|
101
|
+
}
|
|
102
|
+
catch {
|
|
103
|
+
resolve(raw);
|
|
104
|
+
}
|
|
105
|
+
}
|
|
106
|
+
else {
|
|
107
|
+
reject(new Error(`API error (HTTP ${res.statusCode}): ${raw.slice(0, 300)}`));
|
|
108
|
+
}
|
|
109
|
+
});
|
|
110
|
+
});
|
|
111
|
+
req.on('error', reject);
|
|
112
|
+
req.on('timeout', () => {
|
|
113
|
+
req.destroy();
|
|
114
|
+
reject(new Error('Multipart upload timed out'));
|
|
115
|
+
});
|
|
116
|
+
req.write(body);
|
|
117
|
+
req.end();
|
|
118
|
+
});
|
|
119
|
+
}
|
|
62
120
|
/** Upload raw bytes via PUT to an arbitrary URL (presigned S3/R2). */
|
|
63
121
|
async putBytes(url, data, contentType) {
|
|
64
122
|
return new Promise((resolve, reject) => {
|
|
@@ -131,6 +189,16 @@ class ApiClient {
|
|
|
131
189
|
resolve(raw);
|
|
132
190
|
}
|
|
133
191
|
}
|
|
192
|
+
else if (res.statusCode === 401) {
|
|
193
|
+
// The most common cause by far is an expired credential — the old
|
|
194
|
+
// login flow stored 15-minute session JWTs, and CI secrets rot.
|
|
195
|
+
// A bare "Unauthorized" cost real debugging time during the first
|
|
196
|
+
// device run; the fix is one command, so name it.
|
|
197
|
+
reject(new Error(`API error (HTTP 401): ${raw.slice(0, 200)}\n` +
|
|
198
|
+
` Your credential is invalid or has expired.\n` +
|
|
199
|
+
` → Locally: run \`scalebun login\`\n` +
|
|
200
|
+
` → In CI: refresh the SCALEBUN_TOKEN secret (create one in the dashboard under Settings → Access Tokens)`));
|
|
201
|
+
}
|
|
134
202
|
else {
|
|
135
203
|
reject(new Error(`API error (HTTP ${res.statusCode}): ${raw.slice(0, 500)}`));
|
|
136
204
|
}
|
package/lib/api/client.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"client.js","sourceRoot":"","sources":["../../src/api/client.ts"],"names":[],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AAAA,6CAA+B;AAC/B,2CAA6B;
|
|
1
|
+
{"version":3,"file":"client.js","sourceRoot":"","sources":["../../src/api/client.ts"],"names":[],"mappings":"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"}
|
|
@@ -1,9 +1,3 @@
|
|
|
1
1
|
import { Command } from 'commander';
|
|
2
|
-
/**
|
|
3
|
-
* `scalebun ci init` — Sprint 12 (S12-CLI-1).
|
|
4
|
-
*
|
|
5
|
-
* Generates copy-paste CI/CD workflows for GitHub Actions, Bitrise, or CircleCI:
|
|
6
|
-
* npx scalebun ci init --provider github
|
|
7
|
-
*/
|
|
8
2
|
export declare function registerCiInitCommand(program: Command): void;
|
|
9
3
|
//# sourceMappingURL=ci-init.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"ci-init.d.ts","sourceRoot":"","sources":["../../src/commands/ci-init.ts"],"names":[],"mappings":"AAEA,OAAO,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;
|
|
1
|
+
{"version":3,"file":"ci-init.d.ts","sourceRoot":"","sources":["../../src/commands/ci-init.ts"],"names":[],"mappings":"AAEA,OAAO,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AA0KpC,wBAAgB,qBAAqB,CAAC,OAAO,EAAE,OAAO,GAAG,IAAI,CAyC5D"}
|
package/lib/commands/ci-init.js
CHANGED
|
@@ -36,64 +36,208 @@ Object.defineProperty(exports, "__esModule", { value: true });
|
|
|
36
36
|
exports.registerCiInitCommand = registerCiInitCommand;
|
|
37
37
|
const fs = __importStar(require("fs"));
|
|
38
38
|
const path = __importStar(require("path"));
|
|
39
|
-
|
|
39
|
+
/**
|
|
40
|
+
* `scalebun ci init` — generate working CI/CD pipelines for OTA publishing.
|
|
41
|
+
*
|
|
42
|
+
* Credentials in CI are environment variables, no login step:
|
|
43
|
+
* SCALEBUN_TOKEN a personal access token (scalebun_pat_…) — create one in
|
|
44
|
+
* the dashboard (Settings → Access Tokens) or via
|
|
45
|
+
* `scalebun login` locally and copy from the output
|
|
46
|
+
* SCALEBUN_API_URL the backend API base, e.g. https://api.scalebun.com/api/v1
|
|
47
|
+
*
|
|
48
|
+
* `readCredentials()` picks both up automatically, so every command that works
|
|
49
|
+
* locally works headless: publish, rollout, pause, rollback.
|
|
50
|
+
*/
|
|
51
|
+
const GITHUB_ACTIONS_WORKFLOW = `name: Scalebun OTA
|
|
40
52
|
|
|
41
53
|
on:
|
|
42
54
|
push:
|
|
43
|
-
branches: [
|
|
55
|
+
branches: [main]
|
|
56
|
+
# Manual controls from the Actions tab — staged rollout without a laptop.
|
|
57
|
+
workflow_dispatch:
|
|
58
|
+
inputs:
|
|
59
|
+
action:
|
|
60
|
+
description: What to do
|
|
61
|
+
type: choice
|
|
62
|
+
options: [publish, rollout, pause, rollback]
|
|
63
|
+
default: publish
|
|
64
|
+
percent:
|
|
65
|
+
description: Rollout percent (rollout action only)
|
|
66
|
+
default: '100'
|
|
67
|
+
|
|
68
|
+
env:
|
|
69
|
+
# Create a PAT in the Scalebun dashboard (Settings -> Access Tokens) and add
|
|
70
|
+
# both values as repository secrets. Session JWTs expire in minutes - always
|
|
71
|
+
# use a scalebun_pat_... token here.
|
|
72
|
+
SCALEBUN_TOKEN: \${{ secrets.SCALEBUN_TOKEN }}
|
|
73
|
+
SCALEBUN_API_URL: \${{ secrets.SCALEBUN_API_URL }}
|
|
74
|
+
SCALEBUN_APP_ID: \${{ secrets.SCALEBUN_APP_ID }}
|
|
75
|
+
# Required by --sourcemap: without it the map uploads but is never
|
|
76
|
+
# registered for symbolication, so production stack traces stay minified.
|
|
77
|
+
SCALEBUN_SDK_SECRET: \${{ secrets.SCALEBUN_SDK_SECRET }}
|
|
44
78
|
|
|
45
79
|
jobs:
|
|
46
|
-
|
|
80
|
+
ota:
|
|
47
81
|
runs-on: ubuntu-latest
|
|
48
82
|
steps:
|
|
49
83
|
- uses: actions/checkout@v4
|
|
50
84
|
|
|
51
|
-
-
|
|
52
|
-
uses: actions/setup-node@v4
|
|
85
|
+
- uses: actions/setup-node@v4
|
|
53
86
|
with:
|
|
54
87
|
node-version: 20
|
|
88
|
+
cache: npm
|
|
55
89
|
|
|
56
90
|
- name: Install dependencies
|
|
57
91
|
run: npm ci
|
|
58
92
|
|
|
59
|
-
|
|
93
|
+
# ── Publish (push to main, or manual "publish") ──────────────────────
|
|
94
|
+
# Starts at 10%, NOT 100: a staged rollout is the whole point of OTA.
|
|
95
|
+
# Widen it with the manual "rollout" action once health looks clean.
|
|
96
|
+
# NOTE: the channel must already exist - a typo'd channel name is
|
|
97
|
+
# rejected rather than silently created.
|
|
98
|
+
- name: Publish OTA update
|
|
99
|
+
if: github.event_name == 'push' || inputs.action == 'publish'
|
|
100
|
+
# The commit message is UNTRUSTED input. Interpolating \${{ }} straight
|
|
101
|
+
# into run: splices it into the shell — a message with a quote breaks the
|
|
102
|
+
# job, and one with ";cmd;" executes with SCALEBUN_TOKEN in scope.
|
|
103
|
+
# Passing it through env keeps it data.
|
|
60
104
|
env:
|
|
61
|
-
|
|
105
|
+
COMMIT_MESSAGE: \${{ github.event.head_commit.message || 'Manual publish' }}
|
|
62
106
|
run: |
|
|
63
107
|
npx scalebun ota publish \\
|
|
64
|
-
--app-id
|
|
108
|
+
--app-id "$SCALEBUN_APP_ID" \\
|
|
65
109
|
--channel production \\
|
|
66
110
|
--platform android \\
|
|
67
111
|
--hermes \\
|
|
68
|
-
--sourcemap
|
|
112
|
+
--sourcemap \\
|
|
113
|
+
--rollout 10 \\
|
|
114
|
+
--release-note "$COMMIT_MESSAGE"
|
|
115
|
+
|
|
116
|
+
# ── Manual controls ──────────────────────────────────────────────────
|
|
117
|
+
- name: Widen rollout
|
|
118
|
+
if: inputs.action == 'rollout'
|
|
119
|
+
run: npx scalebun ota rollout --app-id "$SCALEBUN_APP_ID" --percent "\${{ inputs.percent }}"
|
|
120
|
+
|
|
121
|
+
- name: Pause release
|
|
122
|
+
if: inputs.action == 'pause'
|
|
123
|
+
run: npx scalebun ota pause --app-id "$SCALEBUN_APP_ID"
|
|
124
|
+
|
|
125
|
+
- name: Roll back release
|
|
126
|
+
if: inputs.action == 'rollback'
|
|
127
|
+
run: npx scalebun ota rollback --app-id "$SCALEBUN_APP_ID" --yes
|
|
69
128
|
`;
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
129
|
+
const GITLAB_CI_TEMPLATE = `# Scalebun OTA — GitLab CI
|
|
130
|
+
#
|
|
131
|
+
# Set these CI/CD variables (Settings -> CI/CD -> Variables, masked):
|
|
132
|
+
# SCALEBUN_TOKEN scalebun_pat_... (dashboard -> Settings -> Access Tokens)
|
|
133
|
+
# SCALEBUN_API_URL e.g. https://api.scalebun.com/api/v1
|
|
134
|
+
# SCALEBUN_APP_ID your application id
|
|
135
|
+
#
|
|
136
|
+
# Session JWTs expire in minutes - always use a scalebun_pat_... token in CI.
|
|
137
|
+
|
|
138
|
+
stages: [ota]
|
|
139
|
+
|
|
140
|
+
.ota-base:
|
|
141
|
+
stage: ota
|
|
142
|
+
image: node:20
|
|
143
|
+
before_script:
|
|
144
|
+
- npm ci
|
|
145
|
+
|
|
146
|
+
# Publishes on every push to the default branch, staged at 10%.
|
|
147
|
+
ota-publish:
|
|
148
|
+
extends: .ota-base
|
|
149
|
+
rules:
|
|
150
|
+
- if: '$CI_COMMIT_BRANCH == $CI_DEFAULT_BRANCH'
|
|
151
|
+
script:
|
|
152
|
+
- npx scalebun ota publish
|
|
153
|
+
--app-id "$SCALEBUN_APP_ID"
|
|
154
|
+
--channel production
|
|
155
|
+
--platform android
|
|
156
|
+
--hermes
|
|
157
|
+
--sourcemap
|
|
158
|
+
--rollout 10
|
|
159
|
+
--release-note "$CI_COMMIT_TITLE"
|
|
160
|
+
|
|
161
|
+
# Manual jobs — run from the pipeline UI once health looks clean (or bad).
|
|
162
|
+
ota-rollout-100:
|
|
163
|
+
extends: .ota-base
|
|
164
|
+
rules: [{ when: manual }]
|
|
165
|
+
script:
|
|
166
|
+
- npx scalebun ota rollout --app-id "$SCALEBUN_APP_ID" --percent 100
|
|
167
|
+
|
|
168
|
+
ota-pause:
|
|
169
|
+
extends: .ota-base
|
|
170
|
+
rules: [{ when: manual }]
|
|
171
|
+
script:
|
|
172
|
+
- npx scalebun ota pause --app-id "$SCALEBUN_APP_ID"
|
|
173
|
+
|
|
174
|
+
ota-rollback:
|
|
175
|
+
extends: .ota-base
|
|
176
|
+
rules: [{ when: manual }]
|
|
177
|
+
script:
|
|
178
|
+
- npx scalebun ota rollback --app-id "$SCALEBUN_APP_ID" --yes
|
|
179
|
+
`;
|
|
180
|
+
function writeTemplate(targetPath, content) {
|
|
181
|
+
if (fs.existsSync(targetPath)) {
|
|
182
|
+
console.error(`❌ ${path.relative(process.cwd(), targetPath)} already exists — refusing to overwrite.\n` +
|
|
183
|
+
' Delete it first if you want a fresh template.');
|
|
184
|
+
return false;
|
|
185
|
+
}
|
|
186
|
+
fs.mkdirSync(path.dirname(targetPath), { recursive: true });
|
|
187
|
+
fs.writeFileSync(targetPath, content, 'utf-8');
|
|
188
|
+
return true;
|
|
189
|
+
}
|
|
190
|
+
function printNextSteps(provider, file) {
|
|
191
|
+
console.log(`✅ ${provider} pipeline generated: ${file}`);
|
|
192
|
+
console.log('');
|
|
193
|
+
console.log('Next steps:');
|
|
194
|
+
console.log(' 1. Create an access token: dashboard → Settings → Access Tokens');
|
|
195
|
+
console.log(' (or run `scalebun login` locally and copy the scalebun_pat_… it prints)');
|
|
196
|
+
console.log(' 2. Add SCALEBUN_TOKEN, SCALEBUN_API_URL and SCALEBUN_APP_ID as CI secrets.');
|
|
197
|
+
console.log(' 3. Make sure the target channel exists (`scalebun ota channels --app-id <id>`).');
|
|
198
|
+
console.log(' 4. Push — the release goes out staged at 10%; widen it from the CI UI.');
|
|
199
|
+
}
|
|
76
200
|
function registerCiInitCommand(program) {
|
|
77
201
|
const ci = program.command('ci').description('CI/CD integration setup');
|
|
78
202
|
ci.command('init')
|
|
79
|
-
.description('Generate CI/CD pipeline
|
|
80
|
-
.option('--provider <name>', 'CI provider: github |
|
|
203
|
+
.description('Generate a CI/CD pipeline for OTA publishing (publish / rollout / pause / rollback)')
|
|
204
|
+
.option('--provider <name>', 'CI provider: github | gitlab', 'github')
|
|
81
205
|
.action((opts) => {
|
|
82
206
|
const provider = opts.provider.toLowerCase();
|
|
83
207
|
if (provider === 'github') {
|
|
84
|
-
const
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
208
|
+
const target = path.join(process.cwd(), '.github', 'workflows', 'scalebun-ota.yml');
|
|
209
|
+
if (writeTemplate(target, GITHUB_ACTIONS_WORKFLOW)) {
|
|
210
|
+
printNextSteps('GitHub Actions', path.relative(process.cwd(), target));
|
|
211
|
+
}
|
|
212
|
+
else {
|
|
213
|
+
process.exit(1);
|
|
214
|
+
}
|
|
215
|
+
}
|
|
216
|
+
else if (provider === 'gitlab') {
|
|
217
|
+
const target = path.join(process.cwd(), '.gitlab-ci.scalebun-ota.yml');
|
|
218
|
+
if (writeTemplate(target, GITLAB_CI_TEMPLATE)) {
|
|
219
|
+
printNextSteps('GitLab CI', path.relative(process.cwd(), target));
|
|
220
|
+
console.log('');
|
|
221
|
+
console.log(" Include it from your .gitlab-ci.yml:");
|
|
222
|
+
console.log(" include:");
|
|
223
|
+
console.log(" - local: .gitlab-ci.scalebun-ota.yml");
|
|
224
|
+
}
|
|
225
|
+
else {
|
|
226
|
+
process.exit(1);
|
|
227
|
+
}
|
|
92
228
|
}
|
|
93
229
|
else {
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
console.log(
|
|
230
|
+
// Any other system: the commands are plain npx calls over env-var
|
|
231
|
+
// credentials, so print the recipe instead of pretending to support it.
|
|
232
|
+
console.log(`ℹ️ No template for "${provider}" — but any CI works. Set these env vars:`);
|
|
233
|
+
console.log(' SCALEBUN_TOKEN (scalebun_pat_… from the dashboard)');
|
|
234
|
+
console.log(' SCALEBUN_API_URL (your backend, e.g. https://api.scalebun.com/api/v1)');
|
|
235
|
+
console.log('');
|
|
236
|
+
console.log(' Then script the commands directly:');
|
|
237
|
+
console.log(' npx scalebun ota publish --app-id $APP_ID --channel production --hermes --rollout 10');
|
|
238
|
+
console.log(' npx scalebun ota rollout --app-id $APP_ID --percent 100');
|
|
239
|
+
console.log(' npx scalebun ota pause --app-id $APP_ID');
|
|
240
|
+
console.log(' npx scalebun ota rollback --app-id $APP_ID --yes');
|
|
97
241
|
}
|
|
98
242
|
});
|
|
99
243
|
}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"ci-init.js","sourceRoot":"","sources":["../../src/commands/ci-init.ts"],"names":[],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
|
|
1
|
+
{"version":3,"file":"ci-init.js","sourceRoot":"","sources":["../../src/commands/ci-init.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
import { Command } from 'commander';
|
|
2
|
+
export declare function registerDoctorCommand(program: Command): void;
|
|
3
|
+
/**
|
|
4
|
+
* All doctor checks as a reusable step (`quickstart` runs it inline).
|
|
5
|
+
* Same contract as the command: exits the process on a blocking failure.
|
|
6
|
+
*/
|
|
7
|
+
export declare function runDoctor(): Promise<void>;
|
|
8
|
+
//# sourceMappingURL=doctor.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"doctor.d.ts","sourceRoot":"","sources":["../../src/commands/doctor.ts"],"names":[],"mappings":"AAEA,OAAO,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AA2DpC,wBAAgB,qBAAqB,CAAC,OAAO,EAAE,OAAO,GAAG,IAAI,CAK5D;AAED;;;GAGG;AACH,wBAAsB,SAAS,IAAI,OAAO,CAAC,IAAI,CAAC,CA6M/C"}
|