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// (immutable, auditable) AND mirrored # to releases/latest/ (what the box pulls). Then the open-swe--deploy SSM # document is fired (tag-scoped to project=open-swe,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- role ARNs (open-swe-iam CfnOutputs). # - the open-swe- 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@v7 - 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@v7 - 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