Forgejo reserves names starting with FORGEJO_, and since runner v13 secrets.FORGEJO_TOKEN, _USER and _REGISTRY no longer reach the job as the values set on the repository: Kaniko logged in with the wrong credentials and every image push failed with UNAUTHORIZED. The registry host and user are not secret (they are in every image name), so write them in the workflow; the token comes from FJ_TOKEN, as in datacenterbingo. Assisted-by: Claude:opus-5-5
111 lines
3.4 KiB
YAML
111 lines
3.4 KiB
YAML
name: Build and Deploy to Production
|
|
|
|
on:
|
|
push:
|
|
branches:
|
|
- main
|
|
|
|
jobs:
|
|
# Same job as in test.yaml (non-main branches); duplicated so a broken
|
|
# build blocks deploy — Forgejo has no cross-workflow needs.
|
|
check:
|
|
runs-on: nix-latest
|
|
# Settings via env, not /etc/nix/nix.conf: in the image that is a
|
|
# symlink into /nix/store, which the runner's nix-store volume
|
|
# shadows, so it dangles once the image moves on.
|
|
env:
|
|
NIX_CONFIG: |
|
|
experimental-features = nix-command flakes
|
|
build-users-group =
|
|
sandbox = false
|
|
steps:
|
|
- name: Prepare container for actions
|
|
run: |
|
|
nix-env -iA nixpkgs.nodejs_22
|
|
|
|
- name: Checkout
|
|
uses: actions/checkout@v4
|
|
|
|
- name: Build site
|
|
run: nix develop -c zola build
|
|
|
|
build:
|
|
runs-on: arch-latest
|
|
needs: check
|
|
container:
|
|
image: gcr.io/kaniko-project/executor:debug
|
|
outputs:
|
|
image_tag: ${{ steps.build_image.outputs.image_tag }}
|
|
steps:
|
|
- name: Build and push Docker Image using Kaniko
|
|
id: build_image
|
|
run: |
|
|
# Tags
|
|
SHORT_SHA=${GITHUB_SHA::8}
|
|
IMAGE_BASE=git.czsk.it/asxpi/blog
|
|
IMAGE_TAG=${IMAGE_BASE}:${SHORT_SHA}
|
|
IMAGE_LATEST=${IMAGE_BASE}:latest
|
|
|
|
# Auth Conf
|
|
mkdir -p /kaniko/.docker
|
|
echo "{\"auths\":{\"git.czsk.it\":{\"auth\":\"$(echo -n asxpi:${{ secrets.FJ_TOKEN }} | base64)\"}}}" > /kaniko/.docker/config.json
|
|
|
|
# Build & push
|
|
/kaniko/executor \
|
|
--context=git://git.czsk.it/${{ github.repository }}.git \
|
|
--git=branch=${{ github.ref_name }} \
|
|
--destination=$IMAGE_TAG \
|
|
--destination=$IMAGE_LATEST
|
|
|
|
# Output the specific tag for deployment
|
|
echo "image_tag=${IMAGE_TAG}" >> $GITHUB_OUTPUT
|
|
|
|
deploy:
|
|
runs-on: arch-latest
|
|
needs: build
|
|
steps:
|
|
- name: Install dependencies
|
|
run: |
|
|
pacman -Syu --noconfirm nodejs openssh rsync
|
|
|
|
- name: Checkout code
|
|
uses: actions/checkout@v4
|
|
|
|
- name: Deploy docker-compose.yml
|
|
uses: easingthemes/ssh-deploy@v5.1.0
|
|
with:
|
|
SSH_PRIVATE_KEY: ${{ secrets.DEPLOY_SSH_KEY }}
|
|
REMOTE_HOST: ${{ secrets.DEPLOY_IP }}
|
|
REMOTE_USER: ${{ secrets.DEPLOY_USER }}
|
|
SOURCE: "docker-compose.yml"
|
|
TARGET: "/opt/blog/"
|
|
|
|
- name: Deploy and update container
|
|
uses: appleboy/ssh-action@v1.2.3
|
|
env:
|
|
NEW_IMAGE: ${{ needs.build.outputs.image_tag }}
|
|
with:
|
|
host: ${{ secrets.DEPLOY_IP }}
|
|
username: ${{ secrets.DEPLOY_USER }}
|
|
key: ${{ secrets.DEPLOY_SSH_KEY }}
|
|
envs: NEW_IMAGE
|
|
script: |
|
|
cd /opt/blog
|
|
|
|
sed -i "s|image:.*|image: $NEW_IMAGE|" docker-compose.yml
|
|
|
|
docker pull $NEW_IMAGE
|
|
docker compose up -d
|
|
|
|
# Wait for the image HEALTHCHECK to report healthy.
|
|
for i in $(seq 1 18); do
|
|
status=$(docker inspect --format '{{.State.Health.Status}}' blog 2>/dev/null || echo missing)
|
|
if [ "$status" = "healthy" ]; then
|
|
echo "Deployment successful!"
|
|
exit 0
|
|
fi
|
|
sleep 5
|
|
done
|
|
echo "blog never became healthy (last status: $status)" >&2
|
|
docker logs --tail 50 blog
|
|
exit 1
|