@scalebun/cli 0.1.0 → 1.0.1
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/bin/scalebun.js +2 -2
- package/lib/api/client.d.ts +2 -0
- package/lib/api/client.d.ts.map +1 -1
- package/lib/api/client.js +14 -0
- 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 +182 -47
- package/lib/commands/ci-init.js.map +1 -1
- package/lib/commands/doctor.d.ts +3 -0
- package/lib/commands/doctor.d.ts.map +1 -0
- package/lib/commands/doctor.js +243 -0
- package/lib/commands/doctor.js.map +1 -0
- package/lib/commands/login.d.ts +16 -4
- package/lib/commands/login.d.ts.map +1 -1
- package/lib/commands/login.js +83 -25
- package/lib/commands/login.js.map +1 -1
- package/lib/commands/ota-keys.d.ts +11 -0
- package/lib/commands/ota-keys.d.ts.map +1 -0
- package/lib/commands/ota-keys.js +199 -0
- package/lib/commands/ota-keys.js.map +1 -0
- package/lib/commands/ota-publish.d.ts.map +1 -1
- package/lib/commands/ota-publish.js +154 -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/index.js +11 -0
- package/lib/index.js.map +1 -1
- package/lib/utils/bundle.d.ts +53 -0
- package/lib/utils/bundle.d.ts.map +1 -1
- package/lib/utils/bundle.js +199 -14
- package/lib/utils/bundle.js.map +1 -1
- package/lib/utils/ui.js +6 -6
- package/package.json +33 -33
package/bin/scalebun.js
CHANGED
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
#!/usr/bin/env node
|
|
2
|
-
require('../lib/index.js');
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
require('../lib/index.js');
|
package/lib/api/client.d.ts
CHANGED
|
@@ -12,6 +12,8 @@ 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>;
|
|
17
19
|
/** Upload raw bytes via PUT to an arbitrary URL (presigned S3/R2). */
|
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;AAExD;;;;GAIG;AACH,qBAAa,SAAS;IACpB,OAAO,CAAC,QAAQ,CAAC,MAAM,CAAS;IAChC,OAAO,CAAC,QAAQ,CAAC,KAAK,CAAS;gBAEnB,KAAK,EAAE,WAAW;IAM9B,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,4CAA4C;IACtC,MAAM,CAAC,CAAC,GAAG,OAAO,EAAE,IAAI,EAAE,MAAM,GAAG,OAAO,CAAC,CAAC,CAAC;IAInD,sEAAsE;IAChE,QAAQ,CAAC,GAAG,EAAE,MAAM,EAAE,IAAI,EAAE,MAAM,EAAE,WAAW,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC;YA6C/D,OAAO;
|
|
1
|
+
{"version":3,"file":"client.d.ts","sourceRoot":"","sources":["../../src/api/client.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,sBAAsB,CAAC;AAExD;;;;GAIG;AACH,qBAAa,SAAS;IACpB,OAAO,CAAC,QAAQ,CAAC,MAAM,CAAS;IAChC,OAAO,CAAC,QAAQ,CAAC,KAAK,CAAS;gBAEnB,KAAK,EAAE,WAAW;IAM9B,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,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
|
@@ -55,6 +55,10 @@ class ApiClient {
|
|
|
55
55
|
async post(path, body) {
|
|
56
56
|
return this.request('POST', path, body);
|
|
57
57
|
}
|
|
58
|
+
/** PATCH request — sends JSON body, returns parsed JSON. */
|
|
59
|
+
async patch(path, body) {
|
|
60
|
+
return this.request('PATCH', path, body);
|
|
61
|
+
}
|
|
58
62
|
/** DELETE request — returns parsed JSON. */
|
|
59
63
|
async delete(path) {
|
|
60
64
|
return this.request('DELETE', path);
|
|
@@ -131,6 +135,16 @@ class ApiClient {
|
|
|
131
135
|
resolve(raw);
|
|
132
136
|
}
|
|
133
137
|
}
|
|
138
|
+
else if (res.statusCode === 401) {
|
|
139
|
+
// The most common cause by far is an expired credential — the old
|
|
140
|
+
// login flow stored 15-minute session JWTs, and CI secrets rot.
|
|
141
|
+
// A bare "Unauthorized" cost real debugging time during the first
|
|
142
|
+
// device run; the fix is one command, so name it.
|
|
143
|
+
reject(new Error(`API error (HTTP 401): ${raw.slice(0, 200)}\n` +
|
|
144
|
+
` Your credential is invalid or has expired.\n` +
|
|
145
|
+
` → Locally: run \`scalebun login\`\n` +
|
|
146
|
+
` → In CI: refresh the SCALEBUN_TOKEN secret (create one in the dashboard under Settings → Access Tokens)`));
|
|
147
|
+
}
|
|
134
148
|
else {
|
|
135
149
|
reject(new Error(`API error (HTTP ${res.statusCode}): ${raw.slice(0, 500)}`));
|
|
136
150
|
}
|
package/lib/api/client.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"client.js","sourceRoot":"","sources":["../../src/api/client.ts"],"names":[],"mappings":"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
|
|
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;AAiKpC,wBAAgB,qBAAqB,CAAC,OAAO,EAAE,OAAO,GAAG,IAAI,CAyC5D"}
|
package/lib/commands/ci-init.js
CHANGED
|
@@ -36,64 +36,199 @@ 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
|
-
const GITHUB_ACTIONS_WORKFLOW = `name: Scalebun OTA Publish
|
|
40
|
-
|
|
41
|
-
on:
|
|
42
|
-
push:
|
|
43
|
-
branches: [ main, production ]
|
|
44
|
-
|
|
45
|
-
jobs:
|
|
46
|
-
publish-ota:
|
|
47
|
-
runs-on: ubuntu-latest
|
|
48
|
-
steps:
|
|
49
|
-
- uses: actions/checkout@v4
|
|
50
|
-
|
|
51
|
-
- name: Setup Node.js
|
|
52
|
-
uses: actions/setup-node@v4
|
|
53
|
-
with:
|
|
54
|
-
node-version: 20
|
|
55
|
-
|
|
56
|
-
- name: Install dependencies
|
|
57
|
-
run: npm ci
|
|
58
|
-
|
|
59
|
-
- name: Publish OTA Update to Scalebun
|
|
60
|
-
env:
|
|
61
|
-
SCALEBUN_TOKEN: \${{ secrets.SCALEBUN_TOKEN }}
|
|
62
|
-
run: |
|
|
63
|
-
npx scalebun ota publish \\
|
|
64
|
-
--app-id \${{ secrets.SCALEBUN_APP_ID }} \\
|
|
65
|
-
--channel production \\
|
|
66
|
-
--platform android \\
|
|
67
|
-
--hermes \\
|
|
68
|
-
--sourcemap
|
|
69
|
-
`;
|
|
70
39
|
/**
|
|
71
|
-
* `scalebun ci init` —
|
|
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
|
|
72
47
|
*
|
|
73
|
-
*
|
|
74
|
-
*
|
|
48
|
+
* `readCredentials()` picks both up automatically, so every command that works
|
|
49
|
+
* locally works headless: publish, rollout, pause, rollback.
|
|
75
50
|
*/
|
|
51
|
+
const GITHUB_ACTIONS_WORKFLOW = `name: Scalebun OTA
|
|
52
|
+
|
|
53
|
+
on:
|
|
54
|
+
push:
|
|
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
|
+
|
|
76
|
+
jobs:
|
|
77
|
+
ota:
|
|
78
|
+
runs-on: ubuntu-latest
|
|
79
|
+
steps:
|
|
80
|
+
- uses: actions/checkout@v4
|
|
81
|
+
|
|
82
|
+
- uses: actions/setup-node@v4
|
|
83
|
+
with:
|
|
84
|
+
node-version: 20
|
|
85
|
+
cache: npm
|
|
86
|
+
|
|
87
|
+
- name: Install dependencies
|
|
88
|
+
run: npm ci
|
|
89
|
+
|
|
90
|
+
# ── Publish (push to main, or manual "publish") ──────────────────────
|
|
91
|
+
# Starts at 10%, NOT 100: a staged rollout is the whole point of OTA.
|
|
92
|
+
# Widen it with the manual "rollout" action once health looks clean.
|
|
93
|
+
# NOTE: the channel must already exist - a typo'd channel name is
|
|
94
|
+
# rejected rather than silently created.
|
|
95
|
+
- name: Publish OTA update
|
|
96
|
+
if: github.event_name == 'push' || inputs.action == 'publish'
|
|
97
|
+
run: |
|
|
98
|
+
npx scalebun ota publish \\
|
|
99
|
+
--app-id "$SCALEBUN_APP_ID" \\
|
|
100
|
+
--channel production \\
|
|
101
|
+
--platform android \\
|
|
102
|
+
--hermes \\
|
|
103
|
+
--sourcemap \\
|
|
104
|
+
--rollout 10 \\
|
|
105
|
+
--release-note "\${{ github.event.head_commit.message || 'Manual publish' }}"
|
|
106
|
+
|
|
107
|
+
# ── Manual controls ──────────────────────────────────────────────────
|
|
108
|
+
- name: Widen rollout
|
|
109
|
+
if: inputs.action == 'rollout'
|
|
110
|
+
run: npx scalebun ota rollout --app-id "$SCALEBUN_APP_ID" --percent "\${{ inputs.percent }}"
|
|
111
|
+
|
|
112
|
+
- name: Pause release
|
|
113
|
+
if: inputs.action == 'pause'
|
|
114
|
+
run: npx scalebun ota pause --app-id "$SCALEBUN_APP_ID"
|
|
115
|
+
|
|
116
|
+
- name: Roll back release
|
|
117
|
+
if: inputs.action == 'rollback'
|
|
118
|
+
run: npx scalebun ota rollback --app-id "$SCALEBUN_APP_ID" --yes
|
|
119
|
+
`;
|
|
120
|
+
const GITLAB_CI_TEMPLATE = `# Scalebun OTA — GitLab CI
|
|
121
|
+
#
|
|
122
|
+
# Set these CI/CD variables (Settings -> CI/CD -> Variables, masked):
|
|
123
|
+
# SCALEBUN_TOKEN scalebun_pat_... (dashboard -> Settings -> Access Tokens)
|
|
124
|
+
# SCALEBUN_API_URL e.g. https://api.scalebun.com/api/v1
|
|
125
|
+
# SCALEBUN_APP_ID your application id
|
|
126
|
+
#
|
|
127
|
+
# Session JWTs expire in minutes - always use a scalebun_pat_... token in CI.
|
|
128
|
+
|
|
129
|
+
stages: [ota]
|
|
130
|
+
|
|
131
|
+
.ota-base:
|
|
132
|
+
stage: ota
|
|
133
|
+
image: node:20
|
|
134
|
+
before_script:
|
|
135
|
+
- npm ci
|
|
136
|
+
|
|
137
|
+
# Publishes on every push to the default branch, staged at 10%.
|
|
138
|
+
ota-publish:
|
|
139
|
+
extends: .ota-base
|
|
140
|
+
rules:
|
|
141
|
+
- if: '$CI_COMMIT_BRANCH == $CI_DEFAULT_BRANCH'
|
|
142
|
+
script:
|
|
143
|
+
- npx scalebun ota publish
|
|
144
|
+
--app-id "$SCALEBUN_APP_ID"
|
|
145
|
+
--channel production
|
|
146
|
+
--platform android
|
|
147
|
+
--hermes
|
|
148
|
+
--sourcemap
|
|
149
|
+
--rollout 10
|
|
150
|
+
--release-note "$CI_COMMIT_TITLE"
|
|
151
|
+
|
|
152
|
+
# Manual jobs — run from the pipeline UI once health looks clean (or bad).
|
|
153
|
+
ota-rollout-100:
|
|
154
|
+
extends: .ota-base
|
|
155
|
+
rules: [{ when: manual }]
|
|
156
|
+
script:
|
|
157
|
+
- npx scalebun ota rollout --app-id "$SCALEBUN_APP_ID" --percent 100
|
|
158
|
+
|
|
159
|
+
ota-pause:
|
|
160
|
+
extends: .ota-base
|
|
161
|
+
rules: [{ when: manual }]
|
|
162
|
+
script:
|
|
163
|
+
- npx scalebun ota pause --app-id "$SCALEBUN_APP_ID"
|
|
164
|
+
|
|
165
|
+
ota-rollback:
|
|
166
|
+
extends: .ota-base
|
|
167
|
+
rules: [{ when: manual }]
|
|
168
|
+
script:
|
|
169
|
+
- npx scalebun ota rollback --app-id "$SCALEBUN_APP_ID" --yes
|
|
170
|
+
`;
|
|
171
|
+
function writeTemplate(targetPath, content) {
|
|
172
|
+
if (fs.existsSync(targetPath)) {
|
|
173
|
+
console.error(`❌ ${path.relative(process.cwd(), targetPath)} already exists — refusing to overwrite.\n` +
|
|
174
|
+
' Delete it first if you want a fresh template.');
|
|
175
|
+
return false;
|
|
176
|
+
}
|
|
177
|
+
fs.mkdirSync(path.dirname(targetPath), { recursive: true });
|
|
178
|
+
fs.writeFileSync(targetPath, content, 'utf-8');
|
|
179
|
+
return true;
|
|
180
|
+
}
|
|
181
|
+
function printNextSteps(provider, file) {
|
|
182
|
+
console.log(`✅ ${provider} pipeline generated: ${file}`);
|
|
183
|
+
console.log('');
|
|
184
|
+
console.log('Next steps:');
|
|
185
|
+
console.log(' 1. Create an access token: dashboard → Settings → Access Tokens');
|
|
186
|
+
console.log(' (or run `scalebun login` locally and copy the scalebun_pat_… it prints)');
|
|
187
|
+
console.log(' 2. Add SCALEBUN_TOKEN, SCALEBUN_API_URL and SCALEBUN_APP_ID as CI secrets.');
|
|
188
|
+
console.log(' 3. Make sure the target channel exists (`scalebun ota channels --app-id <id>`).');
|
|
189
|
+
console.log(' 4. Push — the release goes out staged at 10%; widen it from the CI UI.');
|
|
190
|
+
}
|
|
76
191
|
function registerCiInitCommand(program) {
|
|
77
192
|
const ci = program.command('ci').description('CI/CD integration setup');
|
|
78
193
|
ci.command('init')
|
|
79
|
-
.description('Generate CI/CD pipeline
|
|
80
|
-
.option('--provider <name>', 'CI provider: github |
|
|
194
|
+
.description('Generate a CI/CD pipeline for OTA publishing (publish / rollout / pause / rollback)')
|
|
195
|
+
.option('--provider <name>', 'CI provider: github | gitlab', 'github')
|
|
81
196
|
.action((opts) => {
|
|
82
197
|
const provider = opts.provider.toLowerCase();
|
|
83
198
|
if (provider === 'github') {
|
|
84
|
-
const
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
199
|
+
const target = path.join(process.cwd(), '.github', 'workflows', 'scalebun-ota.yml');
|
|
200
|
+
if (writeTemplate(target, GITHUB_ACTIONS_WORKFLOW)) {
|
|
201
|
+
printNextSteps('GitHub Actions', path.relative(process.cwd(), target));
|
|
202
|
+
}
|
|
203
|
+
else {
|
|
204
|
+
process.exit(1);
|
|
205
|
+
}
|
|
206
|
+
}
|
|
207
|
+
else if (provider === 'gitlab') {
|
|
208
|
+
const target = path.join(process.cwd(), '.gitlab-ci.scalebun-ota.yml');
|
|
209
|
+
if (writeTemplate(target, GITLAB_CI_TEMPLATE)) {
|
|
210
|
+
printNextSteps('GitLab CI', path.relative(process.cwd(), target));
|
|
211
|
+
console.log('');
|
|
212
|
+
console.log(" Include it from your .gitlab-ci.yml:");
|
|
213
|
+
console.log(" include:");
|
|
214
|
+
console.log(" - local: .gitlab-ci.scalebun-ota.yml");
|
|
215
|
+
}
|
|
216
|
+
else {
|
|
217
|
+
process.exit(1);
|
|
218
|
+
}
|
|
92
219
|
}
|
|
93
220
|
else {
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
console.log(
|
|
221
|
+
// Any other system: the commands are plain npx calls over env-var
|
|
222
|
+
// credentials, so print the recipe instead of pretending to support it.
|
|
223
|
+
console.log(`ℹ️ No template for "${provider}" — but any CI works. Set these env vars:`);
|
|
224
|
+
console.log(' SCALEBUN_TOKEN (scalebun_pat_… from the dashboard)');
|
|
225
|
+
console.log(' SCALEBUN_API_URL (your backend, e.g. https://api.scalebun.com/api/v1)');
|
|
226
|
+
console.log('');
|
|
227
|
+
console.log(' Then script the commands directly:');
|
|
228
|
+
console.log(' npx scalebun ota publish --app-id $APP_ID --channel production --hermes --rollout 10');
|
|
229
|
+
console.log(' npx scalebun ota rollout --app-id $APP_ID --percent 100');
|
|
230
|
+
console.log(' npx scalebun ota pause --app-id $APP_ID');
|
|
231
|
+
console.log(' npx scalebun ota rollback --app-id $APP_ID --yes');
|
|
97
232
|
}
|
|
98
233
|
});
|
|
99
234
|
}
|
|
@@ -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 @@
|
|
|
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,CA+M5D"}
|
|
@@ -0,0 +1,243 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
|
|
3
|
+
if (k2 === undefined) k2 = k;
|
|
4
|
+
var desc = Object.getOwnPropertyDescriptor(m, k);
|
|
5
|
+
if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
|
|
6
|
+
desc = { enumerable: true, get: function() { return m[k]; } };
|
|
7
|
+
}
|
|
8
|
+
Object.defineProperty(o, k2, desc);
|
|
9
|
+
}) : (function(o, m, k, k2) {
|
|
10
|
+
if (k2 === undefined) k2 = k;
|
|
11
|
+
o[k2] = m[k];
|
|
12
|
+
}));
|
|
13
|
+
var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
|
|
14
|
+
Object.defineProperty(o, "default", { enumerable: true, value: v });
|
|
15
|
+
}) : function(o, v) {
|
|
16
|
+
o["default"] = v;
|
|
17
|
+
});
|
|
18
|
+
var __importStar = (this && this.__importStar) || (function () {
|
|
19
|
+
var ownKeys = function(o) {
|
|
20
|
+
ownKeys = Object.getOwnPropertyNames || function (o) {
|
|
21
|
+
var ar = [];
|
|
22
|
+
for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
|
|
23
|
+
return ar;
|
|
24
|
+
};
|
|
25
|
+
return ownKeys(o);
|
|
26
|
+
};
|
|
27
|
+
return function (mod) {
|
|
28
|
+
if (mod && mod.__esModule) return mod;
|
|
29
|
+
var result = {};
|
|
30
|
+
if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
|
|
31
|
+
__setModuleDefault(result, mod);
|
|
32
|
+
return result;
|
|
33
|
+
};
|
|
34
|
+
})();
|
|
35
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
36
|
+
exports.registerDoctorCommand = registerDoctorCommand;
|
|
37
|
+
const fs = __importStar(require("fs"));
|
|
38
|
+
const path = __importStar(require("path"));
|
|
39
|
+
const credentials_1 = require("../utils/credentials");
|
|
40
|
+
const client_1 = require("../api/client");
|
|
41
|
+
const bundle_1 = require("../utils/bundle");
|
|
42
|
+
const findings = [];
|
|
43
|
+
function report(level, title, detail) {
|
|
44
|
+
findings.push({ level, title, detail });
|
|
45
|
+
const icon = level === 'ok' ? '✅' : level === 'warn' ? '⚠️ ' : '❌';
|
|
46
|
+
console.log(`${icon} ${title}`);
|
|
47
|
+
if (detail)
|
|
48
|
+
console.log(` ${detail.split('\n').join('\n ')}`);
|
|
49
|
+
}
|
|
50
|
+
/** Find the first file matching `names` under `dir`, skipping heavy folders. */
|
|
51
|
+
function findFile(dir, names, maxDepth = 6) {
|
|
52
|
+
if (maxDepth < 0 || !fs.existsSync(dir))
|
|
53
|
+
return null;
|
|
54
|
+
let entries;
|
|
55
|
+
try {
|
|
56
|
+
entries = fs.readdirSync(dir, { withFileTypes: true });
|
|
57
|
+
}
|
|
58
|
+
catch {
|
|
59
|
+
return null;
|
|
60
|
+
}
|
|
61
|
+
for (const e of entries) {
|
|
62
|
+
if (e.isFile() && names.includes(e.name))
|
|
63
|
+
return path.join(dir, e.name);
|
|
64
|
+
}
|
|
65
|
+
for (const e of entries) {
|
|
66
|
+
if (!e.isDirectory())
|
|
67
|
+
continue;
|
|
68
|
+
if (['node_modules', 'Pods', 'build', '.git', '.gradle'].includes(e.name))
|
|
69
|
+
continue;
|
|
70
|
+
const hit = findFile(path.join(dir, e.name), names, maxDepth - 1);
|
|
71
|
+
if (hit)
|
|
72
|
+
return hit;
|
|
73
|
+
}
|
|
74
|
+
return null;
|
|
75
|
+
}
|
|
76
|
+
function parseMinor(version) {
|
|
77
|
+
if (!version)
|
|
78
|
+
return null;
|
|
79
|
+
const m = /^(\d+)\.(\d+)/.exec(version);
|
|
80
|
+
return m ? [Number(m[1]), Number(m[2])] : null;
|
|
81
|
+
}
|
|
82
|
+
function registerDoctorCommand(program) {
|
|
83
|
+
program
|
|
84
|
+
.command('doctor')
|
|
85
|
+
.description('Check that this project is correctly set up for OTA updates')
|
|
86
|
+
.action(async () => {
|
|
87
|
+
const cwd = process.cwd();
|
|
88
|
+
console.log('\nScalebun doctor\n');
|
|
89
|
+
// ── 1. Credentials ─────────────────────────────────────────────────────
|
|
90
|
+
const creds = (0, credentials_1.readCredentials)();
|
|
91
|
+
if (!creds) {
|
|
92
|
+
report('fail', 'Not logged in', 'Run `scalebun login`, or set SCALEBUN_TOKEN + SCALEBUN_API_URL in CI.');
|
|
93
|
+
}
|
|
94
|
+
else {
|
|
95
|
+
const source = process.env.SCALEBUN_TOKEN ? 'environment variables' : '~/.scalebun/credentials.json';
|
|
96
|
+
if (creds.token.startsWith('scalebun_pat_')) {
|
|
97
|
+
report('ok', `Credentials found (${source}, durable access token)`);
|
|
98
|
+
}
|
|
99
|
+
else {
|
|
100
|
+
report('warn', `Credentials found (${source}) but the token is a session JWT`, 'Session tokens expire in ~15 minutes. Run `scalebun login` again — it now mints\n' +
|
|
101
|
+
'a durable access token automatically.');
|
|
102
|
+
}
|
|
103
|
+
try {
|
|
104
|
+
const me = await new client_1.ApiClient(creds).get('/auth/me');
|
|
105
|
+
report('ok', `Token valid — authenticated as ${me.email}`);
|
|
106
|
+
}
|
|
107
|
+
catch (err) {
|
|
108
|
+
report('fail', 'Stored token no longer works', err.message);
|
|
109
|
+
}
|
|
110
|
+
}
|
|
111
|
+
// ── 2. Project shape ───────────────────────────────────────────────────
|
|
112
|
+
const rnVersion = (0, bundle_1.detectProjectRnVersion)(cwd);
|
|
113
|
+
const expo = (0, bundle_1.isExpoProject)(cwd);
|
|
114
|
+
if (!rnVersion) {
|
|
115
|
+
report('fail', 'React Native not found in node_modules', 'Run this from your app root, after installing dependencies.');
|
|
116
|
+
}
|
|
117
|
+
else {
|
|
118
|
+
report('ok', `React Native ${rnVersion} (${expo ? 'Expo' : 'bare'} project)`);
|
|
119
|
+
}
|
|
120
|
+
const hermesc = (0, bundle_1.resolveHermesc)(cwd);
|
|
121
|
+
if (hermesc) {
|
|
122
|
+
report('ok', 'hermesc found — `--hermes` publishes will compile bytecode');
|
|
123
|
+
}
|
|
124
|
+
else if (rnVersion) {
|
|
125
|
+
report('warn', 'hermesc not found under node_modules/react-native/sdks/hermesc', 'Publishes fall back to plain JS: they work, but cold start is ~20-30% slower\n' +
|
|
126
|
+
'and Hermes-bytecode runtime gating cannot protect these bundles.');
|
|
127
|
+
}
|
|
128
|
+
// ── 3. Android wiring ──────────────────────────────────────────────────
|
|
129
|
+
const gradleProps = path.join(cwd, 'android', 'gradle.properties');
|
|
130
|
+
const mainApp = findFile(path.join(cwd, 'android', 'app', 'src', 'main'), [
|
|
131
|
+
'MainApplication.kt',
|
|
132
|
+
'MainApplication.java',
|
|
133
|
+
]);
|
|
134
|
+
const minor = parseMinor(rnVersion);
|
|
135
|
+
if (!fs.existsSync(path.join(cwd, 'android'))) {
|
|
136
|
+
report('warn', 'No android/ directory — skipping Android checks');
|
|
137
|
+
}
|
|
138
|
+
else {
|
|
139
|
+
const newArch = fs.existsSync(gradleProps) &&
|
|
140
|
+
/newArchEnabled\s*=\s*true/.test(fs.readFileSync(gradleProps, 'utf-8'));
|
|
141
|
+
// The dead zone: bridgeless ignored getJSBundleFile() until RN 0.76.1.
|
|
142
|
+
// An update installs, reports INSTALLED, and the app keeps running the
|
|
143
|
+
// APK asset — the exact failure that killed CodePush on modern RN.
|
|
144
|
+
if (newArch && minor && (minor[1] === 74 || minor[1] === 75) && minor[0] === 0) {
|
|
145
|
+
report('fail', `New Architecture is ON with React Native ${rnVersion} — OTA updates CANNOT LOAD`, 'Bridgeless did not honour getJSBundleFile() until RN 0.76.1. Updates will\n' +
|
|
146
|
+
'install and silently never run (the SDK detects this and disables itself).\n' +
|
|
147
|
+
'Fix: upgrade to RN >= 0.76.1, or set newArchEnabled=false.');
|
|
148
|
+
}
|
|
149
|
+
else if (newArch && rnVersion?.startsWith('0.76.0')) {
|
|
150
|
+
report('fail', 'React Native 0.76.0 exactly — one patch release short of the bridgeless fix', 'Upgrade to 0.76.1 or later.');
|
|
151
|
+
}
|
|
152
|
+
if (!mainApp) {
|
|
153
|
+
report('warn', 'MainApplication.kt/.java not found — cannot verify Android wiring');
|
|
154
|
+
}
|
|
155
|
+
else {
|
|
156
|
+
const src = fs.readFileSync(mainApp, 'utf-8');
|
|
157
|
+
const wired = src.includes('ScaleBunOtaModule.getJSBundleFile');
|
|
158
|
+
const rel = path.relative(cwd, mainApp);
|
|
159
|
+
if (!wired) {
|
|
160
|
+
report('fail', `Android bundle resolution is NOT wired (${rel})`, 'Without it, updates download and install but the app keeps running the bundle\n' +
|
|
161
|
+
'baked into the APK — every metric reports success and nothing changes.\n' +
|
|
162
|
+
(minor && (minor[0] > 0 || minor[1] >= 82)
|
|
163
|
+
? 'RN >= 0.82 (ReactNativeHost was removed) — pass the path to the host:\n' +
|
|
164
|
+
' override val reactHost: ReactHost by lazy {\n' +
|
|
165
|
+
' getDefaultReactHost(context = applicationContext,\n' +
|
|
166
|
+
' packageList = PackageList(this).packages,\n' +
|
|
167
|
+
' jsBundleFilePath = ScaleBunOtaModule.getJSBundleFile(applicationContext))\n' +
|
|
168
|
+
' }'
|
|
169
|
+
: 'Add inside your ReactNativeHost:\n' +
|
|
170
|
+
' override fun getJSBundleFile(): String? =\n' +
|
|
171
|
+
' ScaleBunOtaModule.getJSBundleFile(this@MainApplication) ?: super.getJSBundleFile()'));
|
|
172
|
+
}
|
|
173
|
+
else if (minor &&
|
|
174
|
+
(minor[0] > 0 || minor[1] >= 82) &&
|
|
175
|
+
!src.includes('jsBundleFilePath')) {
|
|
176
|
+
report('fail', `RN ${rnVersion} uses the removed ReactNativeHost override (${rel})`, 'RN 0.82 deleted ReactNativeHost — the getJSBundleFile() override no longer\n' +
|
|
177
|
+
'compiles or runs. Pass jsBundleFilePath to getDefaultReactHost(...) instead.');
|
|
178
|
+
}
|
|
179
|
+
else {
|
|
180
|
+
report('ok', `Android bundle resolution wired (${rel})`);
|
|
181
|
+
}
|
|
182
|
+
}
|
|
183
|
+
}
|
|
184
|
+
// ── 4. iOS wiring ──────────────────────────────────────────────────────
|
|
185
|
+
if (!fs.existsSync(path.join(cwd, 'ios'))) {
|
|
186
|
+
report('warn', 'No ios/ directory — skipping iOS checks');
|
|
187
|
+
}
|
|
188
|
+
else {
|
|
189
|
+
const appDelegate = findFile(path.join(cwd, 'ios'), [
|
|
190
|
+
'AppDelegate.swift',
|
|
191
|
+
'AppDelegate.mm',
|
|
192
|
+
'AppDelegate.m',
|
|
193
|
+
]);
|
|
194
|
+
if (!appDelegate) {
|
|
195
|
+
report('warn', 'AppDelegate not found — cannot verify iOS wiring');
|
|
196
|
+
}
|
|
197
|
+
else {
|
|
198
|
+
const src = fs.readFileSync(appDelegate, 'utf-8');
|
|
199
|
+
const rel = path.relative(cwd, appDelegate);
|
|
200
|
+
if (src.includes('ScaleBunOtaModule.getBundleURL') || src.includes('getBundleURL()')) {
|
|
201
|
+
report('ok', `iOS bundle resolution wired (${rel})`);
|
|
202
|
+
}
|
|
203
|
+
else {
|
|
204
|
+
report('fail', `iOS bundle resolution is NOT wired (${rel})`, 'Override bundleURL to resolve the OTA slot:\n' +
|
|
205
|
+
' override func bundleURL() -> URL? {\n' +
|
|
206
|
+
' #if DEBUG\n' +
|
|
207
|
+
' RCTBundleURLProvider.sharedSettings().jsBundleURL(forBundleRoot: "index")\n' +
|
|
208
|
+
' #else\n' +
|
|
209
|
+
' ScaleBunOtaModule.getBundleURL()\n' +
|
|
210
|
+
' #endif\n' +
|
|
211
|
+
' }');
|
|
212
|
+
}
|
|
213
|
+
}
|
|
214
|
+
}
|
|
215
|
+
// ── 5. Signing ─────────────────────────────────────────────────────────
|
|
216
|
+
const keyPath = path.join(cwd, '.scalebun', 'ota-signing-key.pem');
|
|
217
|
+
if (fs.existsSync(keyPath)) {
|
|
218
|
+
report('ok', 'ed25519 signing key present — publishes are signed');
|
|
219
|
+
const gitignore = path.join(cwd, '.gitignore');
|
|
220
|
+
const ignored = fs.existsSync(gitignore) && /(^|\n)\s*\.scalebun\/?\s*(\n|$)/.test(fs.readFileSync(gitignore, 'utf-8'));
|
|
221
|
+
if (!ignored) {
|
|
222
|
+
report('fail', '.scalebun/ is NOT in .gitignore — the private signing key can be committed', 'Anyone with this key can sign bundles your users will trust.\n' +
|
|
223
|
+
'Fix: echo ".scalebun/" >> .gitignore (and rotate the key if it was ever pushed)');
|
|
224
|
+
}
|
|
225
|
+
}
|
|
226
|
+
else {
|
|
227
|
+
report('warn', 'No signing key — bundles ship on SHA-256 integrity alone', 'Integrity proves bytes arrived intact; only a signature proves they came from you.\n' +
|
|
228
|
+
'Set up: scalebun ota generate-key-pair --app-id <id> --name "release key"');
|
|
229
|
+
}
|
|
230
|
+
// ── Summary ────────────────────────────────────────────────────────────
|
|
231
|
+
const fails = findings.filter((f) => f.level === 'fail').length;
|
|
232
|
+
const warns = findings.filter((f) => f.level === 'warn').length;
|
|
233
|
+
console.log('');
|
|
234
|
+
if (fails > 0) {
|
|
235
|
+
console.log(`${fails} blocking issue(s), ${warns} warning(s). Fix the ❌ items before shipping OTA.`);
|
|
236
|
+
process.exit(1);
|
|
237
|
+
}
|
|
238
|
+
console.log(warns > 0
|
|
239
|
+
? `No blocking issues (${warns} warning(s)). You can ship OTA updates.`
|
|
240
|
+
: 'All checks passed. You can ship OTA updates.');
|
|
241
|
+
});
|
|
242
|
+
}
|
|
243
|
+
//# sourceMappingURL=doctor.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"doctor.js","sourceRoot":"","sources":["../../src/commands/doctor.ts"],"names":[],"mappings":"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"}
|