@rathnasgala/cli 0.0.19 → 0.0.20

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/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@rathnasgala/cli",
3
- "version": "0.0.19",
3
+ "version": "0.0.20",
4
4
  "type": "module",
5
5
  "files": [
6
6
  "src"
package/src/index.js CHANGED
@@ -130,6 +130,9 @@ if (command === 'auth') {
130
130
  ask
131
131
  });
132
132
  const result = await scaffoldSite({
133
+ notify: (message) => process.stdout.write(`${message}\n`),
134
+ ask,
135
+ openUrl: openInBrowser,
133
136
  owner: prepared.owner,
134
137
  repository: prepared.repository,
135
138
  target: prepared.target,
@@ -22,7 +22,47 @@ export async function createPublication({
22
22
  githubAccessToken,
23
23
  name,
24
24
  fetchImpl = fetch,
25
- authorize = exchangeGithubAuthorization
25
+ authorize = exchangeGithubAuthorization,
26
+ notify = () => {},
27
+ ask,
28
+ openUrl = () => false,
29
+ shareAttempts = 3,
30
+ installationsUrl = 'https://github.com/settings/installations'
31
+ }) {
32
+ let created = false;
33
+ for (let attempt = 0; attempt < Math.max(1, shareAttempts); attempt += 1) {
34
+ const result = await requestPublication({
35
+ apiBaseUrl, galaAccessToken, githubAccessToken, name, fetchImpl, authorize
36
+ });
37
+ if (result.ready) return result.publication;
38
+
39
+ /*
40
+ * The repository exists with the right content; the App installation simply cannot see it,
41
+ * because it is scoped to selected repositories rather than all of them. Sharing it is a click,
42
+ * and asking again then returns READY — the server short-circuits on a repository it can
43
+ * already see. The browser editor recovers the same way; without this the CLI dead-ends on a
44
+ * state that is one click from working.
45
+ *
46
+ * After the first attempt the repository exists, so a further refusal reports UNSUPPORTED
47
+ * rather than NEEDS_SHARING — the same situation under a different name.
48
+ */
49
+ const shareable = result.status === 'NEEDS_SHARING' || created;
50
+ created = created || result.status === 'NEEDS_SHARING';
51
+ if (!shareable || typeof ask !== 'function') throw result.failure;
52
+
53
+ notify(`${result.owner ?? ''}/${result.repository ?? name} exists, but the Gala GitHub App `
54
+ + 'cannot reach it yet — its installation covers only selected repositories.');
55
+ notify(`${openUrl(installationsUrl) ? 'Opened' : 'Open'} ${installationsUrl}`);
56
+ await ask('Press enter once the App can access that repository. ');
57
+ }
58
+ throw new Error(
59
+ `The Gala GitHub App still cannot reach the repository for ${name}. Give it access at `
60
+ + `${installationsUrl}, then run scaffold again.`
61
+ );
62
+ }
63
+
64
+ async function requestPublication({
65
+ apiBaseUrl, galaAccessToken, githubAccessToken, name, fetchImpl, authorize
26
66
  }) {
27
67
  const authorization = await authorize({
28
68
  apiBaseUrl, galaAccessToken, githubAccessToken, fetchImpl
@@ -44,19 +84,16 @@ export async function createPublication({
44
84
  const owner = payload?.owner;
45
85
  const repository = payload?.name;
46
86
 
47
- if (status === 'NEEDS_SHARING') {
48
- throw new Error(
49
- `${owner}/${repository} was created from the template, but the Gala GitHub App cannot reach `
50
- + 'it yet. Open https://github.com/settings/installations, give the App access to that '
51
- + 'repository, then run scaffold again with --resume.'
52
- );
53
- }
54
87
  if (status !== 'READY') {
55
- throw new Error(
56
- `Gala could not create the publication repository (${payload?.outcome ?? status}). `
57
- + 'Create it from https://github.com/rathnasgala/site-template yourself, then run scaffold '
58
- + 'with --empty-existing-repository.'
59
- );
88
+ return {
89
+ ready: false, status, owner, repository,
90
+ failure: new Error(
91
+ `Gala could not create the publication repository (${payload?.outcome ?? status}). `
92
+ + 'Give the Gala GitHub App access to it at https://github.com/settings/installations, or '
93
+ + 'create it from https://github.com/rathnasgala/site-template yourself and run scaffold '
94
+ + 'with --empty-existing-repository.'
95
+ )
96
+ };
60
97
  }
61
98
  if (typeof owner !== 'string' || typeof repository !== 'string') {
62
99
  throw new TypeError('Gala publication creation returned no repository identity');
@@ -66,7 +103,7 @@ export async function createPublication({
66
103
  throw new TypeError('Gala publication creation returned no installation');
67
104
  }
68
105
 
69
- return Object.freeze({
106
+ return { ready: true, status, owner, repository, publication: Object.freeze({
70
107
  owner,
71
108
  repository,
72
109
  installationId,
@@ -74,5 +111,5 @@ export async function createPublication({
74
111
  // The server names the repository it actually made, which may differ from what was asked for.
75
112
  fullName: `${owner}/${repository}`,
76
113
  cloneUrl: `https://github.com/${owner}/${repository}.git`
77
- });
114
+ }) };
78
115
  }
@@ -48,6 +48,7 @@ function registrationLocation(owner, topology, canonicalBaseUrl) {
48
48
 
49
49
  export async function scaffoldSite({
50
50
  owner, repository, target, githubInstallationId, siteOptions, emptyExistingRepository = false,
51
+ notify = (message) => process.stdout.write(`${message}\n`), ask, openUrl,
51
52
  resumeExistingCheckout = false, topology = 'provider-default', canonicalBaseUrl, actionRef,
52
53
  buildMode = 'build-and-deploy', templateOwner = 'rathnasgala',
53
54
  templateRepository = 'site-template',
@@ -110,7 +111,8 @@ export async function scaffoldSite({
110
111
  */
111
112
  const created = await createRepository({
112
113
  apiBaseUrl: gala.apiBaseUrl, galaAccessToken: gala.accessToken,
113
- githubAccessToken: github.accessToken, name: repositoryName
114
+ githubAccessToken: github.accessToken, name: repositoryName,
115
+ notify, ask, openUrl
114
116
  });
115
117
  repositoryOwner = segment(created.owner, 'owner');
116
118
  repositoryName = segment(created.repository, 'repository');