aboutsummaryrefslogtreecommitdiff
path: root/packages/bun-lambda/scripts/publish-layer.ts
blob: b7129fc50b6d251b7c7e89507378b5b5e92e1347 (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
import { spawnSync } from "node:child_process";
import { BuildCommand } from "./build-layer";

export class PublishCommand extends BuildCommand {
  static summary = "Publish a custom Lambda layer for Bun.";

  #aws(args: string[]): string {
    this.debug("$", "aws", ...args);
    const { status, stdout, stderr } = spawnSync("aws", args, {
      stdio: "pipe",
    });
    const result = stdout.toString("utf-8").trim();
    if (status === 0) {
      return result;
    }
    const reason = stderr.toString("utf-8").trim() || result;
    throw new Error(`aws ${args.join(" ")} exited with ${status}: ${reason}`);
  }

  async run() {
    const { flags } = await this.parse(PublishCommand);
    this.debug("Options:", flags);
    try {
      const version = this.#aws(["--version"]);
      this.debug("AWS CLI:", version);
    } catch (error) {
      this.debug(error);
      this.error(
        "Install the `aws` CLI to continue: https://docs.aws.amazon.com/cli/latest/userguide/getting-started-install.html",
        { exit: 1 },
      );
    }
    const { layer, region, arch, output, public: isPublic } = flags;
    if (region.includes("*")) {
      // prettier-ignore
      const result = this.#aws([
        "ec2",
        "describe-regions",
        "--query", "Regions[].RegionName",
        "--output", "json"
      ]);
      region.length = 0;
      for (const name of JSON.parse(result)) {
        region.push(name);
      }
    } else if (!region.length) {
      // prettier-ignore
      region.push(this.#aws([
        "configure",
        "get",
        "region"
      ]));
    }
    this.log("Publishing...");
    for (const regionName of region) {
      for (const layerName of layer) {
        // prettier-ignore
        const result = this.#aws([
          "lambda",
          "publish-layer-version",
          "--layer-name", layerName,
          "--region", regionName,
          "--description", "Bun is an incredibly fast JavaScript runtime, bundler, transpiler, and package manager.",
          "--license-info", "MIT",
          "--compatible-architectures", arch === "x64" ? "x86_64" : "arm64",
          "--compatible-runtimes", "provided.al2", "provided",
          "--zip-file", `fileb://${output}`,
          "--output", "json",
        ]);
        const { LayerVersionArn } = JSON.parse(result);
        this.log("Published", LayerVersionArn);
        if (isPublic) {
          // prettier-ignore
          this.#aws([
            "lambda",
            "add-layer-version-permission",
            "--layer-name", layerName,
            "--region", regionName,
            "--version-number", LayerVersionArn.split(":").pop(),
            "--statement-id", `${layerName}-public`,
            "--action", "lambda:GetLayerVersion",
            "--principal", "*",
          ]);
        }
      }
    }
    this.log("Done");
  }
}

await PublishCommand.run(process.argv.slice(2));