cloudron 6.0.0 → 7.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/CHANGELOG.md +4 -0
- package/bin/cloudron +15 -29
- package/bin/cloudron-appstore +4 -7
- package/bin/cloudron-build +18 -8
- package/bin/cloudron-versions +33 -0
- package/eslint.config.js +7 -6
- package/package.json +16 -15
- package/src/actions.js +230 -128
- package/src/appstore-actions.js +31 -59
- package/src/backup-tools.js +22 -24
- package/src/build-actions.js +113 -99
- package/src/completion.js +4 -8
- package/src/config.js +78 -53
- package/src/helper.js +155 -13
- package/src/readline.js +8 -10
- package/src/templates/CloudronManifest.appstore.json.ejs +2 -2
- package/src/versions-actions.js +184 -0
- package/test/test.js +131 -160
- package/src/superagent.js +0 -225
package/src/appstore-actions.js
CHANGED
|
@@ -1,32 +1,14 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
readline = require('./readline.js'),
|
|
13
|
-
safe = require('safetydance'),
|
|
14
|
-
superagent = require('@cloudron/superagent'),
|
|
15
|
-
Table = require('easy-table');
|
|
16
|
-
|
|
17
|
-
exports = module.exports = {
|
|
18
|
-
login,
|
|
19
|
-
logout,
|
|
20
|
-
info,
|
|
21
|
-
listVersions,
|
|
22
|
-
submit,
|
|
23
|
-
upload,
|
|
24
|
-
revoke,
|
|
25
|
-
approve,
|
|
26
|
-
verifyManifest,
|
|
27
|
-
|
|
28
|
-
notify
|
|
29
|
-
};
|
|
1
|
+
import assert from 'assert';
|
|
2
|
+
import * as config from './config.js';
|
|
3
|
+
import { execSync } from 'child_process';
|
|
4
|
+
import fs from 'fs';
|
|
5
|
+
import { exit, locateManifest, parseChangelog } from './helper.js';
|
|
6
|
+
import manifestFormat from '@cloudron/manifest-format';
|
|
7
|
+
import path from 'path';
|
|
8
|
+
import * as readline from './readline.js';
|
|
9
|
+
import safe from '@cloudron/safetydance';
|
|
10
|
+
import superagent from '@cloudron/superagent';
|
|
11
|
+
import Table from 'easy-table';
|
|
30
12
|
|
|
31
13
|
const NO_MANIFEST_FOUND_ERROR_STRING = 'No CloudronManifest.json found';
|
|
32
14
|
|
|
@@ -156,29 +138,6 @@ async function listVersions(localOptions, cmd) {
|
|
|
156
138
|
console.log(t.toString());
|
|
157
139
|
}
|
|
158
140
|
|
|
159
|
-
function parseChangelog(file, version) {
|
|
160
|
-
let changelog = '';
|
|
161
|
-
const data = safe.fs.readFileSync(file, 'utf8');
|
|
162
|
-
if (!data) return null;
|
|
163
|
-
const lines = data.split('\n');
|
|
164
|
-
|
|
165
|
-
version = version.replace(/-.*/, ''); // remove any prerelease
|
|
166
|
-
|
|
167
|
-
let i;
|
|
168
|
-
for (i = 0; i < lines.length; i++) {
|
|
169
|
-
if (lines[i] === '[' + version + ']') break;
|
|
170
|
-
}
|
|
171
|
-
|
|
172
|
-
for (i = i + 1; i < lines.length; i++) {
|
|
173
|
-
if (lines[i] === '') continue;
|
|
174
|
-
if (lines[i][0] === '[') break;
|
|
175
|
-
|
|
176
|
-
changelog += lines[i] + '\n';
|
|
177
|
-
}
|
|
178
|
-
|
|
179
|
-
return changelog;
|
|
180
|
-
}
|
|
181
|
-
|
|
182
141
|
async function addVersion(manifest, baseDir, options) {
|
|
183
142
|
assert.strictEqual(typeof manifest, 'object');
|
|
184
143
|
assert.strictEqual(typeof baseDir, 'string');
|
|
@@ -210,8 +169,7 @@ async function addVersion(manifest, baseDir, options) {
|
|
|
210
169
|
}
|
|
211
170
|
|
|
212
171
|
if (manifest.changelog.slice(0, 7) === 'file://') {
|
|
213
|
-
|
|
214
|
-
changelogPath = path.isAbsolute(changelogPath) ? changelogPath : path.join(baseDir, changelogPath);
|
|
172
|
+
const changelogPath = path.isAbsolute(manifest.changelog.slice(7)) ? manifest.changelog.slice(7) : path.join(baseDir, manifest.changelog.slice(7));
|
|
215
173
|
manifest.changelog = parseChangelog(changelogPath, manifest.version);
|
|
216
174
|
if (!manifest.changelog) throw new Error('Bad changelog format or missing changelog for this version');
|
|
217
175
|
}
|
|
@@ -277,7 +235,7 @@ async function verifyManifest(localOptions, cmd) {
|
|
|
277
235
|
const manifest = result.manifest;
|
|
278
236
|
|
|
279
237
|
const sourceDir = path.dirname(manifestFilePath);
|
|
280
|
-
const appConfig = config.
|
|
238
|
+
const appConfig = config.getAppBuildConfig(sourceDir);
|
|
281
239
|
|
|
282
240
|
// image can be passed in options for buildbot
|
|
283
241
|
if (options.image) {
|
|
@@ -324,7 +282,7 @@ async function upload(localOptions, cmd) {
|
|
|
324
282
|
const manifest = result.manifest;
|
|
325
283
|
|
|
326
284
|
const sourceDir = path.dirname(manifestFilePath);
|
|
327
|
-
const appConfig = config.
|
|
285
|
+
const appConfig = config.getAppBuildConfig(sourceDir);
|
|
328
286
|
|
|
329
287
|
// image can be passed in options for buildbot
|
|
330
288
|
if (options.image) {
|
|
@@ -467,11 +425,11 @@ async function notify() {
|
|
|
467
425
|
if (result.error) return exit(new Error(`Invalid CloudronManifest.json: ${result.error.message}`));
|
|
468
426
|
const { manifest } = result;
|
|
469
427
|
|
|
470
|
-
let postContent
|
|
428
|
+
let postContent;
|
|
471
429
|
if (manifest.changelog.slice(0, 7) === 'file://') {
|
|
472
430
|
const baseDir = path.dirname(manifestFilePath);
|
|
473
|
-
|
|
474
|
-
changelogPath = path.isAbsolute(
|
|
431
|
+
const manifestChangelogPath = manifest.changelog.slice(7);
|
|
432
|
+
const changelogPath = path.isAbsolute(manifestChangelogPath) ? manifestChangelogPath : path.join(baseDir, manifestChangelogPath);
|
|
475
433
|
const changelog = parseChangelog(changelogPath, manifest.version);
|
|
476
434
|
if (!changelog) return exit('Bad changelog format or missing changelog for this version');
|
|
477
435
|
postContent = `[${manifest.version}]\n${changelog}\n`;
|
|
@@ -511,3 +469,17 @@ async function notify() {
|
|
|
511
469
|
if (postResponse.status !== 200) return exit(`Unable to create changelog post: ${requestError(postResponse)}`);
|
|
512
470
|
console.log('Posted to forum');
|
|
513
471
|
}
|
|
472
|
+
|
|
473
|
+
export default {
|
|
474
|
+
login,
|
|
475
|
+
logout,
|
|
476
|
+
info,
|
|
477
|
+
listVersions,
|
|
478
|
+
submit,
|
|
479
|
+
upload,
|
|
480
|
+
revoke,
|
|
481
|
+
approve,
|
|
482
|
+
verifyManifest,
|
|
483
|
+
|
|
484
|
+
notify
|
|
485
|
+
};
|
package/src/backup-tools.js
CHANGED
|
@@ -1,24 +1,14 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
const assert = require('assert'),
|
|
14
|
-
crypto = require('crypto'),
|
|
15
|
-
debug = require('debug')('cloudron-backup'),
|
|
16
|
-
fs = require('fs'),
|
|
17
|
-
path = require('path'),
|
|
18
|
-
readlinePromises = require('readline/promises'),
|
|
19
|
-
safe = require('safetydance'),
|
|
20
|
-
stream = require('stream/promises'),
|
|
21
|
-
TransformStream = require('stream').Transform;
|
|
1
|
+
import assert from 'assert';
|
|
2
|
+
import crypto from 'crypto';
|
|
3
|
+
import createDebug from 'debug';
|
|
4
|
+
import fs from 'fs';
|
|
5
|
+
import path from 'path';
|
|
6
|
+
import readlinePromises from 'readline/promises';
|
|
7
|
+
import safe from '@cloudron/safetydance';
|
|
8
|
+
import stream from 'stream/promises';
|
|
9
|
+
import { Transform as TransformStream } from 'stream';
|
|
10
|
+
|
|
11
|
+
const debug = createDebug('cloudron-backup');
|
|
22
12
|
|
|
23
13
|
function encryptFilePath(filePath, encryption) {
|
|
24
14
|
assert.strictEqual(typeof filePath, 'string');
|
|
@@ -52,9 +42,9 @@ function decryptFilePath(filePath, encryption) {
|
|
|
52
42
|
const buffer = Buffer.from(part, 'base64');
|
|
53
43
|
const iv = buffer.subarray(0, 16);
|
|
54
44
|
|
|
55
|
-
const
|
|
56
|
-
const plainText =
|
|
57
|
-
const plainTextString = Buffer.concat([ plainText,
|
|
45
|
+
const decipher = crypto.createDecipheriv('aes-256-cbc', Buffer.from(encryption.filenameKey, 'hex'), iv);
|
|
46
|
+
const plainText = decipher.update(buffer.subarray(16));
|
|
47
|
+
const plainTextString = Buffer.concat([ plainText, decipher.final() ]).toString('utf8');
|
|
58
48
|
const hmac = crypto.createHmac('sha256', Buffer.from(encryption.filenameHmacKey, 'hex'));
|
|
59
49
|
if (!hmac.update(plainTextString).digest().subarray(0, 16).equals(iv)) return { error: new Error(`mac error decrypting part ${part} of path ${filePath}`) };
|
|
60
50
|
|
|
@@ -332,3 +322,11 @@ async function decryptFilename(filePath, options) {
|
|
|
332
322
|
if (error) return exit(error);
|
|
333
323
|
console.log(decryptedFilePath);
|
|
334
324
|
}
|
|
325
|
+
|
|
326
|
+
export default {
|
|
327
|
+
encrypt,
|
|
328
|
+
decrypt,
|
|
329
|
+
encryptFilename,
|
|
330
|
+
decryptFilename,
|
|
331
|
+
decryptDir
|
|
332
|
+
};
|
package/src/build-actions.js
CHANGED
|
@@ -1,31 +1,20 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
helper = require('./helper.js'),
|
|
19
|
-
manifestFormat = require('@cloudron/manifest-format'),
|
|
20
|
-
micromatch = require('micromatch'),
|
|
21
|
-
os = require('os'),
|
|
22
|
-
path = require('path'),
|
|
23
|
-
readline = require('./readline.js'),
|
|
24
|
-
safe = require('safetydance'),
|
|
25
|
-
stream = require('stream/promises'),
|
|
26
|
-
superagent = require('@cloudron/superagent'),
|
|
27
|
-
tar = require('tar-fs'),
|
|
28
|
-
{ URL } = require('url');
|
|
1
|
+
import assert from 'assert';
|
|
2
|
+
import * as config from './config.js';
|
|
3
|
+
import crypto from 'crypto';
|
|
4
|
+
import { EventSource } from 'eventsource';
|
|
5
|
+
import { execSync } from 'child_process';
|
|
6
|
+
import { exit } from './helper.js';
|
|
7
|
+
import fs from 'fs';
|
|
8
|
+
import * as helper from './helper.js';
|
|
9
|
+
import manifestFormat from '@cloudron/manifest-format';
|
|
10
|
+
import micromatch from 'micromatch';
|
|
11
|
+
import os from 'os';
|
|
12
|
+
import path from 'path';
|
|
13
|
+
import * as readline from './readline.js';
|
|
14
|
+
import safe from '@cloudron/safetydance';
|
|
15
|
+
import stream from 'stream/promises';
|
|
16
|
+
import superagent from '@cloudron/superagent';
|
|
17
|
+
import tar from 'tar-fs';
|
|
29
18
|
|
|
30
19
|
function requestError(response) {
|
|
31
20
|
if (response.status === 401 || response.status === 403) return 'Invalid token. Use cloudron build login again.';
|
|
@@ -33,68 +22,42 @@ function requestError(response) {
|
|
|
33
22
|
return `${response.status} message: ${response.body?.message || response.text || null}`;
|
|
34
23
|
}
|
|
35
24
|
|
|
36
|
-
// analyzes options and merges with any existing build service config
|
|
37
|
-
async function resolveBuildServiceConfig(options) {
|
|
38
|
-
const buildService = config.getBuildServiceConfig();
|
|
39
|
-
if (!buildService.type) buildService.type = 'local'; // default
|
|
40
|
-
|
|
41
|
-
if (options.local) {
|
|
42
|
-
buildService.type = 'local';
|
|
43
|
-
} else if (options.setBuildService) { // stash for future use
|
|
44
|
-
buildService.token = null;
|
|
45
|
-
buildService.url = null;
|
|
46
|
-
buildService.type = 'remote';
|
|
47
|
-
|
|
48
|
-
let url;
|
|
49
|
-
if (typeof options.setBuildService === 'string') {
|
|
50
|
-
url = options.setBuildService;
|
|
51
|
-
} else {
|
|
52
|
-
url = await readline.question('Enter build service URL: ', { });
|
|
53
|
-
}
|
|
54
|
-
|
|
55
|
-
if (url.indexOf('://') === -1) url = `https://${url}`;
|
|
56
|
-
buildService.url = url;
|
|
57
|
-
}
|
|
58
|
-
|
|
59
|
-
if (options.buildServiceToken) buildService.token = options.buildServiceToken;
|
|
60
|
-
|
|
61
|
-
config.setBuildServiceConfig(buildService);
|
|
62
|
-
|
|
63
|
-
return buildService;
|
|
64
|
-
}
|
|
65
25
|
|
|
66
26
|
async function login(localOptions, cmd) {
|
|
67
27
|
const options = cmd.optsWithGlobals();
|
|
68
28
|
|
|
69
|
-
const buildServiceConfig =
|
|
29
|
+
const buildServiceConfig = config.getBuildServiceConfig();
|
|
30
|
+
|
|
31
|
+
let url = options.buildServiceUrl || buildServiceConfig.url;
|
|
32
|
+
if (!url) {
|
|
33
|
+
url = await readline.question('Build Service URL: ', {});
|
|
34
|
+
if (!url) return exit('No build service URL provided.');
|
|
35
|
+
}
|
|
36
|
+
if (url.indexOf('://') === -1) url = `https://${url}`;
|
|
70
37
|
|
|
71
|
-
console.log(
|
|
38
|
+
console.log(`Build Service login (${url}):`);
|
|
72
39
|
|
|
73
40
|
const token = options.buildServiceToken || await readline.question('Token: ', {});
|
|
74
41
|
|
|
75
|
-
const response = await superagent.get(`${
|
|
42
|
+
const response = await superagent.get(`${url}/api/v1/profile`).query({ accessToken: token }).ok(() => true);
|
|
76
43
|
if (response.status === 401 || response.status === 403) return exit(`Authentication error: ${requestError(response)}`);
|
|
77
44
|
if (response.status !== 200) return exit(`Unexpected response: ${requestError(response)}`);
|
|
78
45
|
|
|
79
|
-
|
|
80
|
-
config.setBuildServiceConfig(buildServiceConfig);
|
|
46
|
+
config.setBuildServiceConfig({ type: 'remote', url, token });
|
|
81
47
|
|
|
82
48
|
console.log('Login successful.');
|
|
83
49
|
}
|
|
84
50
|
|
|
85
|
-
|
|
51
|
+
function logout() {
|
|
52
|
+
config.setBuildServiceConfig({});
|
|
53
|
+
console.log('Logged out.');
|
|
54
|
+
}
|
|
55
|
+
|
|
56
|
+
async function followBuildLog(buildServiceConfig, buildId, raw) {
|
|
86
57
|
assert.strictEqual(typeof buildId, 'string');
|
|
87
58
|
assert.strictEqual(typeof raw, 'boolean');
|
|
88
59
|
|
|
89
|
-
const
|
|
90
|
-
let tmp;
|
|
91
|
-
try {
|
|
92
|
-
tmp = new URL(rawUrl);
|
|
93
|
-
} catch {
|
|
94
|
-
tmp = new URL(`http://${rawUrl}`); // if it fails, prepend http://
|
|
95
|
-
}
|
|
96
|
-
|
|
97
|
-
const es = new EventSource(`${tmp.origin}/api/v1/builds/${buildId}/logstream?accessToken=${config.getBuildServiceConfig().token}`);
|
|
60
|
+
const es = new EventSource(`${buildServiceConfig.url}/api/v1/builds/${buildId}/logstream?accessToken=${buildServiceConfig.token}`);
|
|
98
61
|
|
|
99
62
|
let prevId = null, prevWasStatus = false;
|
|
100
63
|
|
|
@@ -155,9 +118,7 @@ async function followBuildLog(buildId, raw) {
|
|
|
155
118
|
});
|
|
156
119
|
}
|
|
157
120
|
|
|
158
|
-
async function getStatus(buildId) {
|
|
159
|
-
const buildServiceConfig = config.getBuildServiceConfig();
|
|
160
|
-
|
|
121
|
+
async function getStatus(buildServiceConfig, buildId) {
|
|
161
122
|
const response2 = await superagent.get(`${buildServiceConfig.url}/api/v1/builds/${buildId}`)
|
|
162
123
|
.query({ accessToken: buildServiceConfig.token })
|
|
163
124
|
.ok(() => true);
|
|
@@ -165,7 +126,7 @@ async function getStatus(buildId) {
|
|
|
165
126
|
return response2.body.status;
|
|
166
127
|
}
|
|
167
128
|
|
|
168
|
-
function dockerignoreMatcher(dockerignorePath) {
|
|
129
|
+
export function dockerignoreMatcher(dockerignorePath) {
|
|
169
130
|
let patterns = [];
|
|
170
131
|
|
|
171
132
|
if (fs.existsSync(dockerignorePath)) {
|
|
@@ -183,8 +144,8 @@ function dockerignoreMatcher(dockerignorePath) {
|
|
|
183
144
|
patterns = patterns.filter(function (line) { return line.length !== 0; });
|
|
184
145
|
}
|
|
185
146
|
|
|
186
|
-
return function ignore(
|
|
187
|
-
return micromatch([
|
|
147
|
+
return function ignore(filePath) {
|
|
148
|
+
return micromatch([ filePath ], patterns, { dot: true }).length == 1;
|
|
188
149
|
};
|
|
189
150
|
}
|
|
190
151
|
|
|
@@ -225,9 +186,9 @@ async function buildLocal(manifest, sourceDir, appConfig, options) {
|
|
|
225
186
|
const match = /.*@sha256:(.*)/.exec(result.trim());
|
|
226
187
|
if (!match) exit('Failed to detect sha256');
|
|
227
188
|
|
|
228
|
-
appConfig.dockerImage =
|
|
189
|
+
appConfig.dockerImage = dockerImage;
|
|
229
190
|
appConfig.dockerImageSha256 = match[1]; // stash this separately for now
|
|
230
|
-
config.
|
|
191
|
+
config.setAppBuildConfig(sourceDir, appConfig);
|
|
231
192
|
}
|
|
232
193
|
|
|
233
194
|
async function buildRemote(manifest, sourceDir, appConfig, options) {
|
|
@@ -290,16 +251,16 @@ async function buildRemote(manifest, sourceDir, appConfig, options) {
|
|
|
290
251
|
const buildId = response.body.id;
|
|
291
252
|
console.log(`BuildId: ${buildId}`);
|
|
292
253
|
|
|
293
|
-
const [logsError] = await safe(followBuildLog(buildId, !!options.raw));
|
|
254
|
+
const [logsError] = await safe(followBuildLog(buildServiceConfig, buildId, !!options.raw));
|
|
294
255
|
if (logsError) console.log(`Failed to get logs: ${logsError.message}`);
|
|
295
256
|
|
|
296
|
-
const [statusError,
|
|
257
|
+
const [statusError, buildStatus] = await safe(getStatus(buildServiceConfig, buildId));
|
|
297
258
|
if (statusError) return exit(`Failed to get status: ${statusError.message}`);
|
|
298
|
-
if (
|
|
259
|
+
if (buildStatus !== 'success') return exit('Failed to build app. See log output above.');
|
|
299
260
|
|
|
300
261
|
appConfig.dockerImage = dockerImage;
|
|
301
262
|
// appConfig.dockerImageSha256 = match[1]; // stash this separately for now
|
|
302
|
-
config.
|
|
263
|
+
config.setAppBuildConfig(sourceDir, appConfig);
|
|
303
264
|
|
|
304
265
|
console.log(`Docker image: ${dockerImage}`);
|
|
305
266
|
console.log('\nBuild successful');
|
|
@@ -320,8 +281,8 @@ async function build(localOptions, cmd) {
|
|
|
320
281
|
const manifest = result.manifest;
|
|
321
282
|
const sourceDir = path.dirname(manifestFilePath);
|
|
322
283
|
|
|
323
|
-
const appConfig = config.
|
|
324
|
-
const buildServiceConfig =
|
|
284
|
+
const appConfig = config.getAppBuildConfig(sourceDir);
|
|
285
|
+
const buildServiceConfig = config.getBuildServiceConfig();
|
|
325
286
|
|
|
326
287
|
let repository = appConfig.repository;
|
|
327
288
|
if (!repository || options.setRepository) {
|
|
@@ -337,41 +298,48 @@ async function build(localOptions, cmd) {
|
|
|
337
298
|
if (parts.length > 1) exit(`repository should not be a URL. Try again without ${parts[0]}://`);
|
|
338
299
|
|
|
339
300
|
appConfig.repository = repository;
|
|
340
|
-
config.
|
|
301
|
+
config.setAppBuildConfig(sourceDir, appConfig);
|
|
341
302
|
}
|
|
342
303
|
|
|
343
304
|
appConfig.gitCommit = execSync('git rev-parse HEAD', { encoding: 'utf8' }).trim(); // when the build gets saved, save the gitCommit also
|
|
344
|
-
if (buildServiceConfig.type === '
|
|
345
|
-
await buildLocal(manifest, sourceDir, appConfig, options);
|
|
346
|
-
} else if (buildServiceConfig.type === 'remote' && buildServiceConfig.url) {
|
|
305
|
+
if (buildServiceConfig.type === 'remote' && buildServiceConfig.url) {
|
|
347
306
|
await buildRemote(manifest, sourceDir, appConfig, options);
|
|
348
307
|
} else {
|
|
349
|
-
|
|
308
|
+
await buildLocal(manifest, sourceDir, appConfig, options);
|
|
350
309
|
}
|
|
351
310
|
}
|
|
352
311
|
|
|
353
312
|
async function logs(localOptions, cmd) {
|
|
354
313
|
const options = cmd.optsWithGlobals();
|
|
355
314
|
|
|
315
|
+
const buildServiceConfig = config.getBuildServiceConfig();
|
|
316
|
+
if (buildServiceConfig.type !== 'remote') return exit('This command only works with the build service. Use cloudron build login first.');
|
|
317
|
+
|
|
356
318
|
if (!options.id) return exit('buildId is required');
|
|
357
319
|
|
|
358
|
-
const [logsError] = await safe(followBuildLog(options.id, !!options.raw));
|
|
320
|
+
const [logsError] = await safe(followBuildLog(buildServiceConfig, options.id, !!options.raw));
|
|
359
321
|
if (logsError) console.log(`Failed to get logs: ${logsError.message}`);
|
|
360
322
|
}
|
|
361
323
|
|
|
362
324
|
async function status(localOptions, cmd) {
|
|
363
325
|
const options = cmd.optsWithGlobals();
|
|
364
326
|
|
|
327
|
+
const buildServiceConfig = config.getBuildServiceConfig();
|
|
328
|
+
if (buildServiceConfig.type !== 'remote') return exit('This command only works with the build service. Use cloudron build login first.');
|
|
329
|
+
|
|
365
330
|
if (!options.id) return exit('buildId is required');
|
|
366
331
|
|
|
367
|
-
const [statusError,
|
|
332
|
+
const [statusError, buildStatus] = await safe(getStatus(buildServiceConfig, options.id));
|
|
368
333
|
if (statusError) return exit(`Failed to get status: ${statusError.message}`);
|
|
369
|
-
console.log(
|
|
334
|
+
console.log(buildStatus);
|
|
370
335
|
}
|
|
371
336
|
|
|
372
337
|
async function push(localOptions, cmd) {
|
|
373
338
|
const options = cmd.optsWithGlobals();
|
|
374
339
|
|
|
340
|
+
const buildServiceConfig = config.getBuildServiceConfig();
|
|
341
|
+
if (buildServiceConfig.type !== 'remote') return exit('This command only works with the build service. Use cloudron build login first.');
|
|
342
|
+
|
|
375
343
|
if (!options.id) return exit('buildId is required');
|
|
376
344
|
let repository, tag;
|
|
377
345
|
if (options.image) {
|
|
@@ -383,18 +351,64 @@ async function push(localOptions, cmd) {
|
|
|
383
351
|
tag = options.tag;
|
|
384
352
|
}
|
|
385
353
|
|
|
386
|
-
const buildServiceConfig = await resolveBuildServiceConfig(options);
|
|
387
|
-
|
|
388
354
|
const response = await superagent.post(`${buildServiceConfig.url}/api/v1/builds/${options.id}/push`)
|
|
389
355
|
.query({ accessToken: buildServiceConfig.token })
|
|
390
356
|
.send({ dockerImageRepo: repository, dockerImageTag: tag })
|
|
391
357
|
.ok(() => true);
|
|
392
358
|
if (response.status !== 201) return exit(`Failed to push: ${requestError(response)}`);
|
|
393
359
|
|
|
394
|
-
const [logsError] = await safe(followBuildLog(options.id, !!options.raw));
|
|
360
|
+
const [logsError] = await safe(followBuildLog(buildServiceConfig, options.id, !!options.raw));
|
|
395
361
|
if (logsError) console.log(`Failed to get logs: ${logsError.message}`);
|
|
396
362
|
|
|
397
|
-
const [statusError,
|
|
363
|
+
const [statusError, buildStatus] = await safe(getStatus(buildServiceConfig, options.id));
|
|
398
364
|
if (statusError) return exit(`Failed to get status: ${statusError.message}`);
|
|
399
|
-
if (
|
|
365
|
+
if (buildStatus !== 'success') return exit('Failed to push app. See log output above.');
|
|
366
|
+
}
|
|
367
|
+
|
|
368
|
+
async function clear(/* localOptions, cmd */) {
|
|
369
|
+
// const options = cmd.optsWithGlobals();
|
|
370
|
+
|
|
371
|
+
// try to find the manifest of this project
|
|
372
|
+
const manifestFilePath = helper.locateManifest();
|
|
373
|
+
if (!manifestFilePath) return exit('No CloudronManifest.json found');
|
|
374
|
+
|
|
375
|
+
const sourceDir = path.dirname(manifestFilePath);
|
|
376
|
+
|
|
377
|
+
config.unsetAppBuildConfig(sourceDir);
|
|
400
378
|
}
|
|
379
|
+
|
|
380
|
+
async function info(/* localOptions, cmd */) {
|
|
381
|
+
// const options = cmd.optsWithGlobals();
|
|
382
|
+
|
|
383
|
+
const buildService = config.getBuildServiceConfig();
|
|
384
|
+
console.log(`Build service type: ${buildService.type || 'local'}`);
|
|
385
|
+
if (buildService.type === 'remote') console.log(`Build service URL: ${buildService.url}`);
|
|
386
|
+
|
|
387
|
+
// try to find the manifest of this project
|
|
388
|
+
const manifestFilePath = helper.locateManifest();
|
|
389
|
+
if (!manifestFilePath) return exit();
|
|
390
|
+
|
|
391
|
+
const sourceDir = path.dirname(manifestFilePath);
|
|
392
|
+
const appConfig = config.getAppBuildConfig(sourceDir);
|
|
393
|
+
|
|
394
|
+
console.log('Build info');
|
|
395
|
+
if (appConfig?.dockerImage) {
|
|
396
|
+
console.log(` Image: ${appConfig.dockerImage}`); // repo:tag
|
|
397
|
+
console.log(` Git commit: ${appConfig.gitCommit || '-'}`);
|
|
398
|
+
console.log(` Image SHA256: ${appConfig.dockerImageSha256 || '-'}`);
|
|
399
|
+
} else {
|
|
400
|
+
console.log(' Image: not built');
|
|
401
|
+
}
|
|
402
|
+
}
|
|
403
|
+
|
|
404
|
+
export default {
|
|
405
|
+
login,
|
|
406
|
+
logout,
|
|
407
|
+
build,
|
|
408
|
+
logs,
|
|
409
|
+
status,
|
|
410
|
+
push,
|
|
411
|
+
clear,
|
|
412
|
+
info,
|
|
413
|
+
dockerignoreMatcher
|
|
414
|
+
};
|
package/src/completion.js
CHANGED
|
@@ -1,11 +1,7 @@
|
|
|
1
|
-
|
|
1
|
+
import * as helper from './helper.js';
|
|
2
|
+
import util from 'util';
|
|
2
3
|
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
const helper = require('./helper.js'),
|
|
6
|
-
util = require('util');
|
|
7
|
-
|
|
8
|
-
exports = module.exports = function (options, cmd) {
|
|
4
|
+
export default function (options, cmd) {
|
|
9
5
|
var completion = '';
|
|
10
6
|
|
|
11
7
|
const commands = [];
|
|
@@ -39,4 +35,4 @@ exports = module.exports = function (options, cmd) {
|
|
|
39
35
|
}
|
|
40
36
|
|
|
41
37
|
console.log(completion);
|
|
42
|
-
}
|
|
38
|
+
}
|