aboutsummaryrefslogtreecommitdiff
path: root/packages/bun-release/scripts/upload-s3.ts
blob: b790eac5ca969688c68a5a8ce2a066a11f83bafd (plain) (blame)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
import { AwsClient } from "aws4fetch";
import { getBuild, getRelease, getSemver } from "../src/github";

const [tag] = process.argv.slice(2);
const bucketUrl = new URL(`${env("AWS_BUCKET")}/`, env("AWS_ENDPOINT"));
const aws = new AwsClient({
  accessKeyId: env("AWS_ACCESS_KEY_ID"),
  secretAccessKey: env("AWS_SECRET_ACCESS_KEY"),
});

const latest = await getRelease();
const release = await getRelease(tag);
console.log("Found release:", release.tag_name);

let paths: string[];
if (latest.tag_name === release.tag_name) {
  paths = ["releases/latest", `releases/${release.tag_name}`];
} else if (release.tag_name === "canary") {
  try {
    const build = await getSemver("canary", await getBuild());
    paths = ["releases/canary", `releases/${build}`];
  } catch (error) {
    console.warn(error);
    paths = ["releases/canary"];
  }
} else {
  paths = [`releases/${release.tag_name}`];
}
console.log("Found paths:", paths);

for (const asset of release.assets) {
  const url = asset.browser_download_url;
  const response = await fetch(url);
  if (!response.ok) {
    throw new Error(
      `Failed to download asset: ${response.status} ${url}`
    );
  }
  const name = asset.name;
  let contentType: string;
  switch (name.split(".").pop()) {
    case "zip":
      contentType = "application/zip";
      break;
    case "txt":
    case "asc":
      contentType = "text/plain";
      break;
    default:
      contentType = response.headers.get("Content-Type") || "";
  }
  const body = await response.arrayBuffer();
  for (const path of paths) {
    const key = `${path}/${name}`;
    console.log("Uploading:", key);
    await uploadToS3({
      key,
      body,
      headers: {
        "Content-Type": contentType,
        "Content-Disposition": `attachment; filename="${name}"`,
      },
    });
  }
}

console.log("Done");

async function uploadToS3({
  key,
  body,
  headers,
}: {
  key: string;
  body: BodyInit;
  headers?: {
    "Content-Type": string;
    "Content-Disposition"?: string;
    "Cache-Control"?: string;
  };
}): Promise<void> {
  const { href } = new URL(key, bucketUrl);
  const response = await aws.fetch(href, {
    method: "PUT",
    body,
    headers,
  });
  if (!response.ok) {
    throw new Error(
      `Failed to upload to S3: ${response.status} ${response.statusText}`
    );
  }
}

function env(name: string): string {
  const value = process.env[name];
  if (!value) {
    throw new Error(`Environment variable not found: "${name}"`);
  }
  return value;
}