mirror of
https://github.com/ivabus/pantry
synced 2024-11-26 18:25:08 +03:00
gpg sign bottles
This commit is contained in:
parent
ea20c7a621
commit
e582b03fe6
3 changed files with 48 additions and 1 deletions
11
.github/workflows/build.yml
vendored
11
.github/workflows/build.yml
vendored
|
@ -197,15 +197,25 @@ jobs:
|
|||
- run: tar xzf artifacts.tgz
|
||||
working-directory: ${{ steps.tea.outputs.prefix }}
|
||||
|
||||
- run: |
|
||||
tea +gnupg.org gpg-agent --daemon || true
|
||||
echo $GPG_PRIVATE_KEY | \
|
||||
base64 -d | \
|
||||
tea +gnupg.org gpg --import --batch --yes
|
||||
env:
|
||||
GPG_PRIVATE_KEY: ${{ secrets.GPG_PRIVATE_KEY }}
|
||||
|
||||
- run: scripts/bottle.ts ${{ needs.build.outputs.built }}
|
||||
id: bottle-xz
|
||||
env:
|
||||
COMPRESSION: xz
|
||||
GPG_KEY_ID: ${{ secrets.GPG_KEY_ID }}
|
||||
|
||||
- run: scripts/bottle.ts ${{ needs.build.outputs.built }}
|
||||
id: bottle-gz
|
||||
env:
|
||||
COMPRESSION: gz
|
||||
GPG_KEY_ID: ${{ secrets.GPG_KEY_ID }}
|
||||
|
||||
- name: upload bottles
|
||||
id: upload
|
||||
|
@ -214,6 +224,7 @@ jobs:
|
|||
--srcs ${{ needs.build.outputs.srcs }} ${{ needs.build.outputs.srcs }}
|
||||
--bottles ${{ steps.bottle-gz.outputs.bottles }} ${{ steps.bottle-xz.outputs.bottles }}
|
||||
--checksums ${{ steps.bottle-gz.outputs.checksums }} ${{ steps.bottle-xz.outputs.checksums }}
|
||||
--signatures ${{ steps.bottle-gz.outputs.signatures }} ${{ steps.bottle-xz.outputs.signatures }}
|
||||
env:
|
||||
AWS_S3_BUCKET: ${{ secrets.AWS_S3_BUCKET }}
|
||||
AWS_ACCESS_KEY_ID: ${{ secrets.AWS_ACCESS_KEY_ID }}
|
||||
|
|
|
@ -5,6 +5,7 @@ dependencies:
|
|||
gnu.org/tar: ^1.34
|
||||
tukaani.org/xz: ^5
|
||||
zlib.net: 1
|
||||
gnupg.org: ^2
|
||||
args:
|
||||
- deno
|
||||
- run
|
||||
|
@ -18,9 +19,10 @@ args:
|
|||
|
||||
import { Installation } from "types"
|
||||
import { useCellar, usePrefix, useFlags, useCache } from "hooks"
|
||||
import { run } from "utils"
|
||||
import { backticks, run } from "utils"
|
||||
import { crypto } from "deno/crypto/mod.ts"
|
||||
import { encode } from "deno/encoding/hex.ts"
|
||||
import { encode as base64Encode } from "deno/encoding/base64.ts"
|
||||
import { set_output } from "./utils/gha.ts"
|
||||
import * as ARGV from "./utils/args.ts"
|
||||
import Path from "path"
|
||||
|
@ -34,7 +36,11 @@ if (import.meta.main) {
|
|||
useFlags()
|
||||
|
||||
const compression = Deno.env.get("COMPRESSION") == 'xz' ? 'xz' : 'gz'
|
||||
const gpgKey = Deno.env.get("GPG_KEY_ID")
|
||||
const gpgPassphrase = Deno.env.get("GPG_PASSPHRASE")
|
||||
if (!gpgKey || !gpgPassphrase) throw new Error("missing GPG_KEY_ID")
|
||||
const checksums: string[] = []
|
||||
const signatures: string[] = []
|
||||
const bottles: Path[] = []
|
||||
|
||||
for await (const pkg of ARGV.pkgs()) {
|
||||
|
@ -43,15 +49,18 @@ if (import.meta.main) {
|
|||
const installation = await cellar.resolve(pkg)
|
||||
const path = await bottle(installation, compression)
|
||||
const checksum = await sha256(path)
|
||||
const signature = await gpg(path, { gpgKey, gpgPassphrase })
|
||||
|
||||
console.log({ bottled: path })
|
||||
|
||||
bottles.push(path)
|
||||
checksums.push(checksum)
|
||||
signatures.push(signature)
|
||||
}
|
||||
|
||||
await set_output("bottles", bottles)
|
||||
await set_output("checksums", checksums)
|
||||
await set_output("signatures", signatures)
|
||||
}
|
||||
|
||||
|
||||
|
@ -70,3 +79,26 @@ export async function sha256(file: Path): Promise<string> {
|
|||
.then(file => crypto.subtle.digest("SHA-256", file.readable))
|
||||
.then(buf => new TextDecoder().decode(encode(new Uint8Array(buf))))
|
||||
}
|
||||
|
||||
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)
|
||||
}
|
|
@ -16,6 +16,7 @@ import { useCache, useFlags, useOffLicense, usePrefix } from "hooks"
|
|||
import { Package, PackageRequirement } from "types"
|
||||
import SemVer, * as semver from "semver"
|
||||
import { basename, dirname } from "deno/path/mod.ts"
|
||||
import { decode as base64Decode } from "deno/encoding/base64.ts"
|
||||
import Path from "path"
|
||||
import { set_output } from "./utils/gha.ts"
|
||||
import { sha256 } from "./bottle.ts"
|
||||
|
@ -101,12 +102,14 @@ const pkgs = args_get("pkgs").map(pkgutils.parse).map(assert_pkg)
|
|||
const srcs = args_get("srcs")
|
||||
const bottles = args_get("bottles")
|
||||
const checksums = args_get("checksums")
|
||||
const signatures = args_get("signatures")
|
||||
|
||||
const rv: string[] = []
|
||||
|
||||
for (const [index, pkg] of pkgs.entries()) {
|
||||
const bottle = new Path(bottles[index])
|
||||
const checksum = checksums[index]
|
||||
const signature = base64Decode(signatures[index])
|
||||
const stowed = cache.decode(bottle)!
|
||||
const key = useOffLicense("s3").key(stowed)
|
||||
const versions = await get_versions(key, pkg, bucket)
|
||||
|
@ -114,6 +117,7 @@ for (const [index, pkg] of pkgs.entries()) {
|
|||
//FIXME stream the bottle (at least) to S3
|
||||
await put(key, bottle, bucket)
|
||||
await put(`${key}.sha256sum`, `${checksum} ${basename(key)}`, bucket)
|
||||
await put(`${key}.asc`, signature, bucket)
|
||||
await put(`${dirname(key)}/versions.txt`, versions.join("\n"), bucket)
|
||||
|
||||
// mirror the sources
|
||||
|
|
Loading…
Reference in a new issue