Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
19 changes: 9 additions & 10 deletions .github/workflows/web-deploy.yml
Original file line number Diff line number Diff line change
Expand Up @@ -44,10 +44,8 @@ jobs:
username: ${{ github.repository_owner }}
password: ${{ secrets.GITHUB_TOKEN }}

- uses: actions/checkout@v4
with:
ref: ${{ steps.meta.outputs.ref }}
fetch-depth: 1
- name: Checkout code
uses: actions/checkout@v5

- name: Git short SHA
id: git
Expand All @@ -59,7 +57,7 @@ jobs:
uses: docker/build-push-action@v6
with:
context: .
file: deploy/Dockerfile
file: ./deployment/Dockerfile
platforms: linux/amd64
push: true
provenance: false
Expand All @@ -77,8 +75,8 @@ jobs:
runs-on: ubuntu-latest
timeout-minutes: 30
steps:
# Need repo files for scp (deploy job does not inherit build-package checkout).
- uses: actions/checkout@v4
- name: Checkout code
uses: actions/checkout@v5

- name: Ensure remote directory
uses: appleboy/ssh-action@v1.2.5
Expand All @@ -98,9 +96,10 @@ jobs:
key: ${{ secrets.DEPLOY_SSH_KEY }}
port: 22
timeout: 2m
source: deploy/docker-compose.yml
source: deployment/docker-compose.yml
target: ~/pengine/
overwrite: true
strip_components: 1

- name: SSH — docker login, compose pull, up
uses: appleboy/ssh-action@v1.2.5
Expand All @@ -118,8 +117,8 @@ jobs:
envs: GHCR_USER,GHCR_TOKEN,PENGINE_WEB_IMAGE
script: |
set -euo pipefail
cd ~/pengine
cd ~/pengine/deployment
echo "$GHCR_TOKEN" | docker login ghcr.io -u "$GHCR_USER" --password-stdin
export PENGINE_WEB_IMAGE
docker compose pull
docker compose up -d --remove-orphans
docker compose up -d
1 change: 0 additions & 1 deletion deploy/Dockerfile → deployment/Dockerfile
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,6 @@ FROM node:22-alpine AS builder
WORKDIR /app

ENV HUSKY=0
ENV NODE_ENV=production

COPY package.json package-lock.json ./
RUN npm ci --ignore-scripts
Expand Down
5 changes: 0 additions & 5 deletions deploy/docker-compose.yml → deployment/docker-compose.yml
Original file line number Diff line number Diff line change
Expand Up @@ -10,11 +10,6 @@ services:
- "1422"
environment:
- NODE_ENV=production
networks:
pengui-network:
aliases:
- pengine
- app
healthcheck:
test: ["CMD", "curl", "-fsS", "http://127.0.0.1:1422/"]
interval: 30s
Expand Down
22 changes: 11 additions & 11 deletions doc/guides/deploying-web.md
Original file line number Diff line number Diff line change
Expand Up @@ -6,8 +6,8 @@ The pengine web bundle is deployed to a remote host via the
[`Deploy web app`](../../.github/workflows/web-deploy.yml) GitHub Actions
workflow. It has two jobs:

1. **Build and push image** — Checks out the input tag and builds [`deploy/Dockerfile`](../../deploy/Dockerfile) from that revision. Steps: **`npm ci`** → [`npm run build:web`](../../package.json) → runtime **[`vite preview`](https://vite.dev/guide/cli#vite-preview)**. CI passes `VITE_APP_ORIGIN=https://pengine.net` as a **build-arg**. **Always** pushes to GHCR: `:<tag>`, `:sha-<short>`, and `:latest`.
2. **Deploy to host** — checks out the workflow branch and **scp**’s [`deploy/docker-compose.yml`](../../deploy/docker-compose.yml) to the server, then SSH runs **`docker login`** → **`docker compose pull`** → **`docker compose up`**. **`PENGINE_WEB_IMAGE`** is **`ghcr.io/<owner>/pengine-web:<tag>`** from the workflow input.
1. **Build and push image** — Checks out the input tag and builds [`deploy/Dockerfile`](../../deployemnt/Dockerfile) from that revision. Steps: **`npm ci`** → [`npm run build:web`](../../package.json) → runtime **[`vite preview`](https://vite.dev/guide/cli#vite-preview)**. CI passes `VITE_APP_ORIGIN=https://pengine.net` as a **build-arg**. **Always** pushes to GHCR: `:<tag>`, `:sha-<short>`, and `:latest`.
2. **Deploy to host** — checks out the workflow branch and **scp**’s [`deploy/docker-compose.yml`](../../deployment/docker-compose.yml) to the server, then SSH runs **`docker login`** → **`docker compose pull`** → **`docker compose up`**. **`PENGINE_WEB_IMAGE`** is **`ghcr.io/<owner>/pengine/web:<tag>`** from the workflow input.

The app listens on **port 1422** inside the container (**Vite preview** — matches
`preview.port` in `vite.config.ts`; dev server stays on **1420**). Add a **host**
Expand All @@ -17,7 +17,7 @@ not defined in this repository — point nginx (or similar) at that upstream URL

## Triggers

- **Manual only** — Actions → *Deploy web app**Run workflow*. Enter a **`tag`**
- **Manual only** — Actions → _Deploy web app__Run workflow_. Enter a **`tag`**
(e.g. `1.0.1` or `v1.0.1`) that exists as a **git ref** on the remote. The workflow
checks out that ref, builds the image, **always pushes** it to GHCR for that tag,
then deploys with **`docker compose pull`** on the host.
Expand All @@ -26,18 +26,18 @@ not defined in this repository — point nginx (or similar) at that upstream URL

## Required secrets

Add under *Settings → Secrets and variables → Actions*:
Add under _Settings → Secrets and variables → Actions_:

| Secret | Value |
| --- | --- |
| `DEPLOY_HOST` | Hostname or IP of the deploy target |
| `DEPLOY_USER` | SSH user on the target (must be in the `docker` group) |
| Secret | Value |
| ---------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ |
| `DEPLOY_HOST` | Hostname or IP of the deploy target |
| `DEPLOY_USER` | SSH user on the target (must be in the `docker` group) |
| `DEPLOY_SSH_KEY` | Private key (full file, `BEGIN`/`END` lines), **no passphrase**. Ed25519 recommended — [generate a deploy key](#ssh-deploy-key). Public key on the host in `~/.ssh/authorized_keys`. |

Optional (not wired in the workflow today; extend the `appleboy` steps if you need host-key pinning):

| Secret | Value |
| --- | --- |
| Secret | Value |
| -------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| Host key fingerprint | [appleboy/ssh-action](https://github.com/appleboy/ssh-action) supports `fingerprint` (SHA256 of the server host key) for MITM protection — add to the workflow `with:` block if you use it. |

GHCR auth on the host uses the per-run `GITHUB_TOKEN` — no extra secret
Expand Down Expand Up @@ -128,7 +128,7 @@ ssh "$DEPLOY_USER@$DEPLOY_HOST" 'docker ps --filter name=pengine'
curl -fsSL https://pengine.net/ | head
```

To roll back, run *Deploy web app* again with an older **`tag`** — the workflow
To roll back, run _Deploy web app_ again with an older **`tag`** — the workflow
rebuilds and overwrites that tag’s image in GHCR, then deploys it.

## Local image build
Expand Down
Loading