mirror of
https://github.com/Sea-Haven-Industries/shoc-backend.git
synced 2026-09-30 15:23:12 +00:00
Add import-only dev and staging state with least-privilege HCP authentication and plan safety guards.
113 lines
4.1 KiB
Bash
113 lines
4.1 KiB
Bash
#!/usr/bin/env bash
|
|
#
|
|
# deploy-api-tf.sh — local Elastic Beanstalk publish for the Terraform POC.
|
|
# Refuses live names. GitHub Actions is the real CD path once the branch is
|
|
# pushed; this script exists only because GHA cannot run until then.
|
|
#
|
|
# Usage:
|
|
# export AWS_PROFILE=seahaven-external-dev
|
|
# bash scripts/deploy-api-tf.sh
|
|
set -euo pipefail
|
|
|
|
REGION="${AWS_REGION:-us-east-1}"
|
|
APPLICATION_NAME="shoc-backend-tf-poc"
|
|
ENVIRONMENT_NAME="shoc-backend-tf-poc"
|
|
SMOKE_URL="https://tf-poc.api.dev.seahaven.com"
|
|
S3_BUCKET="elasticbeanstalk-us-east-1-396287094661"
|
|
|
|
log() { printf '\n\033[1m== %s ==\033[0m\n' "$1"; }
|
|
die() { printf '\033[31mERR\033[0m %s\n' "$1" >&2; exit 1; }
|
|
|
|
[[ "${APPLICATION_NAME}" != "shoc-backend" ]] \
|
|
|| die "refusing live Elastic Beanstalk application shoc-backend"
|
|
[[ "${ENVIRONMENT_NAME}" != "shoc-backend-dev" ]] \
|
|
|| die "refusing live Elastic Beanstalk environment shoc-backend-dev"
|
|
[[ "${SMOKE_URL}" != "https://api.dev.seahaven.com" ]] \
|
|
|| die "refusing live hostname api.dev.seahaven.com"
|
|
|
|
command -v aws >/dev/null 2>&1 || die "aws CLI is required"
|
|
command -v curl >/dev/null 2>&1 || die "curl is required"
|
|
|
|
ACCOUNT="$(aws sts get-caller-identity --query Account --output text)"
|
|
[[ "${ACCOUNT}" == "396287094661" ]] \
|
|
|| die "refusing to deploy outside seahaven-external-dev (caller account ${ACCOUNT})"
|
|
|
|
REPO_ROOT="$(cd "$(dirname "${BASH_SOURCE[0]}")/.." && pwd)"
|
|
cd "$REPO_ROOT"
|
|
|
|
log "package source bundle"
|
|
bash scripts/package-elastic-beanstalk.sh
|
|
|
|
VERSION_LABEL="local-$(date -u +%Y%m%d%H%M%S)-${USER:-unknown}"
|
|
BUNDLE=".artifacts/elastic-beanstalk/site.zip"
|
|
KEY="shoc-backend-tf-poc/${VERSION_LABEL}.zip"
|
|
|
|
log "capture current environment version"
|
|
prev="$(aws elasticbeanstalk describe-environments \
|
|
--environment-names "${ENVIRONMENT_NAME}" \
|
|
--region "${REGION}" \
|
|
--query 'Environments[0].VersionLabel' \
|
|
--output text)"
|
|
echo "${prev}" > .artifacts/elastic-beanstalk/previous-version.txt
|
|
echo "Previous version label: ${prev}"
|
|
|
|
log "upload bundle ${KEY}"
|
|
aws s3 cp "${BUNDLE}" "s3://${S3_BUCKET}/${KEY}" --region "${REGION}"
|
|
|
|
log "create application version ${VERSION_LABEL}"
|
|
aws elasticbeanstalk create-application-version \
|
|
--application-name "${APPLICATION_NAME}" \
|
|
--version-label "${VERSION_LABEL}" \
|
|
--source-bundle "S3Bucket=${S3_BUCKET},S3Key=${KEY}" \
|
|
--region "${REGION}"
|
|
|
|
log "update environment ${ENVIRONMENT_NAME}"
|
|
aws elasticbeanstalk update-environment \
|
|
--environment-name "${ENVIRONMENT_NAME}" \
|
|
--version-label "${VERSION_LABEL}" \
|
|
--region "${REGION}"
|
|
|
|
log "wait until expected version is Ready"
|
|
status="Unknown"
|
|
current="Unknown"
|
|
health="Unknown"
|
|
for _ in $(seq 1 80); do
|
|
read -r status current health < <(
|
|
aws elasticbeanstalk describe-environments \
|
|
--environment-names "${ENVIRONMENT_NAME}" \
|
|
--region "${REGION}" \
|
|
--query 'Environments[0].[Status,VersionLabel,Health]' \
|
|
--output text
|
|
)
|
|
echo "environment status: ${status}; version: ${current}; health: ${health}"
|
|
if [ "${status}" = "Ready" ]; then
|
|
if [ "${current}" = "${VERSION_LABEL}" ] && { [ "${health}" = "Green" ] || [ "${health}" = "Yellow" ]; }; then
|
|
echo "Expected application version is Ready and healthy."
|
|
break
|
|
fi
|
|
die "Environment became Ready without activating expected version ${VERSION_LABEL}."
|
|
fi
|
|
sleep 15
|
|
done
|
|
[[ "${status}" = "Ready" ]] || die "Expected application version did not become Ready."
|
|
|
|
log "smoke ${SMOKE_URL}"
|
|
bash scripts/smoke-elastic-beanstalk.sh "${SMOKE_URL}"
|
|
|
|
log "webhook secret source"
|
|
response_file="$(mktemp)"
|
|
trap 'rm -f "$response_file"' EXIT
|
|
status_code="$(curl --silent --show-error \
|
|
--output "$response_file" \
|
|
--write-out '%{http_code}' \
|
|
--request POST \
|
|
--header 'Content-Type: application/json' \
|
|
--header "X-SH-Timestamp: $(date +%s)" \
|
|
--header 'X-SH-Key-Id: deployment-smoke-invalid-key' \
|
|
--header "X-SH-Signature: v1=$(printf '0%.0s' {1..64})" \
|
|
--data '{}' \
|
|
"${SMOKE_URL}/api/webhooks/work-orders")"
|
|
if [ "${status_code}" != "401" ]; then
|
|
die "Expected enabled webhook to reject the invalid probe with 401; received ${status_code}."
|
|
fi
|
|
echo "webhook HTTP 401"
|