cloudron 8.1.1 → 8.1.2

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 CHANGED
@@ -29,6 +29,14 @@ program.option('--server <server>', 'Cloudron domain')
29
29
  const appstoreCommand = program.command('appstore').description('Commands for publishing to the Appstore')
30
30
  .option('--appstore-token <token>', 'AppStore token');
31
31
 
32
+ appstoreCommand.command('login')
33
+ .description('Login to the appstore')
34
+ .action(appstoreActions.login);
35
+
36
+ appstoreCommand.command('logout')
37
+ .description('Logout from the appstore')
38
+ .action(appstoreActions.logout);
39
+
32
40
  appstoreCommand.command('info')
33
41
  .description('List info of published app')
34
42
  .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": "8.1.1",
3
+ "version": "8.1.2",
4
4
  "license": "MIT",
5
5
  "description": "Cloudron Commandline Tool",
6
6
  "type": "module",
@@ -23,7 +23,7 @@
23
23
  "commander": "^14.0.3",
24
24
  "debug": "^4.4.3",
25
25
  "easy-table": "^1.2.0",
26
- "ejs": "^5.0.1",
26
+ "ejs": "^5.0.2",
27
27
  "eventsource": "^4.1.0",
28
28
  "micromatch": "^4.0.8",
29
29
  "open": "^11.0.0",
@@ -35,8 +35,8 @@
35
35
  },
36
36
  "devDependencies": {
37
37
  "@eslint/js": "^10.0.1",
38
- "eslint": "^10.0.3",
39
- "globals": "^17.4.0",
38
+ "eslint": "^10.2.0",
39
+ "globals": "^17.5.0",
40
40
  "mocha": "^11.7.5"
41
41
  }
42
42
  }
@@ -2,7 +2,7 @@ import assert from 'assert';
2
2
  import * as config from './config.js';
3
3
  import { execSync } from 'child_process';
4
4
  import fs from 'fs';
5
- import { exit, locateManifest, parseChangelog } from './helper.js';
5
+ import { exit, locateManifest, parseChangelog, performOidcLogin } from './helper.js';
6
6
  import manifestFormat from '@cloudron/manifest-format';
7
7
  import path from 'path';
8
8
  import safe from '@cloudron/safetydance';
@@ -14,7 +14,7 @@ const NO_MANIFEST_FOUND_ERROR_STRING = 'No CloudronManifest.json found';
14
14
  function requestError(response) {
15
15
  if (response.status === 401) return 'Invalid token.';
16
16
 
17
- return `${response.status} message: ${response.body?.message || response.text || JSON.stringify(response.body)}`; // body is sometimes just a string like in 401
17
+ return `${response.status} message: ${response.body?.message || JSON.stringify(response.body)}`;
18
18
  }
19
19
 
20
20
  function createRequest(method, apiPath, options) {
@@ -392,38 +392,67 @@ async function notify() {
392
392
 
393
393
  if (!manifest.forumUrl) return exit(new Error('CloudronManifest.json does not have a forumUrl'));
394
394
  const categoryMatch = manifest.forumUrl.match(/category\/(.*)\//);
395
- if (!categoryMatch) return exit('Unable to detect category id');
395
+ if (!categoryMatch) return exit(`Unable to detect category id from forumUrl: ${manifest.forumUrl}`);
396
396
  const categoryId = categoryMatch[1];
397
397
 
398
+ console.log(`[notify] appId: ${manifest.id} version: ${manifest.version} forumUrl: ${manifest.forumUrl} categoryId: ${categoryId}`);
399
+
398
400
  const categoryResponse = await superagent.get(`https://forum.cloudron.io/api/v3/categories/${categoryId}/topics`).set('Authorization', `Bearer ${apiToken}`).ok(() => true);
399
- if (categoryResponse.status !== 200) return exit(`Unable to get topics of category: ${requestError(categoryResponse)}`);
400
- const topic = categoryResponse.body.response.topics.find(t => t.title.toLowerCase().includes('Package Updates'.toLowerCase()));
401
+ if (categoryResponse.status !== 200) return exit(`Unable to get topics of category (status ${categoryResponse.status}): ${requestError(categoryResponse)}`);
402
+
403
+ const allTopics = categoryResponse.body.response.topics;
404
+ console.log(`[notify] Got ${allTopics.length} topics in category. Titles: ${allTopics.map(t => t.title).join(', ')}`);
405
+
406
+ const topic = allTopics.find(t => t.title.toLowerCase().includes('package updates'));
401
407
  if (!topic) return exit('Could not find the Package Update topic');
402
408
  const topicId = topic.tid;
409
+ console.log(`[notify] Found "Package Updates" topic tid: ${topicId}`);
403
410
 
404
411
  const pageCountResponse = await superagent.get(`https://forum.cloudron.io/api/topic/pagination/${topicId}`).set('Authorization', `Bearer ${apiToken}`).ok(() => true);
405
- if (pageCountResponse.status !== 200) return exit(`Unable to get page count of topic: ${requestError(pageCountResponse)}`);
412
+ if (pageCountResponse.status !== 200) return exit(`Unable to get page count of topic (status ${pageCountResponse.status}): ${requestError(pageCountResponse)}`);
406
413
  const pageCount = pageCountResponse.body.pagination.pageCount;
414
+ console.log(`[notify] Topic has ${pageCount} pages to scan for duplicates`);
407
415
 
408
416
  for (let page = 1; page <= pageCount; page++) {
409
417
  const pageResponse = await superagent.get(`https://forum.cloudron.io/api/topic/${topicId}?page=${page}`).set('Authorization', `Bearer ${apiToken}`).ok(() => true);
410
- if (pageResponse.status !== 200) return exit(`Unable to get topics of category: ${requestError(pageResponse)}`);
411
- for (const post of pageResponse.body.posts) { // post.content is html!
418
+ if (pageResponse.status !== 200) return exit(`Unable to get posts of topic page ${page} (status ${pageResponse.status}): ${requestError(pageResponse)}`);
419
+ console.log(`[notify] Page ${page}/${pageCount}: ${pageResponse.body.posts.length} posts`);
420
+ for (const post of pageResponse.body.posts) {
412
421
  if (post.content.includes(`[${manifest.version}]`)) return exit(`Version ${manifest.version} is already on the forum.\n${post.content}`);
413
422
  }
414
423
  }
415
424
 
425
+ console.log(`[notify] No duplicate found, posting version ${manifest.version}`);
426
+
416
427
  // https://docs.nodebb.org/api/write/#tag/topics/paths/~1topics~1%7Btid%7D/post
417
428
  const postData = {
418
429
  content: postContent,
419
430
  toPid: 0 // which post is this post a reply to
420
431
  };
421
432
  const postResponse = await superagent.post(`https://forum.cloudron.io/api/v3/topics/${topicId}`).set('Authorization', `Bearer ${apiToken}`).send(postData).ok(() => true);
422
- if (postResponse.status !== 200) return exit(`Unable to create changelog post: ${requestError(postResponse)}`);
433
+ if (postResponse.status !== 200) return exit(`Unable to create changelog post (status ${postResponse.status}): ${requestError(postResponse)}`);
423
434
  console.log('Posted to forum');
424
435
  }
425
436
 
437
+ async function login() {
438
+ const origin = config.appStoreOrigin();
439
+ const consoleFqdn = origin.replace('https://', '').replace('api.', 'console.') + '/openid';
440
+
441
+ const token = await performOidcLogin(consoleFqdn);
442
+ if (!token) process.exit(1);
443
+
444
+ config.setAppStoreToken(token);
445
+ console.log('Login successful.');
446
+ }
447
+
448
+ function logout() {
449
+ config.setAppStoreToken(null);
450
+ console.log('Logged out.');
451
+ }
452
+
426
453
  export default {
454
+ login,
455
+ logout,
427
456
  info,
428
457
  listVersions,
429
458
  submit,