aws-builds.yml11.2 KBView on GitHub name: AWS Builds
on:
pull_request:
permissions:
contents: read
concurrency:
group: aws-builds-${{ github.event.pull_request.number || github.ref }}
cancel-in-progress: true
jobs:
cedar-app-staging:
name: cedar-app-staging-aws
timeout-minutes: 15
runs-on: ${{ vars.RUNNER_IMAGE || 'ubuntu-latest' }}
steps:
- name: Checkout
uses: actions/checkout@v4
with:
fetch-depth: 0
- name: Determine AWS build scope
id: plan
env:
CEDAR_COMPARE_FROM_SHA: ${{ github.event.pull_request.base.sha }}
CEDAR_COMPARE_TO_SHA: ${{ github.event.pull_request.head.sha }}
run: bash ./aws/scripts/plan-surface-scope.sh
- name: Skip staging app build when not needed
if: steps.plan.outputs.check_frontend != 'true'
run: echo 'No frontend-affecting changes; skipping AWS staging app build.'
- name: Setup pnpm
if: steps.plan.outputs.check_frontend == 'true'
uses: pnpm/action-setup@v4
- name: Setup Node
if: steps.plan.outputs.check_frontend == 'true'
uses: actions/setup-node@v4
with:
node-version: 22
cache: pnpm
- name: Install workspace dependencies
if: steps.plan.outputs.check_frontend == 'true'
run: pnpm install --frozen-lockfile
- name: Build staging app bundle
if: steps.plan.outputs.check_frontend == 'true'
env:
NODE_OPTIONS: --max-old-space-size=4096
CEDAR_AWS_STAGING_APP_DOMAIN: ${{ vars.CEDAR_AWS_STAGING_APP_DOMAIN }}
CEDAR_AWS_STAGING_API_DOMAIN: ${{ vars.CEDAR_AWS_STAGING_API_DOMAIN }}
CEDAR_AWS_STAGING_PUBLIC_APP_URL: ${{ vars.CEDAR_AWS_STAGING_PUBLIC_APP_URL }}
CEDAR_AWS_STAGING_PUBLIC_BACKEND_URL: ${{ vars.CEDAR_AWS_STAGING_PUBLIC_BACKEND_URL }}
VITE_PUBLIC_POSTHOG_KEY: ${{ vars.VITE_PUBLIC_POSTHOG_KEY }}
VITE_PUBLIC_POSTHOG_HOST: ${{ vars.VITE_PUBLIC_POSTHOG_HOST }}
run: |
set -euo pipefail
export VITE_PUBLIC_APP_URL="${CEDAR_AWS_STAGING_PUBLIC_APP_URL:-https://${CEDAR_AWS_STAGING_APP_DOMAIN:-mail-staging.cedarcopilot.com}}"
export VITE_PUBLIC_BACKEND_URL="${CEDAR_AWS_STAGING_PUBLIC_BACKEND_URL:-https://${CEDAR_AWS_STAGING_API_DOMAIN:-api.mail-staging.cedarcopilot.com}}"
# Same-origin /ingest reverse proxy (see aws/lib/stacks/app-stack.ts) so tracker blockers don't drop events.
export VITE_PUBLIC_POSTHOG_HOST="${VITE_PUBLIC_POSTHOG_HOST:-${VITE_PUBLIC_APP_URL%/}/ingest}"
pnpm --filter @zero/mail build
cedar-api-staging:
name: cedar-api-staging-aws
timeout-minutes: 20
runs-on: ${{ vars.RUNNER_IMAGE || 'ubuntu-latest' }}
env:
AWS_REGION: us-east-1
AWS_DEFAULT_REGION: us-east-1
CDK_DEFAULT_ACCOUNT: '619071350399'
CDK_DEFAULT_REGION: us-east-1
CEDAR_AWS_REGION: us-east-1
CEDAR_AWS_VPC_ID: ${{ vars.CEDAR_AWS_VPC_ID || 'vpc-placeholder' }}
CEDAR_AWS_STAGING_APP_DOMAIN: ${{ vars.CEDAR_AWS_STAGING_APP_DOMAIN || 'mail-staging.cedarcopilot.com' }}
CEDAR_AWS_STAGING_API_DOMAIN: ${{ vars.CEDAR_AWS_STAGING_API_DOMAIN || 'api.mail-staging.cedarcopilot.com' }}
CEDAR_AWS_STAGING_CERTIFICATE_ARN: ${{ vars.CEDAR_AWS_STAGING_CERTIFICATE_ARN || 'arn:aws:acm:us-east-1:000000000000:certificate/placeholder' }}
steps:
- name: Checkout
uses: actions/checkout@v4
with:
fetch-depth: 0
- name: Determine AWS build scope
id: plan
env:
CEDAR_COMPARE_FROM_SHA: ${{ github.event.pull_request.base.sha }}
CEDAR_COMPARE_TO_SHA: ${{ github.event.pull_request.head.sha }}
run: bash ./aws/scripts/plan-surface-scope.sh
- name: Skip staging backend build when not needed
if: steps.plan.outputs.check_backend != 'true'
run: echo 'No backend-affecting changes; skipping AWS staging API build.'
- name: Setup pnpm
if: steps.plan.outputs.check_backend == 'true'
uses: pnpm/action-setup@v4
- name: Setup Node
if: steps.plan.outputs.check_backend == 'true'
uses: actions/setup-node@v4
with:
node-version: 22
cache: pnpm
- name: Install workspace dependencies
if: steps.plan.outputs.check_backend == 'true'
run: pnpm install --frozen-lockfile
- name: Install AWS deployment dependencies
if: steps.plan.outputs.check_backend == 'true'
run: pnpm --ignore-workspace --dir aws install --no-frozen-lockfile
- name: Check staging readiness configuration
if: steps.plan.outputs.check_backend == 'true'
run: |
set -euo pipefail
required_vars=(
CEDAR_AWS_VPC_ID
CEDAR_AWS_STAGING_APP_DOMAIN
CEDAR_AWS_STAGING_API_DOMAIN
CEDAR_AWS_STAGING_CERTIFICATE_ARN
)
for var_name in "${required_vars[@]}"; do
val="${!var_name:-}"
if [[ -z "$val" || "$val" == *placeholder* ]]; then
echo "::warning::Staging readiness variable ${var_name} is using a placeholder — build-only check, not deploy-ready"
fi
done
- name: Build server runtimes and typecheck
if: steps.plan.outputs.check_backend == 'true'
run: |
set -euo pipefail
pnpm --filter @zero/server build:api-service
pnpm --filter @zero/server build:chat-service
pnpm --filter @zero/server build:worker-service
pnpm aws:typecheck
cedar-app:
name: cedar-app-aws
timeout-minutes: 15
runs-on: ${{ vars.RUNNER_IMAGE || 'ubuntu-latest' }}
steps:
- name: Checkout
uses: actions/checkout@v4
with:
fetch-depth: 0
- name: Determine AWS build scope
id: plan
env:
CEDAR_COMPARE_FROM_SHA: ${{ github.event.pull_request.base.sha }}
CEDAR_COMPARE_TO_SHA: ${{ github.event.pull_request.head.sha }}
run: bash ./aws/scripts/plan-surface-scope.sh
- name: Skip prod app build when not needed
if: steps.plan.outputs.check_frontend != 'true'
run: echo 'No frontend-affecting changes; skipping AWS prod app build.'
- name: Setup pnpm
if: steps.plan.outputs.check_frontend == 'true'
uses: pnpm/action-setup@v4
- name: Setup Node
if: steps.plan.outputs.check_frontend == 'true'
uses: actions/setup-node@v4
with:
node-version: 22
cache: pnpm
- name: Install workspace dependencies
if: steps.plan.outputs.check_frontend == 'true'
run: pnpm install --frozen-lockfile
- name: Build prod app bundle
if: steps.plan.outputs.check_frontend == 'true'
env:
NODE_OPTIONS: --max-old-space-size=4096
CEDAR_AWS_PROD_APP_DOMAIN: ${{ vars.CEDAR_AWS_PROD_APP_DOMAIN }}
CEDAR_AWS_PROD_API_DOMAIN: ${{ vars.CEDAR_AWS_PROD_API_DOMAIN }}
CEDAR_AWS_PROD_PUBLIC_APP_URL: ${{ vars.CEDAR_AWS_PROD_PUBLIC_APP_URL }}
CEDAR_AWS_PROD_PUBLIC_BACKEND_URL: ${{ vars.CEDAR_AWS_PROD_PUBLIC_BACKEND_URL }}
VITE_PUBLIC_POSTHOG_KEY: ${{ vars.VITE_PUBLIC_POSTHOG_KEY }}
VITE_PUBLIC_POSTHOG_HOST: ${{ vars.VITE_PUBLIC_POSTHOG_HOST }}
run: |
set -euo pipefail
# Resolve the marketing origin through the same helper the prod publisher uses, so
# this validation build cannot drift from what actually ships.
source ./aws/scripts/deploy-utils.sh
marketing_url="$(cedar_marketing_url_for_env prod)"
if [[ -n "$marketing_url" ]]; then
export VITE_PUBLIC_MARKETING_URL="$marketing_url"
fi
export VITE_PUBLIC_APP_URL="${CEDAR_AWS_PROD_PUBLIC_APP_URL:-https://${CEDAR_AWS_PROD_APP_DOMAIN:-mail.cedarcopilot.com}}"
export VITE_PUBLIC_BACKEND_URL="${CEDAR_AWS_PROD_PUBLIC_BACKEND_URL:-https://${CEDAR_AWS_PROD_API_DOMAIN:-api.mail.cedarcopilot.com}}"
export VITE_PUBLIC_POSTHOG_KEY=[redacted]
# Same-origin /ingest reverse proxy (see aws/lib/stacks/app-stack.ts) so tracker blockers don't drop events.
export VITE_PUBLIC_POSTHOG_HOST="${VITE_PUBLIC_POSTHOG_HOST:-${VITE_PUBLIC_APP_URL%/}/ingest}"
pnpm --filter @zero/mail build
cedar-api:
name: cedar-api-aws
timeout-minutes: 20
runs-on: ${{ vars.RUNNER_IMAGE || 'ubuntu-latest' }}
env:
AWS_REGION: us-east-1
AWS_DEFAULT_REGION: us-east-1
CDK_DEFAULT_ACCOUNT: '619071350399'
CDK_DEFAULT_REGION: us-east-1
CEDAR_AWS_REGION: us-east-1
CEDAR_AWS_VPC_ID: ${{ vars.CEDAR_AWS_VPC_ID || 'vpc-placeholder' }}
CEDAR_AWS_PROD_APP_DOMAIN: ${{ vars.CEDAR_AWS_PROD_APP_DOMAIN || 'mail.cedarcopilot.com' }}
CEDAR_AWS_PROD_API_DOMAIN: ${{ vars.CEDAR_AWS_PROD_API_DOMAIN || 'api.mail.cedarcopilot.com' }}
CEDAR_AWS_PROD_CERTIFICATE_ARN: ${{ vars.CEDAR_AWS_PROD_CERTIFICATE_ARN || 'arn:aws:acm:us-east-1:000000000000:certificate/placeholder' }}
CEDAR_AWS_PROD_MARKETING_DOMAINS: ${{ vars.CEDAR_AWS_PROD_MARKETING_DOMAINS || 'cedarcopilot.com,www.cedarcopilot.com' }}
steps:
- name: Checkout
uses: actions/checkout@v4
with:
fetch-depth: 0
- name: Determine AWS build scope
id: plan
env:
CEDAR_COMPARE_FROM_SHA: ${{ github.event.pull_request.base.sha }}
CEDAR_COMPARE_TO_SHA: ${{ github.event.pull_request.head.sha }}
run: bash ./aws/scripts/plan-surface-scope.sh
- name: Skip prod backend build when not needed
if: steps.plan.outputs.check_backend != 'true'
run: echo 'No backend-affecting changes; skipping AWS prod API build.'
- name: Setup pnpm
if: steps.plan.outputs.check_backend == 'true'
uses: pnpm/action-setup@v4
- name: Setup Node
if: steps.plan.outputs.check_backend == 'true'
uses: actions/setup-node@v4
with:
node-version: 22
cache: pnpm
- name: Install workspace dependencies
if: steps.plan.outputs.check_backend == 'true'
run: pnpm install --frozen-lockfile
- name: Install AWS deployment dependencies
if: steps.plan.outputs.check_backend == 'true'
run: pnpm --ignore-workspace --dir aws install --no-frozen-lockfile
- name: Check prod readiness configuration
if: steps.plan.outputs.check_backend == 'true'
run: |
set -euo pipefail
required_vars=(
CEDAR_AWS_VPC_ID
CEDAR_AWS_PROD_APP_DOMAIN
CEDAR_AWS_PROD_API_DOMAIN
CEDAR_AWS_PROD_CERTIFICATE_ARN
)
for var_name in "${required_vars[@]}"; do
val="${!var_name:-}"
if [[ -z "$val" || "$val" == *placeholder* ]]; then
echo "::warning::Prod readiness variable ${var_name} is using a placeholder — build-only check, not deploy-ready"
fi
done
- name: Build server runtimes and typecheck
if: steps.plan.outputs.check_backend == 'true'
run: |
set -euo pipefail
pnpm --filter @zero/server build:api-service
pnpm --filter @zero/server build:chat-service
pnpm --filter @zero/server build:worker-service
pnpm aws:typecheck