RunPlanChecks runs plan checks for a plan.
(ctx context.Context, request *connect.Request[v1pb.RunPlanChecksRequest])
| 457 | |
| 458 | // RunPlanChecks runs plan checks for a plan. |
| 459 | func (s *PlanService) RunPlanChecks(ctx context.Context, request *connect.Request[v1pb.RunPlanChecksRequest]) (*connect.Response[v1pb.RunPlanChecksResponse], error) { |
| 460 | req := request.Msg |
| 461 | projectID, planID, err := common.GetProjectIDPlanID(req.Name) |
| 462 | if err != nil { |
| 463 | return nil, connect.NewError(connect.CodeInvalidArgument, err) |
| 464 | } |
| 465 | project, err := s.store.GetProject(ctx, &store.FindProjectMessage{ |
| 466 | Workspace: common.GetWorkspaceIDFromContext(ctx), |
| 467 | ResourceID: &projectID, |
| 468 | }) |
| 469 | if err != nil { |
| 470 | return nil, connect.NewError(connect.CodeInternal, errors.Wrapf(err, "failed to get project")) |
| 471 | } |
| 472 | if project == nil { |
| 473 | return nil, connect.NewError(connect.CodeNotFound, errors.Errorf("project not found for id: %v", projectID)) |
| 474 | } |
| 475 | plan, err := s.store.GetPlan(ctx, &store.FindPlanMessage{ |
| 476 | Workspace: common.GetWorkspaceIDFromContext(ctx), |
| 477 | UID: &planID, |
| 478 | ProjectID: projectID, |
| 479 | }) |
| 480 | if err != nil { |
| 481 | return nil, connect.NewError(connect.CodeInternal, errors.Wrapf(err, "failed to get plan")) |
| 482 | } |
| 483 | if plan == nil { |
| 484 | return nil, connect.NewError(connect.CodeNotFound, errors.Errorf("plan not found")) |
| 485 | } |
| 486 | if storePlanConfigHasRelease(plan.Config) { |
| 487 | return nil, connect.NewError(connect.CodeInvalidArgument, errors.Errorf("cannot run plan checks because plan %q has release", plan.Name)) |
| 488 | } |
| 489 | // Once a rollout exists the plan is frozen; re-running checks produces the |
| 490 | // same result and is misleading. Match the frontend gate in |
| 491 | // PlanCheckSection.vue / ChecksSection.vue / IssueDetailChecks.tsx. |
| 492 | if plan.Config.GetHasRollout() { |
| 493 | return nil, connect.NewError(connect.CodeFailedPrecondition, errors.Errorf("cannot run plan checks because plan %q already has a rollout", plan.Name)) |
| 494 | } |
| 495 | var databaseGroup *v1pb.DatabaseGroup |
| 496 | for _, spec := range plan.Config.GetSpecs() { |
| 497 | if c, ok := spec.Config.(*storepb.PlanConfig_Spec_ChangeDatabaseConfig); ok { |
| 498 | if len(c.ChangeDatabaseConfig.Targets) == 1 { |
| 499 | if _, _, err := common.GetProjectIDDatabaseGroupID(c.ChangeDatabaseConfig.Targets[0]); err == nil { |
| 500 | dg, err := getDatabaseGroupByName(ctx, s.store, c.ChangeDatabaseConfig.Targets[0], v1pb.DatabaseGroupView_DATABASE_GROUP_VIEW_FULL) |
| 501 | if err != nil { |
| 502 | return nil, connect.NewError(connect.CodeInternal, errors.Errorf("failed to get database group %q: %v", c.ChangeDatabaseConfig.Targets[0], err)) |
| 503 | } |
| 504 | if dg == nil { |
| 505 | return nil, connect.NewError(connect.CodeNotFound, errors.Errorf("database group %q not found", c.ChangeDatabaseConfig.Targets[0])) |
| 506 | } |
| 507 | databaseGroup = dg |
| 508 | break |
| 509 | } |
| 510 | } |
| 511 | } |
| 512 | } |
| 513 | planCheckRun, err := getPlanCheckRunFromPlan(ctx, s.store, project, plan, databaseGroup) |
| 514 | if err != nil { |
| 515 | return nil, connect.NewError(connect.CodeInternal, errors.Wrapf(err, "failed to get plan check run for plan")) |
| 516 | } |
nothing calls this directly
no test coverage detected