Skip to content

Commit c0eb768

Browse files
committed
Update Deploy
1 parent 24de204 commit c0eb768

File tree

7 files changed

+244
-0
lines changed

7 files changed

+244
-0
lines changed

.github/workflows/deploy.yml

Lines changed: 179 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,179 @@
1+
name: CD Deploy to Server (SSH)
2+
3+
on:
4+
# Chỉ chạy sau khi các workflow build đã hoàn tất
5+
workflow_run:
6+
workflows:
7+
- Build & Push Docker Images
8+
- Build & Push coding-service
9+
- Build & Push file-service
10+
types: [ completed ]
11+
# Cho phép chạy tay nếu cần
12+
workflow_dispatch:
13+
14+
permissions:
15+
contents: read
16+
17+
concurrency:
18+
group: deploy-${{ github.event_name }}-${{ github.event.workflow_run.id || github.ref }}
19+
cancel-in-progress: false
20+
21+
jobs:
22+
deploy:
23+
# Chỉ chạy khi workflow build kết thúc SUCCESS và nguồn là main hoặc tag v*.*.*
24+
if: >
25+
(github.event_name == 'workflow_dispatch') ||
26+
(
27+
github.event_name == 'workflow_run' &&
28+
github.event.workflow_run.conclusion == 'success' &&
29+
(
30+
github.event.workflow_run.head_branch == 'main' ||
31+
startsWith(github.event.workflow_run.head_branch, 'v')
32+
)
33+
)
34+
runs-on: ubuntu-latest
35+
environment: production
36+
37+
steps:
38+
- name: Show trigger context (debug)
39+
run: |
40+
echo "event_name: ${{ github.event_name }}"
41+
echo "run.conclusion: ${{ github.event.workflow_run.conclusion || 'N/A' }}"
42+
echo "run.event: ${{ github.event.workflow_run.event || 'N/A' }}"
43+
echo "run.head_branch: ${{ github.event.workflow_run.head_branch || 'N/A' }}"
44+
echo "run.head_sha: ${{ github.event.workflow_run.head_sha || 'N/A' }}"
45+
46+
- name: Checkout
47+
uses: actions/checkout@v4
48+
49+
- name: Derive IMAGE_TAG (from workflow_run or manual)
50+
shell: bash
51+
env:
52+
HEAD_BRANCH: ${{ github.event.workflow_run.head_branch }}
53+
HEAD_SHA: ${{ github.event.workflow_run.head_sha }}
54+
EVENT_NAME: ${{ github.event_name }}
55+
run: |
56+
set -euo pipefail
57+
if [ "$EVENT_NAME" = "workflow_dispatch" ]; then
58+
# chạy tay: mặc định tag theo short SHA của commit hiện tại
59+
echo "IMAGE_TAG=${GITHUB_SHA::12}" >> $GITHUB_ENV
60+
else
61+
# workflow_run: nếu là tag vX.Y.Z -> IMAGE_TAG = X.Y.Z, ngược lại = shortSHA của head_sha
62+
if [[ "${HEAD_BRANCH}" =~ ^v([0-9]+)\.([0-9]+)\.([0-9]+)$ ]]; then
63+
echo "IMAGE_TAG=${HEAD_BRANCH#v}" >> $GITHUB_ENV
64+
else
65+
SHORT="${HEAD_SHA:0:12}"
66+
echo "IMAGE_TAG=${SHORT}" >> $GITHUB_ENV
67+
fi
68+
fi
69+
echo "IMAGE_TAG=$IMAGE_TAG"
70+
71+
- name: Compute .env SHA256
72+
run: |
73+
if [ ! -f .env ]; then
74+
echo "::error::.env không tồn tại trong repo tại thời điểm deploy."
75+
exit 1
76+
fi
77+
echo "ENV_SHA=$(sha256sum .env | awk '{print $1}')" >> $GITHUB_ENV
78+
79+
- name: Prepare deploy bundle
80+
run: |
81+
mkdir -p deploy_bundle
82+
cp -v .env deploy_bundle/.env
83+
cp -v docker-compose.prod-infra.yml deploy_bundle/
84+
cp -v docker-compose.prod-services.yml deploy_bundle/
85+
86+
mkdir -p ops
87+
cat > ops/deploy.sh <<'EOS'
88+
#!/usr/bin/env bash
89+
set -euo pipefail
90+
91+
DEPLOY_DIR="${DEPLOY_DIR:-$HOME/codecampus}"
92+
cd "$DEPLOY_DIR"
93+
94+
cp -f .env ".env.bak.$(date +%Y%m%d-%H%M%S)" || true
95+
96+
if grep -q '^IMAGE_TAG=' .env; then
97+
sed -i "s/^IMAGE_TAG=.*/IMAGE_TAG=${IMAGE_TAG}/" .env
98+
else
99+
echo "IMAGE_TAG=${IMAGE_TAG}" >> .env
100+
fi
101+
102+
set -a
103+
source .env
104+
set +a
105+
106+
compose() {
107+
if docker compose version >/dev/null 2>&1; then
108+
docker compose "$@"
109+
else
110+
docker-compose "$@"
111+
fi
112+
}
113+
114+
if [ -n "${DOCKERHUB_USER:-}" ] && [ -n "${DOCKERHUB_TOKEN:-}" ]; then
115+
echo "docker login Docker Hub..."
116+
echo "$DOCKERHUB_TOKEN" | docker login -u "$DOCKERHUB_USER" --password-stdin
117+
else
118+
echo "Thiếu DOCKERHUB_USER/DOCKERHUB_TOKEN trong .env (image public thì vẫn OK)."
119+
fi
120+
121+
echo "Hạ tầng (idempotent)..."
122+
compose -f docker-compose.prod-infra.yml --env-file .env up -d
123+
124+
echo "Pull images tag ${IMAGE_TAG}..."
125+
compose -f docker-compose.prod-services.yml --env-file .env pull
126+
127+
echo "Up services..."
128+
compose -f docker-compose.prod-services.yml --env-file .env up -d
129+
130+
echo "Prune dangling images..."
131+
docker image prune -f || true
132+
133+
echo "Deploy xong."
134+
EOS
135+
chmod +x ops/deploy.sh
136+
cp -v ops/deploy.sh deploy_bundle/
137+
138+
- name: Upload bundle to server
139+
uses: appleboy/[email protected]
140+
with:
141+
host: ${{ secrets.SSH_HOST }}
142+
username: ${{ secrets.SSH_USER }}
143+
key: ${{ secrets.SSH_PRIVATE_KEY }}
144+
port: ${{ secrets.SSH_PORT || 22 }}
145+
source: "deploy_bundle/*"
146+
target: "${{ secrets.DEPLOY_DIR || '~' }}/codecampus"
147+
overwrite: true
148+
strip_components: 1
149+
150+
- name: Verify .env identical & run deploy
151+
uses: appleboy/[email protected]
152+
env:
153+
IMAGE_TAG: ${{ env.IMAGE_TAG }}
154+
ENV_SHA: ${{ env.ENV_SHA }}
155+
with:
156+
host: ${{ secrets.SSH_HOST }}
157+
username: ${{ secrets.SSH_USER }}
158+
key: ${{ secrets.SSH_PRIVATE_KEY }}
159+
port: ${{ secrets.SSH_PORT || 22 }}
160+
script_stop: true
161+
script: |
162+
set -euo pipefail
163+
DEPLOY_DIR="${DEPLOY_DIR:-${{ secrets.DEPLOY_DIR || '$HOME' }}/codecampus}"
164+
mkdir -p "$DEPLOY_DIR"
165+
cd "$DEPLOY_DIR"
166+
167+
if [ ! -f .env ]; then
168+
echo "::error::Không thấy $DEPLOY_DIR/.env trên server."
169+
exit 1
170+
fi
171+
SERVER_SHA=$(sha256sum .env | awk '{print $1}')
172+
echo "Local .env sha: $ENV_SHA"
173+
echo "Server .env sha: $SERVER_SHA"
174+
if [ "$SERVER_SHA" != "$ENV_SHA" ]; then
175+
echo "::error::.env trên server KHÁC repo. Hủy deploy để tránh sai lệch."
176+
exit 1
177+
fi
178+
179+
IMAGE_TAG="${IMAGE_TAG:-latest}" DEPLOY_DIR="$DEPLOY_DIR" bash ./deploy.sh

deploy-ssh-yunomix2834

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,8 @@
1+
-----BEGIN OPENSSH PRIVATE KEY-----
2+
b3BlbnNzaC1rZXktdjEAAAAABG5vbmUAAAAEbm9uZQAAAAAAAAABAAAAMwAAAAtzc2gtZW
3+
QyNTUxOQAAACBFv/Tc518gRoLO3t4Lw8Kgm46mShdhN1wpJ72nIELm5gAAAKj/gA4A/4AO
4+
AAAAAAtzc2gtZWQyNTUxOQAAACBFv/Tc518gRoLO3t4Lw8Kgm46mShdhN1wpJ72nIELm5g
5+
AAAECyfOvS80b556EouPld5YPW2SlRqvYchAQxCjvsjWd1TUW/9NznXyBGgs7e3gvDwqCb
6+
jqZKF2E3XCknvacgQubmAAAAIGRlcGxveS1zc2gteXVub21peDI4MzRAZ21haWwuY29tAQ
7+
IDBAU=
8+
-----END OPENSSH PRIVATE KEY-----

deploy-ssh-yunomix2834.pub

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIEW/9NznXyBGgs7e3gvDwqCbjqZKF2E3XCknvacgQubm [email protected]

scripts/create-key.bash

Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,21 @@
1+
# Tạo thư mục ~/.ssh (nếu chưa có) và set quyền đúng
2+
mkdir -p ~/.ssh && chmod 700 ~/.ssh
3+
4+
# Tạo file deploy-ssh-yunomix2834.pub với nội dung của public key
5+
cat > ~/.ssh/deploy-ssh-yunomix2834.pub <<'EOF'
6+
ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIEW/9NznXyBGgs7e3gvDwqCbjqZKF2E3XCknvacgQubm [email protected]
7+
EOF
8+
9+
# Set permission cho file public key
10+
chmod 644 ~/.ssh/deploy-ssh-yunomix2834.pub
11+
12+
# Tạo authorized_keys nếu chưa có
13+
touch ~/.ssh/authorized_keys && chmod 600 ~/.ssh/authorized_keys
14+
15+
# Chỉ thêm nếu chưa tồn tại để tránh trùng lặp
16+
grep -qxF -f ~/.ssh/deploy-ssh-yunomix2834.pub ~/.ssh/authorized_keys \
17+
|| cat ~/.ssh/deploy-ssh-yunomix2834.pub >> ~/.ssh/authorized_keys
18+
19+
# Kiểm tra nhanh
20+
ssh-keygen -lf ~/.ssh/deploy-ssh-yunomix2834.pub
21+
# sẽ in fingerprint của key để xác nhận

scripts/generate-deploy-key.sh

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,18 @@
1+
#!/usr/bin/env bash
2+
set -euo pipefail
3+
4+
KEY_NAME="${1:-deploy-ssh-yunomix2834}"
5+
EMAIL_HINT="${2:-deploy-ssh-yunomix2834@gmail.com}"
6+
7+
umask 077
8+
ssh-keygen -t ed25519 -C "$EMAIL_HINT" -f "./${KEY_NAME}" -N ""
9+
10+
echo
11+
echo "Created key pair:"
12+
echo " Private: ./${KEY_NAME}"
13+
echo " Public : ./${KEY_NAME}.pub"
14+
echo
15+
echo "Trên server, thêm public key vào ~/.ssh/authorized_keys:"
16+
echo " cat ${KEY_NAME}.pub >> ~/.ssh/authorized_keys && chmod 600 ~/.ssh/authorized_keys"
17+
echo
18+
echo "Trong GitHub → Secrets, set SSH_PRIVATE_KEY = nội dung file ${KEY_NAME}"

scripts/update-plugin-server.bash

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,17 @@
1+
# Docker + Compose plugin
2+
sudo apt-get update
3+
sudo apt-get install -y ca-certificates curl gnupg
4+
sudo install -m 0755 -d /etc/apt/keyrings
5+
curl -fsSL https://download.docker.com/linux/$(. /etc/os-release; echo "$ID")/gpg \
6+
| sudo gpg --dearmor -o /etc/apt/keyrings/docker.gpg
7+
echo \
8+
"deb [arch=$(dpkg --print-architecture) signed-by=/etc/apt/keyrings/docker.gpg] \
9+
https://download.docker.com/linux/$(. /etc/os-release; echo "$ID") \
10+
$(. /etc/os-release; echo "$VERSION_CODENAME") stable" \
11+
| sudo tee /etc/apt/sources.list.d/docker.list >/dev/null
12+
sudo apt-get update
13+
sudo apt-get install -y docker-ce docker-ce-cli containerd.io docker-buildx-plugin docker-compose-plugin
14+
15+
# Thư mục deploy
16+
mkdir -p /opt/codecampus
17+
sudo chown -R "$USER":"$USER" /opt/codecampus

0 commit comments

Comments
 (0)