1name: Package Preview
2
3# Builds, packs, and publishes preview packages from the job that built them.
4# The job proves it is the run it claims to be by uploading the manifest as
5# an artifact of its own run, which only the job's runtime token can do; the
6# registry reads the artifact list back through the GitHub API. That works
7# the same for pushes, same-repo pull requests, and fork pull requests, and
8# needs no permissions or secrets. The upload has to be an action step: the
9# runtime token is never exposed to `run:` steps.
10
11on:
12 push:
13 branches: [main]
14 paths:
15 - "submodules/distilled"
16 - "packages/**"
17 - "scripts/**"
18 - "package.json"
19 - "pnpm-lock.yaml"
20 - "pnpm-workspace.yaml"
21 - "turbo.json"
22 - "tsconfig.json"
23 - ".github/workflows/pkg.yml"
24 pull_request:
25 types: [opened, synchronize, reopened, labeled]
26 paths:
27 - "submodules/distilled"
28 - "packages/**"
29 - "scripts/**"
30 - "package.json"
31 - "pnpm-lock.yaml"
32 - "pnpm-workspace.yaml"
33 - "turbo.json"
34 - "tsconfig.json"
35 - ".github/workflows/pkg.yml"
36
37permissions:
38 contents: read
39
40env:
41 PKG_REGISTRY: https://pkg.alchemy.run
42
43concurrency:
44 group: pkg-${{ github.event.pull_request.number || github.ref }}
45 cancel-in-progress: ${{ github.event_name == 'pull_request' }}
46
47jobs:
48 publish:
49 name: Publish preview packages
50 runs-on: blacksmith-8vcpu-ubuntu-2404
51 steps:
52 - name: Checkout repository
53 uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1
54 with:
55 # Pack the pull request head rather than the synthetic merge commit,
56 # so every tarball is addressed by a commit that exists on the PR.
57 ref: ${{ github.event.pull_request.head.sha || github.sha }}
58 fetch-depth: 0
59
60 - name: Checkout distilled
61 run: git submodule update --init --depth=1 --checkout -- submodules/distilled
62
63 # No turbo cache here on purpose: the restore keys fall back to any
64 # earlier run, and replayed outputs for the distilled packages, whose
65 # sources live in a submodule, have compiled alchemy against stale
66 # declarations. A clean build is a few minutes and always correct.
67 - name: Setup pnpm, Node.js, Bun and install dependencies
68 uses: pnpm/setup@703c52620218391530e48b9e8870d5c0082e1b9b # v2.1.0
69 with:
70 cache: true
71 install: true
72 require-lockfile: true
73
74 # Cold-building the alchemy package peaks near 17 GB of heap, which
75 # starves the runner agent on a 32 GB machine and drops the job. A soft
76 # limit holds the peak near 11 GB for roughly twice the compile time.
77 - name: Build packages
78 env:
79 GOMEMLIMIT: 6GiB
80 GOGC: "40"
81 run: pnpm build:pkg
82
83 # The @distilled.cloud list is alchemy's dependency set, which `build:pkg`
84 # derives with `--filter=alchemy...`; keep the @alchemy.run list in sync.
85 - name: Pack packages
86 id: pack
87 run: >-
88 pnpm exec pkg pack
89 ${{ contains(github.event.pull_request.labels.*.name, 'force-ci') && '--all' || '' }}
90 --rebuild-all-path 'scripts/copy-package-files.ts'
91 --group 'alchemy=./packages/alchemy'
92 --group '@alchemy.run[Collapsed]=./packages/{better-auth,cloudflare-runtime,frontend-frameworks,node-utils,floci,pkg}'
93 --group '@distilled.cloud[Collapsed]=./submodules/distilled/packages/{core,acme,aws,axiom,cloudflare,doppler,fly-io,github,hetzner,infisical,neon,prisma,planetscale,railway,stripe,zerossl}'
94
95 - name: Vouch for the manifest
96 if: steps.pack.outputs.package-count != '0'
97 uses: actions/upload-artifact@043fb46d1a93c77aae656e7c1c64a875d1fc6a0a # v7.0.1
98 with:
99 name: ${{ steps.pack.outputs.artifact-name }}
100 path: .pkg/pkg-manifest.json
101 include-hidden-files: true
102 if-no-files-found: error
103 retention-days: 1
104
105 - name: Publish packages
106 if: steps.pack.outputs.package-count != '0'
107 run: pnpm exec pkg publish