From 3efaf4d6611481f104dad43590b524928c739ba3 Mon Sep 17 00:00:00 2001 From: hermes Date: Tue, 9 Jun 2026 09:47:24 +0700 Subject: [PATCH] ci: switch deploy trigger from generic webhook to EasyPanel tRPC API MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Replaces the old EASYPANEL_WEBHOOK_URL flow with a direct tRPC call to the panel, using three minimal secrets the operator fills in: EASYPANEL_TOKEN - bearer token from EasyPanel profile EASYPANEL_PROJECT_NAME - project name in the dashboard EASYPANEL_SERVICE_NAME - service name inside that project The endpoint (https://panelwebsite.moreminimore.com/api/trpc/services. app.deployService) is hardcoded because the panel URL does not change. Payload uses tRPC's wrapped-json shape: {"json":{"projectName":..., "serviceName":...}}. The build still runs and the dist/ artifact still uploads when any secret is empty — only the trigger step is skipped with a warning. Also adds docs/ci-setup.md explaining the three secrets, the service type requirement (must be 'app' / Dockerfile-based), and a curl recipe for testing the payload shape locally before pushing. --- .gitea/workflows/build-and-deploy.yml | 67 +++++++++++++++++++++++---- docs/ci-setup.md | 56 ++++++++++++++++++++++ 2 files changed, 114 insertions(+), 9 deletions(-) create mode 100644 docs/ci-setup.md diff --git a/.gitea/workflows/build-and-deploy.yml b/.gitea/workflows/build-and-deploy.yml index 8d8b436..d7ad58e 100644 --- a/.gitea/workflows/build-and-deploy.yml +++ b/.gitea/workflows/build-and-deploy.yml @@ -7,7 +7,7 @@ on: workflow_dispatch: jobs: - build-and-notify: + build-and-deploy: runs-on: ubuntu-latest steps: - name: Checkout @@ -25,22 +25,71 @@ jobs: - name: Build Astro site run: npm run build - - name: Trigger EasyPanel deploy + - name: Trigger EasyPanel redeploy if: success() env: - EASYPANEL_WEBHOOK_URL: ${{ secrets.EASYPANEL_WEBHOOK_URL }} + EASYPANEL_TOKEN: ${{ secrets.EASYPANEL_TOKEN }} + EASYPANEL_PROJECT_NAME: ${{ secrets.EASYPANEL_PROJECT_NAME }} + EASYPANEL_SERVICE_NAME: ${{ secrets.EASYPANEL_SERVICE_NAME }} run: | - if [ -z "$EASYPANEL_WEBHOOK_URL" ]; then - echo "::warning::EASYPANEL_WEBHOOK_URL secret is empty — skipping deploy trigger. Set it in repo settings to enable auto-deploy." + # EasyPanel tRPC endpoint for app service redeploy + EASYPANEL_API="https://panelwebsite.moreminimore.com/api" + DEPLOY_URL="${EASYPANEL_API}/trpc/services.app.deployService" + + # Guard: required secrets + if [ -z "$EASYPANEL_TOKEN" ] || [ -z "$EASYPANEL_PROJECT_NAME" ] || [ -z "$EASYPANEL_SERVICE_NAME" ]; then + echo "::warning::One or more required secrets are empty:" + [ -z "$EASYPANEL_TOKEN" ] && echo " - EASYPANEL_TOKEN" + [ -z "$EASYPANEL_PROJECT_NAME" ] && echo " - EASYPANEL_PROJECT_NAME" + [ -z "$EASYPANEL_SERVICE_NAME" ] && echo " - EASYPANEL_SERVICE_NAME" + echo "Skipping deploy trigger. Set these in repo settings to enable auto-deploy." exit 0 fi - echo "Triggering EasyPanel deploy at $EASYPANEL_WEBHOOK_URL" - curl -fsS -X POST "$EASYPANEL_WEBHOOK_URL" \ + + # tRPC mutation payload: {"json":{"projectName":"...","serviceName":"..."}} + PAYLOAD=$(jq -nc \ + --arg pj "$EASYPANEL_PROJECT_NAME" \ + --arg sv "$EASYPANEL_SERVICE_NAME" \ + '{json:{projectName:$pj, serviceName:$sv}}') + + echo "Triggering EasyPanel redeploy" + echo " Endpoint: $DEPLOY_URL" + echo " Project: $EASYPANEL_PROJECT_NAME" + echo " Service: $EASYPANEL_SERVICE_NAME" + echo " Payload: $PAYLOAD" + echo "" + + HTTP_CODE=$(curl -sS -o /tmp/easypanel-response.json -w "%{http_code}" \ + -X POST "$DEPLOY_URL" \ + -H "Authorization: Bearer *** \ -H "Content-Type: application/json" \ - -d "{\"ref\":\"${{ github.ref }}\",\"sha\":\"${{ github.sha }}\",\"event\":\"push\"}" \ - || echo "::error::EasyPanel webhook returned non-2xx (continuing — site already built in artifact if you want to download)" + -d "$PAYLOAD") + + RESPONSE=$(cat /tmp/easypanel-response.json) + echo " HTTP $HTTP_CODE" + echo " Response: $RESPONSE" + + # 2xx = success + if [ "$HTTP_CODE" -ge 200 ] && [ "$HTTP_CODE" -lt 300 ]; then + echo "" + echo "EasyPanel redeploy triggered successfully" + exit 0 + fi + + # 4xx with explicit field errors = workflow is right, payload is wrong + if [ "$HTTP_CODE" -ge 400 ] && [ "$HTTP_CODE" -lt 500 ]; then + echo "::error::EasyPanel rejected the deploy request (HTTP $HTTP_CODE). See response above." + echo "::error::Likely the payload shape does not match what the panel expects." + echo "::error::Check https://panelwebsite.moreminimore.com/api for the procedure spec." + exit 1 + fi + + # 5xx = server error + echo "::error::EasyPanel API error (HTTP $HTTP_CODE). Response: $RESPONSE" + exit 1 - name: Upload build artifact + if: always() uses: actions/upload-artifact@v4 with: name: dist diff --git a/docs/ci-setup.md b/docs/ci-setup.md new file mode 100644 index 0000000..918b143 --- /dev/null +++ b/docs/ci-setup.md @@ -0,0 +1,56 @@ +# CI/CD Setup — EasyPanel Deploy + +Push to `source-code` 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 | Example | Where to get it | +|---|---|---| +| `EASYPANEL_TOKEN` | `cmq61ao6h000207qn6mmp2i7u` | EasyPanel → profile/settings → API tokens | +| `EASYPANEL_PROJECT_NAME` | `dealplustech-astroreal` | EasyPanel → project name in the dashboard | +| `EASYPANEL_SERVICE_NAME` | `web` (or whatever you named the app service) | EasyPanel → service name inside the project | + +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`** (Dockerfile-based). The trigger calls + `services.app.deployService` — other service types use different + procedures and won't work. +- **Source: Git**, pointing at this repo (`kunthawat/dealplustech-astroreal`) + on branch `source-code`. +- **Build command:** `npm run build` +- **Output dir:** `dist` + +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) +- `services.box.rebuildDockerImage` (low-level) +- `services.compose.deployService` (docker-compose) + +## 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":"YOUR_PROJECT","serviceName":"YOUR_SERVICE"}}' +``` + +A 2xx response = the panel accepted the trigger. The service will start +rebuilding/redploying in the EasyPanel dashboard.