pantry/scripts/bottle.ts

103 lines
2.8 KiB
TypeScript
Raw Normal View History

2022-08-01 22:43:40 +03:00
#!/usr/bin/env -S tea -E
/* ---
2022-09-26 17:56:15 +03:00
dependencies:
gnu.org/tar: ^1.34
tukaani.org/xz: ^5
zlib.net: 1
2022-11-25 06:32:26 +03:00
gnupg.org: ^2
2022-08-01 22:43:40 +03:00
args:
- deno
- run
- --allow-net
- --allow-run
2022-08-17 15:22:22 +03:00
- --allow-env
2022-09-08 23:40:35 +03:00
- --allow-read
- --allow-write
2022-08-01 22:43:40 +03:00
- --import-map={{ srcroot }}/import-map.json
--- */
2022-09-20 14:53:40 +03:00
import { Installation } from "types"
2022-09-27 22:11:35 +03:00
import { useCellar, usePrefix, useFlags, useCache } from "hooks"
2022-12-01 23:59:02 +03:00
import { backticks, panic, run } from "utils"
import { crypto } from "deno/crypto/mod.ts"
2022-09-20 14:53:40 +03:00
import { encode } from "deno/encoding/hex.ts"
2022-11-25 06:32:26 +03:00
import { encode as base64Encode } from "deno/encoding/base64.ts"
2022-09-28 18:14:46 +03:00
import { set_output } from "./utils/gha.ts"
2022-09-30 16:03:03 +03:00
import * as ARGV from "./utils/args.ts"
2022-09-20 14:53:40 +03:00
import Path from "path"
2022-08-17 15:22:22 +03:00
2022-08-01 22:43:40 +03:00
const cellar = useCellar()
2022-09-08 23:40:35 +03:00
//-------------------------------------------------------------------------- main
2022-08-01 22:43:40 +03:00
2022-09-08 23:40:35 +03:00
if (import.meta.main) {
useFlags()
2022-08-01 22:43:40 +03:00
2022-09-26 17:56:15 +03:00
const compression = Deno.env.get("COMPRESSION") == 'xz' ? 'xz' : 'gz'
2022-12-01 23:59:02 +03:00
const gpgKey = Deno.env.get("GPG_KEY_ID") ?? panic("missing GPG_KEY_ID")
const gpgPassphrase = Deno.env.get("GPG_PASSPHRASE") ?? panic("missing GPG_PASSPHRASE")
2022-09-28 18:14:46 +03:00
const checksums: string[] = []
2022-11-25 06:32:26 +03:00
const signatures: string[] = []
2022-09-08 23:40:35 +03:00
const bottles: Path[] = []
2022-09-28 18:14:46 +03:00
2022-09-30 16:03:03 +03:00
for await (const pkg of ARGV.pkgs()) {
2022-09-28 18:14:46 +03:00
console.log({ bottling: pkg })
2022-08-01 22:43:40 +03:00
2022-09-08 23:40:35 +03:00
const installation = await cellar.resolve(pkg)
2022-09-26 17:56:15 +03:00
const path = await bottle(installation, compression)
2022-09-08 23:40:35 +03:00
const checksum = await sha256(path)
2022-11-25 06:32:26 +03:00
const signature = await gpg(path, { gpgKey, gpgPassphrase })
2022-08-01 22:43:40 +03:00
2022-09-28 18:14:46 +03:00
console.log({ bottled: path })
2022-09-08 23:40:35 +03:00
bottles.push(path)
checksums.push(checksum)
2022-11-25 06:32:26 +03:00
signatures.push(signature)
2022-09-08 23:40:35 +03:00
}
await set_output("bottles", bottles.map(b => b.relative({ to: usePrefix() })))
2022-09-28 18:14:46 +03:00
await set_output("checksums", checksums)
2022-11-25 06:32:26 +03:00
await set_output("signatures", signatures)
2022-09-08 23:40:35 +03:00
}
2022-08-01 22:43:40 +03:00
//------------------------------------------------------------------------- funcs
2022-09-26 17:56:15 +03:00
export async function bottle({ path: kegdir, pkg }: Installation, compression: 'gz' | 'xz'): Promise<Path> {
2022-09-27 22:11:35 +03:00
const tarball = useCache().path({ pkg, type: 'bottle', compression })
2022-09-26 17:56:15 +03:00
const z = compression == 'gz' ? 'z' : 'J'
const cwd = usePrefix()
2022-09-26 17:56:15 +03:00
const cmd = ["tar", `c${z}f`, tarball, kegdir.relative({ to: cwd })]
await run({ cmd, cwd })
2022-08-01 22:43:40 +03:00
return tarball
}
export async function sha256(file: Path): Promise<string> {
2022-09-28 18:14:46 +03:00
return await Deno.open(file.string, { read: true })
2022-09-20 14:53:40 +03:00
.then(file => crypto.subtle.digest("SHA-256", file.readable))
.then(buf => new TextDecoder().decode(encode(new Uint8Array(buf))))
2022-09-08 23:40:35 +03:00
}
2022-11-25 06:32:26 +03:00
interface GPGCredentials {
gpgKey: string
gpgPassphrase: string
}
async function gpg(file: Path, { gpgKey, gpgPassphrase }: GPGCredentials): Promise<string> {
const rv = await backticks({
cmd: [
"gpg",
"--detach-sign",
"--armor",
"--output",
"-",
"--local-user",
gpgKey,
"--passphrase",
gpgPassphrase,
file.string
]
})
return base64Encode(rv)
}