fix(deploy): create component deployments with 0 replicas to prevent ImagePullBackOff
All checks were successful
ci/woodpecker/push/woodpecker Pipeline was successful
All checks were successful
ci/woodpecker/push/woodpecker Pipeline was successful
Components are scaffolded before CI builds their images. Previously deployments started with 1 replica, causing ImagePullBackOff until the first build completed. Now deployments start at 0 replicas; CI deploy steps scale to 1 after verifying the image exists in the registry. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
This commit is contained in:
parent
28ab98df0f
commit
b7d0e84946
@ -91,7 +91,10 @@ func (d *Deployer) Deploy(ctx context.Context, spec domain.DeploySpec) error {
|
|||||||
if spec.Port == 0 {
|
if spec.Port == 0 {
|
||||||
spec.Port = 8080
|
spec.Port = 8080
|
||||||
}
|
}
|
||||||
if spec.Replicas == 0 {
|
switch {
|
||||||
|
case spec.Replicas < 0:
|
||||||
|
spec.Replicas = 0 // Explicitly zero: create deployment with no pods
|
||||||
|
case spec.Replicas == 0:
|
||||||
spec.Replicas = d.config.DefaultReplicas
|
spec.Replicas = d.config.DefaultReplicas
|
||||||
}
|
}
|
||||||
if spec.Domain == "" {
|
if spec.Domain == "" {
|
||||||
|
|||||||
@ -54,6 +54,7 @@ deploy-{{COMPONENT_NAME}}:
|
|||||||
image: bitnami/kubectl:latest
|
image: bitnami/kubectl:latest
|
||||||
commands:
|
commands:
|
||||||
- kubectl set image deployment/{{PROJECT_NAME}}-{{COMPONENT_NAME}} {{COMPONENT_NAME}}=registry.threesix.ai/{{PROJECT_NAME}}/{{COMPONENT_NAME}}:${CI_COMMIT_SHA:0:8} -n projects || echo "Deployment not found, skipping"
|
- kubectl set image deployment/{{PROJECT_NAME}}-{{COMPONENT_NAME}} {{COMPONENT_NAME}}=registry.threesix.ai/{{PROJECT_NAME}}/{{COMPONENT_NAME}}:${CI_COMMIT_SHA:0:8} -n projects || echo "Deployment not found, skipping"
|
||||||
|
- kubectl scale deployment/{{PROJECT_NAME}}-{{COMPONENT_NAME}} --replicas=1 -n projects 2>/dev/null || true
|
||||||
when:
|
when:
|
||||||
branch: main
|
branch: main
|
||||||
event: push
|
event: push
|
||||||
|
|||||||
@ -54,6 +54,7 @@ deploy-{{COMPONENT_NAME}}:
|
|||||||
image: bitnami/kubectl:latest
|
image: bitnami/kubectl:latest
|
||||||
commands:
|
commands:
|
||||||
- kubectl set image deployment/{{PROJECT_NAME}}-{{COMPONENT_NAME}} {{COMPONENT_NAME}}=registry.threesix.ai/{{PROJECT_NAME}}/{{COMPONENT_NAME}}:${CI_COMMIT_SHA:0:8} -n projects || echo "Deployment not found, skipping"
|
- kubectl set image deployment/{{PROJECT_NAME}}-{{COMPONENT_NAME}} {{COMPONENT_NAME}}=registry.threesix.ai/{{PROJECT_NAME}}/{{COMPONENT_NAME}}:${CI_COMMIT_SHA:0:8} -n projects || echo "Deployment not found, skipping"
|
||||||
|
- kubectl scale deployment/{{PROJECT_NAME}}-{{COMPONENT_NAME}} --replicas=1 -n projects 2>/dev/null || true
|
||||||
when:
|
when:
|
||||||
branch: main
|
branch: main
|
||||||
event: push
|
event: push
|
||||||
|
|||||||
@ -54,6 +54,7 @@ deploy-{{COMPONENT_NAME}}:
|
|||||||
image: bitnami/kubectl:latest
|
image: bitnami/kubectl:latest
|
||||||
commands:
|
commands:
|
||||||
- kubectl set image deployment/{{PROJECT_NAME}}-{{COMPONENT_NAME}} {{COMPONENT_NAME}}=registry.threesix.ai/{{PROJECT_NAME}}/{{COMPONENT_NAME}}:${CI_COMMIT_SHA:0:8} -n projects || echo "Deployment not found, skipping"
|
- kubectl set image deployment/{{PROJECT_NAME}}-{{COMPONENT_NAME}} {{COMPONENT_NAME}}=registry.threesix.ai/{{PROJECT_NAME}}/{{COMPONENT_NAME}}:${CI_COMMIT_SHA:0:8} -n projects || echo "Deployment not found, skipping"
|
||||||
|
- kubectl scale deployment/{{PROJECT_NAME}}-{{COMPONENT_NAME}} --replicas=1 -n projects 2>/dev/null || true
|
||||||
when:
|
when:
|
||||||
branch: main
|
branch: main
|
||||||
event: push
|
event: push
|
||||||
|
|||||||
@ -56,6 +56,7 @@ deploy-{{COMPONENT_NAME}}:
|
|||||||
image: bitnami/kubectl:latest
|
image: bitnami/kubectl:latest
|
||||||
commands:
|
commands:
|
||||||
- kubectl set image deployment/{{PROJECT_NAME}}-{{COMPONENT_NAME}} {{COMPONENT_NAME}}=registry.threesix.ai/{{PROJECT_NAME}}/{{COMPONENT_NAME}}:${CI_COMMIT_SHA:0:8} -n projects || echo "Deployment not found, skipping"
|
- kubectl set image deployment/{{PROJECT_NAME}}-{{COMPONENT_NAME}} {{COMPONENT_NAME}}=registry.threesix.ai/{{PROJECT_NAME}}/{{COMPONENT_NAME}}:${CI_COMMIT_SHA:0:8} -n projects || echo "Deployment not found, skipping"
|
||||||
|
- kubectl scale deployment/{{PROJECT_NAME}}-{{COMPONENT_NAME}} --replicas=1 -n projects 2>/dev/null || true
|
||||||
when:
|
when:
|
||||||
branch: main
|
branch: main
|
||||||
event: push
|
event: push
|
||||||
|
|||||||
@ -54,6 +54,7 @@ deploy-{{COMPONENT_NAME}}:
|
|||||||
image: bitnami/kubectl:latest
|
image: bitnami/kubectl:latest
|
||||||
commands:
|
commands:
|
||||||
- kubectl set image deployment/{{PROJECT_NAME}}-{{COMPONENT_NAME}} {{COMPONENT_NAME}}=registry.threesix.ai/{{PROJECT_NAME}}/{{COMPONENT_NAME}}:${CI_COMMIT_SHA:0:8} -n projects || echo "Deployment not found, skipping"
|
- kubectl set image deployment/{{PROJECT_NAME}}-{{COMPONENT_NAME}} {{COMPONENT_NAME}}=registry.threesix.ai/{{PROJECT_NAME}}/{{COMPONENT_NAME}}:${CI_COMMIT_SHA:0:8} -n projects || echo "Deployment not found, skipping"
|
||||||
|
- kubectl scale deployment/{{PROJECT_NAME}}-{{COMPONENT_NAME}} --replicas=1 -n projects 2>/dev/null || true
|
||||||
when:
|
when:
|
||||||
branch: main
|
branch: main
|
||||||
event: push
|
event: push
|
||||||
|
|||||||
@ -11,6 +11,8 @@ import (
|
|||||||
|
|
||||||
// createInitialComponentDeployment creates a K8s Deployment for a newly added component.
|
// createInitialComponentDeployment creates a K8s Deployment for a newly added component.
|
||||||
// This ensures the deployment exists before CI runs, so kubectl set image succeeds.
|
// This ensures the deployment exists before CI runs, so kubectl set image succeeds.
|
||||||
|
// Deployments start with 0 replicas to avoid ImagePullBackOff (image doesn't exist yet).
|
||||||
|
// The CI deploy step scales to 1 after building and verifying the image.
|
||||||
// For monorepo projects, updates the project's unified Ingress with path-based routing.
|
// For monorepo projects, updates the project's unified Ingress with path-based routing.
|
||||||
// Failures are logged but don't fail the component creation.
|
// Failures are logged but don't fail the component creation.
|
||||||
func (s *ComponentService) createInitialComponentDeployment(
|
func (s *ComponentService) createInitialComponentDeployment(
|
||||||
@ -41,7 +43,7 @@ func (s *ComponentService) createInitialComponentDeployment(
|
|||||||
Image: image,
|
Image: image,
|
||||||
Domain: projectDomain,
|
Domain: projectDomain,
|
||||||
Port: component.Port,
|
Port: component.Port,
|
||||||
Replicas: 1,
|
Replicas: -1, // Negative = create with 0 replicas (no pods until CI builds the image)
|
||||||
BasePath: basePath,
|
BasePath: basePath,
|
||||||
SiblingServices: siblingServices,
|
SiblingServices: siblingServices,
|
||||||
Secrets: secrets,
|
Secrets: secrets,
|
||||||
|
|||||||
Loading…
Reference in New Issue
Block a user