Nixpacks auto-detect could not find a 'start' script in package.json and bailed out. Astro builds to static files in dist/ — there is no Node server to start. Switching to a Dockerfile + nginx fixes the 'No start command could be found' error from EasyPanel. The workflow also pointed at the source-code branch, but the panel's git source ref for the dealplustech-astro service is 'main', so the trigger was firing for the wrong ref. Both workflows now run on push to main. - Dockerfile: multi-stage node:20-alpine build + nginx:1.27-alpine serve - nginx.conf: gzip, security headers, 1-year cache for hashed assets, try_files fallback for UTF-8 slugs (Astro file-based routing) - .dockerignore: keep build context small (skip CI, docs, .gitea, IDE) - build-and-deploy.yml + lint.yml: branch source-code -> main - docs/ci-setup.md: corrected project + service names (customerwebsite / dealplustech-astro), documented the Dockerfile rationale, added a note for the 'Failed to sync changes' server-side error
86 lines
3.4 KiB
Markdown
86 lines
3.4 KiB
Markdown
# CI/CD Setup — EasyPanel Deploy
|
|
|
|
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
|
|
|
|
## Required Gitea repo secrets
|
|
|
|
Go to **Settings → Actions → Secrets** and add three secrets:
|
|
|
|
| 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 |
|
|
|
|
> ⚠️ Project name ≠ repo name. The site lives in the `customerwebsite`
|
|
> project on the panel; the repo is `dealplustech-astroreal`.
|
|
|
|
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.
|
|
|
|
## EasyPanel service requirements
|
|
|
|
The service on the panel side 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.
|
|
- **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)
|
|
|
|
## Why Dockerfile and not 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:
|
|
|
|
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.
|
|
|
|
`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).
|
|
|
|
## Verifying the trigger payload
|
|
|
|
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.
|
|
|
|
To test the payload shape from your local machine:
|
|
|
|
```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"}}'
|
|
```
|
|
|
|
A 2xx response = the panel accepted the trigger. The service will start
|
|
rebuilding/redploying in the EasyPanel dashboard.
|
|
|
|
## 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.
|