-
Notifications
You must be signed in to change notification settings - Fork 0
/
repo_writer.go
195 lines (176 loc) · 6.91 KB
/
repo_writer.go
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
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
package core
import (
"github.com/hashicorp/hcl/v2/hclwrite"
"github.com/yoanm/go-gh2tf/ghbranch"
"github.com/yoanm/go-gh2tf/ghbranchdefault"
"github.com/yoanm/go-gh2tf/ghbranchprotect"
"github.com/yoanm/go-gh2tf/ghrepository"
"github.com/yoanm/go-tfsig"
)
/** Public **/
func NewHclRepository(repoTfId string, repoConfig *GhRepoConfig, valGen tfsig.ValueGenerator) *hclwrite.File {
hclFile := hclwrite.NewEmptyFile()
appendRepositoryResource(hclFile.Body(), repoConfig, valGen, repoTfId)
appendBranchDefaultResources(hclFile.Body(), repoConfig, valGen, repoTfId)
appendBranchResources(hclFile.Body(), repoConfig, valGen, repoTfId)
appendBranchProtectionResourceContent(hclFile.Body(), repoConfig, valGen, repoTfId)
return hclFile
}
/** Private **/
func appendRepositoryResource(body *hclwrite.Body, c *GhRepoConfig, valGen tfsig.ValueGenerator, repoTfId string) {
tfsig.AppendBlockIfNotNil(
body,
ghrepository.New(
MapToRepositoryRes(c, valGen, repoTfId),
),
)
}
func appendBranchDefaultResources(body *hclwrite.Body, c *GhRepoConfig, valGen tfsig.ValueGenerator, repoTfId string) {
tfsig.AppendNewLineAndBlockIfNotNil(
body,
ghbranchdefault.New(
// /!\ use LinkToRepository, so underlying repository will have to be created before creating default branch
MapToDefaultBranchRes(c.DefaultBranch, valGen, c, repoTfId, LinkToRepository, LinkToBranch),
),
)
}
func appendBranchResources(
body *hclwrite.Body,
repoConfig *GhRepoConfig,
valGen tfsig.ValueGenerator,
repoTfId string,
) {
if repoConfig.Branches != nil {
hasDefaultBranch := repoConfig.DefaultBranch != nil && repoConfig.DefaultBranch.Name != nil
keys, branches := MapToSortedListWithKeys(*repoConfig.Branches)
for idx, branchConfig := range branches {
key := keys[idx]
appendBranchResourceSignature(
body,
repoConfig,
// /!\ use LinkToRepository, so underlying repository will have to be created before
// creating the branch
// /!\ use LinkToBranch, so if a source branch is configured, it will have to be created
// before creating current one
ghbranch.NewSignature(
MapToBranchRes(key, branchConfig, valGen, repoConfig, repoTfId, LinkToRepository, LinkToBranch),
),
hasDefaultBranch,
key,
branchConfig,
)
}
}
}
func appendBranchResourceSignature(
body *hclwrite.Body,
repoConfig *GhRepoConfig,
sig *tfsig.BlockSignature,
hasDefaultBranch bool,
branchName string,
branchConfig *GhBranchConfig,
) {
if sig != nil {
// In case
// - it's the default branch config
ignoreSourceBranch := hasDefaultBranch && *repoConfig.DefaultBranch.Name == branchName
// - or source_branch is the default branch
ignoreSourceBranch = ignoreSourceBranch || (hasDefaultBranch && branchConfig.SourceBranch != nil &&
*repoConfig.DefaultBranch.Name == *branchConfig.SourceBranch)
// - or no source branch configured (which means the same as current default branch)
ignoreSourceBranch = ignoreSourceBranch || branchConfig.SourceBranch == nil
// => append ignore_changes directive on source_branch
// It's useful mostly when switching default branch to another one from outside of terraform,
// or from terraform when following those steps:
// Step 1 - add both current (if not already there) and new branch config(s) with empty
// configuration (brName: {})
// - run github-tf to re-generate terraform config
// Step 3 - if current default branch had no config previously:
// run terraform import github_branch.${repo}-${oldBranch} ${repo}:${oldBranch}
// - run terraform apply to add the new branch
// Step 4 - switch default branch name
// - If old default branch wasn't protected and you don't want to keep old default branch config
// (branches->BRANCH_NAME), jump to Step 5
// - run github-tf to re-generate terraform config
// - run terraform apply
// Step 5 [Optional, but usually] - remove old branch config
// - If you don't want to keep new default branch config (branches->BRANCH_NAME), jump to step 6
// - run github-tf to re-generate terraform config
// - run terraform apply
// Step 6 [Optional] - Remove new branch config
// - run github-tf to re-generate terraform config
// - run terraform state rm github_branch.${repo}-${newBranch}
// - in case step 5 has been done: run terraform apply (will delete old branch)
if ignoreSourceBranch {
sig.Lifecycle(
tfsig.LifecycleConfig{
CreateBeforeDestroy: nil,
PreventDestroy: nil,
IgnoreChanges: []string{"source_branch"},
ReplaceTriggeredBy: nil,
Precondition: nil,
Postcondition: nil,
},
)
}
tfsig.AppendNewLineAndBlockIfNotNil(body, sig.Build())
}
}
func appendBranchProtectionResourceContent(
body *hclwrite.Body,
repoConfig *GhRepoConfig,
valGen tfsig.ValueGenerator,
repoTfId string,
) {
tfsig.AppendNewLineAndBlockIfNotNil(
body,
ghbranchprotect.New(
// /!\ use LinkToRepository, so underlying repository will have to be created before
// creating the branch protection
// /!\ use LinkToBranch, to explicitly bind the protection to the branch, so if something
// change on default_branch resource,
// the protection will be impacted only if the change on default_branch resource succeeded
MapDefaultBranchToBranchProtectionRes(
repoConfig.DefaultBranch,
valGen,
repoConfig,
repoTfId,
LinkToRepository,
LinkToBranch,
),
),
)
if repoConfig.Branches != nil {
// sort branches to always get a predictable output (for tests mostly)
keys, branches := MapToSortedListWithKeys(*repoConfig.Branches)
for idx, branchConfig := range branches {
key := keys[idx]
tfsig.AppendNewLineAndBlockIfNotNil(
body,
ghbranchprotect.New(
// /!\ use LinkToRepository, so underlying repository will have to be created before
// creating the branch protection
// /!\ do not use LinkToBranch, else branch protection will be created only after branch is created
// (which is useless and can be done in parallel)
MapBranchToBranchProtectionRes(&key, branchConfig.Protection, valGen, repoConfig, repoTfId, LinkToRepository),
),
)
}
}
if repoConfig.BranchProtections != nil {
for _, branchProtectionConfig := range *repoConfig.BranchProtections {
tfsig.AppendNewLineAndBlockIfNotNil(
body,
ghbranchprotect.New(
// /!\ use LinkToRepository, so underlying repository will have to be created before
// creating the branch protection
// /!\ do not use LinkToBranch, else branch protection will be created only after
// branch is created (which is useless and can be done in parallel) and in many cases related
// branch config doesn't exist anyway (else it's simpler to move the protection config under
// 'protection' attribute of the related branch)
MapToBranchProtectionRes(branchProtectionConfig, valGen, repoConfig, repoTfId, LinkToRepository),
),
)
}
}
}