Skip to content

Merge pull request #107 from kirill-markin/codex/split-web-api-contracts #206

Merge pull request #107 from kirill-markin/codex/split-web-api-contracts

Merge pull request #107 from kirill-markin/codex/split-web-api-contracts #206

name: AWS/Web Release
on:
push:
branches: [main]
paths:
- 'api/**'
- 'apps/auth/**'
- 'apps/backend/**'
- 'apps/web/**'
- 'apps/admin/**'
- 'db/**'
- 'infra/**'
- 'scripts/check-agent-api-smoke.sh'
- 'scripts/check-api-health.sh'
- 'scripts/check-demo-cognito-users.sh'
- 'scripts/check-public-endpoints.sh'
- 'scripts/deploy-admin.sh'
- 'scripts/deploy-web.sh'
- 'scripts/generate-global-metrics-snapshot.sh'
- 'scripts/migrate-aws.sh'
- 'scripts/write-ci-cdk-context.py'
- '.github/workflows/aws-web-release.yml'
workflow_dispatch:
concurrency:
group: main-release
cancel-in-progress: false
permissions:
actions: read
checks: read
contents: read
id-token: write
env:
AWS_REGION: ${{ vars.AWS_REGION }}
STACK_NAME: FlashcardsOpenSourceApp
jobs:
changes:
name: Detect changed areas
runs-on: ubuntu-24.04
outputs:
aws_changed: ${{ steps.detect.outputs.aws_changed }}
api_changed: ${{ steps.detect.outputs.api_changed }}
auth_changed: ${{ steps.detect.outputs.auth_changed }}
backend_changed: ${{ steps.detect.outputs.backend_changed }}
web_changed: ${{ steps.detect.outputs.web_changed }}
admin_changed: ${{ steps.detect.outputs.admin_changed }}
infra_changed: ${{ steps.detect.outputs.infra_changed }}
changed_files: ${{ steps.detect.outputs.changed_files }}
steps:
- uses: actions/checkout@v6
with:
fetch-depth: 0
- name: Detect changed files
id: detect
env:
PUSH_BEFORE_SHA: ${{ github.event.before }}
run: |
set -euo pipefail
aws_release_script_pattern='^scripts/(check-agent-api-smoke\.sh|check-api-health\.sh|check-demo-cognito-users\.sh|check-public-endpoints\.sh|deploy-admin\.sh|deploy-web\.sh|generate-global-metrics-snapshot\.sh|migrate-aws\.sh|write-ci-cdk-context\.py)$'
changed_files_path="${RUNNER_TEMP}/changed-files.txt"
before_sha="${PUSH_BEFORE_SHA:-}"
if [[ "${GITHUB_EVENT_NAME}" == "workflow_dispatch" ]]; then
printf '%s\n' 'workflow_dispatch (forced AWS deploy)' > "${changed_files_path}"
elif [[ "${GITHUB_EVENT_NAME}" == "push" ]] && [[ -n "${before_sha}" ]] && [[ "${before_sha}" != "0000000000000000000000000000000000000000" ]]; then
git diff --name-only "${before_sha}" "${GITHUB_SHA}" > "${changed_files_path}"
elif git rev-parse HEAD^ >/dev/null 2>&1; then
git diff --name-only HEAD^ HEAD > "${changed_files_path}"
else
git ls-files > "${changed_files_path}"
fi
aws_changed=false
if [[ "${GITHUB_EVENT_NAME}" == "workflow_dispatch" ]]; then
aws_changed=true
elif grep -Eq "^(api/|apps/auth/|apps/backend/|apps/web/|apps/admin/|db/|infra/|\\.github/workflows/aws-web-release\\.yml$)" "${changed_files_path}" || grep -Eq "${aws_release_script_pattern}" "${changed_files_path}"; then
aws_changed=true
fi
api_changed=false
auth_changed=false
backend_changed=false
web_changed=false
admin_changed=false
infra_changed=false
if [[ "${GITHUB_EVENT_NAME}" == "workflow_dispatch" ]]; then
api_changed=true
auth_changed=true
backend_changed=true
web_changed=true
admin_changed=true
infra_changed=true
else
if grep -Eq '^(api/|\.github/workflows/aws-web-release\.yml$)' "${changed_files_path}"; then
api_changed=true
fi
if grep -Eq '^(apps/auth/|\.github/workflows/aws-web-release\.yml$)' "${changed_files_path}"; then
auth_changed=true
fi
if grep -Eq '^(apps/backend/|\.github/workflows/aws-web-release\.yml$)' "${changed_files_path}"; then
backend_changed=true
fi
if grep -Eq '^(apps/web/|apps/backend/src/schedule\.ts$|apps/backend/src/workspaceSchedulerConfig\.ts$|\.github/workflows/aws-web-release\.yml$)' "${changed_files_path}"; then
web_changed=true
fi
if grep -Eq '^(apps/admin/|\.github/workflows/aws-web-release\.yml$)' "${changed_files_path}"; then
admin_changed=true
fi
if grep -Eq '^(infra/|\.github/workflows/aws-web-release\.yml$)' "${changed_files_path}"; then
infra_changed=true
fi
fi
{
echo "aws_changed=${aws_changed}"
echo "api_changed=${api_changed}"
echo "auth_changed=${auth_changed}"
echo "backend_changed=${backend_changed}"
echo "web_changed=${web_changed}"
echo "admin_changed=${admin_changed}"
echo "infra_changed=${infra_changed}"
echo 'changed_files<<EOF'
cat "${changed_files_path}"
echo 'EOF'
} >> "${GITHUB_OUTPUT}"
- name: Summarize changed areas
env:
CHANGED_FILES: ${{ steps.detect.outputs.changed_files }}
run: |
{
echo "## Release scope"
echo ""
echo "- AWS changed: \`${{ steps.detect.outputs.aws_changed }}\`"
echo "- API changed: \`${{ steps.detect.outputs.api_changed }}\`"
echo "- Auth changed: \`${{ steps.detect.outputs.auth_changed }}\`"
echo "- Backend changed: \`${{ steps.detect.outputs.backend_changed }}\`"
echo "- Web changed: \`${{ steps.detect.outputs.web_changed }}\`"
echo "- Admin changed: \`${{ steps.detect.outputs.admin_changed }}\`"
echo "- Infra changed: \`${{ steps.detect.outputs.infra_changed }}\`"
echo ""
echo "### Changed files"
echo ""
if [[ -n "${CHANGED_FILES}" ]]; then
printf '%s\n' "${CHANGED_FILES}"
else
echo "No changed files detected."
fi
} >> "${GITHUB_STEP_SUMMARY}"
pre_deploy_checks:
name: Pre-deploy checks
needs: changes
if: ${{ needs.changes.outputs.aws_changed == 'true' }}
runs-on: ubuntu-24.04
steps:
- uses: actions/checkout@v6
- uses: actions/setup-node@v6
with:
node-version: 24
cache: npm
cache-dependency-path: |
api/package-lock.json
apps/auth/package-lock.json
apps/backend/package-lock.json
apps/web/package-lock.json
apps/admin/package-lock.json
infra/aws/package-lock.json
- name: Install dependencies
run: |
npm ci --prefix api
npm ci --prefix apps/auth
npm ci --prefix apps/backend
npm ci --prefix apps/web
npm ci --prefix apps/admin
npm ci --prefix infra/aws
- name: Lint OpenAPI spec
if: ${{ needs.changes.outputs.api_changed == 'true' }}
run: npm run lint --prefix api
- name: Bundle OpenAPI spec
run: npm run bundle --prefix api
- name: Build auth app
if: ${{ needs.changes.outputs.auth_changed == 'true' }}
run: npm run build --prefix apps/auth
- name: Test auth app
if: ${{ needs.changes.outputs.auth_changed == 'true' }}
run: npm run test --prefix apps/auth
- name: Lint backend
if: ${{ needs.changes.outputs.backend_changed == 'true' }}
run: npm run lint --prefix apps/backend
- name: Build backend
if: ${{ needs.changes.outputs.backend_changed == 'true' }}
run: npm run build --prefix apps/backend
- name: Build web app
if: ${{ needs.changes.outputs.web_changed == 'true' }}
run: npm run build --prefix apps/web
- name: Build admin app
if: ${{ needs.changes.outputs.admin_changed == 'true' }}
run: npm run build --prefix apps/admin
- name: Build infra
if: ${{ needs.changes.outputs.infra_changed == 'true' }}
run: npm run build --prefix infra/aws
- name: Synthesize infra
working-directory: infra/aws
env:
AWS_DEPLOY_ROLE_ARN: ${{ secrets.AWS_DEPLOY_ROLE_ARN }}
CDK_CONTEXT_ALERT_EMAIL: ${{ vars.CDK_ALERT_EMAIL }}
CDK_CONTEXT_ANALYTICS_SSH_ALLOWED_CIDRS: ${{ vars.CDK_ANALYTICS_SSH_ALLOWED_CIDRS }}
CDK_CONTEXT_ANALYTICS_SSH_PUBLIC_KEYS: ${{ vars.CDK_ANALYTICS_SSH_PUBLIC_KEYS }}
CDK_CONTEXT_ANALYTICS_SSH_USERNAME: ${{ vars.CDK_ANALYTICS_SSH_USERNAME }}
CDK_CONTEXT_ANTHROPIC_API_KEY_SECRET_ARN: ${{ vars.CDK_ANTHROPIC_API_KEY_SECRET_ARN }}
CDK_CONTEXT_API_CERTIFICATE_ARN: ${{ vars.CDK_API_CERTIFICATE_ARN }}
CDK_CONTEXT_APEX_REDIRECT_CERTIFICATE_ARN_US_EAST_1: ${{ vars.CDK_APEX_REDIRECT_CERTIFICATE_ARN_US_EAST_1 }}
CDK_CONTEXT_AUTH_CERTIFICATE_ARN: ${{ vars.CDK_AUTH_CERTIFICATE_ARN }}
CDK_CONTEXT_ADMIN_CERTIFICATE_ARN_US_EAST_1: ${{ vars.CDK_ADMIN_CERTIFICATE_ARN_US_EAST_1 }}
CDK_CONTEXT_ADMIN_EMAILS: ${{ vars.CDK_ADMIN_EMAILS }}
CDK_CONTEXT_DEMO_EMAIL_DOSTIP: ${{ vars.CDK_DEMO_EMAIL_DOSTIP }}
CDK_CONTEXT_DEMO_PASSWORD_SECRET_ARN: ${{ vars.CDK_DEMO_PASSWORD_SECRET_ARN }}
CDK_CONTEXT_DOMAIN_NAME: ${{ vars.CDK_DOMAIN_NAME }}
CDK_CONTEXT_GITHUB_REPO: ${{ vars.CDK_GITHUB_REPO }}
CDK_CONTEXT_GLOBAL_METRICS_VISIBLE: ${{ vars.CDK_GLOBAL_METRICS_VISIBLE }}
CDK_CONTEXT_GUEST_AI_WEIGHTED_MONTHLY_TOKEN_CAP: ${{ vars.CDK_GUEST_AI_WEIGHTED_MONTHLY_TOKEN_CAP }}
CDK_CONTEXT_LANGFUSE_BASE_URL: ${{ vars.CDK_LANGFUSE_BASE_URL }}
CDK_CONTEXT_LANGFUSE_PUBLIC_KEY_SECRET_ARN: ${{ vars.CDK_LANGFUSE_PUBLIC_KEY_SECRET_ARN }}
CDK_CONTEXT_LANGFUSE_SECRET_KEY_SECRET_ARN: ${{ vars.CDK_LANGFUSE_SECRET_KEY_SECRET_ARN }}
CDK_CONTEXT_OPENAI_API_KEY_SECRET_ARN: ${{ vars.CDK_OPENAI_API_KEY_SECRET_ARN }}
CDK_CONTEXT_REGION: ${{ vars.AWS_REGION }}
CDK_CONTEXT_RESEND_API_KEY_SECRET_ARN: ${{ vars.CDK_RESEND_API_KEY_SECRET_ARN }}
CDK_CONTEXT_RESEND_SENDER_EMAIL: ${{ vars.CDK_RESEND_SENDER_EMAIL }}
CDK_CONTEXT_WEB_CERTIFICATE_ARN_US_EAST_1: ${{ vars.CDK_WEB_CERTIFICATE_ARN_US_EAST_1 }}
run: |
python3 ../../scripts/write-ci-cdk-context.py \
--output cdk.context.local.json \
--aws-deploy-role-arn "${AWS_DEPLOY_ROLE_ARN}"
npm run synth
aws_deploy:
name: Deploy AWS release
needs:
- changes
- pre_deploy_checks
if: ${{ needs.changes.outputs.aws_changed == 'true' && needs.pre_deploy_checks.result == 'success' }}
runs-on: ubuntu-24.04-arm
timeout-minutes: 30
steps:
- uses: actions/checkout@v6
- uses: actions/setup-node@v6
with:
node-version: 24
cache: npm
cache-dependency-path: |
api/package-lock.json
apps/auth/package-lock.json
apps/backend/package-lock.json
apps/web/package-lock.json
apps/admin/package-lock.json
infra/aws/package-lock.json
- name: Configure AWS credentials (OIDC)
uses: aws-actions/configure-aws-credentials@v6
with:
role-to-assume: ${{ secrets.AWS_DEPLOY_ROLE_ARN }}
aws-region: ${{ env.AWS_REGION }}
- name: Install dependencies
run: |
npm ci --prefix api
npm ci --prefix apps/auth
npm ci --prefix apps/backend
npm ci --prefix apps/web
npm ci --prefix apps/admin
npm ci --prefix infra/aws
- name: Bundle OpenAPI spec
run: npm run bundle --prefix api
- name: CDK deploy
working-directory: infra/aws
env:
AWS_DEPLOY_ROLE_ARN: ${{ secrets.AWS_DEPLOY_ROLE_ARN }}
CDK_CONTEXT_ALERT_EMAIL: ${{ vars.CDK_ALERT_EMAIL }}
CDK_CONTEXT_ANALYTICS_SSH_ALLOWED_CIDRS: ${{ vars.CDK_ANALYTICS_SSH_ALLOWED_CIDRS }}
CDK_CONTEXT_ANALYTICS_SSH_PUBLIC_KEYS: ${{ vars.CDK_ANALYTICS_SSH_PUBLIC_KEYS }}
CDK_CONTEXT_ANALYTICS_SSH_USERNAME: ${{ vars.CDK_ANALYTICS_SSH_USERNAME }}
CDK_CONTEXT_ANTHROPIC_API_KEY_SECRET_ARN: ${{ vars.CDK_ANTHROPIC_API_KEY_SECRET_ARN }}
CDK_CONTEXT_API_CERTIFICATE_ARN: ${{ vars.CDK_API_CERTIFICATE_ARN }}
CDK_CONTEXT_APEX_REDIRECT_CERTIFICATE_ARN_US_EAST_1: ${{ vars.CDK_APEX_REDIRECT_CERTIFICATE_ARN_US_EAST_1 }}
CDK_CONTEXT_AUTH_CERTIFICATE_ARN: ${{ vars.CDK_AUTH_CERTIFICATE_ARN }}
CDK_CONTEXT_ADMIN_CERTIFICATE_ARN_US_EAST_1: ${{ vars.CDK_ADMIN_CERTIFICATE_ARN_US_EAST_1 }}
CDK_CONTEXT_ADMIN_EMAILS: ${{ vars.CDK_ADMIN_EMAILS }}
CDK_CONTEXT_DEMO_EMAIL_DOSTIP: ${{ vars.CDK_DEMO_EMAIL_DOSTIP }}
CDK_CONTEXT_DEMO_PASSWORD_SECRET_ARN: ${{ vars.CDK_DEMO_PASSWORD_SECRET_ARN }}
CDK_CONTEXT_DOMAIN_NAME: ${{ vars.CDK_DOMAIN_NAME }}
CDK_CONTEXT_GITHUB_REPO: ${{ vars.CDK_GITHUB_REPO }}
CDK_CONTEXT_GLOBAL_METRICS_VISIBLE: ${{ vars.CDK_GLOBAL_METRICS_VISIBLE }}
CDK_CONTEXT_GUEST_AI_WEIGHTED_MONTHLY_TOKEN_CAP: ${{ vars.CDK_GUEST_AI_WEIGHTED_MONTHLY_TOKEN_CAP }}
CDK_CONTEXT_LANGFUSE_BASE_URL: ${{ vars.CDK_LANGFUSE_BASE_URL }}
CDK_CONTEXT_LANGFUSE_PUBLIC_KEY_SECRET_ARN: ${{ vars.CDK_LANGFUSE_PUBLIC_KEY_SECRET_ARN }}
CDK_CONTEXT_LANGFUSE_SECRET_KEY_SECRET_ARN: ${{ vars.CDK_LANGFUSE_SECRET_KEY_SECRET_ARN }}
CDK_CONTEXT_OPENAI_API_KEY_SECRET_ARN: ${{ vars.CDK_OPENAI_API_KEY_SECRET_ARN }}
CDK_CONTEXT_REGION: ${{ vars.AWS_REGION }}
CDK_CONTEXT_RESEND_API_KEY_SECRET_ARN: ${{ vars.CDK_RESEND_API_KEY_SECRET_ARN }}
CDK_CONTEXT_RESEND_SENDER_EMAIL: ${{ vars.CDK_RESEND_SENDER_EMAIL }}
CDK_CONTEXT_WEB_CERTIFICATE_ARN_US_EAST_1: ${{ vars.CDK_WEB_CERTIFICATE_ARN_US_EAST_1 }}
run: |
python3 ../../scripts/write-ci-cdk-context.py \
--output cdk.context.local.json \
--aws-deploy-role-arn "${AWS_DEPLOY_ROLE_ARN}"
npx cdk deploy --all --require-approval never
- name: Check demo Cognito users
run: bash scripts/check-demo-cognito-users.sh --stack-name ${{ env.STACK_NAME }} --region ${{ env.AWS_REGION }}
- name: Run database migrations
run: bash scripts/migrate-aws.sh --stack-name ${{ env.STACK_NAME }}
- name: Seed global metrics snapshot
run: bash scripts/generate-global-metrics-snapshot.sh --stack-name ${{ env.STACK_NAME }}
- name: Build web app
run: npm run build --prefix apps/web
- name: Build admin app
run: npm run build --prefix apps/admin
- name: Deploy web assets
run: bash scripts/deploy-web.sh --stack-name ${{ env.STACK_NAME }}
- name: Deploy admin assets
run: bash scripts/deploy-admin.sh --stack-name ${{ env.STACK_NAME }}
- name: Check API health
run: bash scripts/check-api-health.sh --stack-name ${{ env.STACK_NAME }}
- name: Check public custom domains
run: bash scripts/check-public-endpoints.sh --stack-name ${{ env.STACK_NAME }}
- name: Summarize deployed release
run: |
{
echo "## AWS deploy"
echo ""
echo "- Deployed SHA: \`${GITHUB_SHA}\`"
echo "- Web post-deploy smoke: pending next job"
echo "- Agent API post-deploy smoke: pending next job"
echo ""
echo "Manual admin smoke remains required for \`https://admin.<domain>\`."
} >> "${GITHUB_STEP_SUMMARY}"
web_smoke:
name: Web post-deploy smoke
needs:
- changes
- aws_deploy
if: ${{ needs.changes.outputs.aws_changed == 'true' }}
runs-on: ubuntu-24.04
timeout-minutes: 45
steps:
- uses: actions/checkout@v6
- uses: actions/setup-node@v6
with:
node-version: 24
cache: npm
cache-dependency-path: apps/web/package-lock.json
- name: Install web dependencies
run: npm ci --prefix apps/web
- name: Build web app for live smoke
env:
VITE_APP_BASE_URL: https://app.flashcards-open-source-app.com
VITE_API_BASE_URL: https://api.flashcards-open-source-app.com/v1
VITE_AUTH_BASE_URL: https://auth.flashcards-open-source-app.com
run: npm run build --prefix apps/web
- name: Install Playwright Chromium
working-directory: apps/web
run: npx playwright install --with-deps chromium
- name: Run live web smoke test
id: live_smoke
working-directory: apps/web
env:
FLASHCARDS_E2E_APP_BASE_URL: https://app.flashcards-open-source-app.com
FLASHCARDS_E2E_AUTH_BASE_URL: https://auth.flashcards-open-source-app.com
FLASHCARDS_LIVE_REVIEW_EMAIL: google-review@example.com
run: |
set -euo pipefail
cert_dir="${RUNNER_TEMP}/web-live-e2e-cert"
cert_path="${cert_dir}/app.flashcards-open-source-app.com.crt"
key_path="${cert_dir}/app.flashcards-open-source-app.com.key"
server_log_path="${RUNNER_TEMP}/web-live-e2e-server.log"
mkdir -p "${cert_dir}"
openssl req \
-x509 \
-newkey rsa:2048 \
-sha256 \
-nodes \
-days 1 \
-subj "/CN=app.flashcards-open-source-app.com" \
-addext "subjectAltName=DNS:app.flashcards-open-source-app.com" \
-keyout "${key_path}" \
-out "${cert_path}"
printf '127.0.0.1 app.flashcards-open-source-app.com\n' | sudo tee -a /etc/hosts >/dev/null
sudo env PATH="${PATH}" node scripts/serve-dist-https.mjs \
--host 0.0.0.0 \
--port 443 \
--dir dist \
--cert "${cert_path}" \
--key "${key_path}" >"${server_log_path}" 2>&1 &
server_pid=$!
cleanup() {
sudo kill "${server_pid}" >/dev/null 2>&1 || true
}
trap cleanup EXIT
for _ in $(seq 1 30); do
if curl --silent --show-error --fail --insecure https://app.flashcards-open-source-app.com/ >/dev/null; then
break
fi
sleep 1
done
curl --silent --show-error --fail --insecure https://app.flashcards-open-source-app.com/ >/dev/null
npm run test:e2e
- name: Upload Playwright report
if: always()
uses: actions/upload-artifact@v7
with:
name: web-playwright-report
if-no-files-found: ignore
path: apps/web/playwright-report
- name: Upload Playwright test results
if: always()
uses: actions/upload-artifact@v7
with:
name: web-playwright-test-results
if-no-files-found: ignore
path: apps/web/test-results
- name: Summarize smoke result
if: always()
run: |
{
echo "## Web post-deploy smoke"
echo ""
echo "- Deployed SHA: \`${GITHUB_SHA}\`"
echo "- Result: \`${{ steps.live_smoke.outcome }}\`"
echo "- Artifacts: \`web-playwright-report\`, \`web-playwright-test-results\`"
} >> "${GITHUB_STEP_SUMMARY}"
agent_api_smoke:
name: Agent API post-deploy smoke
needs:
- changes
- aws_deploy
if: ${{ needs.changes.outputs.aws_changed == 'true' }}
runs-on: ubuntu-24.04
timeout-minutes: 30
steps:
- uses: actions/checkout@v6
- name: Run agent API smoke test
id: agent_smoke
env:
FLASHCARDS_AGENT_SMOKE_AUTH_BASE_URL: https://auth.flashcards-open-source-app.com
FLASHCARDS_AGENT_SMOKE_API_BASE_URL: https://api.flashcards-open-source-app.com/v1
FLASHCARDS_AGENT_SMOKE_DEMO_EMAIL: google-review@example.com
FLASHCARDS_AGENT_SMOKE_WORKSPACE_PREFIX: "E2E agent api "
FLASHCARDS_AGENT_SMOKE_CONNECTION_LABEL_PREFIX: "E2E agent api "
run: bash scripts/check-agent-api-smoke.sh
- name: Summarize smoke result
if: always()
run: |
{
echo "## Agent API post-deploy smoke"
echo ""
echo "- Deployed SHA: \`${GITHUB_SHA}\`"
echo "- Result: \`${{ steps.agent_smoke.outcome }}\`"
} >> "${GITHUB_STEP_SUMMARY}"
aws_release_status:
name: Resolve AWS release outcome
needs:
- changes
- pre_deploy_checks
- aws_deploy
- web_smoke
- agent_api_smoke
if: ${{ always() }}
runs-on: ubuntu-24.04
outputs:
aws_release_status: ${{ steps.resolve.outputs.aws_release_status }}
steps:
- name: Resolve AWS release status
id: resolve
run: |
set -euo pipefail
aws_release_status="no_aws_changes"
if [[ "${{ needs.changes.outputs.aws_changed }}" == "true" ]]; then
if [[ "${{ needs.pre_deploy_checks.result }}" != "success" ]]; then
aws_release_status="pre_deploy_checks_failed"
elif [[ "${{ needs.aws_deploy.result }}" != "success" ]]; then
aws_release_status="deployment_failed"
elif [[ "${{ needs.web_smoke.result }}" != "success" ]]; then
aws_release_status="web_smoke_failed"
elif [[ "${{ needs.agent_api_smoke.result }}" != "success" ]]; then
aws_release_status="agent_api_smoke_failed"
else
aws_release_status="released"
fi
fi
echo "aws_release_status=${aws_release_status}" >> "${GITHUB_OUTPUT}"
- name: Summarize AWS release outcome
run: |
{
echo "## AWS release outcome"
echo ""
echo "- AWS release status: \`${{ steps.resolve.outputs.aws_release_status }}\`"
} >> "${GITHUB_STEP_SUMMARY}"
release_summary:
name: AWS/Web release summary
if: ${{ always() }}
needs:
- changes
- pre_deploy_checks
- aws_deploy
- web_smoke
- agent_api_smoke
- aws_release_status
runs-on: ubuntu-24.04
steps:
- name: Summarize release outcome
run: |
{
echo "## AWS/Web release summary"
echo ""
echo "- AWS changed: \`${{ needs.changes.outputs.aws_changed }}\`"
echo "- Pre-deploy checks job: \`${{ needs.pre_deploy_checks.result }}\`"
echo "- AWS release status: \`${{ needs.aws_release_status.outputs.aws_release_status }}\`"
echo "- AWS deploy job: \`${{ needs.aws_deploy.result }}\`"
echo "- Web smoke job: \`${{ needs.web_smoke.result }}\`"
echo "- Agent API smoke job: \`${{ needs.agent_api_smoke.result }}\`"
echo "- Run details: ${{ github.server_url }}/${{ github.repository }}/actions/runs/${{ github.run_id }}"
} >> "${GITHUB_STEP_SUMMARY}"
- name: Fail workflow when AWS/Web release is not healthy
run: |
set -euo pipefail
aws_release_status="${{ needs.aws_release_status.outputs.aws_release_status }}"
if [[ "${aws_release_status}" != "no_aws_changes" ]] && [[ "${aws_release_status}" != "released" ]]; then
echo "AWS release finished in non-healthy state: ${aws_release_status}" >&2
exit 1
fi