Skip to content

Commit deddb09

Browse files
authored
fix: big file uploads (#562)
* fix: use readableWebStream() to stream asset contents This allows the uploads to finish without mismatched Content-Length, likely because the original method implied a wrong body encoding or something similar. Unfortunately a GitHub server API mock was not readily available so I had to test manually with a barebones repository. Fixes: #555 Fixes: #556 Signed-off-by: WANG Xuerui <[email protected]> * feat: log when each asset is successfully uploaded Signed-off-by: WANG Xuerui <[email protected]> * build: refresh dist Signed-off-by: WANG Xuerui <[email protected]> * style: format with prettier Signed-off-by: WANG Xuerui <[email protected]> --------- Signed-off-by: WANG Xuerui <[email protected]>
1 parent 33fcd69 commit deddb09

File tree

3 files changed

+29
-25
lines changed

3 files changed

+29
-25
lines changed

__tests__/github.test.ts

+1-2
Original file line numberDiff line numberDiff line change
@@ -14,11 +14,10 @@ describe("github", () => {
1414

1515
describe("asset", () => {
1616
it("derives asset info from a path", async () => {
17-
const { name, mime, size, data } = asset("tests/data/foo/bar.txt");
17+
const { name, mime, size } = asset("tests/data/foo/bar.txt");
1818
assert.equal(name, "bar.txt");
1919
assert.equal(mime, "text/plain");
2020
assert.equal(size, 10);
21-
assert.equal(await text(data), "release me");
2221
});
2322
});
2423
});

dist/index.js

+1-1
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

src/github.ts

+27-22
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
import { GitHub } from "@actions/github/lib/utils";
22
import { Config, isTag, releaseBody, alignAssetName } from "./util";
3-
import { createReadStream, statSync, type ReadStream } from "fs";
3+
import { statSync } from "fs";
4+
import { open } from "fs/promises";
45
import { getType } from "mime";
56
import { basename } from "path";
67

@@ -10,7 +11,6 @@ export interface ReleaseAsset {
1011
name: string;
1112
mime: string;
1213
size: number;
13-
data: ReadStream;
1414
}
1515

1616
export interface Release {
@@ -145,7 +145,6 @@ export const asset = (path: string): ReleaseAsset => {
145145
name: basename(path),
146146
mime: mimeOrDefault(path),
147147
size: statSync(path).size,
148-
data: createReadStream(path, "binary"),
149148
};
150149
};
151150

@@ -161,7 +160,7 @@ export const upload = async (
161160
currentAssets: Array<{ id: number; name: string }>,
162161
): Promise<any> => {
163162
const [owner, repo] = config.github_repository.split("/");
164-
const { name, size, mime, data: body } = asset(path);
163+
const { name, mime, size } = asset(path);
165164
const currentAsset = currentAssets.find(
166165
// note: GitHub renames asset filenames that have special characters, non-alphanumeric characters, and leading or trailing periods. The "List release assets" endpoint lists the renamed filenames.
167166
// due to this renaming we need to be mindful when we compare the file name we're uploading with a name github may already have rewritten for logical comparison
@@ -179,25 +178,31 @@ export const upload = async (
179178
console.log(`⬆️ Uploading ${name}...`);
180179
const endpoint = new URL(url);
181180
endpoint.searchParams.append("name", name);
182-
const resp = await github.request({
183-
method: "POST",
184-
url: endpoint.toString(),
185-
headers: {
186-
"content-length": `${size}`,
187-
"content-type": mime,
188-
authorization: `token ${config.github_token}`,
189-
},
190-
data: body,
191-
});
192-
const json = resp.data;
193-
if (resp.status !== 201) {
194-
throw new Error(
195-
`Failed to upload release asset ${name}. received status code ${
196-
resp.status
197-
}\n${json.message}\n${JSON.stringify(json.errors)}`,
198-
);
181+
const fh = await open(path);
182+
try {
183+
const resp = await github.request({
184+
method: "POST",
185+
url: endpoint.toString(),
186+
headers: {
187+
"content-length": `${size}`,
188+
"content-type": mime,
189+
authorization: `token ${config.github_token}`,
190+
},
191+
data: fh.readableWebStream({ type: "bytes" }),
192+
});
193+
const json = resp.data;
194+
if (resp.status !== 201) {
195+
throw new Error(
196+
`Failed to upload release asset ${name}. received status code ${
197+
resp.status
198+
}\n${json.message}\n${JSON.stringify(json.errors)}`,
199+
);
200+
}
201+
console.log(`✅ Uploaded ${name}`);
202+
return json;
203+
} finally {
204+
await fh.close();
199205
}
200-
return json;
201206
};
202207

203208
export const release = async (

0 commit comments

Comments
 (0)