High-level deployment action that handles both GitOps (ArgoCD) and direct kubectl deployments with automatic detection.
- 🔍 Auto-detects GitOps - Checks for ArgoCD management
- 📝 Updates manifests - Sets image tags, labels, and environment variables
- 🚀 Dual mode - GitOps commit or kubectl apply
- ⏳ Wait for rollout - Monitors deployment status
- 🎯 Namespace management - Creates namespaces as needed
- name: Deploy to Kubernetes
uses: skyhook-io/kustomize-deploy@v1
with:
overlay_dir: deploy/overlays/production
service_name: backend
image: myregistry.io/backend
tag: v1.2.3
environment: production- name: Deploy to Kubernetes
uses: skyhook-io/kustomize-deploy@v1
with:
overlay_dir: deploy/overlays/production
service_name: backend
image: myregistry.io/backend:v1.2.3
environment: production- name: Deploy service with migrator
uses: skyhook-io/kustomize-deploy@v1
with:
overlay_dir: deploy/overlays/production
service_name: backend
images_json: |
[
{"name": "myregistry.io/backend", "newTag": "v1.2.3"},
{"name": "myregistry.io/backend-migrator", "newTag": "v1.2.3"}
]
environment: production| Input | Description | Required | Default |
|---|---|---|---|
working_directory |
Working directory for operations | ❌ | '.' |
overlay_dir |
Path to kustomize overlay directory | ✅ | - |
service_name |
Service name | ✅ | - |
image |
Container image name | ❌* | - |
tag |
Image tag | ❌* | - |
images_json |
Multiple images as JSON array | ❌* | - |
environment |
Environment name | ✅ | - |
actor |
User deploying | ❌ | ${{ github.actor }} |
run_id |
Run ID for tracking | ❌ | ${{ github.run_id }} |
detect_gitops |
Auto-detect GitOps mode from manifests | ❌ | true |
force_mode |
Force deployment mode (gitops, kubectl, or auto) | ❌ | auto |
commit_message |
Commit message for GitOps | ❌ | auto |
create_namespace |
Create namespace if it does not exist | ❌ | true |
wait_timeout |
Timeout for waiting on deployments (seconds) | ❌ | 120 |
env_patches |
Environment file patches (JSON format) | ❌ | - |
* Image input options (choose one):
- Option 1:
image(with embedded tag, e.g.,registry.io/app:v1.2.3) - Option 2:
image+tag(separate, e.g.,image: registry.io/app,tag: v1.2.3) - Option 3:
images_json(for multiple images)
| Output | Description |
|---|---|
mode |
Deployment mode used (gitops or kubectl) |
namespace |
Kubernetes namespace |
deployment |
Primary deployment name |
managed_by |
Value of managed-by label if found |
This action acts as an orchestrator that delegates to specialized sub-actions:
- kustomize-edit validates and normalizes all image inputs (handles image:tag format, separate params, or multi-image JSON)
- Sets image tags, version labels, and deployment metadata
- Patches environment variables in config files (if env_patches provided)
- kustomize-inspect extracts namespace and workloads from kustomization
- Gets primary deployment name
- Validates kustomization builds successfully
- Detects deployment mode by checking for GitOps labels:
app.kubernetes.io/managed-by: argocd # or fluxGitOps Mode:
- Commits changes to git
- Pushes to trigger ArgoCD/Flux sync
Kubectl Mode:
- kustomize-apply applies manifests to cluster
- Waits for rollout to complete
Architecture Note: This action focuses on deployment orchestration. All image input handling (validation, normalization, format conversion) is delegated to
kustomize-edit, ensuring a single source of truth.
- name: Deploy service
uses: skyhook-io/kustomize-deploy@v1
with:
overlay_dir: deploy/overlays/${{ inputs.environment }}
service_name: ${{ inputs.service }}
image: ${{ inputs.registry }}/${{ inputs.service }}
tag: ${{ inputs.tag }}
environment: ${{ inputs.environment }}- name: Deploy service
uses: skyhook-io/kustomize-deploy@v1
with:
overlay_dir: deploy/overlays/${{ inputs.environment }}
service_name: ${{ inputs.service }}
image: ${{ inputs.registry }}/${{ inputs.service }}:${{ inputs.tag }}
environment: ${{ inputs.environment }}- name: Deploy via GitOps
uses: skyhook-io/kustomize-deploy@v1
with:
overlay_dir: deploy/overlays/production
service_name: backend
image: myregistry.io/backend
tag: v1.2.3
environment: production
force_mode: gitops
commit_message: "Deploy backend v1.2.3 to production"- name: Direct deployment
uses: skyhook-io/kustomize-deploy@v1
with:
overlay_dir: deploy/overlays/staging
service_name: frontend
image: myregistry.io/frontend
tag: latest
environment: staging
force_mode: kubectl
wait_timeout: 300- name: Deploy to new namespace
uses: skyhook-io/kustomize-deploy@v1
with:
overlay_dir: deploy/overlays/feature
service_name: api
image: myregistry.io/api
tag: feature-123
environment: feature-123
create_namespace: true- name: Deploy with env patches
uses: skyhook-io/kustomize-deploy@v1
with:
overlay_dir: deploy/overlays/production
service_name: backend
image: myregistry.io/backend
tag: v1.2.3
environment: production
env_patches: |
{
"container.env": {
"SENTRY_RELEASE": "v1.2.3",
"BUILD_ID": "${{ github.run_id }}"
}
}- name: Deploy service with migrator
uses: skyhook-io/kustomize-deploy@v1
with:
overlay_dir: deploy/overlays/production
service_name: backend
images_json: |
[
{"name": "myregistry.io/backend", "newTag": "v1.2.3"},
{"name": "myregistry.io/backend-migrator", "newTag": "v1.2.3"}
]
environment: production- name: Deploy API with DB migrator
uses: skyhook-io/kustomize-deploy@v1
with:
overlay_dir: deploy/overlays/production
service_name: api
images_json: |
[
{"name": "europe-docker.pkg.dev/myproject/api", "newTag": "${{ github.sha }}"},
{"name": "europe-docker.pkg.dev/myproject/api-migrator", "newTag": "${{ github.sha }}"}
]
environment: production
env_patches: |
{
"container.env": {
"SENTRY_RELEASE": "${{ github.sha }}",
"DEPLOYMENT_ID": "${{ github.run_id }}"
}
}The images_json input allows you to deploy services with multiple container images in a single deployment. This is useful for:
- Database migrations: Deploy your app alongside a migrator image that runs as an init container or Job
- Sidecar containers: Update multiple images that run together in the same pod
- Multi-container services: Services with multiple containers (e.g., app + proxy, app + logging agent)
The images_json input expects a JSON array:
[
{
"name": "registry.io/app",
"newTag": "v1.2.3"
},
{
"name": "registry.io/app-migrator",
"newTag": "v1.2.3"
}
]Required fields:
name- Full image name/repository (e.g.,gcr.io/project/image)newTag- Tag to deploy (e.g.,v1.2.3,latest,sha-abc123)
Mutual Exclusivity:
Provide either images_json OR image (with or without tag), not both. Input validation is handled by the underlying kustomize-edit action.
Many services follow this pattern:
- Build both
myappandmyapp-migratorimages with the same tag - Deploy both with
images_json - Migrator runs as Kubernetes Job or init container before the main app starts
- name: Deploy with migrator
uses: skyhook-io/kustomize-deploy@v1
with:
overlay_dir: deploy/overlays/${{ inputs.environment }}
service_name: ${{ inputs.service }}
images_json: |
[
{"name": "registry.io/${{ inputs.service }}", "newTag": "${{ inputs.tag }}"},
{"name": "registry.io/${{ inputs.service }}-migrator", "newTag": "${{ inputs.tag }}"}
]
environment: ${{ inputs.environment }}- Write access to the repository
- ArgoCD configured to watch the repository
- Authenticated kubectl context
- Appropriate RBAC permissions
- Cluster access (use cloud-login action first)
The action will fail if:
- Overlay directory doesn't exist or is missing kustomization.yaml
- Invalid image inputs (validated by kustomize-edit)
- Kustomization build fails (invalid manifests)
- Git push fails (GitOps mode)
- Kubectl apply fails (kubectl mode)
- Deployment doesn't become ready within timeout
- Always use with cloud-login action for kubectl mode
- GitOps mode requires repository write permissions
- Image format options:
- Single image with embedded tag:
image: registry.io/app:v1.2.3(backwards compatible) - Single image with separate tag:
image: registry.io/app+tag: v1.2.3(recommended) - Multiple images:
images_jsonwith array of{"name":"...","newTag":"..."}
- Single image with embedded tag:
- Supports both Deployment and Rollout resources