-
Notifications
You must be signed in to change notification settings - Fork 2
195 lines (168 loc) · 7.17 KB
/
deploy-gateway.yml
File metadata and controls
195 lines (168 loc) · 7.17 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
name: Deploy Gateway
on:
push:
branches: [main]
paths:
- "gateway/**"
- "packages/agent-world-sdk/src/**"
- "packages/agent-world-sdk/package.json"
workflow_dispatch:
concurrency:
group: deploy-gateway
cancel-in-progress: true
permissions:
id-token: write
contents: read
jobs:
deploy:
name: Build & Deploy Gateway
runs-on: ubuntu-latest
env:
ECR_REPOSITORY: awn-gateway
INSTANCE_ID: i-04670f4d1a72c7d5d
GATEWAY_URL: ${{ vars.GATEWAY_URL || 'https://gateway.agentworlds.ai' }}
steps:
- name: Checkout
uses: actions/checkout@v6
- name: Configure AWS credentials
uses: aws-actions/configure-aws-credentials@v6
with:
role-to-assume: ${{ secrets.AWS_DEPLOY_ROLE_ARN }}
aws-region: us-east-2
- name: Update Cloudflare DNS
env:
CF_API_TOKEN: ${{ secrets.CF_API_TOKEN }}
CF_ZONE_ID: ${{ secrets.CF_ZONE_ID }}
run: |
GATEWAY_HOST=$(echo "$GATEWAY_URL" | sed 's|^https\?://||' | cut -d'/' -f1)
EC2_IP="${{ vars.EC2_PUBLIC_IP }}"
if [ -z "$EC2_IP" ]; then
echo "::error::EC2_PUBLIC_IP variable is not set. Add it in repo Settings -> Variables."
exit 1
fi
echo "EC2 public IP: $EC2_IP Gateway: $GATEWAY_HOST"
PAYLOAD="{\"type\":\"A\",\"name\":\"$GATEWAY_HOST\",\"content\":\"$EC2_IP\",\"ttl\":1,\"proxied\":true}"
EXISTING=$(curl -s \
"https://api.cloudflare.com/client/v4/zones/$CF_ZONE_ID/dns_records?type=A&name=$GATEWAY_HOST" \
-H "Authorization: Bearer $CF_API_TOKEN" \
-H "Content-Type: application/json")
if ! echo "$EXISTING" | jq -e '.success == true' > /dev/null 2>&1; then
echo "::warning::Cloudflare API error: $(echo "$EXISTING" | jq -rc '.errors // .')"
echo "Skipping DNS update — record may already be correct."
else
RECORD_ID=$(echo "$EXISTING" | jq -r '.result[0].id // empty')
CURRENT_IP=$(echo "$EXISTING" | jq -r '.result[0].content // empty')
if [ "$CURRENT_IP" = "$EC2_IP" ]; then
echo "DNS already up to date ($GATEWAY_HOST → $EC2_IP), skipping update."
elif [ -n "$RECORD_ID" ]; then
curl -s -X PUT \
"https://api.cloudflare.com/client/v4/zones/$CF_ZONE_ID/dns_records/$RECORD_ID" \
-H "Authorization: Bearer $CF_API_TOKEN" \
-H "Content-Type: application/json" \
-d "$PAYLOAD" | jq -c '{success,errors}'
echo "Updated DNS A record $RECORD_ID → $EC2_IP"
else
curl -s -X POST \
"https://api.cloudflare.com/client/v4/zones/$CF_ZONE_ID/dns_records" \
-H "Authorization: Bearer $CF_API_TOKEN" \
-H "Content-Type: application/json" \
-d "$PAYLOAD" | jq -c '{success,errors}'
echo "Created DNS A record $GATEWAY_HOST → $EC2_IP"
fi
fi
- name: Login to Amazon ECR
id: ecr-login
uses: aws-actions/amazon-ecr-login@v2
- name: Build & push Docker image
env:
REGISTRY: ${{ steps.ecr-login.outputs.registry }}
run: |
IMAGE="$REGISTRY/$ECR_REPOSITORY"
docker build -f gateway/Dockerfile -t "$IMAGE:${{ github.sha }}" -t "$IMAGE:latest" .
docker push "$IMAGE:${{ github.sha }}"
docker push "$IMAGE:latest"
- name: Deploy via SSM
env:
REGISTRY: ${{ steps.ecr-login.outputs.registry }}
run: |
IMAGE="$REGISTRY/$ECR_REPOSITORY:${{ github.sha }}"
# Build SSM parameters via jq to avoid quoting issues.
# The instance role has ecr-pull permissions, so we use the ECR
# credential helper for authentication instead of the aws CLI.
PARAMS=$(jq -cn \
--arg pull "docker pull $IMAGE" \
--arg run "docker run -d --name awn-gateway --restart unless-stopped -p 80:8100 -v /opt/awn-gateway/data:/data -e HTTP_PORT=8100 -e DATA_DIR=/data -e PUBLIC_URL=$GATEWAY_URL -e PUBLIC_ADDR=$(echo $GATEWAY_URL | sed 's|^https\?://||' | cut -d'/' -f1) $IMAGE" \
'{commands: [
"command -v amazon-ecr-credential-helper >/dev/null 2>&1 || apt-get install -y amazon-ecr-credential-helper",
"mkdir -p /root/.docker && printf '"'"'{\"credsStore\":\"ecr-login\"}'"'"' > /root/.docker/config.json",
$pull,
"docker stop awn-gateway 2>/dev/null || true",
"docker rm awn-gateway 2>/dev/null || true",
"fuser -k 80/tcp 2>/dev/null || true",
$run
]}')
COMMAND_ID=$(aws ssm send-command \
--instance-ids "$INSTANCE_ID" \
--document-name "AWS-RunShellScript" \
--parameters "$PARAMS" \
--region us-east-2 \
--query "Command.CommandId" \
--output text)
echo "SSM Command ID: $COMMAND_ID"
sleep 5
for i in $(seq 1 30); do
if STATUS=$(aws ssm get-command-invocation \
--command-id "$COMMAND_ID" \
--instance-id "$INSTANCE_ID" \
--region us-east-2 \
--query "Status" \
--output text 2>&1); then
echo "Attempt $i: Status=$STATUS"
if [ "$STATUS" = "Success" ]; then
echo "Deploy command succeeded"
exit 0
elif [ "$STATUS" = "Failed" ] || [ "$STATUS" = "Cancelled" ] || [ "$STATUS" = "TimedOut" ]; then
echo "Deploy command failed with status: $STATUS"
aws ssm get-command-invocation \
--command-id "$COMMAND_ID" \
--instance-id "$INSTANCE_ID" \
--region us-east-2 \
--query "StandardErrorContent" \
--output text
exit 1
fi
else
echo "Attempt $i: GetCommandInvocation error (will retry): $STATUS"
fi
sleep 10
done
echo "Timed out waiting for deploy command"
exit 1
- name: Health check
run: |
COMMAND_ID=$(aws ssm send-command \
--instance-ids "$INSTANCE_ID" \
--document-name "AWS-RunShellScript" \
--parameters commands='["sleep 5","curl -sf http://localhost/health"]' \
--region us-east-2 \
--query "Command.CommandId" \
--output text)
sleep 15
STATUS=$(aws ssm get-command-invocation \
--command-id "$COMMAND_ID" \
--instance-id "$INSTANCE_ID" \
--region us-east-2 \
--query "Status" \
--output text)
if [ "$STATUS" = "Success" ]; then
echo "Health check passed"
else
echo "Health check failed (status: $STATUS)"
aws ssm get-command-invocation \
--command-id "$COMMAND_ID" \
--instance-id "$INSTANCE_ID" \
--region us-east-2 \
--query "StandardErrorContent" \
--output text
exit 1
fi