Files
portainer-deploy-action/action.yml
2026-06-27 16:43:36 +00:00

118 lines
4.7 KiB
YAML

name: 'Portainer Stack Deploy'
description: 'Deploys or updates a Docker Compose stack via the Portainer API with registry auth, env vars, and health verification. Designed to be called by gitea-deploy-orchestrator or directly.'
inputs:
portainer_url:
description: 'URL to Portainer instance (e.g., http://portainer:9000)'
required: false
default: 'http://portainer:9000'
portainer_token:
description: 'Portainer API Token. May be a long-lived token, or a short-lived token issued by Hermes (see hermes-contract.md).'
required: true
endpoint_id:
description: 'Portainer Environment/Endpoint ID'
required: false
default: '1'
stack_name:
description: 'Name of the stack to create or update. REQUIRED. No default — auto-deriving from repo name produces buggy names like owner/repo on Gitea path-style.'
required: true
compose_file:
description: 'Path to docker-compose.yml file'
required: false
default: 'docker-compose.yml'
env_file:
description: 'Optional path to a .env file. Lines are added to the stack env (existing stack env is overwritten).'
required: false
default: ''
env_vars:
description: 'Comma-separated key=value pairs (added to env_file, override on conflict).'
required: false
default: ''
image:
description: 'Specific image:tag to pin the stack to (e.g. git.homelab.local:8443/owner/repo:abc123d). If set, overrides image references in compose_file and forces pullImage: true.'
required: false
default: ''
image_digest:
description: 'For rollbacks: the specific sha256 digest to deploy. Mutually exclusive with image.'
required: false
default: ''
rollback:
description: 'If true, re-deploys the previous image tag from Portainer stack history. image/image_digest are ignored when this is true.'
required: false
default: 'false'
previous_image_count:
description: 'When rollback=true, how many previous images to keep. Default 2.'
required: false
default: '2'
force_pull:
description: 'Always pullImage:true, even on updates. Default true. Set false if you trust the local image cache.'
required: false
default: 'true'
prune:
description: 'prune:true on updates — removes stopped containers for the stack. Default true.'
required: false
default: 'true'
registry_url:
description: 'Private registry URL if images need auth (e.g., git.homelab.local:8443)'
required: false
default: ''
registry_user:
description: 'Registry username'
required: false
default: ''
registry_pass:
description: 'Registry password or token'
required: false
default: ''
healthcheck_url:
description: 'URL to poll after deploy (e.g., https://app.example.com/health). Empty = skip verification.'
required: false
default: ''
healthcheck_retries:
description: 'Max retry attempts for healthcheck'
required: false
default: '12'
healthcheck_delay:
description: 'Seconds between healthcheck retries'
required: false
default: '10'
output_file:
description: 'Path to write a JSON result file. Schema: {status, action, stack_id, stack_name, image, image_digest, duration_seconds, healthcheck_status, error}.'
required: false
default: ''
fail_on_healthcheck:
description: 'If true (default), a healthcheck failure exits non-zero. If false, the deploy is reported as success-with-warning.'
required: false
default: 'true'
runs:
using: "composite"
steps:
- name: Deploy to Portainer
shell: bash
env:
PORTAINER_URL: ${{ inputs.portainer_url }}
PORTAINER_TOKEN: ${{ inputs.portainer_token }}
ENDPOINT_ID: ${{ inputs.endpoint_id }}
STACK_NAME: ${{ inputs.stack_name }}
COMPOSE_FILE: ${{ inputs.compose_file }}
ENV_FILE: ${{ inputs.env_file }}
ENV_VARS: ${{ inputs.env_vars }}
IMAGE: ${{ inputs.image }}
IMAGE_DIGEST: ${{ inputs.image_digest }}
ROLLBACK: ${{ inputs.rollback }}
PREVIOUS_IMAGE_COUNT: ${{ inputs.previous_image_count }}
FORCE_PULL: ${{ inputs.force_pull }}
PRUNE: ${{ inputs.prune }}
REGISTRY_URL: ${{ inputs.registry_url }}
REGISTRY_USER: ${{ inputs.registry_user }}
REGISTRY_PASS: ${{ inputs.registry_pass }}
HEALTHCHECK_URL: ${{ inputs.healthcheck_url }}
HEALTHCHECK_RETRIES: ${{ inputs.healthcheck_retries }}
HEALTHCHECK_DELAY: ${{ inputs.healthcheck_delay }}
OUTPUT_FILE: ${{ inputs.output_file }}
FAIL_ON_HEALTHCHECK: ${{ inputs.fail_on_healthcheck }}
REPO_NAME: ${{ github.event.repository.name }}
GITHUB_SHA: ${{ github.sha }}
GITHUB_RUN_ID: ${{ github.run_id }}
run: ${{ github.action_path }}/deploy.sh