788eaa390f
- stack.yml: parameterize image tag with ${IMAGE_TAG:-latest} so callers
can pin the SHA; falls back to :latest for manual invocations
- flow.yml: replace service update with `docker stack deploy -c -`
piped over SSH. Handles both first-time deploy and rolling updates.
No more manual `docker stack deploy` on the manager before CI works.
Portainer can still view the stack but should not auto-update the same
one from git — two writers will conflict.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
94 lines
3.2 KiB
YAML
94 lines
3.2 KiB
YAML
# .gitea/workflows/flow.yml
|
|
# =============================================================
|
|
# serso — generic CI/CD flow
|
|
# Copy into any app repo as .gitea/workflows/flow.yml
|
|
# Adjust the env block (STACK_NAME, SERVICE_NAME, APP_DOMAIN) per app
|
|
# =============================================================
|
|
|
|
name: Build & Deploy
|
|
|
|
on:
|
|
push:
|
|
branches:
|
|
- main
|
|
workflow_dispatch:
|
|
|
|
env:
|
|
# ─── Registry ─────────────────────────────────────────────
|
|
REGISTRY: git.dev.serso.org
|
|
IMAGE: ${{ github.repository }} # → owner/reponame
|
|
|
|
# ─── Per-app knobs (edit these) ───────────────────────────
|
|
STACK_NAME: testwebsite # Swarm stack name
|
|
SERVICE_NAME: testwebsite_web # {stack}_{service}
|
|
APP_DOMAIN: testwebsite.dev.serso.org # used only for logging
|
|
|
|
jobs:
|
|
|
|
# ============================================================
|
|
# 1. Build image + push to Gitea registry
|
|
# ============================================================
|
|
build:
|
|
runs-on: ubuntu-latest
|
|
outputs:
|
|
image_tag: ${{ steps.meta.outputs.tag }}
|
|
steps:
|
|
- name: Checkout
|
|
uses: actions/checkout@v4
|
|
|
|
- name: Compute tag
|
|
id: meta
|
|
run: echo "tag=${{ github.sha }}" >> $GITHUB_OUTPUT
|
|
|
|
- name: Log in to Gitea registry
|
|
run: |
|
|
echo "${{ secrets.REGISTRY_PASSWORD }}" | \
|
|
docker login ${{ env.REGISTRY }} \
|
|
--username "${{ vars.REGISTRY_USER }}" \
|
|
--password-stdin
|
|
|
|
- name: Build image
|
|
run: |
|
|
docker build \
|
|
-t ${{ env.REGISTRY }}/${{ env.IMAGE }}:${{ steps.meta.outputs.tag }} \
|
|
-t ${{ env.REGISTRY }}/${{ env.IMAGE }}:latest \
|
|
.
|
|
|
|
- name: Push image
|
|
run: |
|
|
docker push ${{ env.REGISTRY }}/${{ env.IMAGE }}:${{ steps.meta.outputs.tag }}
|
|
docker push ${{ env.REGISTRY }}/${{ env.IMAGE }}:latest
|
|
|
|
# ============================================================
|
|
# 2. Deploy stack to Swarm (creates or updates)
|
|
# ============================================================
|
|
deploy:
|
|
needs: build
|
|
runs-on: ubuntu-latest
|
|
steps:
|
|
- name: Checkout
|
|
uses: actions/checkout@v4
|
|
|
|
- name: Prepare SSH
|
|
run: |
|
|
mkdir -p ~/.ssh
|
|
echo "${{ secrets.DEPLOY_SSH_KEY }}" > ~/.ssh/deploy_key
|
|
chmod 600 ~/.ssh/deploy_key
|
|
ssh-keyscan -H ${{ vars.DEPLOY_HOST }} >> ~/.ssh/known_hosts 2>/dev/null
|
|
|
|
- name: Deploy stack on Swarm
|
|
run: |
|
|
ssh -i ~/.ssh/deploy_key \
|
|
${{ vars.DEPLOY_USER }}@${{ vars.DEPLOY_HOST }} \
|
|
"IMAGE_TAG=${{ needs.build.outputs.image_tag }} \
|
|
docker stack deploy \
|
|
--compose-file - \
|
|
--with-registry-auth \
|
|
--prune \
|
|
${{ env.STACK_NAME }}" < stack.yml
|
|
|
|
- name: Deployed 🎉
|
|
run: |
|
|
echo "App deployed at https://${{ env.APP_DOMAIN }}"
|
|
echo "Image: ${{ env.REGISTRY }}/${{ env.IMAGE }}:${{ needs.build.outputs.image_tag }}"
|