diff --git a/docs/ci-setup.md b/docs/ci-setup.md index 770f1b5..62d4212 100644 --- a/docs/ci-setup.md +++ b/docs/ci-setup.md @@ -1,99 +1,109 @@ -# CI/CD Setup — EasyPanel Deploy +# CI/CD Setup — Deploy via Gitea Webhook -Push to `main` triggers `build-and-deploy.yml`: -1. Builds the Astro static site into `dist/` -2. Uploads `dist/` as a 7-day artifact -3. Calls EasyPanel tRPC endpoint to trigger a redeploy +The site auto-rebuilds on every push to `main` via a Gitea **webhook** +(no Actions runner, no `.gitea/workflows/`, no act_runner required). -## Required Gitea repo secrets +## How it works -Go to **Settings → Actions → Secrets** and add three secrets: +``` +git push origin main + │ + ▼ +Gitea Webhook (Gitea built-in, not Gitea Actions) + │ POST Content-Type: application/json + ▼ +http://110.164.146.47:3000/api/deploy/ + │ HTTP 200 "Deploying..." + ▼ +EasyPanel pulls repo, builds with Dockerfile, redeploys +``` -| Name | Value (for this site) | Where to get it | -|---|---|---| -| `EASYPANEL_TOKEN` | `cmq61xwrv000407qn9e2hhfuw` | EasyPanel → profile/settings → API tokens | -| `EASYPANEL_PROJECT_NAME` | `customerwebsite` | EasyPanel → project name in the dashboard | -| `EASYPANEL_SERVICE_NAME` | `dealplustech-astro` | EasyPanel → service name inside the project | +## One-time webhook setup -> ⚠️ Project name ≠ repo name. The site lives in the `customerwebsite` -> project on the panel; the repo is `dealplustech-astroreal`. +In `https://git.moreminimore.com/kunthawat/dealplustech-astroreal/settings/hooks`: -If any of these are empty, the workflow logs a warning and skips the deploy -trigger. The build still runs and the artifact is still uploaded. +1. Click **Add Webhook → Gitea** +2. Fill in: + - **Payload URL**: `http://110.164.146.47:3000/api/deploy/772d2c3a4a7d8671657c947c059bc1cdc64bd816efb7fbe2` + - **HTTP Method**: `POST` + - **Content Type**: `application/json` + - **Events**: **Push events** + - **Active**: ✓ + - **Branch filter**: leave empty (or `main` to restrict) +3. Click **Add Webhook** +4. Test: click the webhook row → **Test Delivery** → **Push events** → confirm + **Last Response** is HTTP 200. + +Done. From now on every push to main redeploys automatically. ## EasyPanel service requirements -The service on the panel side must be: +The service on the panel side (`project=customerwebsite`, +`service=dealplustech-astro`) must be: - **Type: `app`** -- **Source: Git**, pointing at this repo (`kunthawat/dealplustech-astroreal`) - on branch **`main`** (not `source-code`). -- **Build type: `dockerfile`**, **file: `Dockerfile`** at the repo root. - > The workflow used to trigger nixpacks builds, but nixpacks expects a - > `start` script in `package.json` and an Astro static site doesn't - > have one. Switching to a Dockerfile + nginx fixes that. +- **Source: Git**, branch `main` +- **Build type: `dockerfile`**, file `Dockerfile` at repo root - **Port: `80`** -If you need a different service type later, swap the endpoint in -`.gitea/workflows/build-and-deploy.yml` to the matching procedure: -- `services.app.deployService` (Dockerfile / app) -- `services.box.rebuildDockerImage` (low-level) -- `services.compose.deployService` (docker-compose) +The Dockerfile is two-stage: -## Why Dockerfile and not nixpacks +1. `node:22-alpine` — runs `npm ci` and `npm run build` to produce + `dist/` +2. `nginx:1.27-alpine` — copies `dist/` to nginx's web root and serves + it (with gzip, security headers, 1-year cache for hashed assets, + and a `try_files` fallback for Astro's UTF-8 slugs) -Astro builds to static files in `dist/` — there is no Node server to run. -Nixpacks tries to find a `start` command and fails. The Dockerfile in -this repo: +## Why not Gitea Actions? -1. **Stage 1** (`node:20-alpine`): runs `npm ci` then `npm run build` to - produce `dist/`. -2. **Stage 2** (`nginx:1.27-alpine`): copies `dist/` to nginx's web root - and serves it. +Gitea Actions does **not** ship with managed runners (unlike GitHub +Actions' `ubuntu-latest`). Without a self-hosted `act_runner` registered +with matching labels, any workflow run will fail with +**"No matching online runner with label: ubuntu-latest"**. -`nginx.conf` ships gzip, security headers, 1-year cache for hashed -assets, and a `try_files` fallback for client-side routes (Astro's -file-based routing produces UTF-8 slugs). +The Gitea Webhook mechanism is built into Gitea itself — no runner +required. It fires the same events but POSTs to a URL you control, +which is the simplest possible deploy trigger. -## Verifying the trigger payload +If a real CI step is ever needed (lint, test, build artifact), install +`act_runner` on a box, register it, and write a workflow using +`runs-on: self-hosted`. See `act_runner` docs for setup. -If the deploy runs but the panel rejects it, the response in the workflow -log will show the exact `zodErrors` field telling you which field name -or shape is wrong. Update the `PAYLOAD` JSON in the workflow accordingly. +## Troubleshooting -To test the payload shape from your local machine: +### Push happened, but site didn't update + +1. Open the webhook row in Settings → Webhooks +2. Open **Recent Deliveries** +3. Check the most recent one: + - Status 200 → deploy endpoint received it, check EasyPanel logs + - Status != 200 → check the response body + - **No recent delivery** → webhook is not bound to this branch/event + or the push target branch doesn't match the filter + +### Build fails inside EasyPanel + +1. EasyPanel UI → service `dealplustech-astro` → Logs tab +2. Look for the `nixpacks` or `docker build` step +3. Common failures: + - **"No start command could be found"**: you're on `nixpacks`. Switch + build type to `dockerfile` and point at `Dockerfile` at repo root. + - **"Node.js v20.x is not supported by Astro"**: the Dockerfile is + using `node:20-alpine`. It should be `node:22-alpine` (Astro 6 + requires `>=22.12.0`). + - **"Failed to sync changes"** (HTTP 500 from the deploy endpoint): + usually a panel-side state issue. Retry, or open the service in + the panel UI and check container state. + +### Want to redeploy without a code change + +The webhook URL itself is idempotent. You can hit it directly with: ```bash -curl -sS -X POST \ - "https://panelwebsite.moreminimore.com/api/trpc/services.app.deployService" \ - -H "Authorization: Bearer *** -H "Content-Type: application/json" \ - -d '{"json":{"projectName":"customerwebsite","serviceName":"dealplustech-astro"}}' +curl -X POST \ + "http://110.164.146.47:3000/api/deploy/772d2c3a4a7d8671657c947c059bc1cdc64bd816efb7fbe2" ``` -A 2xx response = the panel accepted the trigger. The service will start -rebuilding/redploying in the EasyPanel dashboard. - -## Common failure: "No start command could be found" (nixpacks) - -Astro builds to static files in `dist/` — there is no Node server to run. -Nixpacks tries to find a `start` command and fails. The Dockerfile in -this repo handles this with a two-stage build (node:22-alpine build + -nginx:1.27-alpine serve). - -## Common failure: "Node.js v20.x is not supported by Astro" - -Astro 6 requires Node `>=22.12.0`. The Dockerfile uses `node:22-alpine`. -If you see this error, the panel is probably reading a stale `node:20` -cached image. Push an empty commit to force a rebuild, or clear the -panel's image cache from the EasyPanel UI. - -## Common failure: "Failed to sync changes" (HTTP 500) - -This is a **server-side** error, not a payload problem. It usually means: - -- The EasyPanel service is currently in a state that can't be redeployed - (e.g. the previous container is stuck, or a build is in progress). -- The Docker daemon on the panel host is busy. - -Try again in a few seconds. If it persists, open the EasyPanel dashboard -and check the service's container state. +A `200` response with body `Deploying...` means the panel accepted the +trigger. The actual rebuild happens in the background — check EasyPanel +UI for the progress.