pantry/scripts/upload.ts
2022-09-22 15:37:54 -04:00

97 lines
2.8 KiB
TypeScript
Executable file
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

#!/usr/bin/env -S tea -E
/*---
args:
- deno
- run
- --allow-net
- --allow-read
- --allow-env
- --import-map={{ srcroot }}/import-map.json
---*/
import { S3 } from "s3"
import { panic, pkg as pkgutils } from "utils"
import { useCache, useFlags } from "hooks"
import { Package } from "types"
import SemVer, * as semver from "semver"
import { dirname, basename } from "deno/path/mod.ts"
useFlags()
if (Deno.args.length === 0) throw new Error("no args supplied")
const s3 = new S3({
accessKeyID: Deno.env.get("AWS_ACCESS_KEY_ID")!,
secretKey: Deno.env.get("AWS_SECRET_ACCESS_KEY")!,
region: "us-east-1",
})
const bucket = s3.getBucket(Deno.env.get("AWS_S3_BUCKET")!)
const encode = (() => { const e = new TextEncoder(); return e.encode.bind(e) })()
const pkgs = args_get("pkgs").map(pkgutils.parse).map(x => "version" in x ? x : panic<Package>())
const bottles = args_get("bottles")
const checksums = args_get("checksums")
function args_get(key: string): string[] {
const it = Deno.args[Symbol.iterator]()
while (true) {
const { value, done } = it.next()
if (done) throw new Error()
if (value === `--${key}`) break
}
const rv: string[] = []
while (true) {
const { value, done } = it.next()
if (done) return rv
if (value.startsWith('--')) return rv
rv.push(value)
}
}
for (const [index, pkg] of pkgs.entries()) {
const bottle = bottles[index]
const checksum = checksums[index]
const key = useCache().s3Key(pkg)
//FIXME stream it to S3
const bottle_contents = await Deno.readFile(bottle)
const checksum_contents = fixup_checksum(await Deno.readFile(checksum), basename(bottle))
const versions = await get_versions(pkg)
console.log({ uploading: key })
await bucket.putObject(key, bottle_contents)
await bucket.putObject(`${key}.sha256sum`, checksum_contents)
await bucket.putObject(`${dirname(key)}/versions.txt`, encode(versions.join("\n")))
console.log({ uploaded: key })
}
//end
async function get_versions(pkg: Package): Promise<SemVer[]> {
const prefix = dirname(useCache().s3Key(pkg))
const rsp = await bucket.listObjects({ prefix })
//FIXME? API isnt clear if these nulls indicate failure or not
//NOTE if this is a new package then some empty results is expected
const got = rsp
?.contents
?.compact(x => x.key)
.map(x => basename(x))
.filter(x => x.match(/v.*\.tar\.gz$/))
.map(x => x.replace(/v(.*)\.tar\.gz/, "$1"))
.compact(semver.parse)
?? []
// have to add pkg.version as put and get are not atomic
return [...new Set([...got, pkg.version])].sort()
}
// Somewhat hacky. We call the bottle on thing locally, and another on the server.
function fixup_checksum(data: Uint8Array, new_file_name: string) {
const checksum = new TextDecoder().decode(data).split(" ")[0]
return new TextEncoder().encode(`${checksum} ${new_file_name}`)
}