Skip to content

Commit 2fa983a

Browse files
authored
push: fix pusher for Bun 1.1.30 (#62)
Bun buffer-like doesn't accept directly a Buffer instance, but an ArrayBufferLike. These changes have also been tested with 1.1.29.
1 parent 2438dd6 commit 2fa983a

File tree

3 files changed

+35
-21
lines changed

3 files changed

+35
-21
lines changed

package.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@
44
"description": "An open-source R2 registry",
55
"main": "index.ts",
66
"scripts": {
7-
"deploy": "wrangler deploy",
7+
"deploy": "wrangler deploy --env production",
88
"dev:miniflare": "cross-env NODE_ENV=development wrangler --env dev dev --port 9999 --live-reload",
99
"typecheck": "tsc",
1010
"test": "vitest --config test/vitest.config.ts run"

push/bun.lockb

0 Bytes
Binary file not shown.

push/index.ts

Lines changed: 34 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -54,7 +54,7 @@ if (imageID === "") {
5454
process.exit(1);
5555
}
5656

57-
const tarFile = imageID + ".tar";
57+
const tarFile = imageID.trim() + ".tar";
5858
const imagePath = ".output-image";
5959
if (!(await file(tarFile).exists())) {
6060
const output = await $`docker save ${image} --output ${tarFile}`;
@@ -119,7 +119,7 @@ await mkdir(cacheFolder, { recursive: true });
119119
const [manifest] = manifests;
120120
const tasks = [];
121121

122-
console.log("compressing...");
122+
console.log("Compressing...");
123123
// Iterate through every layer, read it and compress to a file
124124
for (const layer of manifest.Layers) {
125125
tasks.push(
@@ -142,18 +142,17 @@ for (const layer of manifest.Layers) {
142142
}
143143

144144
const inprogressPath = path.join(cacheFolder, layerName + "-in-progress");
145-
146145
await rm(inprogressPath, { recursive: true });
147-
const layerCacheGzip = file(inprogressPath, {});
148-
146+
const layerCacheGzip = file(inprogressPath);
149147
const cacheWriter = layerCacheGzip.writer();
150148
const hasher = new Bun.CryptoHasher("sha256");
149+
151150
const gzipStream = zlib.createGzip({ level: 9 });
152151
gzipStream.pipe(
153152
new stream.Writable({
154-
write(value, _, callback) {
155-
hasher.update(value);
156-
cacheWriter.write(value);
153+
write(value: Buffer, _, callback) {
154+
cacheWriter.write(value.buffer);
155+
hasher.update(value.buffer);
157156
callback();
158157
},
159158
}),
@@ -165,7 +164,7 @@ for (const layer of manifest.Layers) {
165164
new WritableStream({
166165
write(value) {
167166
return new Promise((res, rej) => {
168-
gzipStream.write(value, "binary", (err) => {
167+
gzipStream.write(value, (err) => {
169168
if (err) {
170169
rej(err);
171170
return;
@@ -175,12 +174,21 @@ for (const layer of manifest.Layers) {
175174
});
176175
},
177176
close() {
178-
gzipStream.end();
177+
return new Promise((res) => {
178+
gzipStream.end(() => {
179+
res();
180+
});
181+
});
179182
},
180183
}),
181184
);
182185

183-
await cacheWriter.flush();
186+
await new Promise((res) =>
187+
gzipStream.flush(() => {
188+
res(true);
189+
}),
190+
);
191+
184192
await cacheWriter.end();
185193
const digest = hasher.digest("hex");
186194
await rename(inprogressPath, path.join(cacheFolder, digest));
@@ -258,8 +266,15 @@ async function pushLayer(layerDigest: string, readableStream: ReadableStream, to
258266
throw new Error("Docker-Upload-UUID not defined in headers");
259267
}
260268

269+
function parseLocation(location: string) {
270+
if (location.startsWith("/")) {
271+
return `${proto}://${imageHost}${location}`;
272+
}
273+
274+
return location;
275+
}
276+
261277
let location = createUploadResponse.headers.get("location") ?? `/v2${imageRepositoryPath}/blobs/uploads/${uploadId}`;
262-
const putChunkUploadURL = `${proto}://${imageHost}${location}`;
263278
const maxToWrite = Math.min(maxChunkLength, totalLayerSize);
264279
let end = Math.min(maxChunkLength, totalLayerSize);
265280
let written = 0;
@@ -268,10 +283,10 @@ async function pushLayer(layerDigest: string, readableStream: ReadableStream, to
268283
while (totalLayerSizeLeft > 0) {
269284
const range = `0-${Math.min(end, totalLayerSize) - 1}`;
270285
const current = new ReadableLimiter(reader as ReadableStreamDefaultReader, maxToWrite, previousReadable);
271-
286+
const patchChunkUploadURL = parseLocation(location);
272287
// we have to do fetchNode because Bun doesn't allow setting custom Content-Length.
273288
// https://github.com/oven-sh/bun/issues/10507
274-
const putChunkResult = await fetchNode(putChunkUploadURL, {
289+
const patchChunkResult = await fetchNode(patchChunkUploadURL, {
275290
method: "PATCH",
276291
body: current,
277292
headers: new Headers({
@@ -280,13 +295,13 @@ async function pushLayer(layerDigest: string, readableStream: ReadableStream, to
280295
"content-length": `${Math.min(totalLayerSizeLeft, maxToWrite)}`,
281296
}),
282297
});
283-
if (!putChunkResult.ok) {
298+
if (!patchChunkResult.ok) {
284299
throw new Error(
285-
`uploading chunk ${putChunkUploadURL} returned ${putChunkResult.status}: ${await putChunkResult.text()}`,
300+
`uploading chunk ${patchChunkUploadURL} returned ${patchChunkResult.status}: ${await patchChunkResult.text()}`,
286301
);
287302
}
288303

289-
const rangeResponse = putChunkResult.headers.get("range");
304+
const rangeResponse = patchChunkResult.headers.get("range");
290305
if (rangeResponse !== range) {
291306
throw new Error(`unexpected Range header ${rangeResponse}, expected ${range}`);
292307
}
@@ -295,14 +310,13 @@ async function pushLayer(layerDigest: string, readableStream: ReadableStream, to
295310
totalLayerSizeLeft -= previousReadable.written;
296311
written += previousReadable.written;
297312
end += previousReadable.written;
298-
location = putChunkResult.headers.get("location") ?? location;
313+
location = patchChunkResult.headers.get("location") ?? location;
299314
if (totalLayerSizeLeft != 0) console.log(layerDigest + ":", totalLayerSizeLeft, "upload bytes left.");
300315
}
301316

302317
const range = `0-${written - 1}`;
303-
const uploadURL = new URL(`${proto}://${imageHost}${location}`);
318+
const uploadURL = new URL(parseLocation(location));
304319
uploadURL.searchParams.append("digest", layerDigest);
305-
306320
const response = await fetch(uploadURL.toString(), {
307321
method: "PUT",
308322
headers: new Headers({

0 commit comments

Comments
 (0)