This commit is contained in:
Saufi
2026-06-16 16:35:16 +08:00
parent d3d21e6c53
commit fb4739e407
7 changed files with 177 additions and 1 deletions

4
.gitattributes vendored Normal file
View File

@@ -0,0 +1,4 @@
# Pastikan skrip shell sentiasa guna line ending LF walaupun di-commit dari Windows.
*.sh text eol=lf
deploy/deploy.sh text eol=lf
docker/php-apache/entrypoint.sh text eol=lf

73
deploy/README.md Normal file
View File

@@ -0,0 +1,73 @@
# Auto-deploy via Git Webhook
Bila ada `git push` ke Gitea, Gitea hantar webhook ke server. Server tarik kod
terbaru dan jalankan `docker compose up --build -d` secara automatik.
Aliran: **push → Gitea webhook → `webhook` listener (port 9000) → `deploy.sh`**
---
## 1. Setup di server production (sekali sahaja)
Andaikan repo berada di `/opt/myansuran` (laraskan path dalam `hooks.json`
dan `myansuran-webhook.service` jika berbeza).
```bash
# a) Pasang webhook listener
sudo apt-get update && sudo apt-get install -y webhook
# b) Pastikan user 'deploy' wujud & ahli group docker (boleh tukar nama user)
sudo useradd -m -G docker deploy 2>/dev/null || sudo usermod -aG docker deploy
# c) Pastikan skrip executable
chmod +x /opt/myansuran/deploy/deploy.sh
# d) Set secret rahsia dalam hooks.json (ganti GANTI_DENGAN_SECRET_RAHSIA)
# Jana satu secret kuat:
openssl rand -hex 32
# Lepas tu edit /opt/myansuran/deploy/hooks.json -> letak nilai itu pada "secret"
# e) Pasang service systemd
sudo cp /opt/myansuran/deploy/myansuran-webhook.service /etc/systemd/system/
sudo systemctl daemon-reload
sudo systemctl enable --now myansuran-webhook
sudo systemctl status myansuran-webhook
```
## 2. Setup webhook di Gitea
Repo → **Settings → Webhooks → Add Webhook → Gitea**:
- **Target URL:** `http://SERVER_IP:9000/hooks/myansuran-deploy`
- **HTTP Method:** `POST`
- **Content Type:** `application/json`
- **Secret:** secret SAMA seperti dalam `hooks.json`
- **Trigger:** Push events sahaja
- **Branch filter:** `main`
Klik **Test Delivery** untuk uji.
## 3. Uji manual
```bash
# Jalankan deploy terus tanpa webhook (untuk debug)
/opt/myansuran/deploy/deploy.sh
# Lihat log webhook
sudo journalctl -u myansuran-webhook -f
```
---
## Nota keselamatan
- Port `9000` hanya perlu dicapai oleh Gitea. Hadkan dengan firewall:
`sudo ufw allow from <IP_GITEA> to any port 9000 proto tcp`
- Atau letak di belakang Nginx/Apache reverse proxy dengan HTTPS.
- Signature HMAC-SHA256 menghalang sesiapa tanpa secret daripada trigger deploy.
## Tukar branch
Default deploy branch ialah `main`. Untuk branch lain, set dalam service:
`ExecStart=... ` tambah `Environment=BRANCH=staging`, dan tukar `refs/heads/main`
dalam `hooks.json` kepada branch berkenaan.

33
deploy/deploy.sh Normal file
View File

@@ -0,0 +1,33 @@
#!/usr/bin/env bash
#
# Skrip deploy yang dipanggil oleh webhook bila ada push ke Gitea.
# Ia mengesan sendiri lokasi repo (folder induk kepada deploy/),
# tarik kod terbaru, dan bina semula container.
#
set -euo pipefail
# Cabang yang akan di-deploy (boleh override: BRANCH=staging ./deploy.sh)
BRANCH="${BRANCH:-master}"
SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
REPO_DIR="$(dirname "$SCRIPT_DIR")"
cd "$REPO_DIR"
LOG() { echo "[$(date '+%Y-%m-%d %H:%M:%S')] $*"; }
LOG "Mula deploy untuk $REPO_DIR (branch: $BRANCH)"
# Tarik kod terbaru — reset --hard supaya server sentiasa padan dengan remote.
git fetch --prune origin
git reset --hard "origin/${BRANCH}"
# Bina & start semula container
docker compose up --build -d
# Bersihkan image lama supaya disk tak penuh
docker image prune -f >/dev/null 2>&1 || true
# Optional: jalankan migration (buang komen kalau perlu)
# docker compose exec -T app php artisan migrate --force
LOG "Deploy selesai."

27
deploy/hooks.json Normal file
View File

@@ -0,0 +1,27 @@
[
{
"id": "myansuran-deploy",
"execute-command": "/opt/myansuran/deploy/deploy.sh",
"command-working-directory": "/opt/myansuran",
"response-message": "Deploy myansuran dicetuskan.",
"include-command-output-in-response": false,
"trigger-rule": {
"and": [
{
"match": {
"type": "payload-hmac-sha256",
"secret": "GANTI_DENGAN_SECRET_RAHSIA",
"parameter": { "source": "header", "name": "X-Gitea-Signature" }
}
},
{
"match": {
"type": "value",
"value": "refs/heads/main",
"parameter": { "source": "payload", "name": "ref" }
}
}
]
}
}
]

View File

@@ -0,0 +1,15 @@
[Unit]
Description=myAnsuran git deploy webhook listener
After=network.target docker.service
Requires=docker.service
[Service]
# User mesti ahli group 'docker' supaya boleh jalankan docker compose tanpa sudo.
User=deploy
WorkingDirectory=/opt/myansuran
ExecStart=/usr/bin/webhook -hooks /opt/myansuran/deploy/hooks.json -port 9000 -verbose -hotreload
Restart=always
RestartSec=5
[Install]
WantedBy=multi-user.target

View File

@@ -19,7 +19,14 @@ RUN apt-get update && apt-get install -y \
COPY --from=composer:2 /usr/bin/composer /usr/bin/composer COPY --from=composer:2 /usr/bin/composer /usr/bin/composer
COPY docker/php-apache/vhost.conf /etc/apache2/sites-available/000-default.conf COPY docker/php-apache/vhost.conf /etc/apache2/sites-available/000-default.conf
COPY docker/php-apache/entrypoint.sh /usr/local/bin/entrypoint.sh
WORKDIR /var/www/html WORKDIR /var/www/html
RUN chown -R www-data:www-data /var/www/html # Buang CR (kalau fail di-checkout dengan line ending Windows) dan jadikan executable
RUN sed -i 's/\r$//' /usr/local/bin/entrypoint.sh \
&& chmod +x /usr/local/bin/entrypoint.sh \
&& chown -R www-data:www-data /var/www/html
ENTRYPOINT ["entrypoint.sh"]
CMD ["apache2-foreground"]

View File

@@ -0,0 +1,17 @@
#!/usr/bin/env bash
set -e
# Bind mount (./src:/var/www/html) menindih ownership dari image, jadi kita
# betulkan permission storage setiap kali container start — bukan masa build.
mkdir -p \
storage/framework/cache/laravel-excel \
storage/framework/sessions \
storage/framework/views \
storage/logs \
bootstrap/cache
chown -R www-data:www-data storage bootstrap/cache
chmod -R 775 storage bootstrap/cache
# Jalankan arahan utama container (apache2-foreground)
exec "$@"