@@ -31,6 +31,7 @@ import (
3131 "github.com/ProtonMail/go-crypto/openpgp"
3232 securejoin "github.com/cyphar/filepath-securejoin"
3333 extgogit "github.com/go-git/go-git/v5"
34+ "github.com/go-git/go-git/v5/plumbing/transport"
3435 "github.com/go-logr/logr"
3536 corev1 "k8s.io/api/core/v1"
3637 metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
@@ -256,9 +257,20 @@ func (r *ImageUpdateAutomationReconciler) Reconcile(ctx context.Context, req ctr
256257 tracelog .Info ("using push branch from $ref.branch" , "branch" , pushBranch )
257258 }
258259
259- debuglog .Info ("attempting to clone git repository" , "gitrepository" , originName , "ref" , checkoutRef , "working" , tmp )
260+ authOpts , err := r .getAuthOpts (ctx , & origin )
261+ if err != nil {
262+ return failWithError (err )
263+ }
264+ var proxyOpts * transport.ProxyOptions
265+ if origin .Spec .ProxySecretRef != nil {
266+ proxyOpts , err = r .getProxyOpts (ctx , origin .Spec .ProxySecretRef .Name , origin .GetNamespace ())
267+ if err != nil {
268+ return failWithError (err )
269+ }
270+ }
260271
261- gitClient , err := r .constructGitClient (ctx , & origin , tmp , switchBranch )
272+ clientOpts := r .getGitClientOpts (authOpts .Transport , proxyOpts , switchBranch )
273+ gitClient , err := gogit .NewClient (tmp , authOpts , clientOpts ... )
262274 if err != nil {
263275 return failWithError (err )
264276 }
@@ -279,6 +291,7 @@ func (r *ImageUpdateAutomationReconciler) Reconcile(ctx context.Context, req ctr
279291 // Use the git operations timeout for the repo.
280292 cloneCtx , cancel := context .WithTimeout (ctx , origin .Spec .Timeout .Duration )
281293 defer cancel ()
294+ debuglog .Info ("attempting to clone git repository" , "gitrepository" , originName , "ref" , checkoutRef , "working" , tmp )
282295 if _ , err := gitClient .Clone (cloneCtx , origin .Spec .URL , opts ); err != nil {
283296 return failWithError (err )
284297 }
@@ -506,6 +519,31 @@ func intervalOrDefault(auto *imagev1.ImageUpdateAutomation) time.Duration {
506519 return auto .Spec .Interval .Duration
507520}
508521
522+ func (r * ImageUpdateAutomationReconciler ) getGitClientOpts (gitTransport git.TransportType , proxyOpts * transport.ProxyOptions ,
523+ diffPushBranch bool ) []gogit.ClientOption {
524+ clientOpts := []gogit.ClientOption {gogit .WithDiskStorage ()}
525+ if gitTransport == git .HTTP {
526+ clientOpts = append (clientOpts , gogit .WithInsecureCredentialsOverHTTP ())
527+ }
528+
529+ if proxyOpts != nil {
530+ clientOpts = append (clientOpts , gogit .WithProxy (* proxyOpts ))
531+ }
532+
533+ // If the push branch is different from the checkout ref, we need to
534+ // have all the references downloaded at clone time, to ensure that
535+ // SwitchBranch will have access to the target branch state. fluxcd/flux2#3384
536+ //
537+ // To always overwrite the push branch, the feature gate
538+ // GitAllBranchReferences can be set to false, which will cause
539+ // the SwitchBranch operation to ignore the remote branch state.
540+ allReferences := r .features [features .GitAllBranchReferences ]
541+ if diffPushBranch {
542+ clientOpts = append (clientOpts , gogit .WithSingleBranch (! allReferences ))
543+ }
544+ return clientOpts
545+ }
546+
509547// automationsForGitRepo fetches all the automations that refer to a
510548// particular source.GitRepository object.
511549func (r * ImageUpdateAutomationReconciler ) automationsForGitRepo (ctx context.Context , obj client.Object ) []reconcile.Request {
@@ -541,20 +579,17 @@ func (r *ImageUpdateAutomationReconciler) automationsForImagePolicy(ctx context.
541579 return reqs
542580}
543581
582+ // getAuthOpts fetches the secret containing the auth options (if specified),
583+ // constructs a git.AuthOptions object using those options along with the provided
584+ // repository's URL and returns it.
544585func (r * ImageUpdateAutomationReconciler ) getAuthOpts (ctx context.Context , repository * sourcev1.GitRepository ) (* git.AuthOptions , error ) {
545586 var data map [string ][]byte
587+ var err error
546588 if repository .Spec .SecretRef != nil {
547- name := types.NamespacedName {
548- Namespace : repository .GetNamespace (),
549- Name : repository .Spec .SecretRef .Name ,
550- }
551-
552- secret := & corev1.Secret {}
553- err := r .Client .Get (ctx , name , secret )
589+ data , err = r .getSecretData (ctx , repository .Spec .SecretRef .Name , repository .GetNamespace ())
554590 if err != nil {
555- return nil , fmt .Errorf ("failed to get secret '%s': %w" , name . String () , err )
591+ return nil , fmt .Errorf ("failed to get auth secret '%s/%s ': %w" , repository . GetNamespace (), repository . Spec . SecretRef . Name , err )
556592 }
557- data = secret .Data
558593 }
559594
560595 u , err := url .Parse (repository .Spec .URL )
@@ -570,36 +605,37 @@ func (r *ImageUpdateAutomationReconciler) getAuthOpts(ctx context.Context, repos
570605 return opts , nil
571606}
572607
573- // constructGitClient constructs and returns a new gogit client.
574- func (r * ImageUpdateAutomationReconciler ) constructGitClient (ctx context.Context ,
575- origin * sourcev1.GitRepository , repoDir string , switchBranch bool ) (* gogit.Client , error ) {
576- authOpts , err := r .getAuthOpts (ctx , origin )
608+ // getProxyOpts fetches the secret containing the proxy settings, constructs a
609+ // transport.ProxyOptions object using those settings and then returns it.
610+ func (r * ImageUpdateAutomationReconciler ) getProxyOpts (ctx context.Context , proxySecretName ,
611+ proxySecretNamespace string ) (* transport.ProxyOptions , error ) {
612+ proxyData , err := r .getSecretData (ctx , proxySecretName , proxySecretNamespace )
577613 if err != nil {
578- return nil , err
614+ return nil , fmt . Errorf ( "failed to get proxy secret '%s/%s': %w" , proxySecretNamespace , proxySecretName , err )
579615 }
580-
581- clientOpts := []gogit.ClientOption {gogit .WithDiskStorage ()}
582- if authOpts .Transport == git .HTTP {
583- clientOpts = append (clientOpts , gogit .WithInsecureCredentialsOverHTTP ())
616+ address , ok := proxyData ["address" ]
617+ if ! ok {
618+ return nil , fmt .Errorf ("invalid proxy secret '%s/%s': key 'address' is missing" , proxySecretNamespace , proxySecretName )
584619 }
585620
586- // If the push branch is different from the checkout ref, we need to
587- // have all the references downloaded at clone time, to ensure that
588- // SwitchBranch will have access to the target branch state. fluxcd/flux2#3384
589- //
590- // To always overwrite the push branch, the feature gate
591- // GitAllBranchReferences can be set to false, which will cause
592- // the SwitchBranch operation to ignore the remote branch state.
593- allReferences := r .features [features .GitAllBranchReferences ]
594- if switchBranch {
595- clientOpts = append (clientOpts , gogit .WithSingleBranch (! allReferences ))
621+ proxyOpts := & transport.ProxyOptions {
622+ URL : string (address ),
623+ Username : string (proxyData ["username" ]),
624+ Password : string (proxyData ["password" ]),
596625 }
626+ return proxyOpts , nil
627+ }
597628
598- gitClient , err := gogit .NewClient (repoDir , authOpts , clientOpts ... )
599- if err != nil {
629+ func (r * ImageUpdateAutomationReconciler ) getSecretData (ctx context.Context , name , namespace string ) (map [string ][]byte , error ) {
630+ key := types.NamespacedName {
631+ Namespace : namespace ,
632+ Name : name ,
633+ }
634+ var secret corev1.Secret
635+ if err := r .Client .Get (ctx , key , & secret ); err != nil {
600636 return nil , err
601637 }
602- return gitClient , nil
638+ return secret . Data , nil
603639}
604640
605641// getSigningEntity retrieves an OpenPGP entity referenced by the
0 commit comments