name: Deploy dev content # Manual dev content deployment during the Terraform adoption (SH-300). # # The push-to-`dev` trigger and the org reusable `cd-cdk.yaml` caller are # retired: `cdk deploy` no longer runs from CI. Infrastructure changes are # administrator-run (`infra/cdk/README.md`) while CloudFormation still owns the # resources, and move to HCP Terraform (`terraform/README.md`) as adoption # completes. Automatic push-to-`dev` releases return with the Terraform # content-CD change, gated on a repository variable. # # This workflow publishes only content: verify, build, `aws s3 sync`, and a # CloudFront invalidation through `scripts/deploy-web.sh`, as the pinned OIDC # deploy role. The bucket and distribution are pinned here so a content deploy # keeps working after CloudFormation relinquishes the stack outputs. on: workflow_dispatch: {} permissions: id-token: write contents: read concurrency: group: deploy-dev cancel-in-progress: false jobs: deploy: name: Publish content to dev # Deploy only the exact dev branch ref: workflow_dispatch can be invoked # from arbitrary refs, and the deploy role trusts only refs/heads/dev. if: github.ref == 'refs/heads/dev' runs-on: ubuntu-latest env: AWS_REGION: us-east-1 VITE_APP_COMMIT_SHA: ${{ github.sha }} steps: - uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1 with: fetch-depth: 0 - uses: actions/setup-node@820762786026740c76f36085b0efc47a31fe5020 # v7.0.0 with: node-version: "24" cache: npm - name: Set up Terraform # Required by `npm run verify` (governance runs terraform fmt/validate). uses: hashicorp/setup-terraform@dfe3c3f87815947d99a8997f908cb6525fc44e9e # v4.0.1 with: terraform_version: "1.16.0" terraform_wrapper: false - name: Quality gates (full verify before any deploy) run: npm ci && npm run verify env: GOVERNANCE_BASE: origin/dev - name: Assume dev deploy role (OIDC) uses: aws-actions/configure-aws-credentials@e6de054238d6b7531b4efff3b6587d9aade6a06c # v6.2.3 with: role-to-assume: arn:aws:iam::396287094661:role/githubdeploy-shoc-frontend-new-dev aws-region: us-east-1 # Builds with the dev values committed in .env.production (VITE_API_URL, # Sentry DSN), syncs to the pinned bucket, and invalidates CloudFront. - name: Build and publish SPA run: bash scripts/deploy-web.sh env: SITE_BUCKET: seahaven-shoc-frontend-dev CLOUDFRONT_DISTRIBUTION_ID: E2CWLM1AFB964P WAIT_FOR_INVALIDATION: "true" - name: Upload private source maps run: bash scripts/upload-sourcemaps.sh env: SENTRY_AUTH_TOKEN: ${{ secrets.SENTRY_AUTH_TOKEN }} - name: Verify deployment run: | set -euo pipefail SITE_URL="https://dev.seahaven.com" if grep -Rq "api.staging.seahaven.com" dist/; then echo "::error::Built assets contain the staging API URL." >&2 exit 1 fi grep -Rq "api.dev.seahaven.com" dist/ echo "Built assets reference the dev API URL." # The invalidation has completed, but give edges a short window to # converge before calling the served index.html wrong. remote_dir="$(mktemp -d)" trap 'rm -rf "${remote_dir}"' EXIT matched=false for i in 1 2 3 4 5 6; do if curl -fsS --max-time 30 "${SITE_URL}" -o "${remote_dir}/index.html" \ && cmp -s dist/index.html "${remote_dir}/index.html"; then matched=true break fi echo "Served index.html does not yet match the published build (attempt ${i}); retrying in 20s..." sleep 20 done if [[ "${matched}" != "true" ]]; then echo "::error::Served index.html does not match the build just published." >&2 exit 1 fi echo "Served index.html matches the published build." curl -fsS --max-time 30 -o /dev/null "${SITE_URL}/login" echo "Extensionless SPA route serves."