| name | deploy |
| description | Deploy the application to staging or production. Validates, builds, pushes Docker image, deploys via Helm, and runs smoke tests. |
| argument-hint | <staging|production> [--skip-build] [--dry-run] |
| disable-model-invocation | true |
| allowed-tools | Read, Bash, Grep, Glob, Edit |
Deploy Application
Deploy this application to the $ARGUMENTS environment.
Parse the arguments:
- First argument: environment (
staging or production). Default to staging if not specified.
--skip-build: Skip Docker build/push, deploy with existing image
--dry-run: Render Helm templates and show diff without actually deploying
Pre-flight Checks
Before deploying, verify ALL of these:
- Git status is clean - no uncommitted changes (warn if dirty, ask to continue)
- On correct branch -
develop for staging, main for production
- Read
package.json to get the current app version
- Sync Chart.yaml appVersion with the version from package.json
- Helm lint passes with the target values file:
helm lint helm/goravel-blog -f helm/goravel-blog/values.<env>.yaml
Build Phase (skip if --skip-build)
Read DOCKER_REGISTRY and DOCKER_IMAGE_NAME from .env (fallbacks: docker.io and books-database).
Construct the full image name: $DOCKER_REGISTRY/<dockerhub-username>/$DOCKER_IMAGE_NAME
-
Build Docker image:
docker build -t $DOCKER_REGISTRY/<username>/$DOCKER_IMAGE_NAME:<tag> \
--build-arg BUILD_DATE=$(date -u +'%Y-%m-%dT%H:%M:%SZ') \
--build-arg VCS_REF=$(git rev-parse --short HEAD) \
.
- For staging: tag =
develop
- For production: tag = version from package.json
-
Scan image with Trivy (if available):
docker run --rm aquasec/trivy image --severity CRITICAL,HIGH $IMAGE:<tag>
Report findings but don't block unless CRITICAL vulnerabilities found.
-
Push image:
docker push $IMAGE:<tag>
Deploy Phase
Dry Run Mode (--dry-run)
Render templates and show what would change:
helm template goravel-blog helm/goravel-blog -f helm/goravel-blog/values.<env>.yaml
helm diff upgrade goravel-blog helm/goravel-blog -f helm/goravel-blog/values.<env>.yaml -n <namespace>
Stop here for dry-run.
Actual Deployment
-
Determine namespace: books-staging or books-production
-
Run Helm upgrade:
helm upgrade --install goravel-blog helm/goravel-blog \
-f helm/goravel-blog/values.<env>.yaml \
-n <namespace> --create-namespace \
--set image.tag=<tag> \
--atomic --timeout 10m \
--wait
For production, ask for explicit confirmation before executing.
-
Verify rollout:
kubectl rollout status deployment/goravel-blog -n <namespace> --timeout=300s
Post-Deploy Verification
-
Check pod status:
kubectl get pods -n <namespace> -l app.kubernetes.io/name=goravel-blog
-
Get ingress URL:
kubectl get ingress -n <namespace>
-
Smoke test the health endpoint (if accessible):
curl -sf https://<host>/health
Rollback
If deployment fails, Helm --atomic auto-rolls back. If post-deploy checks fail, offer to run:
helm rollback goravel-blog -n <namespace>
Summary
Output a deployment summary table:
| Item | Value |
|---|
| Environment | staging/production |
| Version | x.y.z |
| Image | $DOCKER_REGISTRY//$DOCKER_IMAGE_NAME:tag |
| Namespace | books-xxx |
| Status | SUCCESS/FAILED |
| URL | https://... |