Part 5: CI/CD
Hand the stack to GitHub Actions: pushes to main deploy to prod, pull
requests get their own stage, and closing a pull request destroys it.
Move state somewhere CI can read
Section titled “Move state somewhere CI can read”A runner can’t see your .alchemy/ directory, and Archil has no state
store of its own. Use a remote one, such as a
Postgres database you already run
(install @alchemy.run/sql and @effect/sql-pg):
import { postgresState } from "@alchemy.run/sql/PostgresState";import * as Config from "effect/Config";
export default Alchemy.Stack( "MyApp", { providers: Archil.providers(), state: Alchemy.localState() }, { providers: Archil.providers(), state: postgresState({ url: Config.Redacted("STATE_DATABASE_URL") }), },Cloudflare.state(), AWS.state() and GCP.state() work too if you
already use that cloud. See State stores.
Store your key in GitHub
Section titled “Store your key in GitHub”Archil creates API keys only in the console, so CI uses one you create there. Create a key for CI under API Keys, then store it and the state database URL as repository secrets:
gh secret set ARCHIL_API_KEYgh secret set STATE_DATABASE_URLArchil.providers() reads ARCHIL_API_KEY (and ARCHIL_REGION, if
set) from the environment when no profile is selected.
Create the workflow
Section titled “Create the workflow”name: Deployon: push: branches: [main] pull_request: types: [opened, reopened, synchronize, closed]
concurrency: group: deploy-${{ github.ref }} cancel-in-progress: false
env: STAGE: >- ${{ github.event_name == 'pull_request' && format('pr-{0}', github.event.number) || 'prod' }} ARCHIL_API_KEY: ${{ secrets.ARCHIL_API_KEY }} STATE_DATABASE_URL: ${{ secrets.STATE_DATABASE_URL }}
jobs: deploy: if: github.event.action != 'closed' runs-on: ubuntu-latest steps: - uses: actions/checkout@v4 - uses: oven-sh/setup-bun@v2 - run: bun install - run: bun alchemy deploy --stage ${{ env.STAGE }} --yes
cleanup: if: github.event_name == 'pull_request' && github.event.action == 'closed' runs-on: ubuntu-latest steps: - uses: actions/checkout@v4 - uses: oven-sh/setup-bun@v2 - run: bun install - name: Refuse to destroy prod run: test "${{ env.STAGE }}" != "prod" - run: bun alchemy destroy --stage ${{ env.STAGE }} --yesPull requests deploy to pr-<number>, and main deploys to prod. The
cleanup job refuses to destroy prod.
Rotate the key
Section titled “Rotate the key”Archil can’t scope or expire API keys. To rotate one, create a new key
in the console, run gh secret set ARCHIL_API_KEY again, redeploy, then
delete the old key. Hosts that call Archil’s control plane pick up the
new key on that deploy; hosts that only use disks hold their own disk
users and aren’t affected.
- A remote state store lets every runner see the same deploys.
- Each pull request gets its own stage, destroyed when it closes.
- The Archil key lives in a repository secret.