@@ -17,6 +17,7 @@ limitations under the License.
17
17
package alphaupdate
18
18
19
19
import (
20
+ "bytes"
20
21
"fmt"
21
22
"io"
22
23
"net/http"
@@ -98,12 +99,18 @@ var _ = Describe("kubebuilder", func() {
98
99
By ("cleaning up test artifacts" )
99
100
_ = os .RemoveAll (filepath .Dir (pathBinFromVersion ))
100
101
_ = os .RemoveAll (kbc .Dir )
102
+ kbc .Destroy ()
101
103
})
102
104
103
105
It ("should update project from v4.5.2 to v4.6.0 without conflicts" , func () {
106
+ By ("running alpha update from v4.5.2 to v4.6.0" )
104
107
runAlphaUpdate (kbc .Dir , kbc , toVersion , false )
108
+
109
+ By ("checking that custom code is preserved" )
105
110
validateCustomCodePreservation (kbc .Dir )
106
- validateConflictMarkers (kbc .Dir , false )
111
+
112
+ By ("checking that no conflict markers are present in the project files" )
113
+ Expect (hasConflictMarkers (kbc .Dir )).To (BeFalse ())
107
114
108
115
By ("checking that go module is upgraded" )
109
116
validateCommonGoModule (kbc .Dir )
@@ -113,14 +120,52 @@ var _ = Describe("kubebuilder", func() {
113
120
})
114
121
115
122
It ("should update project from v4.5.2 to v4.7.0 with --force flag and create conflict markers" , func () {
123
+ By ("modifying original Makefile to use CONTROLLER_TOOLS_VERSION v0.17.3" )
124
+ modifyMakefileControllerTools (kbc .Dir , "v0.17.3" )
125
+
116
126
By ("running alpha update to v4.7.0 with --force flag" )
117
127
runAlphaUpdate (kbc .Dir , kbc , toVersionWithConflict , true )
118
128
119
- By ("checking that markers for conflicts are present " )
120
- validateConflictMarkers (kbc .Dir , true )
129
+ By ("checking that custom code is preserved " )
130
+ validateCustomCodePreservation (kbc .Dir )
121
131
122
- By ("checking that go module is upgraded" )
132
+ By ("checking that conflict markers are present in the project files" )
133
+ Expect (hasConflictMarkers (kbc .Dir )).To (BeTrue ())
134
+
135
+ By ("checking that go module is upgraded to expected versions" )
123
136
validateCommonGoModule (kbc .Dir )
137
+
138
+ By ("checking that Makefile is updated and has conflict between old and new versions in Makefile" )
139
+ makefilePath := filepath .Join (kbc .Dir , "Makefile" )
140
+ content , err := os .ReadFile (makefilePath )
141
+ Expect (err ).NotTo (HaveOccurred (), "Failed to read Makefile after update" )
142
+ makefileStr := string (content )
143
+
144
+ // Should update to the new version
145
+ Expect (makefileStr ).To (ContainSubstring (`GOLANGCI_LINT_VERSION ?= v2.1.6` ))
146
+
147
+ // The original project was scaffolded with v0.17.2 (from v4.5.2).
148
+ // The user manually updated it to v0.17.3.
149
+ // The target upgrade version (v4.7.0) introduces v0.18.0.
150
+ //
151
+ // Because both the user's version (v0.17.3) and the scaffold version (v0.18.0) differ,
152
+ // we expect Git to insert conflict markers around this line in the Makefile:
153
+ //
154
+ // <<<<<<< HEAD
155
+ // CONTROLLER_TOOLS_VERSION ?= v0.18.0
156
+ // =======
157
+ // CONTROLLER_TOOLS_VERSION ?= v0.17.3
158
+ // >>>>>>> tmp-original-*
159
+ Expect (makefileStr ).To (ContainSubstring ("<<<<<<<" ),
160
+ "Expected conflict marker <<<<<<< in Makefile" )
161
+ Expect (makefileStr ).To (ContainSubstring ("=======" ),
162
+ "Expected conflict separator ======= in Makefile" )
163
+ Expect (makefileStr ).To (ContainSubstring (">>>>>>>" ),
164
+ "Expected conflict marker >>>>>>> in Makefile" )
165
+ Expect (makefileStr ).To (ContainSubstring ("CONTROLLER_TOOLS_VERSION ?= v0.17.3" ),
166
+ "Expected original user version in conflict" )
167
+ Expect (makefileStr ).To (ContainSubstring ("CONTROLLER_TOOLS_VERSION ?= v0.18.0" ),
168
+ "Expected latest scaffold version in conflict" )
124
169
})
125
170
126
171
It ("should stop when updating the project from v4.5.2 to v4.7.0 without the flag force" , func () {
@@ -130,6 +175,9 @@ var _ = Describe("kubebuilder", func() {
130
175
By ("validating that merge stopped with conflicts requiring manual resolution" )
131
176
validateConflictState (kbc .Dir )
132
177
178
+ By ("checking that custom code is preserved" )
179
+ validateCustomCodePreservation (kbc .Dir )
180
+
133
181
By ("checking that go module is upgraded" )
134
182
validateCommonGoModule (kbc .Dir )
135
183
})
@@ -147,6 +195,28 @@ var _ = Describe("kubebuilder", func() {
147
195
})
148
196
})
149
197
198
+ func modifyMakefileControllerTools (projectDir , newVersion string ) {
199
+ makefilePath := filepath .Join (projectDir , "Makefile" )
200
+ oldLine := "CONTROLLER_TOOLS_VERSION ?= v0.17.2"
201
+ newLine := fmt .Sprintf ("CONTROLLER_TOOLS_VERSION ?= %s" , newVersion )
202
+
203
+ By ("replacing the controller-tools version in the Makefile" )
204
+ Expect (util .ReplaceInFile (makefilePath , oldLine , newLine )).
205
+ To (Succeed (), "Failed to update CONTROLLER_TOOLS_VERSION in Makefile" )
206
+
207
+ By ("committing the Makefile change to simulate user customization" )
208
+ cmds := [][]string {
209
+ {"git" , "add" , "Makefile" },
210
+ {"git" , "commit" , "-m" , fmt .Sprintf ("User modified CONTROLLER_TOOLS_VERSION to %s" , newVersion )},
211
+ }
212
+ for _ , args := range cmds {
213
+ cmd := exec .Command (args [0 ], args [1 :]... )
214
+ cmd .Dir = projectDir
215
+ output , err := cmd .CombinedOutput ()
216
+ Expect (err ).NotTo (HaveOccurred (), fmt .Sprintf ("Git command failed: %s" , output ))
217
+ }
218
+ }
219
+
150
220
func validateMakefileContent (projectDir string ) {
151
221
makefilePath := filepath .Join (projectDir , "Makefile" )
152
222
content , err := os .ReadFile (makefilePath )
@@ -283,34 +353,37 @@ func validateCustomCodePreservation(projectDir string) {
283
353
Expect (string (controllerContent )).To (ContainSubstring (controllerImplementation ))
284
354
}
285
355
286
- func validateConflictMarkers (projectDir string , expectMarkers bool ) {
287
- files := []string {
288
- filepath .Join (projectDir , "api" , "v1" , "testoperator_types.go" ),
289
- filepath .Join (projectDir , "internal" , "controller" , "testoperator_controller.go" ),
290
- }
291
- found := false
292
- for _ , file := range files {
293
- content , err := os .ReadFile (file )
294
- if err != nil {
295
- continue
356
+ func hasConflictMarkers (projectDir string ) bool {
357
+ hasMarker := false
358
+
359
+ err := filepath .Walk (projectDir , func (path string , info os.FileInfo , err error ) error {
360
+ if err != nil || info .IsDir () {
361
+ return nil
362
+ }
363
+
364
+ content , readErr := os .ReadFile (path )
365
+ if readErr != nil || bytes .Contains (content , []byte {0 }) {
366
+ return nil // skip unreadable or binary files
296
367
}
368
+
297
369
if strings .Contains (string (content ), "<<<<<<<" ) {
298
- found = true
299
- break
370
+ hasMarker = true
371
+ return fmt . Errorf ( "conflict marker found in %s" , path ) // short-circuit early
300
372
}
373
+ return nil
374
+ })
375
+
376
+ if err != nil && hasMarker {
377
+ return true
301
378
}
302
- if expectMarkers {
303
- Expect (found ).To (BeTrue ())
304
- } else {
305
- Expect (found ).To (BeFalse ())
306
- }
379
+ return false
307
380
}
308
381
309
382
func validateConflictState (projectDir string ) {
310
383
By ("validating merge stopped with conflicts requiring manual resolution" )
311
384
312
385
// 1. Check file contents for conflict markers
313
- validateConflictMarkers ( projectDir , true )
386
+ Expect ( hasConflictMarkers ( projectDir )). To ( BeTrue () )
314
387
315
388
// 2. Check Git status for conflict-tracked files (UU = both modified)
316
389
cmd := exec .Command ("git" , "status" , "--porcelain" )
0 commit comments