pkg-pr-new 0.0.4 → 0.0.6
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/dist/index.js +1144 -8488
- package/index.ts +204 -72
- package/package.json +7 -3
package/index.ts
CHANGED
|
@@ -2,15 +2,19 @@ import { defineCommand, runMain, parseArgs } from "citty";
|
|
|
2
2
|
import assert from "node:assert";
|
|
3
3
|
import path from "path";
|
|
4
4
|
import ezSpawn from "@jsdevtools/ez-spawn";
|
|
5
|
-
|
|
5
|
+
import { createHash } from "node:crypto";
|
|
6
6
|
import { hash } from "ohash";
|
|
7
|
+
import fsSync from "fs";
|
|
7
8
|
import fs from "fs/promises";
|
|
8
9
|
import { Octokit } from "@octokit/action";
|
|
9
|
-
import { pathToFileURL } from "node:url";
|
|
10
10
|
import { getPackageManifest } from "query-registry";
|
|
11
11
|
import { extractOwnerAndRepo, extractRepository } from "@pkg-pr-new/utils";
|
|
12
|
+
import fg from "fast-glob";
|
|
13
|
+
import ignore from "ignore";
|
|
12
14
|
import "./environments";
|
|
13
15
|
import pkg from "./package.json" with { type: "json" };
|
|
16
|
+
import { isBinaryFile } from "isbinaryfile";
|
|
17
|
+
import { readPackageJSON, writePackageJSON } from "pkg-types";
|
|
14
18
|
|
|
15
19
|
declare global {
|
|
16
20
|
var API_URL: string;
|
|
@@ -18,42 +22,6 @@ declare global {
|
|
|
18
22
|
|
|
19
23
|
const publishUrl = new URL("/publish", API_URL);
|
|
20
24
|
|
|
21
|
-
if (!process.env.TEST && process.env.GITHUB_ACTIONS !== "true") {
|
|
22
|
-
console.error("Continuous Releases are only available in Github Actions.");
|
|
23
|
-
process.exit(1);
|
|
24
|
-
}
|
|
25
|
-
const octokit = new Octokit();
|
|
26
|
-
|
|
27
|
-
const {
|
|
28
|
-
GITHUB_SERVER_URL,
|
|
29
|
-
GITHUB_REPOSITORY,
|
|
30
|
-
GITHUB_RUN_ID,
|
|
31
|
-
GITHUB_RUN_ATTEMPT,
|
|
32
|
-
GITHUB_ACTOR_ID,
|
|
33
|
-
GITHUB_SHA,
|
|
34
|
-
} = process.env;
|
|
35
|
-
|
|
36
|
-
const [owner, repo] = GITHUB_REPOSITORY.split("/");
|
|
37
|
-
|
|
38
|
-
const commit = await octokit.git.getCommit({
|
|
39
|
-
owner,
|
|
40
|
-
repo,
|
|
41
|
-
commit_sha: GITHUB_SHA,
|
|
42
|
-
});
|
|
43
|
-
|
|
44
|
-
const commitTimestamp = Date.parse(commit.data.committer.date);
|
|
45
|
-
|
|
46
|
-
// Note: If you need to use a workflow run's URL from within a job, you can combine these variables: $GITHUB_SERVER_URL/$GITHUB_REPOSITORY/actions/runs/$GITHUB_RUN_ID
|
|
47
|
-
const url = `${GITHUB_SERVER_URL}/${owner}/${repo}/actions/runs/${GITHUB_RUN_ID}`;
|
|
48
|
-
|
|
49
|
-
const metadata = {
|
|
50
|
-
url,
|
|
51
|
-
attempt: Number(GITHUB_RUN_ATTEMPT),
|
|
52
|
-
actor: Number(GITHUB_ACTOR_ID),
|
|
53
|
-
};
|
|
54
|
-
|
|
55
|
-
const key = hash(metadata);
|
|
56
|
-
|
|
57
25
|
const main = defineCommand({
|
|
58
26
|
meta: {
|
|
59
27
|
version: pkg.version,
|
|
@@ -69,67 +37,191 @@ const main = defineCommand({
|
|
|
69
37
|
description:
|
|
70
38
|
"compact urls. The shortest form of urls like pkg.pr.new/tinybench@a832a55)",
|
|
71
39
|
},
|
|
40
|
+
pnpm: {
|
|
41
|
+
type: "boolean",
|
|
42
|
+
description: "use `pnpm pack` instead of `npm pack --json`",
|
|
43
|
+
},
|
|
44
|
+
template: {
|
|
45
|
+
type: "string",
|
|
46
|
+
description:
|
|
47
|
+
"generate stackblitz templates out of directories in the current repo with the new built packages",
|
|
48
|
+
},
|
|
72
49
|
},
|
|
73
50
|
run: async ({ args }) => {
|
|
74
|
-
const
|
|
51
|
+
const paths = (args._.length ? args._ : ["."])
|
|
52
|
+
.flatMap((p) => (fg.isDynamicPattern(p) ? fg.sync(p) : p))
|
|
53
|
+
.map((p) => path.resolve(p));
|
|
75
54
|
|
|
76
|
-
const
|
|
77
|
-
|
|
78
|
-
|
|
55
|
+
const templates = (
|
|
56
|
+
typeof args.template === "string"
|
|
57
|
+
? [args.template]
|
|
58
|
+
: ([...(args.template ?? [])] as string[])
|
|
59
|
+
)
|
|
60
|
+
.flatMap((p) => (fg.isDynamicPattern(p) ? fg.sync(p) : p))
|
|
61
|
+
.map((p) => path.resolve(p));
|
|
62
|
+
|
|
63
|
+
const formData = new FormData();
|
|
64
|
+
|
|
65
|
+
const isCompact = !!args.compact;
|
|
66
|
+
const isPnpm = !!args.pnpm;
|
|
67
|
+
|
|
68
|
+
if (!process.env.TEST && process.env.GITHUB_ACTIONS !== "true") {
|
|
69
|
+
console.error(
|
|
70
|
+
"Continuous Releases are only available in Github Actions.",
|
|
71
|
+
);
|
|
72
|
+
process.exit(1);
|
|
73
|
+
}
|
|
74
|
+
const octokit = new Octokit();
|
|
75
|
+
|
|
76
|
+
const {
|
|
77
|
+
GITHUB_SERVER_URL,
|
|
78
|
+
GITHUB_REPOSITORY,
|
|
79
|
+
GITHUB_RUN_ID,
|
|
80
|
+
GITHUB_RUN_ATTEMPT,
|
|
81
|
+
GITHUB_ACTOR_ID,
|
|
82
|
+
} = process.env;
|
|
83
|
+
|
|
84
|
+
const [owner, repo] = GITHUB_REPOSITORY.split("/");
|
|
85
|
+
|
|
86
|
+
// Note: If you need to use a workflow run's URL from within a job, you can combine these variables: $GITHUB_SERVER_URL/$GITHUB_REPOSITORY/actions/runs/$GITHUB_RUN_ID
|
|
87
|
+
const url = `${GITHUB_SERVER_URL}/${owner}/${repo}/actions/runs/${GITHUB_RUN_ID}`;
|
|
88
|
+
|
|
89
|
+
const metadata = {
|
|
90
|
+
url,
|
|
91
|
+
attempt: Number(GITHUB_RUN_ATTEMPT),
|
|
92
|
+
actor: Number(GITHUB_ACTOR_ID),
|
|
93
|
+
};
|
|
94
|
+
|
|
95
|
+
const key = hash(metadata);
|
|
96
|
+
|
|
97
|
+
const checkResponse = await fetch(new URL("/check", API_URL), {
|
|
98
|
+
method: "POST",
|
|
99
|
+
body: JSON.stringify({
|
|
100
|
+
owner,
|
|
101
|
+
repo,
|
|
102
|
+
key,
|
|
103
|
+
}),
|
|
104
|
+
});
|
|
105
|
+
|
|
106
|
+
if (!checkResponse.ok) {
|
|
107
|
+
console.log(await checkResponse.text());
|
|
108
|
+
process.exit(1);
|
|
109
|
+
}
|
|
110
|
+
|
|
111
|
+
const { sha } = await checkResponse.json();
|
|
79
112
|
|
|
80
113
|
const deps: Map<string, string> = new Map();
|
|
81
|
-
|
|
114
|
+
|
|
82
115
|
for (const p of paths) {
|
|
83
116
|
const pJsonPath = path.resolve(p, "package.json");
|
|
84
|
-
const
|
|
117
|
+
const pJson = await readPackageJSON(pJsonPath);
|
|
118
|
+
|
|
119
|
+
if (!pJson.name) {
|
|
120
|
+
throw new Error(`"name" field in ${pJsonPath} should be defined`);
|
|
121
|
+
}
|
|
85
122
|
|
|
86
|
-
if (
|
|
87
|
-
await verifyCompactMode(name);
|
|
123
|
+
if (isCompact) {
|
|
124
|
+
await verifyCompactMode(pJson.name);
|
|
88
125
|
}
|
|
89
126
|
|
|
90
127
|
deps.set(
|
|
91
|
-
name,
|
|
128
|
+
pJson.name,
|
|
92
129
|
new URL(
|
|
93
|
-
`/${owner}/${repo}/${name}@${
|
|
130
|
+
`/${owner}/${repo}/${pJson.name}@${sha}`,
|
|
94
131
|
API_URL,
|
|
95
132
|
).href,
|
|
96
133
|
);
|
|
97
134
|
}
|
|
98
|
-
for (const p of paths) {
|
|
99
|
-
const pJsonPath = path.resolve(p, "package.json");
|
|
100
|
-
const content = await fs.readFile(pJsonPath, "utf-8");
|
|
101
|
-
pJsonContent.set(pJsonPath, content);
|
|
102
135
|
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
136
|
+
for (const templateDir of templates) {
|
|
137
|
+
const pJsonPath = path.resolve(templateDir, "package.json");
|
|
138
|
+
const pJson = await readPackageJSON(pJsonPath);
|
|
139
|
+
|
|
140
|
+
if (!pJson.name) {
|
|
141
|
+
throw new Error(`"name" field in ${pJsonPath} should be defined`);
|
|
142
|
+
}
|
|
143
|
+
|
|
144
|
+
console.log("preparing template:", pJson.name);
|
|
145
|
+
|
|
146
|
+
const restore = await writeDeps(templateDir, deps);
|
|
147
|
+
|
|
148
|
+
const gitignorePath = path.join(templateDir, ".gitignore");
|
|
149
|
+
const ig = ignore();
|
|
150
|
+
ig.add("node_modules");
|
|
151
|
+
|
|
152
|
+
if (fsSync.existsSync(gitignorePath)) {
|
|
153
|
+
const gitignoreContent = await fs.readFile(gitignorePath, "utf8");
|
|
154
|
+
ig.add(gitignoreContent);
|
|
155
|
+
}
|
|
156
|
+
|
|
157
|
+
const files = await fg(["**/*"], {
|
|
158
|
+
cwd: templateDir,
|
|
159
|
+
dot: true,
|
|
160
|
+
onlyFiles: true,
|
|
161
|
+
});
|
|
162
|
+
|
|
163
|
+
const filteredFiles = files.filter((file) => !ig.ignores(file));
|
|
164
|
+
|
|
165
|
+
for (const filePath of filteredFiles) {
|
|
166
|
+
const file = await fs.readFile(path.join(templateDir, filePath));
|
|
167
|
+
const isBinary = await isBinaryFile(file);
|
|
168
|
+
const blob = new Blob([file.buffer], {
|
|
169
|
+
type: "application/octet-stream",
|
|
170
|
+
});
|
|
171
|
+
formData.append(
|
|
172
|
+
`template:${pJson.name}:${encodeURIComponent(filePath)}`,
|
|
173
|
+
isBinary ? blob : await blob.text(),
|
|
174
|
+
);
|
|
175
|
+
}
|
|
176
|
+
await restore();
|
|
107
177
|
}
|
|
108
|
-
|
|
178
|
+
|
|
179
|
+
const restoreMap = new Map<
|
|
180
|
+
string,
|
|
181
|
+
Awaited<ReturnType<typeof writeDeps>>
|
|
182
|
+
>();
|
|
183
|
+
for (const p of paths) {
|
|
184
|
+
restoreMap.set(p, await writeDeps(p, deps));
|
|
185
|
+
}
|
|
186
|
+
|
|
187
|
+
const shasums: Record<string, string> = {};
|
|
109
188
|
for (const p of paths) {
|
|
110
189
|
const pJsonPath = path.resolve(p, "package.json");
|
|
111
190
|
try {
|
|
112
|
-
const
|
|
113
|
-
|
|
191
|
+
const pJson = await readPackageJSON(pJsonPath);
|
|
192
|
+
|
|
193
|
+
if (!pJson.name) {
|
|
194
|
+
throw new Error(
|
|
195
|
+
`"name" field in ${pJsonPath} should be defined`,
|
|
196
|
+
);
|
|
197
|
+
}
|
|
114
198
|
|
|
115
|
-
const
|
|
116
|
-
|
|
199
|
+
const { filename, shasum } = await resolveTarball(
|
|
200
|
+
isPnpm ? "pnpm" : "npm",
|
|
201
|
+
p,
|
|
202
|
+
);
|
|
203
|
+
|
|
204
|
+
shasums[pJson.name] = shasum;
|
|
205
|
+
console.log(`shasum for ${pJson.name}(${filename}): ${shasum}`);
|
|
206
|
+
|
|
207
|
+
const file = await fs.readFile(path.resolve(p, filename));
|
|
117
208
|
|
|
118
209
|
const blob = new Blob([file], {
|
|
119
210
|
type: "application/octet-stream",
|
|
120
211
|
});
|
|
121
|
-
formData.append(name
|
|
212
|
+
formData.append(`package:${pJson.name}`, blob, filename);
|
|
122
213
|
} finally {
|
|
123
|
-
await
|
|
214
|
+
await restoreMap.get(pJsonPath)?.();
|
|
124
215
|
}
|
|
125
216
|
}
|
|
126
217
|
|
|
127
218
|
const res = await fetch(publishUrl, {
|
|
128
219
|
method: "POST",
|
|
129
220
|
headers: {
|
|
130
|
-
"sb-compact": `${
|
|
221
|
+
"sb-compact": `${isCompact}`,
|
|
131
222
|
"sb-key": key,
|
|
132
|
-
"sb-
|
|
223
|
+
"sb-shasums": JSON.stringify(shasums),
|
|
224
|
+
"sb-run-id": GITHUB_RUN_ID,
|
|
133
225
|
},
|
|
134
226
|
body: formData,
|
|
135
227
|
});
|
|
@@ -140,9 +232,15 @@ const main = defineCommand({
|
|
|
140
232
|
`publishing failed: ${await res.text()}`,
|
|
141
233
|
);
|
|
142
234
|
|
|
235
|
+
console.log("\n");
|
|
143
236
|
console.log(
|
|
144
|
-
`⚡️ Your npm packages are published.
|
|
145
|
-
|
|
237
|
+
`⚡️ Your npm packages are published.\n${[...formData.keys()]
|
|
238
|
+
.filter((k) => k.startsWith("package:"))
|
|
239
|
+
.map(
|
|
240
|
+
(name, i) =>
|
|
241
|
+
`${name.slice("package:".length)}: npm i ${laterRes.urls[i]}`,
|
|
242
|
+
)
|
|
243
|
+
.join("\n")}`,
|
|
146
244
|
);
|
|
147
245
|
},
|
|
148
246
|
};
|
|
@@ -158,12 +256,46 @@ const main = defineCommand({
|
|
|
158
256
|
|
|
159
257
|
runMain(main);
|
|
160
258
|
|
|
161
|
-
|
|
162
|
-
|
|
163
|
-
|
|
164
|
-
|
|
259
|
+
// TODO: we'll add support for yarn if users hit issues with npm
|
|
260
|
+
async function resolveTarball(pm: "npm" | "pnpm", p: string) {
|
|
261
|
+
if (pm === "npm") {
|
|
262
|
+
const { stdout } = await ezSpawn.async("npm pack --json", {
|
|
263
|
+
stdio: "overlapped",
|
|
264
|
+
cwd: p,
|
|
265
|
+
});
|
|
266
|
+
|
|
267
|
+
const { filename, shasum }: { filename: string; shasum: string } =
|
|
268
|
+
JSON.parse(stdout)[0];
|
|
269
|
+
|
|
270
|
+
return { filename, shasum };
|
|
271
|
+
} else if (pm === "pnpm") {
|
|
272
|
+
const { stdout } = await ezSpawn.async("pnpm pack", {
|
|
273
|
+
stdio: "overlapped",
|
|
274
|
+
cwd: p,
|
|
275
|
+
});
|
|
276
|
+
const filename = stdout.trim();
|
|
277
|
+
|
|
278
|
+
const shasum = createHash("sha1")
|
|
279
|
+
.update(await fs.readFile(path.resolve(p, filename)))
|
|
280
|
+
.digest("hex");
|
|
281
|
+
|
|
282
|
+
return { filename, shasum };
|
|
283
|
+
}
|
|
284
|
+
throw new Error("Could not resolve package manager");
|
|
285
|
+
}
|
|
286
|
+
|
|
287
|
+
async function writeDeps(p: string, deps: Map<string, string>) {
|
|
288
|
+
const pJsonPath = path.resolve(p, "package.json");
|
|
289
|
+
const content = await fs.readFile(pJsonPath, "utf-8");
|
|
290
|
+
|
|
291
|
+
const pJson = await readPackageJSON(pJsonPath);
|
|
292
|
+
|
|
293
|
+
hijackDeps(deps, pJson.dependencies);
|
|
294
|
+
hijackDeps(deps, pJson.devDependencies);
|
|
295
|
+
|
|
296
|
+
await writePackageJSON(pJsonPath, pJson);
|
|
165
297
|
|
|
166
|
-
return
|
|
298
|
+
return () => fs.writeFile(pJsonPath, content);
|
|
167
299
|
}
|
|
168
300
|
|
|
169
301
|
function hijackDeps(
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "pkg-pr-new",
|
|
3
|
-
"version": "0.0.
|
|
3
|
+
"version": "0.0.6",
|
|
4
4
|
"description": "",
|
|
5
5
|
"main": "index.js",
|
|
6
6
|
"type": "module",
|
|
@@ -17,12 +17,16 @@
|
|
|
17
17
|
"license": "ISC",
|
|
18
18
|
"dependencies": {
|
|
19
19
|
"@jsdevtools/ez-spawn": "^3.0.4",
|
|
20
|
-
"@octokit/action": "^6.0
|
|
20
|
+
"@octokit/action": "^6.1.0",
|
|
21
|
+
"fast-glob": "^3.3.2",
|
|
22
|
+
"ignore": "^5.3.1",
|
|
23
|
+
"isbinaryfile": "^5.0.2",
|
|
24
|
+
"pkg-types": "^1.1.1",
|
|
25
|
+
"query-registry": "^3.0.0"
|
|
21
26
|
},
|
|
22
27
|
"devDependencies": {
|
|
23
28
|
"@pkg-pr-new/utils": "workspace:^",
|
|
24
29
|
"citty": "^0.1.6",
|
|
25
|
-
"query-registry": "^3.0.0",
|
|
26
30
|
"tsup": "^8.0.2"
|
|
27
31
|
}
|
|
28
32
|
}
|