feat(deploy-rsync): Reusable Workflow fuer rsync-Deploys via SSH

Wiederverwendbare Action fuer alle IDF-Repos, die per rsync auf einen
Plesk-Server deployen wollen (Flow, Apps, kuenftig weitere).

Inputs: ssh_host, ssh_user, deploy_path, optional ref + extra_excludes.
Secret: SSH_PRIVATE_KEY (im Caller-Repo zu hinterlegen).
Standard-Excludes: .git/, .gitea/, .gitignore, CHANGELOG.md, README.md.
This commit is contained in:
2026-04-27 17:29:24 +00:00
parent 0f7062b0c4
commit 10fe6f7348
+114
View File
@@ -0,0 +1,114 @@
name: Reusable Deploy via rsync
# Wiederverwendbarer Deploy-Workflow fuer IDF-Projekte.
# Repository-Pfad: ideenfabrik/idf-ci/.gitea/workflows/deploy-rsync.yml
#
# Aufruf aus einem Caller-Repo:
#
# jobs:
# deploy:
# uses: ideenfabrik/idf-ci/.gitea/workflows/deploy-rsync.yml@v1
# with:
# ssh_host: ${{ vars.SSH_HOST }}
# ssh_user: ${{ vars.SSH_USER }}
# deploy_path: ${{ vars.DEPLOY_PATH }}
# ref: ${{ github.event.inputs.ref || github.ref }}
# extra_excludes: |
# kiosk-config.php
# kiosk-config.example.php
# secrets: inherit
#
# Caller-Repo muss hinterlegen:
# Secret SSH_PRIVATE_KEY private Key fuer den Deploy-User
# Variable SSH_HOST Host/IP des Live-Servers
# Variable SSH_USER SSH-Login-User
# Variable DEPLOY_PATH Zielpfad auf dem Server
on:
workflow_call:
inputs:
ssh_host:
required: true
type: string
description: 'Ziel-Host fuer rsync ueber SSH'
ssh_user:
required: true
type: string
description: 'SSH-Login-User'
deploy_path:
required: true
type: string
description: 'Zielpfad auf dem Server'
ref:
required: false
type: string
default: ''
description: 'Branch/Tag zum Deployen (default: github.ref)'
extra_excludes:
required: false
type: string
default: ''
description: 'Zusaetzliche rsync --exclude Patterns, eine pro Zeile'
secrets:
SSH_PRIVATE_KEY:
required: true
jobs:
deploy:
runs-on: self-hosted
steps:
- name: Checkout
uses: actions/checkout@v4
with:
ref: ${{ inputs.ref || github.ref }}
- name: Verify rsync + ssh available
run: |
command -v rsync >/dev/null || { echo "::error::rsync ist auf dem Runner nicht installiert"; exit 1; }
command -v ssh >/dev/null || { echo "::error::ssh ist auf dem Runner nicht installiert"; exit 1; }
rsync --version | head -1
ssh -V
- name: Setup SSH key
run: |
mkdir -p ~/.ssh
chmod 700 ~/.ssh
KEY_FILE="$HOME/.ssh/id_ed25519_deploy_${{ github.run_id }}"
printf '%s\n' "${{ secrets.SSH_PRIVATE_KEY }}" > "$KEY_FILE"
chmod 600 "$KEY_FILE"
echo "DEPLOY_KEY_FILE=$KEY_FILE" >> "$GITHUB_ENV"
ssh-keyscan -H "${{ inputs.ssh_host }}" >> ~/.ssh/known_hosts 2>/dev/null
- name: Deploy via rsync
env:
EXTRA_EXCLUDES: ${{ inputs.extra_excludes }}
run: |
# Standard-Excludes -- gilt fuer alle Deploys
BASE_EXCLUDES=(
--exclude='.git/'
--exclude='.gitea/'
--exclude='.gitignore'
--exclude='CHANGELOG.md'
--exclude='README.md'
)
# Caller-spezifische Excludes (multiline -> array)
EXTRA=()
while IFS= read -r line; do
line="${line#"${line%%[![:space:]]*}"}"
line="${line%"${line##*[![:space:]]}"}"
[ -n "$line" ] && EXTRA+=( "--exclude=$line" )
done <<<"$EXTRA_EXCLUDES"
rsync -avz "${BASE_EXCLUDES[@]}" "${EXTRA[@]}" \
-e "ssh -i $DEPLOY_KEY_FILE -o StrictHostKeyChecking=yes" \
./ \
"${{ inputs.ssh_user }}@${{ inputs.ssh_host }}:${{ inputs.deploy_path }}/"
- name: Cleanup deploy key
if: always()
run: rm -f "$DEPLOY_KEY_FILE"
- name: Done
run: |
echo "Deployed ${{ github.ref_name }} to ${{ inputs.deploy_path }} on ${{ inputs.ssh_host }}"