-
Notifications
You must be signed in to change notification settings - Fork 12
chore: init force deploy #723
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: main
Are you sure you want to change the base?
Changes from all commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,12 @@ | ||
| local openapi = import '../lib/openapi.libsonnet'; | ||
|
|
||
| { | ||
| ReleaseTargetForceDeployEvent: { | ||
| type: 'object', | ||
| required: ['releaseTarget', 'version'], | ||
| properties: { | ||
| releaseTarget: openapi.schemaRef('ReleaseTarget'), | ||
| version: openapi.schemaRef('DeploymentVersion'), | ||
| }, | ||
| }, | ||
| } |
Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -285,6 +285,16 @@ func (m *Manager) Redeploy(ctx context.Context, releaseTarget *oapi.ReleaseTarge | |
| WithTrigger(trace.TriggerManual)) | ||
| } | ||
|
|
||
| func (m *Manager) ForceDeploy(ctx context.Context, releaseTarget *oapi.ReleaseTarget, version *oapi.DeploymentVersion) error { | ||
| ctx, span := tracer.Start(ctx, "ForceDeploy") | ||
| defer span.End() | ||
|
|
||
| return m.ReconcileTarget(ctx, releaseTarget, | ||
| WithSkipEligibilityCheck(true), | ||
| WithTrigger(trace.TriggerManual), | ||
| WithForceDeployVersion(version)) | ||
| } | ||
|
Comment on lines
+288
to
+296
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Add validation and documentation. The
Consider applying this pattern: +// ForceDeploy forces deployment of a specific version for a release target,
+// bypassing policy-based version selection and eligibility checks.
+//
+// Unlike Redeploy which uses the policy-determined version, ForceDeploy deploys
+// the exact version specified, regardless of policies. This is useful for rollbacks
+// or emergency deployments.
+//
+// Returns error if:
+// - version is nil
+// - version doesn't belong to the target's deployment
+// - A job is already in progress for this release target
+// - Planning or execution fails
func (m *Manager) ForceDeploy(ctx context.Context, releaseTarget *oapi.ReleaseTarget, version *oapi.DeploymentVersion) error {
ctx, span := tracer.Start(ctx, "ForceDeploy")
defer span.End()
+ // Validate inputs
+ if version == nil {
+ err := fmt.Errorf("version cannot be nil")
+ span.RecordError(err)
+ span.SetStatus(codes.Error, "invalid input")
+ return err
+ }
+
+ if version.DeploymentId != releaseTarget.DeploymentId {
+ err := fmt.Errorf("version %s does not belong to deployment %s", version.Id, releaseTarget.DeploymentId)
+ span.RecordError(err)
+ span.SetStatus(codes.Error, "version mismatch")
+ return err
+ }
+
+ // Check if there's already a job in progress for this release target
+ inProgressJobs := m.store.Jobs.GetJobsInProcessingStateForReleaseTarget(releaseTarget)
+ if len(inProgressJobs) > 0 {
+ var jobId string
+ var jobStatus oapi.JobStatus
+ for _, job := range inProgressJobs {
+ jobId = job.Id
+ jobStatus = job.Status
+ break
+ }
+
+ err := fmt.Errorf("cannot force deploy: job %s already in progress (status: %s)", jobId, jobStatus)
+ span.RecordError(err)
+ span.SetStatus(codes.Error, "job in progress")
+ log.Warn("ForceDeploy blocked: job already in progress",
+ "releaseTargetKey", releaseTarget.Key(),
+ "jobId", jobId,
+ "jobStatus", jobStatus)
+ return err
+ }
+
return m.ReconcileTarget(ctx, releaseTarget,
WithSkipEligibilityCheck(true),
WithTrigger(trace.TriggerManual),
WithForceDeployVersion(version))
}
🤖 Prompt for AI Agents |
||
|
|
||
| // reconcileTargetWithRelationships is like ReconcileTarget but accepts pre-computed resource relationships. | ||
| // This is an optimization to avoid recomputing relationships for multiple release targets that share the same resource. | ||
| // After reconciliation completes, it caches the computed state for use by other APIs. | ||
|
|
||
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
🧩 Analysis chain
Verify validation of forced deployment versions upstream.
The forced version bypasses all policy-based selection (Step 2), which could lead to deploying versions in invalid states or belonging to different deployments if not validated upstream.
Ensure the caller (likely
manager.ForceDeploy) validates:releaseTarget.DeploymentId)Run the following script to check validation in the force deploy flow:
🏁 Script executed:
Length of output: 495
🏁 Script executed:
Length of output: 3880
🏁 Script executed:
Length of output: 4849
🏁 Script executed:
Length of output: 1957
Add validation for forced deployment versions to prevent deploying invalid states or wrong deployments.
The forced version (line 136) bypasses all policy validation (Step 2) without checking the version status (could be "Building", "Failed", or "Paused") or confirming it belongs to the correct deployment. Add validation after line 142:
Also add validation in
ForceDeploy(manager.go:288) before passing the version toReconcileTarget, or clearly document that callers are responsible for validation.🤖 Prompt for AI Agents