mirror of
https://github.com/Sea-Haven-Industries/open-swe.git
synced 2026-09-30 20:53:15 +00:00
The systemd unit booted with a literal `@@OPENSWE_ENV@@` (fetch-config.sh got the token, not "dev" -> exit 2 -> crash-loop) because user-data.sh is double-templated: CDK substitutes @@tokens@@ AND user-data seds @@tokens@@ into the baked systemd/nginx files. CDK's `.replace(/@@OPENSWE_ENV@@/g, "dev")` clobbered the sed PATTERN (`s|@@OPENSWE_ENV@@|...|` -> `s|dev|...|`, a no-op), so the unit's token never got replaced. Same collision hit @@SERVER_NAME@@ (masked by nginx default_server). Fix: CDK tokens move to a DISTINCT delimiter %%...%% (rendered in app-service.ts); the @@...@@ tokens stay for the baked-template seds. No AMI rebuild (templates unchanged). Add a guard test asserting no unresolved %%CDK%% token survives in the synthesized user-data. Also add .github/scripts/** to build-artifacts paths so script-only changes trigger a publish. jest 20/20; tsc + shellcheck clean; rendered user-data: OPENSWE_ENV="dev", SERVER_NAME="openswe-dev.seahaven.com", @@ sed patterns preserved, 16872 B.
123 lines
4.5 KiB
YAML
123 lines
4.5 KiB
YAML
name: Build & publish app artifacts
|
|
|
|
# T7 + T19 — build the release (SPA + Python source) and publish it to the per-env
|
|
# S3 artifact bucket, then roll the box to it.
|
|
#
|
|
# push to dev → publish to open-swe-dev-assets → deploy dev box (AUTO)
|
|
# push to main → publish to open-swe-prod-assets → deploy prod box (manual approval: env "prod")
|
|
#
|
|
# Two artifacts (the box's deploy.sh pulls both from releases/latest/):
|
|
# spa.tar.gz = the built dashboard SPA (vite -> ui/.output/public). Built HERE
|
|
# (not on the box) — the build is memory-heavy and the box is small.
|
|
# app.tar.gz = the Python source tree (NO ui/, NO .venv). The box runs
|
|
# `uv sync` to build a native-ARM64 venv at the real runtime path.
|
|
#
|
|
# Each release is uploaded under releases/<sha>/ (immutable, auditable) AND mirrored
|
|
# to releases/latest/ (what the box pulls). Then the open-swe-<env>-deploy SSM
|
|
# document is fired (tag-scoped to project=open-swe,env=<env>) to roll the box.
|
|
#
|
|
# OIDC subject alignment (matches the per-env app-role trust in infra/lib/config.ts):
|
|
# - publish-dev declares NO `environment:` → sub = repo:…:ref:refs/heads/dev
|
|
# - publish-prod declares `environment: prod` → sub = repo:…:environment:prod
|
|
# (also triggers the prod Environment's required-reviewer approval gate).
|
|
#
|
|
# Prerequisites:
|
|
# - repo variables AWS_DEPLOY_ROLE_APP_DEV / AWS_DEPLOY_ROLE_APP_PROD = the
|
|
# githubdeploy-open-swe-app-<env> role ARNs (open-swe-iam CfnOutputs).
|
|
# - the open-swe-<env> stack deployed (creates the bucket + the SSM deploy doc).
|
|
|
|
permissions:
|
|
contents: read
|
|
|
|
on:
|
|
push:
|
|
branches: [dev, main]
|
|
paths:
|
|
- "agent/**"
|
|
- "ui/**"
|
|
- "deploy/**"
|
|
- "langgraph.json"
|
|
- "pyproject.toml"
|
|
- "uv.lock"
|
|
- ".github/workflows/build-artifacts.yml"
|
|
- ".github/scripts/**"
|
|
workflow_dispatch:
|
|
|
|
concurrency:
|
|
# one publish+deploy per branch at a time; never cancel an in-flight release.
|
|
group: build-artifacts-${{ github.ref }}
|
|
cancel-in-progress: false
|
|
|
|
jobs:
|
|
publish-dev:
|
|
name: Publish + deploy (dev)
|
|
if: ${{ github.ref == 'refs/heads/dev' }}
|
|
runs-on: ubuntu-latest
|
|
timeout-minutes: 30
|
|
permissions:
|
|
id-token: write
|
|
contents: read
|
|
env:
|
|
ENV: dev
|
|
BUCKET: open-swe-dev-assets
|
|
DEPLOY_DOC: open-swe-dev-deploy
|
|
steps:
|
|
- uses: actions/checkout@v6
|
|
- uses: oven-sh/setup-bun@v2
|
|
with:
|
|
bun-version: latest
|
|
- name: Build SPA (vite -> ui/.output/public)
|
|
working-directory: ui
|
|
# vite's bundle exceeds Node's default ~2 GB heap (the build that needed an
|
|
# 8 GB swapfile on-box); the runner has ~16 GB, so lift the heap cap.
|
|
env:
|
|
NODE_OPTIONS: "--max-old-space-size=8192"
|
|
run: |
|
|
bun install --frozen-lockfile
|
|
bun run build
|
|
- name: Package artifacts
|
|
run: bash .github/scripts/package-artifacts.sh
|
|
- uses: aws-actions/configure-aws-credentials@v6
|
|
with:
|
|
role-to-assume: ${{ vars.AWS_DEPLOY_ROLE_APP_DEV }}
|
|
aws-region: us-east-1
|
|
- name: Publish to S3 + roll the box
|
|
run: bash .github/scripts/publish-and-deploy.sh
|
|
|
|
publish-prod:
|
|
name: Publish + deploy (prod)
|
|
if: ${{ github.ref == 'refs/heads/main' }}
|
|
runs-on: ubuntu-latest
|
|
timeout-minutes: 30
|
|
# Manual-approval gate: the "prod" Environment requires a reviewer (Adam). Also
|
|
# makes the OIDC sub …:environment:prod (matches the prod app-role trust).
|
|
environment: prod
|
|
permissions:
|
|
id-token: write
|
|
contents: read
|
|
env:
|
|
ENV: prod
|
|
BUCKET: open-swe-prod-assets
|
|
DEPLOY_DOC: open-swe-prod-deploy
|
|
steps:
|
|
- uses: actions/checkout@v6
|
|
- uses: oven-sh/setup-bun@v2
|
|
with:
|
|
bun-version: latest
|
|
- name: Build SPA (vite -> ui/.output/public)
|
|
working-directory: ui
|
|
# vite's bundle exceeds Node's default ~2 GB heap (the build that needed an
|
|
# 8 GB swapfile on-box); the runner has ~16 GB, so lift the heap cap.
|
|
env:
|
|
NODE_OPTIONS: "--max-old-space-size=8192"
|
|
run: |
|
|
bun install --frozen-lockfile
|
|
bun run build
|
|
- name: Package artifacts
|
|
run: bash .github/scripts/package-artifacts.sh
|
|
- uses: aws-actions/configure-aws-credentials@v6
|
|
with:
|
|
role-to-assume: ${{ vars.AWS_DEPLOY_ROLE_APP_PROD }}
|
|
aws-region: us-east-1
|
|
- name: Publish to S3 + roll the box
|
|
run: bash .github/scripts/publish-and-deploy.sh
|