github.com/khulnasoft/codebase@v0.0.0-20231214144635-a707781cbb24/cienv/github_actions.go (about)

     1  package cienv
     2  
     3  import (
     4  	"encoding/json"
     5  	"errors"
     6  	"os"
     7  )
     8  
     9  // https://docs.github.com/en/actions/reference/environment-variables#default-environment-variables
    10  type GitHubEvent struct {
    11  	PullRequest GitHubPullRequest `json:"pull_request"`
    12  	Repository  struct {
    13  		Owner struct {
    14  			Login string `json:"login"`
    15  		} `json:"owner"`
    16  		Name string `json:"name"`
    17  	} `json:"repository"`
    18  	CheckSuite struct {
    19  		After        string              `json:"after"`
    20  		PullRequests []GitHubPullRequest `json:"pull_requests"`
    21  	} `json:"check_suite"`
    22  	HeadCommit struct {
    23  		ID string `json:"id"`
    24  	} `json:"head_commit"`
    25  	ActionName string `json:"-"` // this is defined as env GITHUB_EVENT_NAME
    26  }
    27  
    28  type GitHubRepo struct {
    29  	Owner struct {
    30  		ID int64 `json:"id"`
    31  	}
    32  }
    33  
    34  type GitHubPullRequest struct {
    35  	Number int `json:"number"`
    36  	Head   struct {
    37  		Sha  string     `json:"sha"`
    38  		Ref  string     `json:"ref"`
    39  		Repo GitHubRepo `json:"repo"`
    40  	} `json:"head"`
    41  	Base struct {
    42  		Repo GitHubRepo `json:"repo"`
    43  	} `json:"base"`
    44  }
    45  
    46  // LoadGitHubEvent loads GitHubEvent if it's running in GitHub Actions.
    47  func LoadGitHubEvent() (*GitHubEvent, error) {
    48  	eventPath := os.Getenv("GITHUB_EVENT_PATH")
    49  	if eventPath == "" {
    50  		return nil, errors.New("GITHUB_EVENT_PATH not found")
    51  	}
    52  	return loadGitHubEventFromPath(eventPath)
    53  }
    54  
    55  func loadGitHubEventFromPath(eventPath string) (*GitHubEvent, error) {
    56  	f, err := os.Open(eventPath)
    57  	if err != nil {
    58  		return nil, err
    59  	}
    60  	defer f.Close()
    61  	var event GitHubEvent
    62  	if err := json.NewDecoder(f).Decode(&event); err != nil {
    63  		return nil, err
    64  	}
    65  	event.ActionName = os.Getenv("GITHUB_EVENT_NAME")
    66  	return &event, nil
    67  }
    68  
    69  func getBuildInfoFromGitHubAction() (*BuildInfo, bool, error) {
    70  	eventPath := os.Getenv("GITHUB_EVENT_PATH")
    71  	if eventPath == "" {
    72  		return nil, false, errors.New("GITHUB_EVENT_PATH not found")
    73  	}
    74  	return getBuildInfoFromGitHubActionEventPath(eventPath)
    75  }
    76  func getBuildInfoFromGitHubActionEventPath(eventPath string) (*BuildInfo, bool, error) {
    77  	event, err := loadGitHubEventFromPath(eventPath)
    78  	if err != nil {
    79  		return nil, false, err
    80  	}
    81  	info := &BuildInfo{
    82  		Owner:       event.Repository.Owner.Login,
    83  		Repo:        event.Repository.Name,
    84  		PullRequest: event.PullRequest.Number,
    85  		Branch:      event.PullRequest.Head.Ref,
    86  		SHA:         event.PullRequest.Head.Sha,
    87  	}
    88  	// For re-run check_suite event.
    89  	if info.PullRequest == 0 && len(event.CheckSuite.PullRequests) > 0 {
    90  		pr := event.CheckSuite.PullRequests[0]
    91  		info.PullRequest = pr.Number
    92  		info.Branch = pr.Head.Ref
    93  		info.SHA = pr.Head.Sha
    94  	}
    95  	if info.SHA == "" {
    96  		info.SHA = event.HeadCommit.ID
    97  	}
    98  	if info.SHA == "" {
    99  		info.SHA = os.Getenv("GITHUB_SHA")
   100  	}
   101  	return info, info.PullRequest != 0, nil
   102  }
   103  
   104  // IsInGitHubAction returns true if codebase is running in GitHub Actions.
   105  func IsInGitHubAction() bool {
   106  	// https://docs.github.com/en/actions/learn-github-actions/variables#default-environment-variables
   107  	// > Always set to true when GitHub Actions is running the workflow.
   108  	// > You can use this variable to differentiate when tests are being run locally or by GitHub Actions.
   109  	return os.Getenv("GITHUB_ACTIONS") != ""
   110  }
   111  
   112  // HasReadOnlyPermissionGitHubToken returns true if codebase is running in GitHub
   113  // Actions and running for PullRequests from forked repository with read-only token.
   114  // https://docs.github.com/en/actions/reference/events-that-trigger-workflows#pull_request_target
   115  func HasReadOnlyPermissionGitHubToken() bool {
   116  	event, err := LoadGitHubEvent()
   117  	if err != nil {
   118  		return false
   119  	}
   120  	isForkedRepo := event.PullRequest.Head.Repo.Owner.ID != event.PullRequest.Base.Repo.Owner.ID
   121  	return isForkedRepo && event.ActionName != "pull_request_target"
   122  }