func()

in controllers/codebasebranch/chain/put_branch_in_git/put_branch_in_git.go [27:148]


func (h PutBranchInGit) ServeRequest(ctx context.Context, branch *codebaseApi.CodebaseBranch) error {
	log := ctrl.LoggerFrom(ctx)

	if branch.Status.Git == codebaseApi.CodebaseBranchGitStatusBranchCreated {
		log.Info("Branch is already created in git")

		if err := handler.NextServeOrNil(ctx, h.Next, branch); err != nil {
			return fmt.Errorf("failed to process next handler in chain: %w", err)
		}

		return nil
	}

	log.Info("Start creating branch in git")

	if err := h.setIntermediateSuccessFields(branch, codebaseApi.AcceptCodebaseBranchRegistration); err != nil {
		return err
	}

	codebase := &codebaseApi.Codebase{}
	if err := h.Client.Get(ctx, client.ObjectKey{
		Namespace: branch.Namespace,
		Name:      branch.Spec.CodebaseName,
	}, codebase); err != nil {
		setFailedFields(branch, codebaseApi.PutGitBranch, err.Error())

		return fmt.Errorf("failed to fetch Codebase: %w", err)
	}

	if !codebase.Status.Available {
		log.Info("failed to start reconciling for branch; codebase is unavailable", "codebase", codebase.Name)
		return util.NewCodebaseBranchReconcileError(fmt.Sprintf("%v codebase is unavailable", codebase.Name))
	}

	gitServer := &codebaseApi.GitServer{}
	if err := h.Client.Get(
		ctx,
		client.ObjectKey{
			Namespace: branch.Namespace,
			Name:      codebase.Spec.GitServer,
		},
		gitServer,
	); err != nil {
		setFailedFields(branch, codebaseApi.PutGitBranch, err.Error())

		return fmt.Errorf("failed to fetch GitServer: %w", err)
	}

	secret := &corev1.Secret{}
	if err := h.Client.Get(
		ctx,
		client.ObjectKey{
			Namespace: branch.Namespace,
			Name:      gitServer.Spec.NameSshKeySecret,
		},
		secret,
	); err != nil {
		err = fmt.Errorf("failed to get %v secret: %w", gitServer.Spec.NameSshKeySecret, err)
		setFailedFields(branch, codebaseApi.PutGitBranch, err.Error())

		return err
	}

	wd := util.GetWorkDir(branch.Spec.CodebaseName, fmt.Sprintf("%v-%v", branch.Namespace, branch.Spec.BranchName))
	if !checkDirectory(wd) {
		repoSshUrl := util.GetSSHUrl(gitServer, codebase.Spec.GetProjectID())

		if err := h.Git.CloneRepositoryBySsh(
			ctx,
			string(secret.Data[util.PrivateSShKeyName]),
			gitServer.Spec.GitUser,
			repoSshUrl,
			wd,
			gitServer.Spec.SshPort,
		); err != nil {
			setFailedFields(branch, codebaseApi.PutGitBranch, err.Error())

			return fmt.Errorf("failed to clone repository: %w", err)
		}
	}

	currentBranchName, err := h.Git.GetCurrentBranchName(wd)
	if err != nil {
		return fmt.Errorf("failed to get current branch name: %w", err)
	}

	if currentBranchName != codebase.Spec.DefaultBranch {
		if err = h.Git.CheckoutRemoteBranchBySSH(string(secret.Data[util.PrivateSShKeyName]), gitServer.Spec.GitUser, wd, codebase.Spec.DefaultBranch); err != nil {
			return fmt.Errorf("failed to checkout to default branch %s: %w", codebase.Spec.DefaultBranch, err)
		}
	}

	err = h.Git.CreateRemoteBranch(string(secret.Data[util.PrivateSShKeyName]), gitServer.Spec.GitUser, wd, branch.Spec.BranchName, branch.Spec.FromCommit, gitServer.Spec.SshPort)
	if err != nil {
		setFailedFields(branch, codebaseApi.PutGitBranch, err.Error())

		// We need to remove work directory if branch creation failed(push error).
		// Otherwise, the next time the branch creation will be skipped because local branch already exists.
		if err = util.RemoveDirectory(wd); err != nil {
			log.Error(err, "failed to remove directory", "path", wd)
		}

		return fmt.Errorf("failed to create remote branch: %w", err)
	}

	branch.Status.Git = codebaseApi.CodebaseBranchGitStatusBranchCreated
	if err = h.Client.Status().Update(ctx, branch); err != nil {
		branch.Status.Git = ""
		setFailedFields(branch, codebaseApi.PutGitBranch, err.Error())

		return fmt.Errorf("failed to update CodebaseBranch status: %w", err)
	}

	log.Info("Branch has been created in git")

	err = handler.NextServeOrNil(ctx, h.Next, branch)
	if err != nil {
		return fmt.Errorf("failed to process next handler in chain: %w", err)
	}

	return nil
}