mirror of
https://github.com/heygen-com/hyperframes.git
synced 2026-10-30 09:16:55 +00:00
feat(aws-lambda): attach the arm64 video image to releases and pin it (#6070)
* feat(aws-lambda): attach the arm64 video image to releases and pin it The release builds the arm64 video function image from the handler ZIP it attaches, attaches it as an OCI layout tarball with its sha256, and pins it in prebuilt/video-image.json, read through prebuiltVideoImage(). A retried release reuses the image already attached. * fix(aws-lambda): keep the release pin script out of the published package pin-handler-zip.ts is run from a checkout by publish.yml; nothing in dist or the CLI imports it. Leaving it out keeps aws-lambda under its size budget with the video image reader added.
This commit is contained in:
@@ -3,8 +3,14 @@ import { createHash } from "node:crypto";
|
||||
import { existsSync, mkdirSync, mkdtempSync, readFileSync, rmSync, writeFileSync } from "node:fs";
|
||||
import { tmpdir } from "node:os";
|
||||
import { join } from "node:path";
|
||||
import { adapterPackageRoot, prebuiltHandler } from "../src/sdk/prebuiltHandler.js";
|
||||
import { pinHandlerZip } from "./pin-handler-zip.js";
|
||||
import {
|
||||
adapterPackageRoot,
|
||||
prebuiltHandler,
|
||||
prebuiltVideoImage,
|
||||
VIDEO_IMAGE_ASSET,
|
||||
VIDEO_IMAGE_MANIFEST_FILE,
|
||||
} from "../src/sdk/prebuiltHandler.js";
|
||||
import { pinHandlerZip, pinReleaseAsset } from "./pin-handler-zip.js";
|
||||
|
||||
const examples = join(import.meta.dir, "..", "..", "..", "examples", "aws-lambda");
|
||||
const realTemplate = readFileSync(join(examples, "template.yaml"), "utf-8");
|
||||
@@ -93,6 +99,31 @@ describe("pinHandlerZip", () => {
|
||||
});
|
||||
});
|
||||
|
||||
describe("pinReleaseAsset", () => {
|
||||
it("pins the arm64 video image beside the handler zip without touching the zip's pin", () => {
|
||||
const { root, pkgDir } = fixtureRepo();
|
||||
writeFileSync(join(pkgDir, "dist", "handler.zip"), "zip");
|
||||
const zipPin = pinHandlerZip(root);
|
||||
const image = Buffer.from("oci layout tar");
|
||||
writeFileSync(join(root, "dist", VIDEO_IMAGE_ASSET), image);
|
||||
const sha256 = createHash("sha256").update(image).digest("hex");
|
||||
|
||||
const manifest = pinReleaseAsset(root, VIDEO_IMAGE_ASSET, VIDEO_IMAGE_MANIFEST_FILE);
|
||||
|
||||
expect(manifest).toEqual({
|
||||
version: "9.8.7",
|
||||
url: "https://github.com/heygen-com/hyperframes/releases/download/v9.8.7/hyperframes-lambda-video-arm64.oci.tar",
|
||||
sha256,
|
||||
bytes: image.length,
|
||||
});
|
||||
expect(readFileSync(join(root, "dist", "hyperframes-lambda-video-arm64.sha256"), "utf-8")).toBe(
|
||||
`${sha256} hyperframes-lambda-video-arm64.oci.tar\n`,
|
||||
);
|
||||
expect(prebuiltVideoImage(pkgDir)).toEqual(manifest);
|
||||
expect(prebuiltHandler(pkgDir)?.sha256).toBe(zipPin.sha256);
|
||||
});
|
||||
});
|
||||
|
||||
describe("prebuiltHandler", () => {
|
||||
it("reads from its own package root", () => {
|
||||
expect(adapterPackageRoot()).toBe(join(import.meta.dir, ".."));
|
||||
@@ -102,4 +133,11 @@ describe("prebuiltHandler", () => {
|
||||
const { pkgDir } = fixtureRepo();
|
||||
expect(prebuiltHandler(pkgDir)).toBeUndefined();
|
||||
});
|
||||
|
||||
it("has no video image when the package pins only the zip", () => {
|
||||
const { root, pkgDir } = fixtureRepo();
|
||||
writeFileSync(join(pkgDir, "dist", "handler.zip"), "zip");
|
||||
pinHandlerZip(root);
|
||||
expect(prebuiltVideoImage(pkgDir)).toBeUndefined();
|
||||
});
|
||||
});
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
#!/usr/bin/env bun
|
||||
// Release step: writes the handler ZIP's pin (asset URL + sha256) and the SAM template into the
|
||||
// package. A retried release run reuses the ZIP already on the release.
|
||||
// package, or with --video-image the arm64 video image's pin. A retried release run reuses the
|
||||
// asset already on the release.
|
||||
import { createHash } from "node:crypto";
|
||||
import { existsSync, mkdirSync, readFileSync, renameSync, rmSync, writeFileSync } from "node:fs";
|
||||
import { dirname, join, resolve } from "node:path";
|
||||
@@ -8,17 +9,42 @@ import { fileURLToPath } from "node:url";
|
||||
import {
|
||||
HANDLER_MANIFEST_FILE,
|
||||
HANDLER_ZIP_ASSET,
|
||||
type HandlerZipManifest,
|
||||
PREBUILT_DIR,
|
||||
type ReleaseAssetManifest,
|
||||
VIDEO_IMAGE_ASSET,
|
||||
VIDEO_IMAGE_MANIFEST_FILE,
|
||||
} from "../src/sdk/prebuiltHandler.js";
|
||||
import { writePrebuiltTemplate } from "./prebuilt-template.mjs";
|
||||
|
||||
export function pinHandlerZip(repoRoot: string): HandlerZipManifest {
|
||||
/** Hashes `dist/<asset>`, writes its `.sha256` beside it and its pin to `prebuilt/<manifestFile>`. */
|
||||
export function pinReleaseAsset(
|
||||
repoRoot: string,
|
||||
asset: string,
|
||||
manifestFile: string,
|
||||
): ReleaseAssetManifest {
|
||||
const pkgDir = join(repoRoot, "packages", "aws-lambda");
|
||||
const pkg = JSON.parse(readFileSync(join(pkgDir, "package.json"), "utf-8")) as {
|
||||
version: string;
|
||||
repository: { url: string };
|
||||
};
|
||||
const bytes = readFileSync(join(repoRoot, "dist", asset));
|
||||
const sha256 = createHash("sha256").update(bytes).digest("hex");
|
||||
writeFileSync(join(repoRoot, "dist", `${asset.split(".")[0]}.sha256`), `${sha256} ${asset}\n`);
|
||||
|
||||
const manifest: ReleaseAssetManifest = {
|
||||
version: pkg.version,
|
||||
url: `${pkg.repository.url}/releases/download/v${pkg.version}/${asset}`,
|
||||
sha256,
|
||||
bytes: bytes.length,
|
||||
};
|
||||
const outDir = join(pkgDir, PREBUILT_DIR);
|
||||
mkdirSync(outDir, { recursive: true });
|
||||
writeFileSync(join(outDir, manifestFile), `${JSON.stringify(manifest, null, 2)}\n`);
|
||||
return manifest;
|
||||
}
|
||||
|
||||
export function pinHandlerZip(repoRoot: string): ReleaseAssetManifest {
|
||||
const pkgDir = join(repoRoot, "packages", "aws-lambda");
|
||||
const asset = join(repoRoot, "dist", HANDLER_ZIP_ASSET);
|
||||
const built = join(pkgDir, "dist", "handler.zip");
|
||||
if (existsSync(built)) {
|
||||
@@ -26,23 +52,14 @@ export function pinHandlerZip(repoRoot: string): HandlerZipManifest {
|
||||
renameSync(built, asset);
|
||||
rmSync(`${built}.manifest.json`, { force: true });
|
||||
}
|
||||
const bytes = readFileSync(asset);
|
||||
const sha256 = createHash("sha256").update(bytes).digest("hex");
|
||||
writeFileSync(asset.replace(/\.zip$/, ".sha256"), `${sha256} ${HANDLER_ZIP_ASSET}\n`);
|
||||
|
||||
const outDir = join(pkgDir, PREBUILT_DIR);
|
||||
writePrebuiltTemplate(repoRoot, outDir);
|
||||
const manifest: HandlerZipManifest = {
|
||||
version: pkg.version,
|
||||
url: `${pkg.repository.url}/releases/download/v${pkg.version}/${HANDLER_ZIP_ASSET}`,
|
||||
sha256,
|
||||
bytes: bytes.length,
|
||||
};
|
||||
writeFileSync(join(outDir, HANDLER_MANIFEST_FILE), `${JSON.stringify(manifest, null, 2)}\n`);
|
||||
return manifest;
|
||||
writePrebuiltTemplate(repoRoot, join(pkgDir, PREBUILT_DIR));
|
||||
return pinReleaseAsset(repoRoot, HANDLER_ZIP_ASSET, HANDLER_MANIFEST_FILE);
|
||||
}
|
||||
|
||||
if (import.meta.main) {
|
||||
const repoRoot = resolve(dirname(fileURLToPath(import.meta.url)), "../../..");
|
||||
console.log(JSON.stringify(pinHandlerZip(repoRoot), null, 2));
|
||||
const manifest = process.argv.includes("--video-image")
|
||||
? pinReleaseAsset(repoRoot, VIDEO_IMAGE_ASSET, VIDEO_IMAGE_MANIFEST_FILE)
|
||||
: pinHandlerZip(repoRoot);
|
||||
console.log(JSON.stringify(manifest, null, 2));
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user