cloudron 5.11.8 → 5.11.9
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/cloudron-appstore +1 -4
- package/package.json +2 -2
- package/src/appstore-actions.js +24 -64
package/bin/cloudron-appstore
CHANGED
|
@@ -32,16 +32,13 @@ program.command('info')
|
|
|
32
32
|
program.command('approve')
|
|
33
33
|
.description('Approve a submitted app version')
|
|
34
34
|
.option('--appstore-id <appid@version>', 'Appstore id and version')
|
|
35
|
+
.option('--no-git-push', 'Do not attempt to push to git repo')
|
|
35
36
|
.action(appstoreActions.approve);
|
|
36
37
|
|
|
37
38
|
program.command('notify')
|
|
38
39
|
.description('Notify forum about successful app submission')
|
|
39
40
|
.action(appstoreActions.notify);
|
|
40
41
|
|
|
41
|
-
program.command('tag <version>')
|
|
42
|
-
.description('Tag the repo')
|
|
43
|
-
.action(appstoreActions.tag);
|
|
44
|
-
|
|
45
42
|
program.command('revoke')
|
|
46
43
|
.description('Revoke a published app version')
|
|
47
44
|
.option('--appstore-id <appid@version>', 'Appstore id and version')
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "cloudron",
|
|
3
|
-
"version": "5.11.
|
|
3
|
+
"version": "5.11.9",
|
|
4
4
|
"license": "MIT",
|
|
5
5
|
"description": "Cloudron Commandline Tool",
|
|
6
6
|
"main": "main.js",
|
|
@@ -18,7 +18,7 @@
|
|
|
18
18
|
"author": "Cloudron Developers <support@cloudron.io>",
|
|
19
19
|
"dependencies": {
|
|
20
20
|
"async": "^3.2.5",
|
|
21
|
-
"cloudron-manifestformat": "^5.
|
|
21
|
+
"cloudron-manifestformat": "^5.26.2",
|
|
22
22
|
"commander": "^12.1.0",
|
|
23
23
|
"debug": "^4.3.5",
|
|
24
24
|
"easy-table": "^1.2.0",
|
package/src/appstore-actions.js
CHANGED
|
@@ -25,7 +25,6 @@ exports = module.exports = {
|
|
|
25
25
|
revoke,
|
|
26
26
|
approve,
|
|
27
27
|
|
|
28
|
-
tag,
|
|
29
28
|
notify
|
|
30
29
|
};
|
|
31
30
|
|
|
@@ -305,7 +304,7 @@ async function upload(localOptions, cmd) {
|
|
|
305
304
|
|
|
306
305
|
const [repo, tag] = manifest.dockerImage.split(':');
|
|
307
306
|
const [tagError, tagResponse] = await safe(superagent.get(`https://hub.docker.com/v2/repositories/${repo}/tags/${tag}`).ok(() => true));
|
|
308
|
-
if (tagError || tagResponse.statusCode !== 200) return exit(`Failed to find docker image in dockerhub. check https://hub.docker.com/r/${repo}/tags : ${requestError(tagResponse)}`);
|
|
307
|
+
if (tagError || tagResponse.statusCode !== 200) return exit(`Failed to find docker image in dockerhub. check https://hub.docker.com/r/${repo}/tags : ${tagError || requestError(tagResponse)}`);
|
|
309
308
|
|
|
310
309
|
// ensure the app is known on the appstore side
|
|
311
310
|
const baseDir = path.dirname(manifestFilePath);
|
|
@@ -366,9 +365,32 @@ async function approve(localOptions, cmd) {
|
|
|
366
365
|
|
|
367
366
|
console.log(`Approving ${appstoreId}@${version}`);
|
|
368
367
|
|
|
368
|
+
let defaultBranch, latestTag;
|
|
369
|
+
if (options.gitPush) {
|
|
370
|
+
// Git repo pre-flight checks: checking if latest tag matches latest commit
|
|
371
|
+
defaultBranch = safe.child_process.execSync(`git symbolic-ref refs/remotes/origin/HEAD | sed 's@^refs/remotes/origin/@@'`, { encoding: 'utf8' });
|
|
372
|
+
if (safe.error) return exit(`Failed to get default branch: ${safe.error.message}`);
|
|
373
|
+
|
|
374
|
+
const defaultBranchSha = safe.child_process.execSync(`git rev-parse ${defaultBranch}`, { encoding: 'utf8' });
|
|
375
|
+
if (safe.error) return exit(`Failed to get head of ${defaultBranch}: ${safe.error.message}`);
|
|
376
|
+
|
|
377
|
+
latestTag = safe.child_process.execSync('git describe --tags --abbrev=0', { encoding: 'utf8' });
|
|
378
|
+
if (safe.error) return exit(`Failed to get latest tag: ${safe.error.message}`);
|
|
379
|
+
|
|
380
|
+
const latestTagSha = safe.child_process.execSync(`git rev-list -n 1 ${latestTag}`, { encoding: 'utf8' });
|
|
381
|
+
if (safe.error) return exit(`Failed to get head of ${defaultBranch}: ${safe.error.message}`);
|
|
382
|
+
|
|
383
|
+
if (defaultBranchSha !== latestTagSha) return exit(`Latest tag ${latestTag} does not match HEAD of ${defaultBranch}`);
|
|
384
|
+
}
|
|
385
|
+
|
|
369
386
|
const response = await createRequest('POST', `/api/v1/developers/apps/${appstoreId}/versions/${version}/approve`, options);
|
|
370
387
|
if (response.statusCode !== 200) return exit(`Failed to approve version: ${requestError(response)}`);
|
|
371
388
|
|
|
389
|
+
if (options.gitPush) {
|
|
390
|
+
safe.child_process.execSync(`git push --atomic origin ${defaultBranch} ${latestTag}`, { encoding: 'utf8' });
|
|
391
|
+
if (safe.error) return exit(`Failed to get last release tag: ${safe.error.message}`);
|
|
392
|
+
}
|
|
393
|
+
|
|
372
394
|
console.log('Approved.');
|
|
373
395
|
console.log('');
|
|
374
396
|
|
|
@@ -382,68 +404,6 @@ async function approve(localOptions, cmd) {
|
|
|
382
404
|
console.log('');
|
|
383
405
|
}
|
|
384
406
|
|
|
385
|
-
async function tag(version) {
|
|
386
|
-
const basename = `${path.basename(process.cwd())}`;
|
|
387
|
-
if (!basename.endsWith('-app')) return exit('Does not look like a app repo. Has to end with -app');
|
|
388
|
-
|
|
389
|
-
if (!semver.valid(version)) return exit(`${version} is not a valid semver`);
|
|
390
|
-
|
|
391
|
-
const latestTag = safe.child_process.execSync('git describe --tags --abbrev=0', { encoding: 'utf8' });
|
|
392
|
-
if (safe.error) return exit(`Failed to get last release tag: ${safe.error.message}`);
|
|
393
|
-
|
|
394
|
-
const manifestFilePath = locateManifest();
|
|
395
|
-
if (!manifestFilePath) return exit('Could not locate CloudronManifest.json');
|
|
396
|
-
|
|
397
|
-
const result = manifestFormat.parseFile(manifestFilePath);
|
|
398
|
-
if (result.error) return exit(new Error(`Invalid CloudronManifest.json: ${result.error.message}`));
|
|
399
|
-
const { manifest } = result;
|
|
400
|
-
|
|
401
|
-
const latestVersion = latestTag.match(/v(.*)/)[1];
|
|
402
|
-
|
|
403
|
-
if (semver.lte(version, latestVersion)) return exit(`${version} is less than or equal to last repo tag ${latestVersion}`);
|
|
404
|
-
if (semver.inc(latestVersion, 'major') !== version
|
|
405
|
-
&& semver.inc(latestVersion, 'minor') !== version
|
|
406
|
-
&& semver.inc(latestVersion, 'patch') !== version) {
|
|
407
|
-
return exit(`${version} is not the next major/minor/patch of last published version ${latestVersion}`);
|
|
408
|
-
}
|
|
409
|
-
|
|
410
|
-
const latestRenovateCommit = safe.child_process.execSync('git log -n 1 --committer=renovatebot@cloudron.io --pretty="format:%h,%aI,%s"', { encoding: 'utf8' });
|
|
411
|
-
if (!latestRenovateCommit) return exit('Could not find a commit from renovate bot');
|
|
412
|
-
|
|
413
|
-
const [ , , commitMessage ] = latestRenovateCommit.split(',');
|
|
414
|
-
const repoDir = path.dirname(manifestFilePath);
|
|
415
|
-
const upstreamVersion = commitMessage.match(/update dependency .* to (.*)/)[1];
|
|
416
|
-
|
|
417
|
-
console.log(`Enter the changelog for ${upstreamVersion}: (press ctrl+D to finish)`);
|
|
418
|
-
const rawChangelog = fs.readFileSync(0, 'utf-8');
|
|
419
|
-
const mdChangelog = rawChangelog.split('\n').map(line => {
|
|
420
|
-
line = line.trim();
|
|
421
|
-
line = line.replace(/[\u{0080}-\u{FFFF}]/gu, ''); // only ascii
|
|
422
|
-
line = line.replace(/^\* /, ''); // replace any "* " in the front
|
|
423
|
-
return line ? `* ${line}` : '';
|
|
424
|
-
}).join('\n');
|
|
425
|
-
const newChangelog = `\n[${version}]\n* Update ${manifest.title} to ${upstreamVersion}\n${mdChangelog}\n`;
|
|
426
|
-
const changelogFile = `${repoDir}/${manifest.changelog.replace('file://', '')}`; // sometimes CHANGELOG, sometimes CHANGELOG.md
|
|
427
|
-
fs.appendFileSync(changelogFile, newChangelog);
|
|
428
|
-
|
|
429
|
-
manifest.version = version;
|
|
430
|
-
manifest.upstreamVersion = upstreamVersion;
|
|
431
|
-
fs.writeFileSync('CloudronManifest.json', JSON.stringify(manifest, null, 2));
|
|
432
|
-
|
|
433
|
-
// git branch --show-current does not work in CI :/
|
|
434
|
-
const mainOrMaster = safe.child_process.execSync('git branch -r --list origin/master origin/main', { encoding: 'utf8' });
|
|
435
|
-
if (safe.error) return exit('Could not determine branch name');
|
|
436
|
-
const branch = mainOrMaster.includes('master') ? 'master' : 'main';
|
|
437
|
-
|
|
438
|
-
execSync(`git commit -a -m 'Version ${version}'`, { encoding: 'utf8' });
|
|
439
|
-
execSync(`git tag v${version} -a -m 'Version ${version}'`, { encoding: 'utf8' });
|
|
440
|
-
console.log(`git push --atomic origin ${branch} v${version}`);
|
|
441
|
-
execSync(`git push --atomic origin HEAD:${branch} v${version}`, { encoding: 'utf8' }); // push this tag only. in CI, we might have a git cache
|
|
442
|
-
if (safe.error) return exit(`Failed to push tag v${version} and branch ${branch}: ${safe.error.message}`, { encoding: 'utf8' });
|
|
443
|
-
|
|
444
|
-
console.log(`Created tag v${version} and pushed branch ${branch}`);
|
|
445
|
-
}
|
|
446
|
-
|
|
447
407
|
// https://docs.nodebb.org/api/read/
|
|
448
408
|
// https://docs.nodebb.org/api/write/
|
|
449
409
|
async function notify() {
|