@@ -390,6 +390,62 @@ Images:
390390 Expect (gitServer .StopSSH ()).To (Succeed ())
391391 })
392392
393+ Context ("with PushSpec" , func () {
394+
395+ var (
396+ update * imagev1.ImageUpdateAutomation
397+ pushBranch string
398+ )
399+
400+ BeforeEach (func () {
401+ commitInRepo (cloneLocalRepoURL , branch , "Install setter marker" , func (tmp string ) {
402+ replaceMarker (tmp , policyKey )
403+ })
404+ waitForNewHead (localRepo , branch )
405+
406+ pushBranch = "pr-" + randStringRunes (5 )
407+
408+ update = & imagev1.ImageUpdateAutomation {
409+ Spec : imagev1.ImageUpdateAutomationSpec {
410+ Interval : metav1.Duration {Duration : 2 * time .Hour },
411+ Checkout : imagev1.GitCheckoutSpec {
412+ GitRepositoryRef : meta.LocalObjectReference {
413+ Name : gitRepoKey .Name ,
414+ },
415+ Branch : branch ,
416+ },
417+ Update : & imagev1.UpdateStrategy {
418+ Strategy : imagev1 .UpdateStrategySetters ,
419+ },
420+ Commit : imagev1.CommitSpec {
421+ MessageTemplate : commitMessage ,
422+ },
423+ Push : & imagev1.PushSpec {
424+ Branch : pushBranch ,
425+ },
426+ },
427+ }
428+ update .Name = "update-" + randStringRunes (5 )
429+ update .Namespace = namespace .Name
430+
431+ Expect (k8sClient .Create (context .Background (), update )).To (Succeed ())
432+ })
433+
434+ It ("creates and pushes the push branch" , func () {
435+ waitForNewHead (localRepo , pushBranch )
436+ head , err := localRepo .Reference (plumbing .NewRemoteReferenceName (originRemote , pushBranch ), true )
437+ Expect (err ).NotTo (HaveOccurred ())
438+ commit , err := localRepo .CommitObject (head .Hash ())
439+ Expect (err ).ToNot (HaveOccurred ())
440+ Expect (commit .Message ).To (Equal (commitMessage ))
441+ })
442+
443+ AfterEach (func () {
444+ Expect (k8sClient .Delete (context .Background (), update )).To (Succeed ())
445+ })
446+
447+ })
448+
393449 Context ("with Setters" , func () {
394450
395451 var (
@@ -586,20 +642,49 @@ func setterRef(name types.NamespacedName) string {
586642 return fmt .Sprintf (`{"%s": "%s:%s"}` , update .SetterShortHand , name .Namespace , name .Name )
587643}
588644
645+ // waitForHead fetches the remote branch given until it differs from
646+ // the remote ref locally (or if there's no ref locally, until it has
647+ // fetched the remote branch). It resets the working tree head to the
648+ // remote branch ref.
589649func waitForNewHead (repo * git.Repository , branch string ) {
590- head , _ := repo .Head ()
591- headHash := head .Hash ().String ()
592650 working , err := repo .Worktree ()
593651 Expect (err ).ToNot (HaveOccurred ())
652+
653+ // Try to find the remote branch in the repo locally; this will
654+ // fail if we're on a branch that didn't exist when we cloned the
655+ // repo (e.g., if the automation is pushing to another branch).
656+ remoteHeadHash := ""
657+ remoteBranch := plumbing .NewRemoteReferenceName (originRemote , branch )
658+ remoteHead , err := repo .Reference (remoteBranch , false )
659+ if err != plumbing .ErrReferenceNotFound {
660+ Expect (err ).ToNot (HaveOccurred ())
661+ }
662+ if err == nil {
663+ remoteHeadHash = remoteHead .Hash ().String ()
664+ } // otherwise, any reference fetched will do.
665+
666+ // Now try to fetch new commits from that remote branch
594667 Eventually (func () bool {
595- if working .Pull (& git.PullOptions {
596- ReferenceName : plumbing .NewBranchReferenceName (branch ),
668+ if err := repo .Fetch (& git.FetchOptions {
669+ RefSpecs : []config.RefSpec {
670+ config .RefSpec ("refs/heads/" + branch + ":refs/remotes/origin/" + branch ),
671+ },
597672 }); err != nil {
598673 return false
599674 }
600- h , _ := repo .Head ()
601- return headHash != h .Hash ().String ()
675+ remoteHead , err = repo .Reference (remoteBranch , false )
676+ if err != nil {
677+ return false
678+ }
679+ return remoteHead .Hash ().String () != remoteHeadHash
602680 }, timeout , time .Second ).Should (BeTrue ())
681+
682+ // New commits in the remote branch -- reset the working tree head
683+ // to that. Note this does not create a local branch tracking the
684+ // remote, so it is a detached head.
685+ Expect (working .Reset (& git.ResetOptions {
686+ Commit : remoteHead .Hash (),
687+ })).To (Succeed ())
603688}
604689
605690func compareRepoWithExpected (repoURL , branch , fixture string , changeFixture func (tmp string )) {
0 commit comments