pob 38.10.0 → 38.12.0
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/lib/generators/app/PobAppGenerator.js +24 -5
- package/lib/generators/app/vite/AppViteGenerator.js +50 -3
- package/lib/generators/app/vite/templates/index.html.ejs +11 -0
- package/lib/generators/app/vite/templates/index.ts.ejs +1 -0
- package/lib/generators/app/vite/templates/vite.config.js.ejs +8 -0
- package/lib/generators/common/babel/templates/app.rollup.config.mjs.ejs +1 -0
- package/lib/generators/common/babel/templates/lib.rollup.config.mjs.ejs +1 -0
- package/lib/generators/common/e2e/CommonE2eGenerator.js +6 -1
- package/lib/generators/common/format-lint/CommonLintGenerator.js +142 -85
- package/lib/generators/common/format-lint/templates/oxfmtrc.jsonc.ejs +1 -0
- package/lib/generators/common/husky/templates/lint-staged.config.js.txt +1 -0
- package/lib/generators/common/release/templates/workflow-release.yml.ejs +2 -1
- package/lib/generators/common/testing/templates/vite.config.js.ejs +1 -0
- package/lib/generators/common/transpiler/templates/app.rollup.config.mjs.ejs +1 -0
- package/lib/generators/common/transpiler/templates/lib.rollup.config.mjs.ejs +1 -0
- package/lib/generators/common/typescript/templates/tsconfig.check-js.json.ejs +1 -0
- package/lib/generators/common/typescript/templates/tsconfig.json.ejs +1 -0
- package/lib/generators/common/typescript/templates/tsconfig.tools.json.ejs +1 -0
- package/lib/generators/core/bun/templates/bunfig.toml.ejs +1 -0
- package/lib/generators/core/ci/templates/github-action-documentation-workflow.yml.ejs +2 -1
- package/lib/generators/core/ci/templates/github-action-push-workflow-split.yml.ejs +6 -5
- package/lib/generators/core/ci/templates/github-action-push-workflow.yml.ejs +2 -1
- package/lib/generators/core/claude/CoreClaudeGenerator.js +1 -1
- package/lib/generators/core/editorconfig/templates/editorconfig +1 -0
- package/lib/generators/core/git/CoreGitGenerator.js +72 -57
- package/lib/generators/core/git/generators/github/CoreGitGithubGenerator.js +192 -145
- package/lib/generators/core/gitignore/templates/gitignore.ejs +1 -0
- package/lib/generators/core/npm/templates/npmignore.ejs +1 -0
- package/lib/generators/core/package/CorePackageGenerator.js +21 -8
- package/lib/generators/core/pnpm/CorePnpmGenerator.js +30 -9
- package/lib/generators/core/vscode/templates/extensions.json.ejs +1 -0
- package/lib/generators/core/vscode/templates/settings.json.ejs +1 -0
- package/lib/generators/core/yarn/templates/yarn_gitignore.ejs +1 -0
- package/lib/generators/lib/doc/LibDocGenerator.js +3 -1
- package/lib/generators/lib/doc/templates/tsconfig.doc.json.ejs +1 -0
- package/lib/generators/lib/doc/templates/tsconfig.doc.json.lerna.ejs +1 -0
- package/lib/generators/lib/readme/LibReadmeGenerator.js +2 -2
- package/lib/generators/monorepo/PobMonorepoGenerator.js +26 -5
- package/lib/generators/monorepo/templates/monorepo.rollup.config.mjs.ejs +1 -0
- package/lib/generators/monorepo/typescript/MonorepoTypescriptGenerator.js +21 -10
- package/lib/generators/monorepo/typescript/templates/tsconfig.json.ejs +1 -0
- package/lib/generators/monorepo/typescript/templates/tsconfig.tools.json.ejs +1 -0
- package/lib/generators/monorepo/workspaces/MonorepoWorkspacesGenerator.js +16 -8
- package/lib/generators/pob/PobBaseGenerator.js +1 -1
- package/lib/pob.js +49 -12
- package/lib/utils/git.js +34 -0
- package/lib/utils/git.test.js +71 -0
- package/lib/utils/workspaceUtils.js +10 -0
- package/lib/utils/workspaceUtils.test.js +15 -0
- package/package.json +13 -13
- package/lib/generators/common/format-lint/templates/eslint.config.js.ejs +0 -5
|
@@ -1,8 +1,15 @@
|
|
|
1
1
|
import remoteUrl from "git-remote-url";
|
|
2
2
|
import githubUsername from "github-username";
|
|
3
3
|
import Generator from "yeoman-generator";
|
|
4
|
+
import { getRepoName, parseRepositoryUrl } from "../../../utils/git.js";
|
|
4
5
|
import * as packageUtils from "../../../utils/package.js";
|
|
5
6
|
|
|
7
|
+
const gitHostDomains = {
|
|
8
|
+
github: "github.com",
|
|
9
|
+
gitlab: "gitlab.com",
|
|
10
|
+
bitbucket: "bitbucket.org",
|
|
11
|
+
};
|
|
12
|
+
|
|
6
13
|
export default class CoreGitGenerator extends Generator {
|
|
7
14
|
constructor(args, opts) {
|
|
8
15
|
super(args, opts);
|
|
@@ -34,29 +41,29 @@ export default class CoreGitGenerator extends Generator {
|
|
|
34
41
|
}
|
|
35
42
|
|
|
36
43
|
async initializing() {
|
|
37
|
-
|
|
44
|
+
// the real remote, kept apart from the package.json fallback: only a real
|
|
45
|
+
// remote means the repository already exists
|
|
46
|
+
this.originUrl = await remoteUrl(this.destinationPath(), "origin").catch(
|
|
38
47
|
() => "",
|
|
39
48
|
);
|
|
40
49
|
|
|
41
|
-
|
|
50
|
+
let repository = parseRepositoryUrl(this.originUrl);
|
|
51
|
+
|
|
52
|
+
if (!this.originUrl) {
|
|
42
53
|
const pkg = this.fs.readJSON(this.destinationPath("package.json"), {});
|
|
43
|
-
|
|
54
|
+
repository = parseRepositoryUrl(pkg.repository);
|
|
55
|
+
if (pkg.repository && !repository) {
|
|
56
|
+
console.warn(
|
|
57
|
+
`git: ignoring invalid repository in package.json: ${JSON.stringify(pkg.repository)}`,
|
|
58
|
+
);
|
|
59
|
+
}
|
|
44
60
|
}
|
|
45
61
|
|
|
46
|
-
this.
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
/^(?:git@|https?:\/\/)(?:([^./:]+)(?:\.com)?[/:])?([^/:]+)\/([^./:]+)(?:.git)?/,
|
|
52
|
-
);
|
|
53
|
-
if (!match) return;
|
|
54
|
-
const [, gitHost, gitAccount, repoName] = match;
|
|
55
|
-
this.gitHost = gitHost || "github";
|
|
56
|
-
this.gitHostAccount = gitAccount;
|
|
57
|
-
if (repoName !== "undefined") {
|
|
58
|
-
this.repoName = repoName;
|
|
59
|
-
}
|
|
62
|
+
this.hasRepositoryUrl = !!(this.originUrl || repository);
|
|
63
|
+
if (!repository) return;
|
|
64
|
+
this.gitHost = repository.gitHost;
|
|
65
|
+
this.gitHostAccount = repository.gitAccount;
|
|
66
|
+
this.repoName = repository.repoName;
|
|
60
67
|
}
|
|
61
68
|
|
|
62
69
|
async prompting() {
|
|
@@ -72,9 +79,12 @@ export default class CoreGitGenerator extends Generator {
|
|
|
72
79
|
type: "list",
|
|
73
80
|
name: "gitHost",
|
|
74
81
|
message: "Which git host service would you like ?",
|
|
75
|
-
default: this.gitHost || (this.
|
|
82
|
+
default: this.gitHost || (this.hasRepositoryUrl ? "none" : "github"),
|
|
76
83
|
choices: [
|
|
77
|
-
{
|
|
84
|
+
{
|
|
85
|
+
value: "none",
|
|
86
|
+
name: !this.hasRepositoryUrl ? "none" : "don't change",
|
|
87
|
+
},
|
|
78
88
|
"github",
|
|
79
89
|
"bitbucket",
|
|
80
90
|
"gitlab",
|
|
@@ -121,23 +131,35 @@ export default class CoreGitGenerator extends Generator {
|
|
|
121
131
|
writing() {
|
|
122
132
|
console.log("git: writing");
|
|
123
133
|
|
|
124
|
-
if (this.gitHost === "none") {
|
|
134
|
+
if (this.gitHost === "none" || !this.gitHostAccount) {
|
|
125
135
|
return;
|
|
126
136
|
}
|
|
127
137
|
|
|
128
138
|
const pkg = this.fs.readJSON(this.destinationPath("package.json"), {});
|
|
129
|
-
const repoName = this.repoName ||
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
|
|
139
|
+
const repoName = this.repoName || getRepoName(pkg.name);
|
|
140
|
+
const repositoryUrl = `https://${this.gitHost}.com/${this.gitHostAccount}/${repoName}`;
|
|
141
|
+
|
|
142
|
+
// keep a custom homepage, but fix one pointing to another repository on the
|
|
143
|
+
// same host
|
|
144
|
+
const isHomepageInRepository = (homepage) => {
|
|
145
|
+
const lowerHomepage = homepage.toLowerCase();
|
|
146
|
+
const lowerRepositoryUrl = repositoryUrl.toLowerCase();
|
|
147
|
+
return (
|
|
148
|
+
lowerHomepage === lowerRepositoryUrl ||
|
|
149
|
+
lowerHomepage.startsWith(`${lowerRepositoryUrl}/`) ||
|
|
150
|
+
lowerHomepage.startsWith(`${lowerRepositoryUrl}#`)
|
|
151
|
+
);
|
|
152
|
+
};
|
|
153
|
+
if (
|
|
154
|
+
!pkg.homepage ||
|
|
155
|
+
(pkg.homepage.startsWith(`https://${this.gitHost}.com/`) &&
|
|
156
|
+
!isHomepageInRepository(pkg.homepage))
|
|
157
|
+
) {
|
|
158
|
+
pkg.homepage = repositoryUrl;
|
|
138
159
|
}
|
|
160
|
+
pkg.bugs = { url: `${repositoryUrl}/issues` };
|
|
139
161
|
|
|
140
|
-
const repository =
|
|
162
|
+
const repository = `${repositoryUrl}.git`;
|
|
141
163
|
|
|
142
164
|
if (pkg.repository !== repository) {
|
|
143
165
|
pkg.repository = repository;
|
|
@@ -147,37 +169,30 @@ export default class CoreGitGenerator extends Generator {
|
|
|
147
169
|
|
|
148
170
|
const cwd = this.destinationPath();
|
|
149
171
|
|
|
150
|
-
|
|
151
|
-
this.
|
|
172
|
+
const isGitRepository =
|
|
173
|
+
this.spawnSync("git", ["rev-parse", "--git-dir"], {
|
|
152
174
|
cwd,
|
|
153
175
|
stdio: "ignore",
|
|
154
176
|
reject: false,
|
|
155
|
-
}).
|
|
156
|
-
if (
|
|
157
|
-
this.
|
|
158
|
-
|
|
159
|
-
if (!this.originUrl) {
|
|
160
|
-
let repoSSH = pkg.repository;
|
|
161
|
-
if (pkg.repository && !pkg.repository.includes(".git")) {
|
|
162
|
-
/* this.spawnCommandSync('curl', [
|
|
163
|
-
'--silent',
|
|
164
|
-
'--write-out',
|
|
165
|
-
'"%{http_code}"',
|
|
166
|
-
'--output',
|
|
167
|
-
'/dev/null',
|
|
168
|
-
'-i',
|
|
169
|
-
'-u',
|
|
170
|
-
this.options.githubAccount,
|
|
171
|
-
`-d "{"name": "${this.options.name}", "auto_init": true}`,
|
|
172
|
-
'https://api.github.com/user/repos',
|
|
173
|
-
], { cwd }); */
|
|
174
|
-
|
|
175
|
-
repoSSH = pkg.repository;
|
|
176
|
-
}
|
|
177
|
+
}).exitCode === 0;
|
|
178
|
+
if (!isGitRepository) {
|
|
179
|
+
this.spawnSync("git", ["init"], { cwd });
|
|
180
|
+
}
|
|
177
181
|
|
|
178
|
-
|
|
179
|
-
|
|
180
|
-
|
|
182
|
+
if (!this.originUrl) {
|
|
183
|
+
const remoteHost = gitHostDomains[this.gitHost];
|
|
184
|
+
if (remoteHost) {
|
|
185
|
+
const originSSH = `git@${remoteHost}:${this.gitHostAccount}/${repoName}.git`;
|
|
186
|
+
const { exitCode } = this.spawnSync(
|
|
187
|
+
"git",
|
|
188
|
+
["remote", "add", "origin", originSSH],
|
|
189
|
+
{ cwd, reject: false },
|
|
190
|
+
);
|
|
191
|
+
if (exitCode !== 0) {
|
|
192
|
+
console.warn(
|
|
193
|
+
`git: failed to add origin, run by hand: git remote add origin ${originSSH}`,
|
|
194
|
+
);
|
|
195
|
+
}
|
|
181
196
|
}
|
|
182
197
|
}
|
|
183
198
|
}
|
|
@@ -1,10 +1,10 @@
|
|
|
1
|
-
/*
|
|
1
|
+
/* oxlint-disable eslint-js/camelcase */
|
|
2
2
|
|
|
3
3
|
import { spawnSync } from "node:child_process";
|
|
4
4
|
import * as os from "node:os";
|
|
5
5
|
import Generator from "yeoman-generator";
|
|
6
|
+
import { getRepoName } from "../../../../../utils/git.js";
|
|
6
7
|
import { ciContexts } from "../../../ci/CoreCIGenerator.js";
|
|
7
|
-
// const packageUtils = require('../../../../../utils/package');
|
|
8
8
|
|
|
9
9
|
const readTokenFromKeychain = () => {
|
|
10
10
|
if (process.platform !== "darwin") return undefined;
|
|
@@ -26,71 +26,36 @@ const readTokenFromKeychain = () => {
|
|
|
26
26
|
|
|
27
27
|
const GITHUB_TOKEN = process.env.POB_GITHUB_TOKEN || readTokenFromKeychain();
|
|
28
28
|
|
|
29
|
-
const
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
29
|
+
const MISSING_TOKEN_HELP =
|
|
30
|
+
'Create a token with https://github.com/settings/tokens/new?scopes=repo&description=POB%20Generator and set it in the POB_GITHUB_TOKEN env variable, or store it in the macOS keychain with: security add-generic-password -s pob-github-token -a "$USER" -w';
|
|
31
|
+
|
|
32
|
+
class GithubRequestError extends Error {
|
|
33
|
+
constructor(method, url, status, body) {
|
|
34
|
+
super(`${method} ${url} failed with status ${status}: ${body}`);
|
|
35
|
+
this.name = "GithubRequestError";
|
|
36
|
+
this.status = status;
|
|
37
|
+
}
|
|
38
|
+
}
|
|
37
39
|
|
|
38
|
-
const
|
|
39
|
-
fetch(`https://api.github.com/${url}`, {
|
|
40
|
-
method
|
|
41
|
-
body: JSON.stringify(jsonBody),
|
|
40
|
+
const githubRequest = async (method, url, jsonBody) => {
|
|
41
|
+
const res = await fetch(`https://api.github.com/${url}`, {
|
|
42
|
+
method,
|
|
43
|
+
body: jsonBody === undefined ? undefined : JSON.stringify(jsonBody),
|
|
42
44
|
headers: {
|
|
45
|
+
accept: "application/vnd.github+json",
|
|
43
46
|
authorization: `token ${GITHUB_TOKEN}`,
|
|
44
47
|
},
|
|
45
|
-
})
|
|
46
|
-
|
|
47
|
-
const
|
|
48
|
-
|
|
49
|
-
repo,
|
|
50
|
-
onlyLatestLTS,
|
|
51
|
-
spawnCommandSync,
|
|
52
|
-
) => {
|
|
53
|
-
if (!ciContexts || ciContexts.length === 0) {
|
|
54
|
-
throw new Error("Invalid ciContexts: []");
|
|
48
|
+
});
|
|
49
|
+
if (!res.ok) {
|
|
50
|
+
const body = await res.text().catch(() => "");
|
|
51
|
+
throw new GithubRequestError(method, url, res.status, body);
|
|
55
52
|
}
|
|
53
|
+
return res.json();
|
|
54
|
+
};
|
|
56
55
|
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
"git",
|
|
61
|
-
["ls-remote", "--heads", `git@github.com:${owner}/${repo}.git`, branch],
|
|
62
|
-
{ stdio: "pipe" },
|
|
63
|
-
);
|
|
64
|
-
|
|
65
|
-
const isBranchExists =
|
|
66
|
-
result.exitCode === 0 && result.stdout.toString().trim() !== "";
|
|
67
|
-
|
|
68
|
-
if (isBranchExists) {
|
|
69
|
-
await putJson(`repos/${owner}/${repo}/branches/${branch}/protection`, {
|
|
70
|
-
required_status_checks: {
|
|
71
|
-
strict: false,
|
|
72
|
-
contexts: ciContexts,
|
|
73
|
-
},
|
|
74
|
-
enforce_admins: false, // true,
|
|
75
|
-
required_pull_request_reviews: null,
|
|
76
|
-
restrictions: null,
|
|
77
|
-
required_linear_history: true,
|
|
78
|
-
allow_force_pushes: true, // false
|
|
79
|
-
allow_deletions: false,
|
|
80
|
-
});
|
|
81
|
-
if (branch === "master") {
|
|
82
|
-
console.warn('You should rename your "master" branch to "main"');
|
|
83
|
-
}
|
|
84
|
-
} else if (branch === "main") {
|
|
85
|
-
throw new Error(`Branch ${branch} does not exist`);
|
|
86
|
-
}
|
|
87
|
-
} catch (error) {
|
|
88
|
-
if (branch === "main") {
|
|
89
|
-
console.error(`Failed to configure ${branch} branch protection`);
|
|
90
|
-
console.error(error.stack || error.message || error);
|
|
91
|
-
}
|
|
92
|
-
}
|
|
93
|
-
}
|
|
56
|
+
const printError = (message, error) => {
|
|
57
|
+
console.error(message);
|
|
58
|
+
console.error(error.stack || error.message || error);
|
|
94
59
|
};
|
|
95
60
|
|
|
96
61
|
const githubRepoConfig = {
|
|
@@ -123,8 +88,8 @@ export default class CoreGitGithubGenerator extends Generator {
|
|
|
123
88
|
|
|
124
89
|
this.option("repoName", {
|
|
125
90
|
type: String,
|
|
126
|
-
required:
|
|
127
|
-
description: "repo name",
|
|
91
|
+
required: false,
|
|
92
|
+
description: "repo name, computed from the package name when missing",
|
|
128
93
|
});
|
|
129
94
|
|
|
130
95
|
this.option("onlyLatestLTS", {
|
|
@@ -139,107 +104,189 @@ export default class CoreGitGithubGenerator extends Generator {
|
|
|
139
104
|
description: "split CI jobs for faster result",
|
|
140
105
|
});
|
|
141
106
|
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
}
|
|
107
|
+
this.option("ciEnabled", {
|
|
108
|
+
type: Boolean,
|
|
109
|
+
required: true,
|
|
110
|
+
description: "ci enabled",
|
|
111
|
+
});
|
|
147
112
|
}
|
|
148
113
|
|
|
149
|
-
async
|
|
150
|
-
if (!
|
|
151
|
-
|
|
152
|
-
|
|
114
|
+
async configureProtectionRule(owner, repo) {
|
|
115
|
+
if (!this.options.ciEnabled) return;
|
|
116
|
+
if (ciContexts.length === 0) {
|
|
117
|
+
console.warn("No ci contexts: branch protection not configured");
|
|
118
|
+
return;
|
|
119
|
+
}
|
|
153
120
|
|
|
154
|
-
const
|
|
155
|
-
const name = pkg.name.endsWith("-monorepo")
|
|
156
|
-
? pkg.name.slice(0, -"-monorepo".length)
|
|
157
|
-
: pkg.name;
|
|
121
|
+
const cwd = this.destinationPath();
|
|
158
122
|
|
|
159
|
-
|
|
123
|
+
for (const branch of ["main", "master"]) {
|
|
160
124
|
try {
|
|
161
|
-
|
|
162
|
-
|
|
163
|
-
|
|
164
|
-
|
|
165
|
-
|
|
166
|
-
|
|
167
|
-
|
|
168
|
-
|
|
169
|
-
|
|
170
|
-
|
|
171
|
-
|
|
172
|
-
|
|
173
|
-
|
|
125
|
+
const result = this.spawnSync(
|
|
126
|
+
"git",
|
|
127
|
+
["ls-remote", "--heads", "origin", branch],
|
|
128
|
+
{ cwd, stdio: "pipe", reject: false },
|
|
129
|
+
);
|
|
130
|
+
|
|
131
|
+
const isBranchExists =
|
|
132
|
+
result.exitCode === 0 && result.stdout.toString().trim() !== "";
|
|
133
|
+
|
|
134
|
+
if (isBranchExists) {
|
|
135
|
+
await githubRequest(
|
|
136
|
+
"PUT",
|
|
137
|
+
`repos/${owner}/${repo}/branches/${branch}/protection`,
|
|
138
|
+
{
|
|
139
|
+
required_status_checks: {
|
|
140
|
+
strict: false,
|
|
141
|
+
contexts: ciContexts,
|
|
142
|
+
},
|
|
143
|
+
enforce_admins: false, // true,
|
|
144
|
+
required_pull_request_reviews: null,
|
|
145
|
+
restrictions: null,
|
|
146
|
+
required_linear_history: true,
|
|
147
|
+
allow_force_pushes: true, // false
|
|
148
|
+
allow_deletions: false,
|
|
149
|
+
},
|
|
150
|
+
);
|
|
151
|
+
if (branch === "master") {
|
|
152
|
+
console.warn('You should rename your "master" branch to "main"');
|
|
174
153
|
}
|
|
154
|
+
} else if (branch === "main") {
|
|
155
|
+
throw new Error(`Branch ${branch} does not exist`);
|
|
156
|
+
}
|
|
157
|
+
} catch (error) {
|
|
158
|
+
if (branch === "main") {
|
|
159
|
+
printError(`Failed to configure ${branch} branch protection`, error);
|
|
175
160
|
}
|
|
161
|
+
}
|
|
162
|
+
}
|
|
163
|
+
}
|
|
164
|
+
|
|
165
|
+
/**
|
|
166
|
+
* Runs a step of the repository setup, printing which step failed and what
|
|
167
|
+
* to run by hand instead of stopping the run.
|
|
168
|
+
*/
|
|
169
|
+
runStep(description, manualCommand, fn) {
|
|
170
|
+
try {
|
|
171
|
+
fn();
|
|
172
|
+
return true;
|
|
173
|
+
} catch (error) {
|
|
174
|
+
printError(
|
|
175
|
+
`Failed to ${description}. Run by hand: ${manualCommand}`,
|
|
176
|
+
error,
|
|
177
|
+
);
|
|
178
|
+
return false;
|
|
179
|
+
}
|
|
180
|
+
}
|
|
181
|
+
|
|
182
|
+
async createRepository(owner, repo, pkg) {
|
|
183
|
+
const cwd = this.destinationPath();
|
|
176
184
|
|
|
177
|
-
|
|
178
|
-
|
|
179
|
-
|
|
180
|
-
|
|
181
|
-
|
|
182
|
-
|
|
183
|
-
|
|
185
|
+
try {
|
|
186
|
+
const user = await githubRequest("GET", "user");
|
|
187
|
+
const isOrganization = user.login.toLowerCase() !== owner.toLowerCase();
|
|
188
|
+
await githubRequest(
|
|
189
|
+
"POST",
|
|
190
|
+
isOrganization ? `orgs/${owner}/repos` : "user/repos",
|
|
191
|
+
{
|
|
192
|
+
name: repo,
|
|
193
|
+
description: pkg.description,
|
|
194
|
+
homepage: null,
|
|
195
|
+
// only projects with an open source license are public: making a
|
|
196
|
+
// pushed public repository private does not undo its exposure
|
|
197
|
+
private: !pkg.license || pkg.license === "UNLICENSED",
|
|
198
|
+
auto_init: false,
|
|
199
|
+
...githubRepoConfig,
|
|
200
|
+
},
|
|
201
|
+
);
|
|
202
|
+
} catch (error) {
|
|
203
|
+
if (error.status !== 422) {
|
|
204
|
+
printError(
|
|
205
|
+
`Failed to create github repository ${owner}/${repo}: nothing was committed or pushed`,
|
|
206
|
+
error,
|
|
207
|
+
);
|
|
208
|
+
return;
|
|
209
|
+
}
|
|
210
|
+
console.warn(
|
|
211
|
+
`github repository ${owner}/${repo} already exists, syncing its settings`,
|
|
212
|
+
);
|
|
213
|
+
await this.syncRepository(owner, repo, pkg);
|
|
214
|
+
}
|
|
215
|
+
|
|
216
|
+
const hasCommit =
|
|
217
|
+
this.spawnSync("git", ["rev-parse", "--verify", "HEAD"], {
|
|
218
|
+
cwd,
|
|
219
|
+
stdio: "ignore",
|
|
220
|
+
reject: false,
|
|
221
|
+
}).exitCode === 0;
|
|
222
|
+
|
|
223
|
+
if (!hasCommit) {
|
|
224
|
+
const committed = this.runStep(
|
|
225
|
+
"create the initial commit",
|
|
226
|
+
'git add --all . && git commit -m "chore: initial commit [skip ci]"',
|
|
227
|
+
() => {
|
|
228
|
+
this.spawnSync("git", ["add", "--all", "."], { cwd });
|
|
229
|
+
// generated files are already formatted by pob, and hooks may need
|
|
230
|
+
// tools not installed yet
|
|
231
|
+
this.spawnSync(
|
|
184
232
|
"git",
|
|
185
|
-
[
|
|
186
|
-
|
|
187
|
-
"add",
|
|
188
|
-
"origin",
|
|
189
|
-
`git@github.com:christophehurpeau/${name}.git`,
|
|
190
|
-
],
|
|
191
|
-
{ cwd },
|
|
233
|
+
["commit", "-m", "chore: initial commit [skip ci]"],
|
|
234
|
+
{ cwd, env: { POB_GIT_HOOKS: "0" } },
|
|
192
235
|
);
|
|
193
|
-
|
|
194
|
-
|
|
195
|
-
|
|
196
|
-
|
|
197
|
-
"git",
|
|
198
|
-
["commit", "-m", "chore: initial commit [skip ci]"],
|
|
199
|
-
{ cwd },
|
|
200
|
-
);
|
|
201
|
-
this.spawnCommandSync("git", ["branch", "-M", "main"], {
|
|
202
|
-
cwd,
|
|
203
|
-
});
|
|
204
|
-
this.spawnCommandSync("git", ["push", "-u", "origin", "main"], {
|
|
205
|
-
cwd,
|
|
206
|
-
});
|
|
207
|
-
|
|
208
|
-
await configureProtectionRule(
|
|
209
|
-
owner,
|
|
210
|
-
repo,
|
|
211
|
-
this.options.onlyLatestLTS,
|
|
212
|
-
this.spawnCommandSync.bind(this),
|
|
213
|
-
);
|
|
236
|
+
},
|
|
237
|
+
);
|
|
238
|
+
if (!committed) return;
|
|
239
|
+
}
|
|
214
240
|
|
|
215
|
-
|
|
216
|
-
|
|
217
|
-
|
|
218
|
-
|
|
219
|
-
|
|
220
|
-
|
|
221
|
-
}
|
|
222
|
-
|
|
223
|
-
|
|
241
|
+
const pushed = this.runStep(
|
|
242
|
+
"push to github",
|
|
243
|
+
"git branch -M main && git push -u origin main",
|
|
244
|
+
() => {
|
|
245
|
+
this.spawnSync("git", ["branch", "-M", "main"], { cwd });
|
|
246
|
+
this.spawnSync("git", ["push", "-u", "origin", "main"], { cwd });
|
|
247
|
+
},
|
|
248
|
+
);
|
|
249
|
+
if (!pushed) return;
|
|
250
|
+
|
|
251
|
+
await this.configureProtectionRule(owner, repo);
|
|
252
|
+
}
|
|
224
253
|
|
|
225
|
-
|
|
254
|
+
async syncRepository(owner, repo, pkg) {
|
|
255
|
+
try {
|
|
256
|
+
await githubRequest("PATCH", `repos/${owner}/${repo}`, {
|
|
226
257
|
name: repo,
|
|
227
|
-
/* pkg.name
|
|
228
|
-
.replace(/-(lerna|monorepo)$/, '')
|
|
229
|
-
.replace(/^@([^-]*)-/, '$1-') */
|
|
230
258
|
description: pkg.description,
|
|
231
|
-
// homepage: null,
|
|
232
259
|
...githubRepoConfig,
|
|
233
260
|
});
|
|
261
|
+
} catch (error) {
|
|
262
|
+
printError(`Failed to sync github repository ${owner}/${repo}`, error);
|
|
263
|
+
}
|
|
264
|
+
}
|
|
234
265
|
|
|
235
|
-
|
|
236
|
-
|
|
237
|
-
|
|
238
|
-
|
|
239
|
-
|
|
240
|
-
|
|
266
|
+
async end() {
|
|
267
|
+
const pkg = this.fs.readJSON(this.destinationPath("package.json"), {});
|
|
268
|
+
const owner = this.options.gitHostAccount;
|
|
269
|
+
const repo = this.options.repoName || getRepoName(pkg.name);
|
|
270
|
+
|
|
271
|
+
if (!GITHUB_TOKEN) {
|
|
272
|
+
if (this.options.shouldCreate) {
|
|
273
|
+
console.warn(
|
|
274
|
+
`Missing POB_GITHUB_TOKEN: the github repository ${owner}/${repo} was not created, nothing was committed or pushed. ${MISSING_TOKEN_HELP}`,
|
|
275
|
+
);
|
|
276
|
+
} else if (process.env.CI !== "true") {
|
|
277
|
+
console.warn(
|
|
278
|
+
`Missing POB_GITHUB_TOKEN: github repository settings not synced. ${MISSING_TOKEN_HELP}`,
|
|
241
279
|
);
|
|
242
280
|
}
|
|
281
|
+
return;
|
|
282
|
+
}
|
|
283
|
+
|
|
284
|
+
if (this.options.shouldCreate) {
|
|
285
|
+
await this.createRepository(owner, repo, pkg);
|
|
286
|
+
} else {
|
|
287
|
+
console.log("sync github info");
|
|
288
|
+
await this.syncRepository(owner, repo, pkg);
|
|
289
|
+
await this.configureProtectionRule(owner, repo);
|
|
243
290
|
}
|
|
244
291
|
}
|
|
245
292
|
}
|
|
@@ -121,6 +121,18 @@ export default class CorePackageGenerator extends Generator {
|
|
|
121
121
|
pkg.type = this.options.packageType;
|
|
122
122
|
}
|
|
123
123
|
|
|
124
|
+
// packages of a monorepo share the author, the license and the type of the
|
|
125
|
+
// root package.json
|
|
126
|
+
const rootPkg =
|
|
127
|
+
inMonorepo && !inMonorepo.root ? inMonorepo.rootMonorepoPkg : undefined;
|
|
128
|
+
if (rootPkg) {
|
|
129
|
+
if (!pkg.author && !pkg.authors && rootPkg.author) {
|
|
130
|
+
pkg.author = rootPkg.author;
|
|
131
|
+
}
|
|
132
|
+
if (!pkg.type && rootPkg.type) pkg.type = rootPkg.type;
|
|
133
|
+
}
|
|
134
|
+
const defaultLicense = rootPkg?.license;
|
|
135
|
+
|
|
124
136
|
let author = packageUtils.parsePkgAuthor(pkg);
|
|
125
137
|
|
|
126
138
|
const props = await this.prompt(
|
|
@@ -160,7 +172,7 @@ export default class CorePackageGenerator extends Generator {
|
|
|
160
172
|
message: "License Type",
|
|
161
173
|
type: "list",
|
|
162
174
|
choices: ["MIT", "ISC", "UNLICENSED"],
|
|
163
|
-
when: !pkg.license,
|
|
175
|
+
when: !pkg.license && !defaultLicense,
|
|
164
176
|
},
|
|
165
177
|
].filter(Boolean),
|
|
166
178
|
);
|
|
@@ -257,15 +269,16 @@ export default class CorePackageGenerator extends Generator {
|
|
|
257
269
|
}
|
|
258
270
|
|
|
259
271
|
if (!pkg.license) {
|
|
260
|
-
pkg.license = props.license;
|
|
261
|
-
this.
|
|
262
|
-
|
|
263
|
-
|
|
264
|
-
|
|
272
|
+
pkg.license = props.license || defaultLicense;
|
|
273
|
+
const licenseTemplatePath = this.templatePath(
|
|
274
|
+
`licenses/${pkg.license}.ejs`,
|
|
275
|
+
);
|
|
276
|
+
if (fs.existsSync(licenseTemplatePath)) {
|
|
277
|
+
this.fs.copyTpl(licenseTemplatePath, this.destinationPath("LICENSE"), {
|
|
265
278
|
year: new Date().getFullYear(),
|
|
266
279
|
author: pkg.author,
|
|
267
|
-
}
|
|
268
|
-
|
|
280
|
+
});
|
|
281
|
+
}
|
|
269
282
|
}
|
|
270
283
|
|
|
271
284
|
if (pkg.private) {
|