github.com/vipcoin-gold/reviewdog@v1.0.2/cienv/cienv.go (about)

     1  // Package cienv provides utility for environment variable in CI services.
     2  package cienv
     3  
     4  import (
     5  	"errors"
     6  	"os"
     7  	"regexp"
     8  	"strconv"
     9  	"strings"
    10  )
    11  
    12  // BuildInfo represents build information about GitHub or GitLab project.
    13  type BuildInfo struct {
    14  	Owner string
    15  	Repo  string
    16  	SHA   string
    17  
    18  	// Optional.
    19  	PullRequest int // MergeRequest for GitLab.
    20  
    21  	// Optional.
    22  	Branch string
    23  
    24  	// Gerrit related params
    25  	GerritChangeID   string
    26  	GerritRevisionID string
    27  }
    28  
    29  // GetBuildInfo returns BuildInfo from environment variables.
    30  //
    31  // Supported CI services' documents:
    32  // - Travis CI: https://docs.travis-ci.com/user/environment-variables/
    33  // - Circle CI: https://circleci.com/docs/environment-variables/
    34  // - Drone.io: http://docs.drone.io/environment-reference/
    35  // - GitLab CI: https://docs.gitlab.com/ee/ci/variables/#predefined-variables-environment-variables
    36  // - GitLab CI doesn't export ID of Merge Request. https://gitlab.com/gitlab-org/gitlab-ce/issues/15280
    37  func GetBuildInfo() (prInfo *BuildInfo, isPR bool, err error) {
    38  	if IsInGitHubAction() {
    39  		return getBuildInfoFromGitHubAction()
    40  	}
    41  	owner, repo := getOwnerAndRepoFromSlug([]string{
    42  		"TRAVIS_REPO_SLUG",
    43  		"DRONE_REPO", // drone<=0.4
    44  		"BITBUCKET_REPO_FULL_NAME",
    45  	})
    46  	if owner == "" {
    47  		owner = getOneEnvValue([]string{
    48  			"CI_REPO_OWNER", // common
    49  			"CIRCLE_PROJECT_USERNAME",
    50  			"DRONE_REPO_OWNER",
    51  			"CI_PROJECT_NAMESPACE", // GitLab CI
    52  		})
    53  	}
    54  	if owner == "" {
    55  		return nil, false, errors.New("cannot get repo owner from environment variable. Set CI_REPO_OWNER?")
    56  	}
    57  
    58  	if repo == "" {
    59  		repo = getOneEnvValue([]string{
    60  			"CI_REPO_NAME", // common
    61  			"CIRCLE_PROJECT_REPONAME",
    62  			"DRONE_REPO_NAME",
    63  			"CI_PROJECT_NAME", // GitLab CI
    64  		})
    65  	}
    66  
    67  	if repo == "" {
    68  		return nil, false, errors.New("cannot get repo name from environment variable. Set CI_REPO_NAME?")
    69  	}
    70  
    71  	sha := getOneEnvValue([]string{
    72  		"CI_COMMIT", // common
    73  		"TRAVIS_PULL_REQUEST_SHA",
    74  		"TRAVIS_COMMIT",
    75  		"CIRCLE_SHA1",
    76  		"DRONE_COMMIT",
    77  		"CI_COMMIT_SHA", // GitLab CI
    78  		"BITBUCKET_COMMIT",
    79  	})
    80  	if sha == "" {
    81  		return nil, false, errors.New("cannot get commit SHA from environment variable. Set CI_COMMIT?")
    82  	}
    83  
    84  	branch := getOneEnvValue([]string{
    85  		"CI_BRANCH", // common
    86  		"TRAVIS_PULL_REQUEST_BRANCH",
    87  		"CIRCLE_BRANCH",
    88  		"DRONE_COMMIT_BRANCH",
    89  		// present only if PR pipeline
    90  		"BITBUCKET_PR_DESTINATION_BRANCH",
    91  		"BITBUCKET_BRANCH",
    92  	})
    93  
    94  	pr := getPullRequestNum()
    95  
    96  	return &BuildInfo{
    97  		Owner:       owner,
    98  		Repo:        repo,
    99  		PullRequest: pr,
   100  		SHA:         sha,
   101  		Branch:      branch,
   102  	}, pr != 0, nil
   103  }
   104  
   105  // GetGerritBuildInfo returns Gerrit specific build info
   106  func GetGerritBuildInfo() (*BuildInfo, error) {
   107  	changeID := os.Getenv("GERRIT_CHANGE_ID")
   108  	if changeID == "" {
   109  		return nil, errors.New("cannot get change id from environment variable. Set GERRIT_CHANGE_ID ?")
   110  	}
   111  
   112  	revisionID := os.Getenv("GERRIT_REVISION_ID")
   113  	if revisionID == "" {
   114  		return nil, errors.New("cannot get revision id from environment variable. Set GERRIT_REVISION_ID ?")
   115  	}
   116  
   117  	branch := os.Getenv("GERRIT_BRANCH")
   118  	if branch == "" {
   119  		return nil, errors.New("cannot get branch from environment variable. Set GERRIT_BRANCH ?")
   120  	}
   121  
   122  	return &BuildInfo{
   123  		GerritChangeID:   changeID,
   124  		GerritRevisionID: revisionID,
   125  		Branch:           branch,
   126  	}, nil
   127  }
   128  
   129  func getPullRequestNum() int {
   130  	envs := []string{
   131  		// Common.
   132  		"CI_PULL_REQUEST",
   133  		// Travis CI.
   134  		"TRAVIS_PULL_REQUEST",
   135  		// Circle CI.
   136  		"CIRCLE_PULL_REQUEST", // CircleCI 2.0
   137  		"CIRCLE_PR_NUMBER",    // For Pull Request by a fork repository
   138  		// drone.io.
   139  		"DRONE_PULL_REQUEST",
   140  		// GitLab CI MergeTrains
   141  		"CI_MERGE_REQUEST_IID",
   142  		"BITBUCKET_PR_ID",
   143  	}
   144  	// regexp.MustCompile() in func intentionally because this func is called
   145  	// once for one run.
   146  	re := regexp.MustCompile(`[1-9]\d*$`)
   147  	for _, env := range envs {
   148  		prm := re.FindString(os.Getenv(env))
   149  		pr, _ := strconv.Atoi(prm)
   150  		if pr != 0 {
   151  			return pr
   152  		}
   153  	}
   154  	return 0
   155  }
   156  
   157  func getOneEnvValue(envs []string) string {
   158  	for _, env := range envs {
   159  		if v := os.Getenv(env); v != "" {
   160  			return v
   161  		}
   162  	}
   163  	return ""
   164  }
   165  
   166  func getOwnerAndRepoFromSlug(slugEnvs []string) (string, string) {
   167  	repoSlug := getOneEnvValue(slugEnvs)
   168  	ownerAndRepo := strings.SplitN(repoSlug, "/", 2)
   169  	if len(ownerAndRepo) < 2 {
   170  		return "", ""
   171  	}
   172  	return ownerAndRepo[0], ownerAndRepo[1]
   173  }