-
Notifications
You must be signed in to change notification settings - Fork 5
201 lines (182 loc) · 7.44 KB
/
Copy pathdeploy-relay.yml
File metadata and controls
201 lines (182 loc) · 7.44 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
196
197
198
199
200
201
name: deploy relay
# Ops controls for the CI relay (moqx-main.ci.openmoq.org + moqx-000 alias).
# Restart, redeploy with a specific image tag, or change the log level.
on:
workflow_dispatch:
inputs:
restart_only:
description: "Restart container without redeploying"
required: false
type: boolean
default: false
image_tag:
description: "Image tag (default derived from branch)"
required: false
default: ""
type: string
domain:
description: "Hostname (default derived from branch)"
required: false
default: ""
type: string
logging:
description: "Log level (default INFO)"
required: false
default: "default"
type: choice
options:
- "default"
- "WARN"
- "DBG1"
- "DBG2"
- "DBG3"
- "DBG4"
enable_stats:
description: "Enable stats dashboard (default enabled)"
required: false
type: boolean
default: true
permissions:
contents: read
packages: read
env:
RELAY_PORT: 4433
ADMIN_PORT: 8000
jobs:
deploy:
runs-on: [self-hosted, linode]
steps:
- uses: actions/checkout@v4
- name: Compute deployment target
id: target
run: |
# Branch label: main → "main"; release/<name> → "<name>"
# Rolling Docker tag: <label>-latest (symmetric across branches)
BRANCH="${{ github.ref_name }}"
if [[ "$BRANCH" == "main" ]]; then
LABEL="main"
else
LABEL="${BRANCH#release/}"
fi
DEFAULT_TAG="${LABEL}-latest"
# Explicit input overrides, otherwise computed defaults
IMAGE_TAG="${{ inputs.image_tag }}"
IMAGE_TAG="${IMAGE_TAG:-$DEFAULT_TAG}"
DOMAIN="${{ inputs.domain }}"
DOMAIN="${DOMAIN:-moqx-${LABEL}.ci.openmoq.org}"
# Qualify a bare label (no dot) into the CI zone, so an explicit
# `domain=moqx-main` works the same as the full FQDN.
if [[ "$DOMAIN" != *.* ]]; then
DOMAIN="${DOMAIN}.ci.openmoq.org"
fi
echo "image_tag=$IMAGE_TAG" >> "$GITHUB_OUTPUT"
echo "domain=$DOMAIN" >> "$GITHUB_OUTPUT"
echo "Deploying ghcr.io/${{ github.repository }}:${IMAGE_TAG} → ${DOMAIN}"
- name: Ensure DNS A record
if: ${{ !inputs.restart_only }}
env:
DOMAIN: ${{ steps.target.outputs.domain }}
AWS_ACCESS_KEY_ID: ${{ secrets.OMOQ_CERTBOT_ACCESS_KEY_ID }}
AWS_SECRET_ACCESS_KEY: ${{ secrets.OMOQ_CERTBOT_SECRET_ACCESS_KEY }}
AWS_DEFAULT_REGION: us-east-1
HOSTED_ZONE_ID: Z0079758316CI99B99FLR
run: |
# Discover the public IP of this self-hosted runner (the deploy target)
IP=$(curl -sf https://checkip.amazonaws.com | tr -d '[:space:]')
if [[ -z "$IP" ]]; then
echo "::error::Could not determine runner public IP"
exit 1
fi
echo "Runner public IP: $IP"
echo "Ensuring A record: $DOMAIN → $IP"
# Check current record (if any). UPSERT is idempotent — only changes
# if the record is missing or pointing elsewhere.
CHANGE_FILE=$(mktemp)
cat > "$CHANGE_FILE" <<EOF
{
"Comment": "moqx deploy: $DOMAIN",
"Changes": [{
"Action": "UPSERT",
"ResourceRecordSet": {
"Name": "$DOMAIN",
"Type": "A",
"TTL": 300,
"ResourceRecords": [{"Value": "$IP"}]
}
}]
}
EOF
CHANGE_ID=$(aws route53 change-resource-record-sets \
--hosted-zone-id "$HOSTED_ZONE_ID" \
--change-batch "file://$CHANGE_FILE" \
--query 'ChangeInfo.Id' --output text)
echo "Route53 change submitted: $CHANGE_ID"
# Wait for the change to propagate (usually seconds). Bounded wait
# so a slow Route53 doesn't hang the deploy forever.
echo "Waiting for DNS change to propagate..."
aws route53 wait resource-record-sets-changed --id "$CHANGE_ID"
echo "DNS change INSYNC"
rm -f "$CHANGE_FILE"
- name: Log in to GHCR
run: echo "${{ secrets.GITHUB_TOKEN }}" | docker login ghcr.io -u ${{ github.actor }} --password-stdin
- name: Run
working-directory: docker
env:
RESTART_ONLY: ${{ inputs.restart_only }}
LOGGING: ${{ inputs.logging }}
DOMAIN: ${{ steps.target.outputs.domain }}
IMAGE_TAG: ${{ steps.target.outputs.image_tag }}
AWS_ACCESS_KEY_ID: ${{ secrets.OMOQ_CERTBOT_ACCESS_KEY_ID }}
AWS_SECRET_ACCESS_KEY: ${{ secrets.OMOQ_CERTBOT_SECRET_ACCESS_KEY }}
ENABLE_STATS: ${{ inputs.enable_stats }}
STATS_USER: ${{ secrets.STATS_USER }}
STATS_PASSWORD: ${{ secrets.STATS_PASSWORD }}
GRAFANA_ADMIN_PASSWORD: ${{ secrets.GRAFANA_ADMIN_PASSWORD }}
run: |
if [ "$RESTART_ONLY" = "true" ]; then
echo "==> Restarting relay..."
docker compose restart moqx
for i in $(seq 1 30); do
curl -sf "http://127.0.0.1:${ADMIN_PORT}/info" >/dev/null 2>&1 && break
sleep 1
[ "$i" -eq 30 ] && { echo "::error::relay did not respond after restart"; docker compose logs moqx; exit 1; }
done
echo "==> Relay restarted: $(curl -sf http://127.0.0.1:${ADMIN_PORT}/info)"
exit 0
fi
# folly XLOG override ("default" from the dialog = no override).
LOGGING_CFG=""
[ "${LOGGING}" != "default" ] && LOGGING_CFG="${LOGGING}"
# Ensure TLS cert
CERT="/etc/letsencrypt/live/${DOMAIN}/fullchain.pem"
if [ ! -f "$CERT" ]; then
echo "::warning::No cert for ${DOMAIN} — provisioning via Route53"
sudo -E certbot certonly --dns-route53 \
-d "$DOMAIN" --non-interactive --agree-tos \
--email gmarzot@openmoq.org
elif ! sudo openssl x509 -in "$CERT" -noout -checkend 2592000 2>/dev/null; then
echo "::warning::Cert for ${DOMAIN} expires within 30 days — renewing"
sudo -E certbot renew --cert-name "$DOMAIN"
else
echo "Cert for ${DOMAIN} is valid"
fi
# Deploy via the shared core (same script ci-main uses): writes .env,
# pulls IMAGE_TAG (retagged :latest for compose), brings up the relay
# + stats + public dashboard when ENABLE_STATS, health check, publish.
PULL_IMAGE="ghcr.io/${{ github.repository }}:${IMAGE_TAG}" \
MOQX_LOGGING="$LOGGING_CFG" \
bash relay-deploy.sh
- name: Notify Slack
if: always()
env:
SLACK_WEBHOOK_URL: ${{ secrets.OMOQ_SLACK_WEBHOOK_URL }}
DOMAIN: ${{ steps.target.outputs.domain }}
IMAGE_TAG: ${{ steps.target.outputs.image_tag }}
run: |
SHORT="${GITHUB_SHA:0:7}"
ACTION=${{ inputs.restart_only && '"restarted"' || '"deployed"' }}
STATUS=${{ job.status == 'success' && '":rocket:"' || '":x:"' }}
TEXT="${STATUS} *${{ github.repository }}* ${ACTION} \`${IMAGE_TAG}\` on \`${DOMAIN}:${RELAY_PORT}\`"
curl -sf -X POST "$SLACK_WEBHOOK_URL" \
-H "Content-Type: application/json" \
--data "{\"text\": \"${TEXT}\"}" || true