5282eb57c9
Deploy / deploy (push) Successful in 1m36s
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
136 lines
4.0 KiB
Bash
Executable File
136 lines
4.0 KiB
Bash
Executable File
#!/usr/bin/env bash
|
|
# deploy.sh <tag> — deploy release to EC2
|
|
# Works in two modes:
|
|
# 1. Automated (after compile.sh): uses dist/ built in the same job
|
|
# 2. Manual/rollback: downloads assets from Forgejo Release by tag
|
|
set -euo pipefail
|
|
|
|
TAG="$1"
|
|
|
|
echo "==> deploy: tag=${TAG}"
|
|
|
|
# Download from Forgejo if dist/ was not built in this job
|
|
if [ ! -f dist/jiu-server ] || [ ! -f dist/web.tar.gz ] || [ ! -f dist/configs.tar.gz ]; then
|
|
echo "==> deploy: dist/ incomplete — downloading assets for ${TAG} from Forgejo"
|
|
mkdir -p dist
|
|
|
|
curl -kf \
|
|
-H "Authorization: token ${FORGEJO_TOKEN}" \
|
|
"${FORGEJO_URL}/api/v1/repos/${GITEA_REPOSITORY}/releases/tags/${TAG}" \
|
|
-o /tmp/release-info.json
|
|
|
|
python3 - <<'PYEOF'
|
|
import json, urllib.request, ssl, os, sys
|
|
|
|
ctx = ssl.create_default_context()
|
|
ctx.check_hostname = False
|
|
ctx.verify_mode = ssl.CERT_NONE
|
|
|
|
with open('/tmp/release-info.json') as f:
|
|
release = json.load(f)
|
|
|
|
token = os.environ['FORGEJO_TOKEN']
|
|
forgejo_url = os.environ['FORGEJO_URL']
|
|
repo = os.environ['GITEA_REPOSITORY']
|
|
release_id = release['id']
|
|
|
|
for asset in release.get('assets', []):
|
|
url = f"{forgejo_url}/api/v1/repos/{repo}/releases/{release_id}/assets/{asset['id']}"
|
|
req = urllib.request.Request(url, headers={'Authorization': f'token {token}'})
|
|
with urllib.request.urlopen(req, context=ctx) as resp:
|
|
with open(f"dist/{asset['name']}", 'wb') as out:
|
|
out.write(resp.read())
|
|
print(f"Downloaded: {asset['name']}")
|
|
PYEOF
|
|
fi
|
|
|
|
echo "==> deploy: dist/ contents:"
|
|
ls -lh dist/
|
|
|
|
# Extract configs (nginx, version.yaml, etc.)
|
|
rm -rf /tmp/jiu-configs
|
|
mkdir -p /tmp/jiu-configs
|
|
tar -xzf dist/configs.tar.gz -C /tmp/jiu-configs
|
|
|
|
# Extract Flutter web build
|
|
rm -rf /tmp/jiu-web-new
|
|
mkdir -p /tmp/jiu-web-new
|
|
tar -xzf dist/web.tar.gz -C /tmp/jiu-web-new --strip-components=1
|
|
|
|
# Setup SSH
|
|
mkdir -p ~/.ssh
|
|
printf '%s' "${EC2_SSH_KEY}" > ~/.ssh/ec2_deploy.pem
|
|
chmod 600 ~/.ssh/ec2_deploy.pem
|
|
ssh-keyscan -H "${EC2_HOST}" >> ~/.ssh/known_hosts
|
|
|
|
SSH="ssh -i ~/.ssh/ec2_deploy.pem -o StrictHostKeyChecking=no"
|
|
SCP="scp -O -i ~/.ssh/ec2_deploy.pem"
|
|
|
|
echo "==> deploy: uploading files to EC2"
|
|
|
|
# Upload backend binary
|
|
${SCP} dist/jiu-server "${EC2_USER}@${EC2_HOST}:/tmp/jiu-server"
|
|
|
|
# Upload version.yaml
|
|
${SCP} /tmp/jiu-configs/backend/config/version.yaml "${EC2_USER}@${EC2_HOST}:/tmp/version.yaml"
|
|
|
|
# Upload nginx config
|
|
${SCP} /tmp/jiu-configs/deploy/nginx-jiu.conf "${EC2_USER}@${EC2_HOST}:/tmp/nginx-jiu.conf"
|
|
|
|
# Upload Flutter web
|
|
rsync -avz --delete -e "ssh -i ~/.ssh/ec2_deploy.pem -o StrictHostKeyChecking=no" \
|
|
/tmp/jiu-web-new/ "${EC2_USER}@${EC2_HOST}:/tmp/jiu-web-new/"
|
|
|
|
# Upload marketing site (from repo checkout)
|
|
rsync -avz --delete -e "ssh -i ~/.ssh/ec2_deploy.pem -o StrictHostKeyChecking=no" \
|
|
web/ "${EC2_USER}@${EC2_HOST}:/tmp/jiu-marketing-new/"
|
|
|
|
echo "==> deploy: running remote deploy"
|
|
|
|
${SSH} "${EC2_USER}@${EC2_HOST}" << 'ENDSSH'
|
|
set -e
|
|
|
|
# Replace backend binary
|
|
sudo systemctl stop jiu
|
|
cp /tmp/jiu-server /opt/jiu/backend/jiu-server
|
|
chmod +x /opt/jiu/backend/jiu-server
|
|
|
|
# Update version config
|
|
mkdir -p /opt/jiu/backend/config
|
|
cp /tmp/version.yaml /opt/jiu/backend/config/version.yaml
|
|
|
|
# Start and health check
|
|
sudo systemctl start jiu
|
|
echo "Waiting for health check..."
|
|
for i in $(seq 1 30); do
|
|
if curl -f http://localhost:8080/health > /dev/null 2>&1; then
|
|
echo "Health check passed"
|
|
break
|
|
fi
|
|
sleep 2
|
|
done
|
|
curl -f http://localhost:8080/health > /dev/null || { echo "Health check failed!"; exit 1; }
|
|
|
|
# Swap Flutter web app (atomic)
|
|
rm -rf /opt/jiu/web-old
|
|
mv /opt/jiu/web /opt/jiu/web-old 2>/dev/null || true
|
|
mv /tmp/jiu-web-new /opt/jiu/web
|
|
|
|
# Update marketing site
|
|
mkdir -p /opt/jiu/marketing
|
|
rsync -a --delete /tmp/jiu-marketing-new/ /opt/jiu/marketing/
|
|
rm -rf /tmp/jiu-marketing-new
|
|
|
|
# Update nginx config and reload
|
|
sudo cp /tmp/nginx-jiu.conf /etc/nginx/conf.d/jiu.conf
|
|
sudo nginx -t && sudo nginx -s reload
|
|
|
|
echo "Deploy complete!"
|
|
ENDSSH
|
|
|
|
# Cleanup SSH key
|
|
rm -f ~/.ssh/ec2_deploy.pem
|
|
rm -rf /tmp/jiu-configs /tmp/jiu-web-new
|
|
|
|
echo "==> deploy: done"
|