- Go 100%
|
All checks were successful
Build / release (push) Successful in 21s
Reviewed-on: System-Design/deploy-tool#3 |
||
|---|---|---|
| .forgejo/workflows | ||
| .gitignore | ||
| go.mod | ||
| main.go | ||
| main_test.go | ||
| README.md | ||
deploy
A Go CLI tool for deploying Helm charts and raw Kubernetes manifests via kapp and vals.
Supports multiple environments, namespace-scoped deployments, optional CRD deployment and a --dry-run mode that shows what would change without applying anything.
Requirements
| Tool | Purpose |
|---|---|
helm |
Render Helm charts |
vals |
Resolve secret references in YAML |
kapp |
Apply / delete Kubernetes resources |
kubectl |
Create namespaces |
All four tools must be available in $PATH.
Build
go build -o deploy deploy.go
No external Go dependencies – only the standard library is used.
Usage
./deploy [flags]
| Flag | Default | Description |
|---|---|---|
--env |
staging |
Environment folder to deploy |
--namespace |
(all) | Only process _deployment_<namespace>.json |
--dry-run |
false |
Show what would change without applying anything |
Examples
# Deploy staging (all deployment files)
./deploy
# Deploy a specific environment
./deploy --env production
# Deploy only the monitoring namespace in staging
./deploy --namespace monitoring
# Dry-run for production
./deploy --env production --dry-run
# Dry-run for a single namespace
./deploy --env production --namespace monitoring --dry-run
Directory structure
.
├── deploy.go
├── base/
│ ├── cluster.yml # Global base values (all envs)
│ └── <name>.yml # Per-chart base values
├── staging/
│ ├── _deployment.json # Deployment config (all namespaces)
│ ├── _deployment_monitoring.json # Deployment config (monitoring only)
│ ├── _deployment_storage.json # Deployment config (storage only)
│ ├── cluster.yml # Staging-wide values override
│ └── <namespace>/
│ ├── <name>.yml # Per-chart values override
│ └── <manifest>.yaml # Optional raw manifest
└── production/
├── _deployment.json
└── ...
Values files are loaded in this order (later files take precedence):
./base/cluster.yml./<env>/cluster.yml./base/<name>.yml(or./base/<base>.ymlifbaseis set)./<env>/<namespace>/<name>.yml
Deployment files
When --namespace is not set, the tool processes all deployment files in the environment folder in this order:
_deployment.json(if present)_deployment_<namespace>.json(all matches, alphabetically)
When --namespace is set, only _deployment_<namespace>.json is processed.
_deployment.json / _deployment_<namespace>.json
{
"app_k8s_deploy_helm_charts": [
{
"namespace": "monitoring",
"applications": [
{
"name": "kube-prometheus-stack",
"chart_ref": "prometheus-community/kube-prometheus-stack",
"state": "present",
"version": "58.0.0",
"deploy_crds": true
},
{
"name": "alertmanager",
"chart_ref": "prometheus-community/alertmanager",
"base": "prometheus-common",
"state": "present"
},
{
"name": "my-configmap",
"state": "present",
"manifest": "my-configmap.yaml"
},
{
"name": "old-app",
"chart_ref": "my-repo/old-app",
"state": "absent"
}
]
}
]
}
Application fields
| Field | Type | Required | Description |
|---|---|---|---|
name |
string | ✅ | Release name and kapp app identifier |
state |
string | ✅ | present to deploy, absent to delete |
chart_ref |
string | ❌ | Helm chart reference. If omitted, Helm is skipped entirely |
version |
string | ❌ | Helm chart version. Omit to use latest |
manifest |
string | ❌ | Path to a raw YAML manifest relative to ./<env>/<namespace>/ |
deploy_crds |
bool | ❌ | Pass --include-crds to helm template (default: false) |
base |
string | ❌ | Override base values filename. Loads ./base/<base>.yml instead of ./base/<name>.yml |
base field
By default the tool looks for ./base/<name>.yml as the per-chart base values file.
Set base to load a different file from the base/ folder instead:
{ "name": "alertmanager", "base": "prometheus-common" }
This loads ./base/prometheus-common.yml instead of ./base/alertmanager.yml.
Useful when multiple charts share the same base values file.
Behaviour matrix
chart_ref |
manifest |
Result |
|---|---|---|
| ✅ | ❌ | Helm chart rendered and deployed via kapp |
| ✅ | ✅ | Helm chart + manifest merged into one kapp deploy |
| ❌ | ✅ | Only the raw manifest is processed via vals and deployed via kapp |
| ❌ | ❌ | Entry is skipped with a warning |
kapp app naming
Each application is registered in kapp under the name:
<env>-<namespace>-<name>
Example: staging-monitoring-kube-prometheus-stack
The kapp app itself is always stored in the gitops namespace.
Dry-run mode
--dry-run has two layers:
- Local commands (
helm template,vals eval,kubectl,cat) – only printed, not executed. An empty temporary file is created so the pipeline does not break. - kapp – instead of
kapp -y deploy, the tool runs:
kapp deploy --diff-run --diff-changes
This connects to the real cluster and shows exactly which resources would be added, changed or deleted – without applying anything.
kapp delete in dry-run is only printed, never executed.
vals secret resolution
All YAML passed to kapp runs through vals eval -f - first.
This resolves secret references such as:
password: ref+vault://secret/myapp#/password
token: ref+awssecrets://myapp/token
See the vals documentation for supported backends.
CRD deployment
Setting deploy_crds: true passes --include-crds to helm template.
Note:
helm template --include-crdsdoes not render CRDs that live in thecrds/directory of a chart. For reliable CRD deployment it is recommended tohelm pull --untarthe chart and apply thecrds/directory separately before the main deploy.