@rathnasgala/cli 1.1.6 → 1.1.8

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/README.md CHANGED
@@ -31,8 +31,12 @@ accepted and its `.git` directory is preserved. To reserve a custom domain durin
31
31
  before activating it.
32
32
 
33
33
  It signs you in to Gala and to GitHub if you are not already, creates the repository, registers the
34
- publication, and leaves a working checkout in the folder. When it finishes it prints the address
35
- your publication will live at.
34
+ publication, and leaves a working checkout in the folder. GitHub starts the first deployment in the
35
+ background. The command links to that deployment rather than presenting the public address as live
36
+ before GitHub has finished.
37
+
38
+ On the first run, it opens GitHub's Gala App installation page. Choose the account Gala may use,
39
+ finish the installation, and return to the terminal; the same command resumes automatically.
36
40
 
37
41
  If the Gala GitHub App has not been given access to the new repository, it says so and links to the
38
42
  one page that grants it — GitHub has no way for an app to grant itself access, so that click is
@@ -40,12 +44,19 @@ unavoidable. Everything else is automatic.
40
44
 
41
45
  ## Write
42
46
 
47
+ Every command continues to run through `npx`; `init` does not install a global `gala` executable.
48
+ To see every command, run:
49
+
50
+ ```console
51
+ npx --yes @rathnasgala/cli@latest --help
52
+ ```
53
+
43
54
  ```console
44
55
  npx --yes @rathnasgala/cli@latest new "The places we return to"
45
56
  ```
46
57
 
47
- This creates the Markdown file and tells you the address the post will appear at. Write below the
48
- second `---` line.
58
+ This creates a local Markdown draft; it does not publish anything. It also tells you the address the
59
+ post will use after a successful publication. Write below the second `---` line.
49
60
 
50
61
  ```console
51
62
  npx --yes @rathnasgala/cli@latest preview
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@rathnasgala/cli",
3
- "version": "1.1.6",
3
+ "version": "1.1.8",
4
4
  "type": "module",
5
5
  "files": [
6
6
  "src"
@@ -26,7 +26,8 @@ import { customDomain } from '../domain.js';
26
26
  * - **GitHub** turns on Pages by itself once publishing creates a `gh-pages` branch. The CLI used
27
27
  * to poll ten minutes for a run it had caused, then call an API that changed nothing.
28
28
  *
29
- * What is left is genuinely the CLI's: asking what to call it, cloning, and reporting the address.
29
+ * What is left is genuinely the CLI's: asking what to call it, cloning, and explaining the next
30
+ * steps without presenting a deployment as live before GitHub has finished it.
30
31
  */
31
32
  const NAME = /^[a-z0-9]+(?:-[a-z0-9]+)*$/;
32
33
  const GITHUB_APP_INSTALLATION_URL = 'https://github.com/apps/gala67-app/installations/new';
@@ -87,10 +88,6 @@ export async function init({ terminal, options, cwd = process.cwd() }) {
87
88
  // writer's copy is the publication as it actually exists.
88
89
  await git.takeRemote();
89
90
 
90
- terminal.done(`Created ${created.owner}/${created.name}`);
91
- terminal.result(publicationUrl(registration, created));
92
- terminal.note(path.relative(cwd, directory) || '.');
93
-
94
91
  let domainChange;
95
92
  if (checkedDomain?.host) {
96
93
  terminal.step(`Reserving ${checkedDomain.host}`);
@@ -107,9 +104,13 @@ export async function init({ terminal, options, cwd = process.cwd() }) {
107
104
  }
108
105
  }
109
106
 
110
- terminal.blank();
111
- terminal.note('gala new "Your first post"');
112
- if (domainChange) terminal.note('gala domain check');
107
+ reportCreatedPublication({
108
+ terminal,
109
+ owner: created.owner,
110
+ name: created.name,
111
+ directoryLabel: path.relative(cwd, directory) || '.',
112
+ hasDomainChange: domainChange != null
113
+ });
113
114
 
114
115
  return { owner: created.owner, name: created.name, siteId: registration.siteId, root: directory };
115
116
  }
@@ -160,14 +161,32 @@ async function createPublication({ terminal, api, capability, name, github, inst
160
161
  throw new Error(`Gala still cannot reach the repository for ${name}.`);
161
162
  }
162
163
 
163
- export async function publicationAccount({ terminal, api, capability }) {
164
- const state = await api.githubInstallationAccounts({ capability });
165
- const accounts = Array.isArray(state?.accounts) ? state.accounts : [];
164
+ export async function publicationAccount({
165
+ terminal,
166
+ api,
167
+ capability,
168
+ pause = (milliseconds) => new Promise((resolve) => { setTimeout(resolve, milliseconds); })
169
+ }) {
170
+ let state = await api.githubInstallationAccounts({ capability });
171
+ let accounts = Array.isArray(state?.accounts) ? state.accounts : [];
166
172
  if (accounts.length === 0) {
167
- throw new Error(
168
- `Install or request the Gala GitHub App at ${state?.installationUrl
169
- ?? GITHUB_APP_INSTALLATION_URL} and try again.`
170
- );
173
+ const url = state?.installationUrl ?? GITHUB_APP_INSTALLATION_URL;
174
+ terminal.blank();
175
+ terminal.step('Connect Gala to a GitHub account');
176
+ terminal.note('GitHub will ask which account and repositories Gala may use');
177
+ terminal.openUrl(url);
178
+ if (!await terminal.waitForEnter('Once the Gala GitHub App is installed')) {
179
+ throw new Error(`Install or request the Gala GitHub App at ${url}, then run this again.`);
180
+ }
181
+
182
+ for (let attempt = 0; attempt < 5 && accounts.length === 0; attempt += 1) {
183
+ if (attempt > 0) await pause(1000);
184
+ state = await api.githubInstallationAccounts({ capability });
185
+ accounts = Array.isArray(state?.accounts) ? state.accounts : [];
186
+ }
187
+ if (accounts.length === 0) {
188
+ throw new Error(`Gala still cannot see a GitHub App installation. Check ${url}, then run this again.`);
189
+ }
171
190
  }
172
191
  const personal = accounts.find((account) => account?.organization === false);
173
192
  if (personal) return personal;
@@ -265,10 +284,37 @@ async function hasReference(directory) {
265
284
  return false;
266
285
  }
267
286
 
268
- function publicationUrl(registration, created) {
269
- const base = registration?.canonicalBaseUrl ?? `https://${created.owner.toLowerCase()}.github.io`;
270
- const prefix = registration?.pathPrefix ?? `/${created.name}`;
271
- return `${base}${prefix === '/' ? '' : prefix}/`;
287
+ export function reportCreatedPublication({
288
+ terminal,
289
+ owner,
290
+ name,
291
+ directoryLabel,
292
+ hasDomainChange = false
293
+ }) {
294
+ const run = 'npx --yes @rathnasgala/cli@latest';
295
+ terminal.done(`Created ${owner}/${name}`);
296
+ terminal.note('The first deployment is running in GitHub Actions. The public site is not live yet.');
297
+ terminal.note(`track it at https://github.com/${owner}/${name}/actions`);
298
+
299
+ terminal.blank();
300
+ terminal.result('Next steps');
301
+ if (directoryLabel !== '.') terminal.note(`cd ${shellArgument(directoryLabel)}`);
302
+ terminal.note(`${run} new "Your first post"`);
303
+ terminal.note('creates a local Markdown draft; it does not publish');
304
+ terminal.note(`${run} preview`);
305
+ terminal.note('builds and serves the publication locally');
306
+ terminal.note(`${run} publish`);
307
+ terminal.note('checks and sends the work to GitHub');
308
+ if (hasDomainChange) {
309
+ terminal.note(`${run} domain check`);
310
+ terminal.note('checks whether the custom domain is ready');
311
+ }
312
+ terminal.note(`${run} --help`);
313
+ terminal.note('lists every available command');
314
+ }
315
+
316
+ function shellArgument(value) {
317
+ return /^[A-Za-z0-9_./-]+$/.test(value) ? value : `'${value.replaceAll("'", "'\\''")}'`;
272
318
  }
273
319
 
274
320
  function idempotencyKey(owner, name) {
@@ -54,7 +54,7 @@ export async function createPost({ terminal, options, cwd = process.cwd(), now =
54
54
  if (address != null) terminal.note(`will appear at ${address}`);
55
55
 
56
56
  terminal.blank();
57
- terminal.note('write below the second --- line, then: gala preview');
57
+ terminal.note('write below the second --- line, then: npx --yes @rathnasgala/cli@latest preview');
58
58
  return { file, metadata };
59
59
  }
60
60