name: Deploy (Compose) "on": workflow_call: inputs: runner: description: "Single runner label (example: ubuntu-latest or self-hosted)" required: true type: string runner_json: description: "Optional JSON array of runner labels (example: [\"self-hosted\",\"prod\"]). If set, overrides runner." required: false type: string default: "" image: description: Image reference to deploy (registry/repo:tag or @sha256) required: true type: string registry: description: "Registry host for optional docker login (example: harbor.hcmc.online). If empty, login step is skipped." required: false type: string default: "" workdir: description: Directory containing compose files on the target runner required: false type: string default: . compose_args: description: Arguments after `docker compose` required: false type: string default: up -d --pull always --remove-orphans secrets: REGISTRY_USERNAME: description: "Optional registry username for docker login (recommended for private registries)" required: false REGISTRY_PASSWORD: description: "Optional registry password/token for docker login (recommended for private registries)" required: false jobs: deploy: runs-on: ${{ inputs.runner_json != '' && fromJSON(inputs.runner_json) || inputs.runner }} env: REGISTRY_USERNAME: ${{ secrets.REGISTRY_USERNAME }} REGISTRY_PASSWORD: ${{ secrets.REGISTRY_PASSWORD }} steps: - name: Checkout uses: actions/checkout@v4 - name: Docker Login (Optional) if: inputs.registry != '' && env.REGISTRY_USERNAME != '' && env.REGISTRY_PASSWORD != '' uses: docker/login-action@v3 with: registry: ${{ inputs.registry }} username: ${{ env.REGISTRY_USERNAME }} password: ${{ env.REGISTRY_PASSWORD }} - name: Show target server (Linux/macOS) if: runner.os != 'Windows' shell: bash run: | echo "Deploying on runner: ${{ inputs.runner }}" echo "Image: ${{ inputs.image }}" - name: Show target server (Windows) if: runner.os == 'Windows' shell: pwsh run: | Write-Output "Deploying on runner: ${{ inputs.runner }}" Write-Output "Image: ${{ inputs.image }}" - name: Compose Up (Linux/macOS) if: runner.os != 'Windows' shell: bash working-directory: ${{ inputs.workdir }} env: DOCKER_IMAGE: ${{ inputs.image }} run: | set -euo pipefail docker compose ${{ inputs.compose_args }} - name: Compose Up (Windows) if: runner.os == 'Windows' shell: pwsh working-directory: ${{ inputs.workdir }} env: DOCKER_IMAGE: ${{ inputs.image }} run: | docker compose ${{ inputs.compose_args }}