name: "Deploy: app.torqvoice.com" on: workflow_dispatch: inputs: tag: description: "Image tag to deploy (e.g. latest, v1.3.0, dev-abc1234)" required: false default: "latest" jobs: deploy: runs-on: [self-hosted, Linux, X64, hetzner] steps: - name: Log in to GitHub Container Registry run: echo "${{ secrets.GHCR_TOKEN }}" | docker login ghcr.io -u ${{ github.actor }} --password-stdin - name: Create deployment files env: VIRTUAL_HOST: ${{ secrets.CLOUD_VIRTUAL_HOST }} DATABASE_URL: ${{ secrets.CLOUD_DATABASE_URL }} BETTER_AUTH_SECRET: ${{ secrets.CLOUD_BETTER_AUTH_SECRET }} APP_URL: ${{ secrets.CLOUD_APP_URL }} STRIPE_SECRET_KEY: ${{ secrets.CLOUD_STRIPE_SECRET_KEY }} STRIPE_WEBHOOK_SECRET: ${{ secrets.CLOUD_STRIPE_WEBHOOK_SECRET }} STRIPE_PRO_PRICE_ID: ${{ secrets.CLOUD_STRIPE_PRO_PRICE_ID }} STRIPE_ENTERPRISE_PRICE_ID: ${{ secrets.CLOUD_STRIPE_ENTERPRISE_PRICE_ID }} DATA_PATH: ${{ secrets.DATA_PATH }} run: | mkdir -p $HOME/torqvoice-deploy/prod cd $HOME/torqvoice-deploy/prod env | grep -E '^(VIRTUAL_HOST|DATA_PATH|DATABASE_URL|BETTER_AUTH_SECRET|APP_URL|STRIPE_)' > .env cat > docker-compose.yml << 'COMPOSE' networks: proxy: external: true name: proxy services: torqvoice-app: container_name: torqvoice-app image: ghcr.io/torqvoice/torqvoice:${APP_TAG:-latest} restart: unless-stopped volumes: - ${DATA_PATH}/torqvoice_data:/app/data expose: - "3000" environment: VIRTUAL_HOST: ${VIRTUAL_HOST} VIRTUAL_PORT: "3000" LETSENCRYPT_HOST: ${VIRTUAL_HOST} DATABASE_URL: ${DATABASE_URL} BETTER_AUTH_SECRET: ${BETTER_AUTH_SECRET} NEXT_PUBLIC_APP_URL: ${APP_URL} TORQVOICE_MODE: cloud STRIPE_SECRET_KEY: ${STRIPE_SECRET_KEY} STRIPE_WEBHOOK_SECRET: ${STRIPE_WEBHOOK_SECRET} STRIPE_PRO_PRICE_ID: ${STRIPE_PRO_PRICE_ID} STRIPE_ENTERPRISE_PRICE_ID: ${STRIPE_ENTERPRISE_PRICE_ID} networks: - proxy COMPOSE - name: Ensure data directory permissions run: | DATA_DIR="${{ secrets.DATA_PATH }}/torqvoice_data" mkdir -p "$DATA_DIR" docker run --rm -v "$DATA_DIR":/data alpine chown -R 1001:1001 /data - name: Deploy run: | cd $HOME/torqvoice-deploy/prod APP_TAG=${{ inputs.tag }} docker compose up -d --pull always - name: Prune old images and build cache run: docker image prune -f && docker builder prune -f