github.com/aigarnetwork/aigar@v0.0.0-20191115204914-d59a6eb70f8e/internal/build/env.go (about)

     1  //  Copyright 2018 The go-ethereum Authors
     2  //  Copyright 2019 The go-aigar Authors
     3  //  This file is part of the go-aigar library.
     4  //
     5  //  The go-aigar library is free software: you can redistribute it and/or modify
     6  //  it under the terms of the GNU Lesser General Public License as published by
     7  //  the Free Software Foundation, either version 3 of the License, or
     8  //  (at your option) any later version.
     9  //
    10  //  The go-aigar library is distributed in the hope that it will be useful,
    11  //  but WITHOUT ANY WARRANTY; without even the implied warranty of
    12  //  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
    13  //  GNU Lesser General Public License for more details.
    14  //
    15  //  You should have received a copy of the GNU Lesser General Public License
    16  //  along with the go-aigar library. If not, see <http://www.gnu.org/licenses/>.
    17  
    18  package build
    19  
    20  import (
    21  	"flag"
    22  	"fmt"
    23  	"os"
    24  	"regexp"
    25  	"strconv"
    26  	"strings"
    27  	"time"
    28  )
    29  
    30  var (
    31  	// These flags override values in build env.
    32  	GitCommitFlag   = flag.String("git-commit", "", `Overrides git commit hash embedded into executables`)
    33  	GitBranchFlag   = flag.String("git-branch", "", `Overrides git branch being built`)
    34  	GitTagFlag      = flag.String("git-tag", "", `Overrides git tag being built`)
    35  	BuildnumFlag    = flag.String("buildnum", "", `Overrides CI build number`)
    36  	PullRequestFlag = flag.Bool("pull-request", false, `Overrides pull request status of the build`)
    37  	CronJobFlag     = flag.Bool("cron-job", false, `Overrides cron job status of the build`)
    38  )
    39  
    40  // Environment contains metadata provided by the build environment.
    41  type Environment struct {
    42  	Name                      string // name of the environment
    43  	Repo                      string // name of GitHub repo
    44  	Commit, Date, Branch, Tag string // Git info
    45  	Buildnum                  string
    46  	IsPullRequest             bool
    47  	IsCronJob                 bool
    48  }
    49  
    50  func (env Environment) String() string {
    51  	return fmt.Sprintf("%s env (commit:%s date:%s branch:%s tag:%s buildnum:%s pr:%t)",
    52  		env.Name, env.Commit, env.Date, env.Branch, env.Tag, env.Buildnum, env.IsPullRequest)
    53  }
    54  
    55  // Env returns metadata about the current CI environment, falling back to LocalEnv
    56  // if not running on CI.
    57  func Env() Environment {
    58  	switch {
    59  	case os.Getenv("CI") == "true" && os.Getenv("TRAVIS") == "true":
    60  		commit := os.Getenv("TRAVIS_PULL_REQUEST_SHA")
    61  		if commit == "" {
    62  			commit = os.Getenv("TRAVIS_COMMIT")
    63  		}
    64  		return Environment{
    65  			Name:          "travis",
    66  			Repo:          os.Getenv("TRAVIS_REPO_SLUG"),
    67  			Commit:        commit,
    68  			Date:          getDate(commit),
    69  			Branch:        os.Getenv("TRAVIS_BRANCH"),
    70  			Tag:           os.Getenv("TRAVIS_TAG"),
    71  			Buildnum:      os.Getenv("TRAVIS_BUILD_NUMBER"),
    72  			IsPullRequest: os.Getenv("TRAVIS_PULL_REQUEST") != "false",
    73  			IsCronJob:     os.Getenv("TRAVIS_EVENT_TYPE") == "cron",
    74  		}
    75  	case os.Getenv("CI") == "True" && os.Getenv("APPVEYOR") == "True":
    76  		commit := os.Getenv("APPVEYOR_PULL_REQUEST_HEAD_COMMIT")
    77  		if commit == "" {
    78  			commit = os.Getenv("APPVEYOR_REPO_COMMIT")
    79  		}
    80  		return Environment{
    81  			Name:          "appveyor",
    82  			Repo:          os.Getenv("APPVEYOR_REPO_NAME"),
    83  			Commit:        commit,
    84  			Date:          getDate(commit),
    85  			Branch:        os.Getenv("APPVEYOR_REPO_BRANCH"),
    86  			Tag:           os.Getenv("APPVEYOR_REPO_TAG_NAME"),
    87  			Buildnum:      os.Getenv("APPVEYOR_BUILD_NUMBER"),
    88  			IsPullRequest: os.Getenv("APPVEYOR_PULL_REQUEST_NUMBER") != "",
    89  			IsCronJob:     os.Getenv("APPVEYOR_SCHEDULED_BUILD") == "True",
    90  		}
    91  	default:
    92  		return LocalEnv()
    93  	}
    94  }
    95  
    96  // LocalEnv returns build environment metadata gathered from git.
    97  func LocalEnv() Environment {
    98  	env := applyEnvFlags(Environment{Name: "local", Repo: "AigarNetwork/aigar"})
    99  
   100  	head := readGitFile("HEAD")
   101  	if fields := strings.Fields(head); len(fields) == 2 {
   102  		head = fields[1]
   103  	} else {
   104  		// In this case we are in "detached head" state
   105  		// see: https://git-scm.com/docs/git-checkout#_detached_head
   106  		// Additional check required to verify, that file contains commit hash
   107  		commitRe, _ := regexp.Compile("^([0-9a-f]{40})$")
   108  		if commit := commitRe.FindString(head); commit != "" && env.Commit == "" {
   109  			env.Commit = commit
   110  		}
   111  		return env
   112  	}
   113  	if env.Commit == "" {
   114  		env.Commit = readGitFile(head)
   115  	}
   116  	env.Date = getDate(env.Commit)
   117  	if env.Branch == "" {
   118  		if head != "HEAD" {
   119  			env.Branch = strings.TrimPrefix(head, "refs/heads/")
   120  		}
   121  	}
   122  	if info, err := os.Stat(".git/objects"); err == nil && info.IsDir() && env.Tag == "" {
   123  		env.Tag = firstLine(RunGit("tag", "-l", "--points-at", "HEAD"))
   124  	}
   125  	return env
   126  }
   127  
   128  func firstLine(s string) string {
   129  	return strings.Split(s, "\n")[0]
   130  }
   131  
   132  func getDate(commit string) string {
   133  	if commit == "" {
   134  		return ""
   135  	}
   136  	out := RunGit("show", "-s", "--format=%ct", commit)
   137  	if out == "" {
   138  		return ""
   139  	}
   140  	date, err := strconv.ParseInt(strings.TrimSpace(out), 10, 64)
   141  	if err != nil {
   142  		panic(fmt.Sprintf("failed to parse git commit date: %v", err))
   143  	}
   144  	return time.Unix(date, 0).Format("20060102")
   145  }
   146  
   147  func applyEnvFlags(env Environment) Environment {
   148  	if !flag.Parsed() {
   149  		panic("you need to call flag.Parse before Env or LocalEnv")
   150  	}
   151  	if *GitCommitFlag != "" {
   152  		env.Commit = *GitCommitFlag
   153  	}
   154  	if *GitBranchFlag != "" {
   155  		env.Branch = *GitBranchFlag
   156  	}
   157  	if *GitTagFlag != "" {
   158  		env.Tag = *GitTagFlag
   159  	}
   160  	if *BuildnumFlag != "" {
   161  		env.Buildnum = *BuildnumFlag
   162  	}
   163  	if *PullRequestFlag {
   164  		env.IsPullRequest = true
   165  	}
   166  	if *CronJobFlag {
   167  		env.IsCronJob = true
   168  	}
   169  	return env
   170  }