name: Deploy Stacks on: push: branches: [main] paths: - 'stacks/**' workflow_dispatch: inputs: stack: description: 'Stack to deploy (or "all")' required: true default: 'all' env: STACKS_DIR: /var/core jobs: detect-changes: runs-on: ubuntu-prod outputs: stacks: ${{ steps.changes.outputs.stacks }} steps: - uses: actions/checkout@v4 with: fetch-depth: 2 - name: Find changed stacks id: changes run: | if [ "${{ github.event_name }}" = "workflow_dispatch" ]; then if [ "${{ github.event.inputs.stack }}" = "all" ]; then STACKS=$(ls stacks/ | tr '\n' ' ') else STACKS="${{ github.event.inputs.stack }}" fi else STACKS=$(git diff --name-only HEAD~1 HEAD | grep '^stacks/' | cut -d'/' -f2 | sort -u | tr '\n' ' ') fi echo "stacks=$STACKS" >> $GITHUB_OUTPUT echo "Detected stacks to deploy: $STACKS" deploy: needs: detect-changes if: needs.detect-changes.outputs.stacks != '' runs-on: ubuntu-prod strategy: matrix: stack: ${{ fromJson(format('["{0}"]', join(fromJson(format('["{0}"]', replace(needs.detect-changes.outputs.stacks, ' ', '","'))), '","'))) }} fail-fast: false steps: - uses: actions/checkout@v4 - name: Create .env file run: | cd stacks/${{ matrix.stack }} if [ -f ".env.template" ]; then envsubst < .env.template > .env fi env: # Global DOMAIN: ${{ secrets.DOMAIN }} VOLUMES_ROOT: ${{ secrets.VOLUMES_ROOT }} # Traefik ACME_EMAIL: ${{ secrets.ACME_EMAIL }} # Authentik AUTHENTIK_SECRET_KEY: ${{ secrets.AUTHENTIK_SECRET_KEY }} AUTHENTIK_PG_PASS: ${{ secrets.AUTHENTIK_PG_PASS }} # Immich IMMICH_DB_PASSWORD: ${{ secrets.IMMICH_DB_PASSWORD }} # Planka PLANKA_SECRET_KEY: ${{ secrets.PLANKA_SECRET_KEY }} PLANKA_OIDC_CLIENT_ID: ${{ secrets.PLANKA_OIDC_CLIENT_ID }} PLANKA_OIDC_CLIENT_SECRET: ${{ secrets.PLANKA_OIDC_CLIENT_SECRET }} # Registry REGISTRY_HTTP_SECRET: ${{ secrets.REGISTRY_HTTP_SECRET }} REGISTRY_HTPASSWD: ${{ secrets.REGISTRY_HTPASSWD }} # Memento MEMENTO_AUTH_SECRET: ${{ secrets.MEMENTO_AUTH_SECRET }} MEMENTO_AUTHENTIK_CLIENT_ID: ${{ secrets.MEMENTO_AUTHENTIK_CLIENT_ID }} MEMENTO_AUTHENTIK_CLIENT_SECRET: ${{ secrets.MEMENTO_AUTHENTIK_CLIENT_SECRET }} # Bookclub BOOKCLUB_SMTP_HOST: ${{ secrets.BOOKCLUB_SMTP_HOST }} BOOKCLUB_SMTP_USER: ${{ secrets.BOOKCLUB_SMTP_USER }} BOOKCLUB_SMTP_PASS: ${{ secrets.BOOKCLUB_SMTP_PASS }} BOOKCLUB_MAIL_FROM: ${{ secrets.BOOKCLUB_MAIL_FROM }} BOOKCLUB_MAIL_TO: ${{ secrets.BOOKCLUB_MAIL_TO }} BOOKCLUB_SECRET_PHRASE: ${{ secrets.BOOKCLUB_SECRET_PHRASE }} # Perilous PERILOUS_CODE_SERVER_PASSWORD: ${{ secrets.PERILOUS_CODE_SERVER_PASSWORD }} - name: Deploy ${{ matrix.stack }} run: | STACK_DIR="${{ env.STACKS_DIR }}/${{ matrix.stack }}" # Create stack directory if needed mkdir -p "$STACK_DIR" # Copy files to stack directory cp -r stacks/${{ matrix.stack }}/* "$STACK_DIR/" cd "$STACK_DIR" # Pull and deploy docker compose pull --ignore-pull-failures || true docker compose up -d --remove-orphans echo "✅ Deployed ${{ matrix.stack }}" - name: Verify deployment run: | sleep 5 cd ${{ env.STACKS_DIR }}/${{ matrix.stack }} docker compose ps