@@ -2,9 +2,9 @@ name: deploy-test
22
33on :
44 workflow_dispatch :
5- # push:
6- # branches:
7- # - develop
5+ push :
6+ branches :
7+ - develop
88
99permissions :
1010 contents : read
@@ -14,10 +14,7 @@ concurrency:
1414 cancel-in-progress : false
1515
1616env :
17- API_IMAGE_REPOSITORY : cixing-api
18- POSTGRES_IMAGE : postgres:16-alpine
19- REDIS_IMAGE : redis:7-alpine
20- MAILPIT_IMAGE : axllent/mailpit:v1.29.7
17+ ACR_REPO : registry.cn-hangzhou.aliyuncs.com/muxi/memento
2118
2219jobs :
2320 deploy :
@@ -34,36 +31,52 @@ jobs:
3431 TEST_SERVER_SSH_KEY : ${{ secrets.TEST_SERVER_SSH_KEY }}
3532 TEST_CONFIG_YAML : ${{ secrets.TEST_CONFIG_YAML }}
3633 TEST_POSTGRES_PASSWORD : ${{ secrets.TEST_POSTGRES_PASSWORD }}
34+ ACR_USERNAME : ${{ secrets.ACR_USERNAME }}
35+ ACR_PASSWORD : ${{ secrets.ACR_PASSWORD }}
3736 run : |
3837 set -eu
3938 test -n "$TEST_SERVER_HOST"
4039 test -n "$TEST_SERVER_USERNAME"
4140 test -n "$TEST_SERVER_SSH_KEY"
4241 test -n "$TEST_CONFIG_YAML"
4342 test -n "$TEST_POSTGRES_PASSWORD"
43+ test -n "$ACR_USERNAME"
44+ test -n "$ACR_PASSWORD"
4445
45- - name : Build API image
46+ - name : Login to ACR
47+ env :
48+ ACR_USERNAME : ${{ secrets.ACR_USERNAME }}
49+ ACR_PASSWORD : ${{ secrets.ACR_PASSWORD }}
4650 run : |
47- set -eu
48- IMAGE_LOCAL="${API_IMAGE_REPOSITORY}:${GITHUB_SHA}"
49- docker build --platform linux/amd64 -f deploy/docker/Dockerfile.api -t "$IMAGE_LOCAL" .
50- echo "CIXING_IMAGE=$IMAGE_LOCAL" >> "$GITHUB_ENV"
51+ echo "$ACR_PASSWORD" | docker login --username "$ACR_USERNAME" --password-stdin registry.cn-hangzhou.aliyuncs.com
5152
52- - name : Pull dependency images
53+ - name : Build and push cixing-api to ACR
5354 run : |
5455 set -eu
55- docker pull --platform linux/amd64 "$POSTGRES_IMAGE"
56- docker pull --platform linux/amd64 "$REDIS_IMAGE"
57- docker pull --platform linux/amd64 "$MAILPIT_IMAGE"
56+ IMAGE_TAG="${GITHUB_SHA}"
57+ IMAGE_ACR="${ACR_REPO}:${IMAGE_TAG}"
58+ docker build --platform linux/amd64 -f deploy/docker/Dockerfile.api -t "cixing-api:${IMAGE_TAG}" -t "$IMAGE_ACR" .
59+ docker push "$IMAGE_ACR"
5860
59- - name : Save deployment images
61+ - name : Mirror base images to ACR (skip if tag exists)
6062 run : |
6163 set -eu
62- mkdir -p /tmp/cixing-deploy/images
63- docker save "$CIXING_IMAGE" | gzip > /tmp/cixing-deploy/images/cixing-api.tar.gz
64- docker save "$POSTGRES_IMAGE" | gzip > /tmp/cixing-deploy/images/postgres.tar.gz
65- docker save "$REDIS_IMAGE" | gzip > /tmp/cixing-deploy/images/redis.tar.gz
66- docker save "$MAILPIT_IMAGE" | gzip > /tmp/cixing-deploy/images/mailpit.tar.gz
64+ mirror() {
65+ local source="$1"
66+ local name="$2"
67+ local acr_tag="${ACR_REGISTRY}/${name}"
68+ if docker manifest inspect "$acr_tag" >/dev/null 2>&1; then
69+ echo "skip $name: already in ACR"
70+ return
71+ fi
72+ echo "mirroring $source -> $acr_tag"
73+ docker pull --platform linux/amd64 "$source"
74+ docker tag "$source" "$acr_tag"
75+ docker push "$acr_tag"
76+ }
77+ mirror "${POSTGRES_IMAGE:-postgres:16-alpine}" postgres
78+ mirror "${REDIS_IMAGE:-redis:7-alpine}" redis
79+ mirror "${MAILPIT_IMAGE:-axllent/mailpit:v1.29.7}" mailpit
6780
6881 - name : Prepare deployment files
6982 env :
@@ -75,14 +88,13 @@ jobs:
7588 cp deploy/compose/docker-compose.prod.yml /tmp/cixing-deploy/docker-compose.yml
7689 printf '%s' "$TEST_CONFIG_YAML" > /tmp/cixing-deploy/config.yaml
7790 {
78- echo "CIXING_IMAGE=${CIXING_IMAGE }"
79- echo "POSTGRES_IMAGE=${POSTGRES_IMAGE} "
80- echo "REDIS_IMAGE=${REDIS_IMAGE} "
81- echo "MAILPIT_IMAGE=${MAILPIT_IMAGE} "
91+ echo "CIXING_IMAGE=${ACR_REPO}:${GITHUB_SHA }"
92+ echo "POSTGRES_IMAGE=postgres:16-alpine "
93+ echo "REDIS_IMAGE=redis:7-alpine "
94+ echo "MAILPIT_IMAGE=axllent/mailpit:v1.29.7 "
8295 echo "POSTGRES_PASSWORD=${TEST_POSTGRES_PASSWORD}"
8396 echo "API_PORT=8080"
8497 echo "MAILPIT_UI_PORT=8025"
85- echo "DOMAIN=test.memento.muxixyz.com"
8698 } > /tmp/cixing-deploy/deploy.env
8799
88100 - name : Configure SSH
@@ -96,36 +108,33 @@ jobs:
96108 chmod 600 ~/.ssh/id_test_server
97109 ssh-keyscan -H "$TEST_SERVER_HOST" >> ~/.ssh/known_hosts
98110
99- - name : Upload deployment assets
111+ - name : Upload deployment files
100112 env :
101113 TEST_SERVER_HOST : ${{ secrets.TEST_SERVER_HOST }}
102114 TEST_SERVER_USERNAME : ${{ secrets.TEST_SERVER_USERNAME }}
103115 run : |
104116 set -eu
117+ SCP_OPTS="-o ConnectTimeout=10 -o ServerAliveInterval=15 -i ~/.ssh/id_test_server"
118+
105119 ssh -i ~/.ssh/id_test_server "$TEST_SERVER_USERNAME@$TEST_SERVER_HOST" \
106- "sudo mkdir -p /opt/cixing/config /opt/cixing/images && sudo chown -R $TEST_SERVER_USERNAME /opt/cixing"
107- scp -i ~/.ssh/id_test_server /tmp/cixing-deploy/docker-compose.yml \
120+ "sudo mkdir -p /opt/cixing/config && sudo chown -R $TEST_SERVER_USERNAME /opt/cixing"
121+
122+ scp $SCP_OPTS /tmp/cixing-deploy/docker-compose.yml \
108123 "$TEST_SERVER_USERNAME@$TEST_SERVER_HOST:/opt/cixing/docker-compose.yml"
109- scp -i ~/.ssh/id_test_server /tmp/cixing-deploy/deploy.env \
124+ scp $SCP_OPTS /tmp/cixing-deploy/deploy.env \
110125 "$TEST_SERVER_USERNAME@$TEST_SERVER_HOST:/opt/cixing/deploy.env"
111- scp -i ~/.ssh/id_test_server /tmp/cixing-deploy/config.yaml \
126+ scp $SCP_OPTS /tmp/cixing-deploy/config.yaml \
112127 "$TEST_SERVER_USERNAME@$TEST_SERVER_HOST:/opt/cixing/config/config.yaml"
113- scp -i ~/.ssh/id_test_server /tmp/cixing-deploy/images/cixing-api.tar.gz \
114- "$TEST_SERVER_USERNAME@$TEST_SERVER_HOST:/opt/cixing/images/cixing-api.tar.gz"
115- scp -i ~/.ssh/id_test_server /tmp/cixing-deploy/images/postgres.tar.gz \
116- "$TEST_SERVER_USERNAME@$TEST_SERVER_HOST:/opt/cixing/images/postgres.tar.gz"
117- scp -i ~/.ssh/id_test_server /tmp/cixing-deploy/images/redis.tar.gz \
118- "$TEST_SERVER_USERNAME@$TEST_SERVER_HOST:/opt/cixing/images/redis.tar.gz"
119- scp -i ~/.ssh/id_test_server /tmp/cixing-deploy/images/mailpit.tar.gz \
120- "$TEST_SERVER_USERNAME@$TEST_SERVER_HOST:/opt/cixing/images/mailpit.tar.gz"
121128
122129 - name : Deploy on ECS
123130 env :
124131 TEST_SERVER_HOST : ${{ secrets.TEST_SERVER_HOST }}
125132 TEST_SERVER_USERNAME : ${{ secrets.TEST_SERVER_USERNAME }}
133+ ACR_USERNAME : ${{ secrets.ACR_USERNAME }}
134+ ACR_PASSWORD : ${{ secrets.ACR_PASSWORD }}
126135 run : |
127136 set -eu
128- ssh -i ~/.ssh/id_test_server "$TEST_SERVER_USERNAME@$TEST_SERVER_HOST" <<'REMOTE'
137+ ssh -i ~/.ssh/id_test_server "$TEST_SERVER_USERNAME@$TEST_SERVER_HOST" "ACR_USERNAME='${ACR_USERNAME}' ACR_PASSWORD='${ACR_PASSWORD}' /bin/sh -s" <<'REMOTE'
129138 set -eu
130139 cd /opt/cixing
131140 DOCKER="docker"
@@ -158,14 +167,13 @@ jobs:
158167 compose ps
159168 compose logs --tail=200 api
160169 }
161- cleanup_deployment_artifacts() {
162- echo "cleaning deployment artifacts"
163- rm -f /opt/cixing/images/*.tar.gz || true
164- current_image="$(awk -F= '$1=="CIXING_IMAGE"{print $2}' /opt/cixing/deploy.env)"
165- if [ -z "$current_image" ]; then
170+ cleanup_old_images() {
171+ echo "cleaning old cixing-api images"
172+ current_tag="$(awk -F= '$1=="CIXING_IMAGE"{print $2}' /opt/cixing/deploy.env | sed 's|.*:||')"
173+ if [ -z "$current_tag" ]; then
166174 return 0
167175 fi
168- for image_ref in $($DOCKER images --format '{{.Repository}}:{{.Tag}}' | grep '^ cixing-api: ' | grep -F -x - v "$current_image " || true); do
176+ for image_ref in $($DOCKER images --format '{{.Repository}}:{{.Tag}}' | grep 'cixing\|memento ' | grep -v "$current_tag " || true); do
169177 $DOCKER rmi "$image_ref" >/dev/null 2>&1 || true
170178 done
171179 }
@@ -200,10 +208,14 @@ jobs:
200208 chmod 600 /opt/cixing/deploy.env
201209 chmod 644 /opt/cixing/config/config.yaml
202210 cleanup_existing_compose_state
203- gzip -dc /opt/cixing/images/cixing-api.tar.gz | $DOCKER load
204- gzip -dc /opt/cixing/images/postgres.tar.gz | $DOCKER load
205- gzip -dc /opt/cixing/images/redis.tar.gz | $DOCKER load
206- gzip -dc /opt/cixing/images/mailpit.tar.gz | $DOCKER load
211+
212+ echo "pulling images from ACR"
213+ # Only pull cixing-api from ACR (base images already exist on host)
214+ CIXING_IMAGE="$(grep '^CIXING_IMAGE=' /opt/cixing/deploy.env | cut -d= -f2-)"
215+ echo "$ACR_PASSWORD" | $DOCKER login --username "$ACR_USERNAME" --password-stdin registry.cn-hangzhou.aliyuncs.com
216+ echo "pulling $CIXING_IMAGE"
217+ $DOCKER pull "$CIXING_IMAGE"
218+
207219 echo "starting dependency services"
208220 compose up -d postgres redis mailpit
209221 echo "running database migrations"
@@ -264,7 +276,7 @@ jobs:
264276 final_api_state="$($DOCKER inspect --format '{{.State.Status}}' "$final_api_container_id")"
265277 final_api_health="$($DOCKER inspect --format '{{if .State.Health}}{{.State.Health.Status}}{{else}}missing{{end}}' "$final_api_container_id")"
266278 echo "final api status: container=$final_api_container_id state=$final_api_state health=$final_api_health"
267- cleanup_deployment_artifacts
279+ cleanup_old_images
268280 compose ps
269281 compose logs --tail=80 api
270282 REMOTE
0 commit comments