Repository navigation
128 lines (125 loc) · 5.76 KB
/
Copy pathplugin-stats-deploy.yml
File metadata and controls
128 lines (125 loc) · 5.76 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
name: Deploy plugin stats
on:
push:
branches: [dev]
paths:
- 'apps/server/**'
- 'deploy/plugin-stats/**'
- '.github/workflows/plugin-stats-deploy.yml'
workflow_dispatch:
concurrency:
group: plugin-stats-production
cancel-in-progress: false
jobs:
deploy:
runs-on: ubuntu-24.04
services:
mysql:
image: mysql:8.0
env:
MYSQL_ROOT_PASSWORD: integration-only-password
MYSQL_DATABASE: toolforge_stats_test
ports: ['3306:3306']
options: >-
--health-cmd="mysqladmin ping -h127.0.0.1 -pintegration-only-password"
--health-interval=5s --health-timeout=3s --health-retries=20
defaults:
run:
working-directory: apps/server
steps:
- uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2
with:
persist-credentials: false
- uses: actions/setup-go@d35c59abb061a4a6fb18e82ac0862c26744d6ab5 # v5.5.0
with:
go-version: '1.26.10'
check-latest: true
cache-dependency-path: apps/server/go.sum
- name: Test
env:
TEST_MYSQL_DSN: root:integration-only-password@tcp(127.0.0.1:3306)/toolforge_stats_test?parseTime=true
run: |
test -z "$(gofmt -l .)"
go mod download
go mod verify
go vet ./...
go test -race -count=1 ./...
- name: Build Linux amd64 binary
run: |
mkdir -p build
CGO_ENABLED=0 GOOS=linux GOARCH=amd64 go build -trimpath -ldflags "-s -w -X main.buildSHA=$GITHUB_SHA" -o build/plugin-stats ./cmd/plugin-stats
sha256sum build/plugin-stats > build/plugin-stats.sha256
- name: Generate runtime config
run: |
cp ../../deploy/plugin-stats/toolforge-plugin-stats.service build/
# Single-quote every value: the file is sourced by dash (sh) during
# migration and parsed by systemd; unquoted parentheses break sh.
cat > build/runtime.env <<EOF
MYSQL_DSN='${{ secrets.DB_USER }}:${{ secrets.DB_PASSWORD }}@tcp(${{ secrets.DB_HOST }}:${{ secrets.DB_PORT }})/${{ secrets.DB_NAME }}?allowNativePasswords=true'
STATS_LISTEN_ADDR='127.0.0.1:8088'
PLUGIN_ASSET_BASE_URL='https://plugins.toolforge.devlive.org'
RECEIPT_ACTIVE_KID='2026-01'
RECEIPT_KEYS_JSON='{"2026-01":"${{ secrets.RECEIPT_KEY }}"}'
COS_SECRET_ID='${{ secrets.COS_SECRET_ID }}'
COS_SECRET_KEY='${{ secrets.COS_SECRET_KEY }}'
EOF
chmod 600 build/runtime.env
- name: Upload to server
uses: appleboy/scp-action@master
with:
host: ${{ secrets.SSH_HOST }}
username: ${{ secrets.SSH_USER }}
key: ${{ secrets.SSH_KEY }}
source: 'apps/server/build/plugin-stats,apps/server/build/plugin-stats.sha256,apps/server/build/runtime.env,apps/server/build/toolforge-plugin-stats.service'
target: /tmp/stats-deploy
strip_components: 0
- name: Install and restart
uses: appleboy/ssh-action@master
env:
SHA: ${{ github.sha }}
with:
host: ${{ secrets.SSH_HOST }}
username: ${{ secrets.SSH_USER }}
key: ${{ secrets.SSH_KEY }}
envs: SHA
script: |
set -eu
cd /tmp/stats-deploy/apps/server/build
echo "==> install release $SHA"
sudo id toolforge-stats >/dev/null 2>&1 || sudo useradd --system --no-create-home --shell /usr/sbin/nologin toolforge-stats
sudo install -d -o root -g root -m 755 /opt/toolforge-plugin-stats/releases
sudo install -d -o root -g toolforge-stats -m 750 /etc/toolforge-plugin-stats
release=/opt/toolforge-plugin-stats/releases/$SHA
sudo install -d -o root -g root -m 755 "$release"
echo "$(cut -d ' ' -f 1 plugin-stats.sha256) plugin-stats" | sha256sum -c --status
sudo install -m 755 plugin-stats "$release/plugin-stats"
sudo install -m 640 -o root -g toolforge-stats runtime.env /etc/toolforge-plugin-stats/runtime.env
sudo install -m 644 toolforge-plugin-stats.service /etc/systemd/system/toolforge-plugin-stats.service
sudo systemctl daemon-reload
sudo systemctl enable toolforge-plugin-stats >/dev/null
echo "==> migrate"
sudo bash -c "set -a; . /etc/toolforge-plugin-stats/runtime.env; set +a; exec '$release/plugin-stats' migrate up"
echo "==> switch and restart"
previous=$(sudo readlink -f /opt/toolforge-plugin-stats/current 2>/dev/null || true)
sudo ln -sfn "$release" /opt/toolforge-plugin-stats/current.next
sudo mv -Tf /opt/toolforge-plugin-stats/current.next /opt/toolforge-plugin-stats/current
sudo systemctl restart toolforge-plugin-stats
ok=false
for _ in $(seq 1 30); do
if curl -fsS --max-time 2 http://127.0.0.1:8088/readyz 2>/dev/null | grep -q "\"buildSha\":\"$SHA\""; then ok=true; break; fi
sleep 1
done
if [ "$ok" != true ]; then
if [ -n "$previous" ]; then
sudo ln -sfn "$previous" /opt/toolforge-plugin-stats/current.rollback
sudo mv -Tf /opt/toolforge-plugin-stats/current.rollback /opt/toolforge-plugin-stats/current
sudo systemctl restart toolforge-plugin-stats
echo 'New release failed readiness; rolled back to the previous release.' >&2
else
sudo systemctl stop toolforge-plugin-stats || true
echo 'First deployment failed readiness; service stopped for inspection.' >&2
fi
exit 1
fi
sudo rm -rf /tmp/stats-deploy
echo "Deployed $SHA"