100 lines
3.8 KiB
YAML
100 lines
3.8 KiB
YAML
# Publish and redeploy (US08-04). Adapted from the crowdsec-admin deploy workflow:
|
|
# build, log in to the Gitea registry, push, trigger the Portainer webhook, prune.
|
|
# The difference is the gate — this project has a required suite that must not be
|
|
# skipped, so publishing happens only after `Test` (`.gitea/workflows/test.yml`)
|
|
# succeeded on `main`, never on the push itself.
|
|
#
|
|
# The stack is managed by Portainer from git (`docker-compose.yml`), and the runtime
|
|
# secrets it needs — vision key, Immich key, access secret — live in the Portainer
|
|
# stack's environment. They are deliberately not repository secrets and are not in the
|
|
# image: rotation stays in one place, and a repository read never discloses them.
|
|
#
|
|
# Repository secrets required:
|
|
# REGISTRY_USER user with write:package on the registry
|
|
# REGISTRY_TOKEN that user's token
|
|
# PORTAINER_WEBHOOK_URL POST URL from the stack's auto-update setting
|
|
|
|
name: Deploy
|
|
|
|
on:
|
|
workflow_run:
|
|
workflows:
|
|
- Test
|
|
types:
|
|
- completed
|
|
branches:
|
|
- main
|
|
workflow_dispatch:
|
|
inputs:
|
|
dry_run:
|
|
description: Build and push a scratch tag only — leave `latest` and the running stack alone
|
|
type: boolean
|
|
default: true
|
|
|
|
concurrency:
|
|
# Deliberately not keyed by commit: the point is that two deploys of *different*
|
|
# commits cannot overlap. Queued, not cancelled — a half-pushed tag set is worse
|
|
# than a late one.
|
|
group: deploy
|
|
cancel-in-progress: false
|
|
|
|
env:
|
|
IMAGE: git.domverse-berlin.eu/domverse/photoanalyzer
|
|
# The commit that was tested, not whatever `main` points at by the time this starts.
|
|
SHA: ${{ gitea.event.workflow_run.head_sha || gitea.sha }}
|
|
|
|
jobs:
|
|
publish:
|
|
# A completed `Test` run is not a passing one.
|
|
if: >-
|
|
(gitea.event_name == 'workflow_run' && gitea.event.workflow_run.conclusion == 'success')
|
|
|| (gitea.event_name == 'workflow_dispatch' && inputs.dry_run == false)
|
|
runs-on: ubuntu-latest
|
|
steps:
|
|
- name: Checkout
|
|
uses: actions/checkout@v4
|
|
with:
|
|
ref: ${{ env.SHA }}
|
|
|
|
- name: Log in to the Gitea registry
|
|
run: echo "${{ secrets.REGISTRY_TOKEN }}" | docker login git.domverse-berlin.eu -u "${{ secrets.REGISTRY_USER }}" --password-stdin
|
|
|
|
- name: Build and push
|
|
# The commit tag is pushed first, so a `latest` that exists is always a tag
|
|
# that also exists under its own commit — which is what makes a rollback a
|
|
# tag change rather than a rebuild.
|
|
run: |
|
|
docker build -t "$IMAGE:$SHA" -t "$IMAGE:latest" .
|
|
docker push "$IMAGE:$SHA"
|
|
docker push "$IMAGE:latest"
|
|
|
|
- name: Trigger the Portainer redeploy
|
|
# --fail turns an HTTP error into a non-zero exit: a redeploy that did not
|
|
# happen must not read as a green deploy.
|
|
run: curl -sS --fail -X POST "${{ secrets.PORTAINER_WEBHOOK_URL }}"
|
|
|
|
- name: Prune dangling images
|
|
# Untagged layers only. Published tags are the rollback history; `-a` would
|
|
# delete exactly the images this workflow exists to keep.
|
|
run: docker image prune -f
|
|
|
|
dry-run:
|
|
# Manual only, and the default: prove the image still builds and the registry
|
|
# still accepts it without moving `latest` or touching the running stack.
|
|
if: gitea.event_name == 'workflow_dispatch' && inputs.dry_run
|
|
runs-on: ubuntu-latest
|
|
steps:
|
|
- name: Checkout
|
|
uses: actions/checkout@v4
|
|
|
|
- name: Log in to the Gitea registry
|
|
run: echo "${{ secrets.REGISTRY_TOKEN }}" | docker login git.domverse-berlin.eu -u "${{ secrets.REGISTRY_USER }}" --password-stdin
|
|
|
|
- name: Build and push a scratch tag
|
|
run: |
|
|
docker build -t "$IMAGE:scratch-$SHA" .
|
|
docker push "$IMAGE:scratch-$SHA"
|
|
|
|
- name: Prune dangling images
|
|
run: docker image prune -f
|