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
98 lines
3.4 KiB
YAML
98 lines
3.4 KiB
YAML
name: Build & Deploy to EasyPanel
|
|
|
|
on:
|
|
push:
|
|
branches:
|
|
- main
|
|
workflow_dispatch:
|
|
|
|
jobs:
|
|
build-and-deploy:
|
|
runs-on: ubuntu-latest
|
|
steps:
|
|
- name: Checkout
|
|
uses: actions/checkout@v4
|
|
|
|
- name: Setup Node.js
|
|
uses: actions/setup-node@v4
|
|
with:
|
|
node-version: '20'
|
|
cache: 'npm'
|
|
|
|
- name: Install dependencies
|
|
run: npm ci --no-audit --no-fund
|
|
|
|
- name: Build Astro site
|
|
run: npm run build
|
|
|
|
- name: Trigger EasyPanel redeploy
|
|
if: success()
|
|
env:
|
|
EASYPANEL_TOKEN: ${{ secrets.EASYPANEL_TOKEN }}
|
|
EASYPANEL_PROJECT_NAME: ${{ secrets.EASYPANEL_PROJECT_NAME }}
|
|
EASYPANEL_SERVICE_NAME: ${{ secrets.EASYPANEL_SERVICE_NAME }}
|
|
run: |
|
|
# 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
|
|
|
|
# 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 "$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
|
|
path: dist/
|
|
retention-days: 7
|