github.com/jenkins-x/jx/v2@v2.1.155/pkg/github/github_app.go (about)

     1  package github
     2  
     3  import (
     4  	"fmt"
     5  
     6  	"encoding/json"
     7  
     8  	"github.com/jenkins-x/jx-logging/pkg/log"
     9  	"github.com/jenkins-x/jx/v2/pkg/cmd/clients"
    10  	"github.com/jenkins-x/jx/v2/pkg/config"
    11  	"github.com/jenkins-x/jx/v2/pkg/kube"
    12  	"github.com/jenkins-x/jx/v2/pkg/util"
    13  	"github.com/pkg/errors"
    14  )
    15  
    16  //GithubApp represents a Github App install
    17  type GithubApp struct {
    18  	Factory clients.Factory
    19  }
    20  
    21  type response struct {
    22  	Installed    bool
    23  	AccessToRepo bool
    24  	URL          string
    25  	AppName      string
    26  }
    27  
    28  // Install - confirms that the github app is installed and if it isn't then prints out a url for the user to install
    29  func (gh *GithubApp) Install(owner string, repo string, fileHandles util.IOFileHandles, newRepo bool) (bool, error) {
    30  	installed, accessToRepo, url, appName, err := gh.isInstalled(owner, repo)
    31  	if err != nil {
    32  		return false, errors.Wrap(err, "when querying whether the Github App is installed")
    33  	}
    34  	if appName == "" {
    35  		// if the appName is empty lets use Jenkins X as the default
    36  		appName = "Jenkins X"
    37  	}
    38  
    39  	if installed {
    40  		fmt.Println(fmt.Sprintf("'%s' Github App installed", util.ColorInfo(appName)))
    41  		if newRepo {
    42  			// if this is a new repo we can't confirm if it has access at this stage
    43  			return false, nil
    44  		}
    45  		if !accessToRepo {
    46  			fmt.Fprintf(fileHandles.Out, "Please confirm '%s' Github App has access to repository %s. Click this url \n%s\n\n", util.ColorInfo(appName), repo, util.ColorInfo(url))
    47  		}
    48  	} else {
    49  		fmt.Fprintf(fileHandles.Out, "Please install '%s' Github App into your organisation/account %s and allow access to repository %s. Click this url \n%s\n\n", util.ColorInfo(appName), owner, repo, util.ColorInfo(url))
    50  	}
    51  	if !accessToRepo {
    52  		accessToRepo, err = util.Confirm(fmt.Sprintf("Does the '%s' Github App have access to repository", util.ColorInfo(appName)), false,
    53  			fmt.Sprintf("Please install '%s' Github App into your organisation and grant access to repositories", util.ColorInfo(appName)), fileHandles)
    54  		if err != nil {
    55  			return false, err
    56  		}
    57  	}
    58  	if !accessToRepo {
    59  		return false, errors.New(fmt.Sprintf("Please install '%s' Github App", util.ColorInfo(appName)))
    60  	}
    61  	return accessToRepo, err
    62  }
    63  
    64  func (gh *GithubApp) isInstalled(owner string, repo string) (bool, bool, string, string, error) {
    65  	requirementConfig, err := gh.getRequirementConfig()
    66  	if err != nil {
    67  		return false, false, "", "", err
    68  	}
    69  
    70  	if requirementConfig.GithubApp != nil {
    71  		url := requirementConfig.GithubApp.URL + "/installed/" + owner + "/" + repo
    72  
    73  		if url != "" {
    74  			respBody, err := util.CallWithExponentialBackOff(url, "", "GET", []byte{}, nil)
    75  			log.Logger().Debug(string(respBody))
    76  			if err != nil {
    77  				return false, false, "", "", errors.Wrapf(err, "error getting response from github app via %s", url)
    78  			}
    79  
    80  			response := &response{}
    81  
    82  			err = json.Unmarshal(respBody, response)
    83  
    84  			if err != nil {
    85  				return false, false, "", "", errors.Wrapf(err, "error marshalling response %s", url)
    86  			}
    87  			return response.Installed, response.AccessToRepo, response.URL, response.AppName, nil
    88  		}
    89  	}
    90  	return false, false, "", "", errors.New("unable to locate github app ")
    91  }
    92  
    93  func (gh *GithubApp) getRequirementConfig() (*config.RequirementsConfig, error) {
    94  	jxClient, ns, err := gh.Factory.CreateJXClient()
    95  	if err != nil {
    96  		log.Logger().Errorf("error creating jx client %v", err)
    97  		return nil, err
    98  	}
    99  
   100  	teamSettings, err := kube.GetDevEnvTeamSettings(jxClient, ns)
   101  	if err != nil {
   102  		log.Logger().Errorf("error getting team settings from jx client %v", err)
   103  		return nil, err
   104  	}
   105  
   106  	requirementConfig, err := config.GetRequirementsConfigFromTeamSettings(teamSettings)
   107  	if err != nil {
   108  		log.Logger().Errorf("error getting requirement config from team settings %v", err)
   109  		return nil, err
   110  	}
   111  	return requirementConfig, nil
   112  }