ci: deploy the verified local image
All checks were successful
Test and deploy / Verify production build (push) Successful in 10m25s
All checks were successful
Test and deploy / Verify production build (push) Successful in 10m25s
Build and test the Next.js application once with persistent BuildKit caches, smoke-test the immutable runtime image, and activate that same image through the shared production Docker daemon with serialized rollback-safe deployment.
This commit is contained in:
@@ -1,20 +1,27 @@
|
||||
# Deployment
|
||||
|
||||
The Gitea Actions workflow in `.gitea/workflows/ci-cd.yml` verifies every pull
|
||||
request and every push to `main`. A successful push to `main` is then deployed
|
||||
over SSH. The server builds the exact Git archive tested by CI, starts the
|
||||
Compose service, and waits for its container health check.
|
||||
request and every push to `main`. A successful push to `main` builds one
|
||||
verified Docker image on the shared host daemon, smoke-tests it, and activates
|
||||
that exact commit-tagged image over SSH without uploading source or rebuilding.
|
||||
|
||||
Releases are stored in `<DEPLOY_PATH>/releases/<commit-sha>`. The `current`
|
||||
Release manifests are stored in `<DEPLOY_PATH>/releases/<commit-sha>`. Each
|
||||
manifest records the immutable image tag and Gitea run number. The `current`
|
||||
symlink is changed only after the new container is healthy. If startup fails,
|
||||
the deployment script automatically rebuilds and starts the previous release.
|
||||
the deployment script restarts the previous image without rebuilding it.
|
||||
|
||||
## Gitea Actions setup
|
||||
|
||||
Enable **Repository Actions** in the repository settings and register a trusted
|
||||
Gitea Runner. The workflow uses the `ubuntu-latest` label; that runner image must
|
||||
provide Bash, Git, `tar`, OpenSSH (`ssh` and `scp`), and standard GNU utilities.
|
||||
Node.js 22 is installed by the workflow.
|
||||
Enable **Repository Actions** in the repository settings and register the
|
||||
dedicated trusted runner maintained in
|
||||
`https://git.amiirkhl.ir/amiirkhl/portfolio-gitea-runner`. The
|
||||
workflow uses the `portfolio-ci` label. Its reusable job image provides Node.js
|
||||
22, Bash, Git, OpenSSH, Docker CLI, Buildx, and Compose. Runner capacity remains
|
||||
one because Gitea, builds, and production share a 2-core/4-GB server.
|
||||
|
||||
The runner and job container use the host Docker socket. Restrict the label to
|
||||
this trusted repository and disable Actions for fork pull requests. The workflow
|
||||
also skips pull requests whose head repository differs from this repository.
|
||||
|
||||
After the first successful verification run, protect `main` in Gitea and make
|
||||
the **Verify production build** status check required. This prevents a pull
|
||||
@@ -46,8 +53,9 @@ the protection against a man-in-the-middle attack.
|
||||
|
||||
## One-time server setup
|
||||
|
||||
The server needs Docker Engine with the Compose v2 plugin. The deployment user
|
||||
must be able to run `docker` without an interactive password prompt.
|
||||
The server needs Docker Engine with the Compose v2 and Buildx plugins. The
|
||||
runner and deployment user must reach the same Docker daemon, and the deployment
|
||||
user must run `docker` without an interactive password prompt.
|
||||
|
||||
Create the deployment root and the external network once:
|
||||
|
||||
@@ -88,9 +96,30 @@ optimizer-cache invalidation API.
|
||||
For an emergency manual deployment from a checkout on the server:
|
||||
|
||||
```sh
|
||||
docker compose --project-name portfolio up --detach --build --remove-orphans
|
||||
docker compose \
|
||||
--project-name portfolio \
|
||||
--file compose.yaml \
|
||||
--file compose.build.yaml \
|
||||
up --detach --build --remove-orphans
|
||||
```
|
||||
|
||||
This legacy path builds `amiirkhl-portfolio:latest` and is intentionally kept
|
||||
outside the normal CI deployment. Existing source-based release directories can
|
||||
still be started with their original Compose file during migration. Automatic
|
||||
rollback begins with the first successful image-based release because older
|
||||
release directories do not contain `release.env` image metadata.
|
||||
|
||||
## Pipeline timing verification
|
||||
|
||||
After migrating the runner, record one cold run and three normal source-change
|
||||
runs. Expand the **Set up job** and **Complete job** sections in Gitea when
|
||||
capturing the results. For each run, record checkout, verification build, audit,
|
||||
runtime image creation, smoke test, deployment health wait, and completion time.
|
||||
All three warm runs should finish below 180 seconds without OOM events or
|
||||
production health failures. If they do not, collect `docker stats`, `free -h`,
|
||||
`df -h`, `docker system df`, `docker buildx du --builder portfolio-builder`, and
|
||||
the runner logs before changing or removing any quality gate.
|
||||
|
||||
Old versioned release directories are deliberately retained for rollback. They
|
||||
can be removed manually after a newer release has been proven stable; keep the
|
||||
directory referenced by the `current` symlink.
|
||||
|
||||
Reference in New Issue
Block a user