diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml index bafa92fc..8894f3a3 100644 --- a/.github/workflows/build.yml +++ b/.github/workflows/build.yml @@ -121,7 +121,7 @@ jobs: - os: [self-hosted, linux, ARM64] name: linux+aarch64 outputs: - HAS_SECRETS: ${{ secrets.AWS_S3_CACHE != '' }} + HAS_SECRETS: ${{ env.HAS_SECRETS }} container: ${{ matrix.platform.container }} steps: - uses: actions/checkout@v3 @@ -154,10 +154,15 @@ jobs: - run: tea.xyz/var/pantry/scripts/test.ts ${{ inputs.projects }} + - run: + echo "HAS_SECRETS=$HAS_SECRETS" >>$GITHUB_ENV + env: + HAS_SECRETS: ${{ secrets.AWS_S3_CACHE != null }} + stage: needs: [test] # this only works for PRs from our team to our repo (security! :( ) - if: startsWith(github.ref, 'refs/pull/') && startsWith(github.repository, 'teaxyz/pantry.') && needs.test.outputs.HAS_SECRETS + if: startsWith(github.ref, 'refs/pull/') && startsWith(github.repository, 'teaxyz/pantry.') && needs.test.outputs.HAS_SECRETS == 'true' runs-on: ubuntu-latest strategy: matrix: diff --git a/.github/workflows/cd.yml b/.github/workflows/cd.yml index 203e89cf..d75f3f4c 100644 --- a/.github/workflows/cd.yml +++ b/.github/workflows/cd.yml @@ -8,7 +8,7 @@ jobs: cd: runs-on: ubuntu-latest outputs: - HAS_SECRETS: ${{ secrets.AWS_S3_CACHE != '' }} + HAS_ARTIFACTS: ${{ env.HAS_ARTIFACTS }} steps: - uses: actions/checkout@v3 - run: > @@ -17,16 +17,22 @@ jobs: jq -sc . | curl https://app.tea.xyz/api/receiveWatcherProjects --fail -X PUT \ -H "content-type: application/json" -H "authorization: bearer ${{ secrets.TEA_API_TOKEN }}" -d @- + - run: ./scripts/has-artifacts.ts ${{ github.repository }} ${{ github.sha }} >>$GITHUB_ENV + env: + GITHUB_TOKEN: ${{github.token}} + AWS_S3_CACHE: ${{ secrets.AWS_S3_CACHE }} + AWS_ACCESS_KEY_ID: ${{ secrets.AWS_ACCESS_KEY_ID }} + AWS_SECRET_ACCESS_KEY: ${{ secrets.AWS_SECRET_ACCESS_KEY }} + bottle-pr: needs: [cd] - #FIXME: will fail (harmlessly) on non-merge/non-new-version runs, and won't work on 3rd-party PRs - if: ${{ needs.cd.outputs.HAS_SECRETS }} + if: ${{ needs.cd.outputs.HAS_ARTIFACTS == 'true' }} uses: ./.github/workflows/bottle.yml secrets: inherit bottle-standalone: runs-on: ubuntu-latest needs: [cd] - if: ${{ ! needs.cd.outputs.HAS_SECRETS }} + if: ${{ needs.cd.outputs.HAS_ARTIFACTS == 'false' }} steps: - uses: actions/checkout@v3 - uses: technote-space/get-diff-action@v6 diff --git a/scripts/fetch-pr-artifacts.ts b/scripts/fetch-pr-artifacts.ts index e9708c93..4558bf08 100755 --- a/scripts/fetch-pr-artifacts.ts +++ b/scripts/fetch-pr-artifacts.ts @@ -13,40 +13,48 @@ args: /// Test /// ./scripts/fetch-pr-artifacts.ts e582b03fe6efedde80f9569403555f4513dbec91 -import { S3 } from "https://deno.land/x/s3@0.5.0/mod.ts"; -import { panic, undent } from "utils/index.ts"; +import { S3 } from "s3"; +import { panic, undent } from "utils"; /// Main /// ------------------------------------------------------------------------------- -const usage = "usage: fetch-pr-artifacts.ts {REPO} {SHA} {platform+arch}" -const repo = Deno.args[0] ?? panic(usage) -const ref = Deno.args[1] ?? panic(usage) -const flavor = Deno.args[2] ?? panic(usage) +if (import.meta.main) { + const usage = "usage: fetch-pr-artifacts.ts {REPO} {SHA} {platform+arch}" + const repo = Deno.args[0] ?? panic(usage) + const ref = Deno.args[1] ?? panic(usage) + const flavor = Deno.args[2] ?? panic(usage) -const res = await queryGraphQL(prQuery(repo)) + const pr = await find_pr(repo, ref) -const node = res.repository?.ref?.target?.history?.edges.find(n => n.node.oid === ref) -const pr = node?.node.associatedPullRequests.nodes[0].number + if (!pr) throw new Error(`No PR found for commit ${ref} in ${repo}`) -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_CACHE")!) + 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_CACHE")!) -const key = `pull-request/${repo.split("/")[1]}/${pr}/${flavor}` -const artifacts = (await bucket.getObject(key)) ?? panic("No artifacts found") + const key = `pull-request/${repo.split("/")[1]}/${pr}/${flavor}` + const artifacts = (await bucket.getObject(key)) ?? panic("No artifacts found") -const file = await Deno.open("artifacts.tgz", { create: true, write: true }) -await artifacts.body.pipeTo(file.writable) + const file = await Deno.open("artifacts.tgz", { create: true, write: true }) + await artifacts.body.pipeTo(file.writable) -Deno.stdout.write(new TextEncoder().encode(`PR=${pr}`)) + Deno.stdout.write(new TextEncoder().encode(`PR=${pr}`)) +} /// Functions /// ------------------------------------------------------------------------------- +export async function find_pr(repo: string, ref: string): Promise { + const res = await queryGraphQL(prQuery(repo)) + + const node = res.repository?.ref?.target?.history?.edges.find(n => n.node.oid === ref) + return node?.node.associatedPullRequests.nodes[0].number +} + async function queryGraphQL(query: string): Promise { const headers: HeadersInit = {} const token = Deno.env.get("GITHUB_TOKEN") ?? panic("GitHub GraphQL requires you set $GITHUB_TOKEN") diff --git a/scripts/has-artifacts.ts b/scripts/has-artifacts.ts new file mode 100755 index 00000000..c3940109 --- /dev/null +++ b/scripts/has-artifacts.ts @@ -0,0 +1,46 @@ +#!/usr/bin/env -S tea -E + +/*--- +args: + - deno + - run + - --allow-net + - --allow-env + - --import-map={{ srcroot }}/import-map.json +---*/ + +/// Test +/// ./scripts/has-artifacts.ts e582b03fe6efedde80f9569403555f4513dbec91 + +import { S3 } from "s3"; +import { panic } from "utils"; +import { find_pr } from "./fetch-pr-artifacts.ts"; + +/// Main +/// ------------------------------------------------------------------------------- + +if (import.meta.main) { + const usage = "usage: has-artifacts.ts {REPO} {SHA}" + const repo = Deno.args[0] ?? panic(usage) + const ref = Deno.args[1] ?? panic(usage) + + const pr = await find_pr(repo, ref) + + if (!pr) { + Deno.stdout.write(new TextEncoder().encode("HAS_ARTIFACTS=false")) + Deno.exit(0) + } + + 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_CACHE")!) + + const objects = await bucket.listObjects({ prefix: `pull-request/${repo.split("/")[1]}/${pr}/` }) + + const hasArtifacts = (objects?.contents?.length || 0) > 0 + + Deno.stdout.write(new TextEncoder().encode(`HAS_ARTIFACTS=${hasArtifacts ? "true" : "false"}`)) +}