-
Notifications
You must be signed in to change notification settings - Fork 9
Expand file tree
/
Copy pathput_gitlab_ci_config.go
More file actions
138 lines (109 loc) · 4.15 KB
/
put_gitlab_ci_config.go
File metadata and controls
138 lines (109 loc) · 4.15 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
package chain
import (
"context"
"fmt"
"os"
"path/filepath"
ctrl "sigs.k8s.io/controller-runtime"
"sigs.k8s.io/controller-runtime/pkg/client"
codebaseApi "github.com/epam/edp-codebase-operator/v2/api/v1"
gitproviderv2 "github.com/epam/edp-codebase-operator/v2/pkg/git"
gitlabci "github.com/epam/edp-codebase-operator/v2/pkg/gitlab"
"github.com/epam/edp-codebase-operator/v2/pkg/util"
)
type PutGitLabCIConfig struct {
client client.Client
gitlabCIManager gitlabci.Manager
gitProviderFactory gitproviderv2.GitProviderFactory
}
func NewPutGitLabCIConfig(
c client.Client,
m gitlabci.Manager,
gitProviderFactory gitproviderv2.GitProviderFactory,
) *PutGitLabCIConfig {
return &PutGitLabCIConfig{client: c, gitlabCIManager: m, gitProviderFactory: gitProviderFactory}
}
func (h *PutGitLabCIConfig) ServeRequest(ctx context.Context, codebase *codebaseApi.Codebase) error {
log := ctrl.LoggerFrom(ctx)
// Skip if not GitLab CI
if codebase.Spec.CiTool != util.CIGitLab {
log.Info("Skip GitLab CI config injection, not using GitLab CI")
return nil
}
// Skip if already pushed (this stage or later)
if codebase.Status.Git == util.ProjectGitLabCIPushedStatus ||
codebase.Status.Git == util.ProjectTemplatesPushedStatus {
log.Info("Skip GitLab CI config, already pushed in previous run")
return nil
}
// Skip if already exists
if h.gitlabCIAlreadyExists(codebase) {
log.Info("Skip GitLab CI config, already exists in repository")
return nil
}
log.Info("Start pushing GitLab CI config")
if err := h.tryToPushGitLabCIConfig(ctx, codebase); err != nil {
setFailedFields(codebase, codebaseApi.RepositoryProvisioning, err.Error())
return fmt.Errorf("failed to push GitLab CI config for %v codebase: %w", codebase.Name, err)
}
log.Info("End pushing GitLab CI config")
// Set status to mark this stage complete
if err := updateGitStatusWithPatch(
ctx,
h.client,
codebase,
codebaseApi.RepositoryProvisioning,
util.ProjectGitLabCIPushedStatus,
); err != nil {
return err
}
log.Info("GitLab CI status has been set successfully")
return nil
}
// gitlabCIAlreadyExists is a fast-path optimization that checks whether
// .gitlab-ci.yml already exists in the local working directory, avoiding the
// expensive clone+checkout round-trip when the file was written by a prior
// reconciliation run. The manager's InjectGitLabCIConfig has its own os.Stat
// guard as a safety invariant, so this check is purely an optimization.
func (h *PutGitLabCIConfig) gitlabCIAlreadyExists(codebase *codebaseApi.Codebase) bool {
wd := util.GetWorkDir(codebase.Name, codebase.Namespace)
gitlabCIPath := filepath.Join(wd, gitlabci.GitLabCIFileName)
// Check if file exists locally first
if _, err := os.Stat(gitlabCIPath); err == nil {
return true
}
return false
}
func (h *PutGitLabCIConfig) tryToPushGitLabCIConfig(ctx context.Context, codebase *codebaseApi.Codebase) error {
log := ctrl.LoggerFrom(ctx)
// Prepare git repository (get server, clone, checkout)
gitCtx, err := PrepareGitRepository(ctx, h.client, codebase, h.gitProviderFactory)
if err != nil {
setFailedFields(codebase, codebaseApi.RepositoryProvisioning, err.Error())
return fmt.Errorf("failed to prepare git repository: %w", err)
}
// Create git provider using factory
g := h.gitProviderFactory(gitproviderv2.NewConfigFromGitServerAndSecret(gitCtx.GitServer, gitCtx.GitServerSecret))
// Inject GitLab CI configuration
log.Info("Start injecting GitLab CI config")
err = h.gitlabCIManager.InjectGitLabCIConfig(ctx, codebase, gitCtx.WorkDir)
if err != nil {
return fmt.Errorf("failed to inject GitLab CI config: %w", err)
}
log.Info("GitLab CI config has been injected")
log.Info("Start committing changes")
// Commit changes
err = g.Commit(ctx, gitCtx.WorkDir, "Add GitLab CI configuration")
if err != nil {
return fmt.Errorf("failed to commit changes: %w", err)
}
log.Info("Changes have been committed")
log.Info("Start pushing changes")
// Push changes
err = g.Push(ctx, gitCtx.WorkDir, gitproviderv2.RefSpecPushAllBranches)
if err != nil {
return fmt.Errorf("failed to push changes: %w", err)
}
log.Info("GitLab CI config has been pushed successfully")
return nil
}