@@ -11,29 +11,31 @@ import (
1111)
1212
1313// gitGetHead accepts a git directory and returns head commit OID / error
14- func gitGetHead (workspaceDir string ) (string , error ) {
14+ func gitGetHead (workspaceDir string ) (headOID string , warning string , err error ) {
15+ // Check if DeepSource's Test coverage action triggered this first before executing any git commands.
16+ headOID , err = getTestCoverageActionCommit ()
17+ if headOID != "" {
18+ return
19+ }
20+
21+ // get the top commit manually, using git command
22+ headOID , err = fetchHeadManually (workspaceDir )
23+ if err != nil {
24+ fmt .Println (err )
25+ sentry .CaptureException (err )
26+ return
27+ }
28+
1529 // TRAVIS CI
16- // Get USER env variable.
1730 if envUser := os .Getenv ("USER" ); envUser == "travis" {
18- // Travis creates a merge commit for pull requests on forks.
19- // The head of commit is this merge commit, which does not match the commit of deepsource check.
20- // Fetch value of pull request SHA. If this is a PR, it will return SHA of HEAD commit of the PR, else "".
21- // If prSHA is not empty, that means we got an SHA, which is HEAD. Return this.
22- if prSHA := os .Getenv ("TRAVIS_PULL_REQUEST_SHA" ); len (prSHA ) > 0 {
23- return prSHA , nil
24- }
31+ headOID , warning , err = getTravisCommit (headOID )
32+ return
2533 }
2634
2735 // GITHUB ACTIONS
28- // Check if it is a GitHub Action Environment
29- // If it is: then get the HEAD from `GITHUB_SHA` environment
3036 if _ , isGitHubEnv := os .LookupEnv ("GITHUB_ACTIONS" ); isGitHubEnv {
31- // When GITHUB_REF is not set, GITHUB_SHA points to original commit.
32- // When set, it points to the "latest *merge* commit in the branch".
33- // Ref: https://help.github.com/en/actions/reference/events-that-trigger-workflows#pull-request-event-pull_request
34- if _ , isBranchCommit := os .LookupEnv ("GITHUB_REF" ); ! isBranchCommit {
35- return os .Getenv ("GITHUB_SHA" ), nil
36- }
37+ headOID , warning , err = getGitHubActionsCommit (headOID )
38+ return
3739 }
3840
3941 // Check if the `GIT_COMMIT_SHA` environment variable exists. If yes, return this as
@@ -47,18 +49,11 @@ func gitGetHead(workspaceDir string) (string, error) {
4749 // GIT_COMMIT_SHA=$(git --no-pager rev-parse HEAD | tr -d '\n')
4850 // docker run -e DEEPSOURCE_DSN -e GIT_COMMIT_SHA ...
4951 if _ , isManuallyInjectedSHA := os .LookupEnv ("GIT_COMMIT_SHA" ); isManuallyInjectedSHA {
50- return os .Getenv ("GIT_COMMIT_SHA" ), nil
52+ return os .Getenv ("GIT_COMMIT_SHA" ), "" , nil
5153 }
5254
53- // If we are here, it means this is neither GitHub Action on default branch,
54- // nor a travis env with PR. Continue to fetch the headOID via the git command.
55- headOID , err := fetchHeadManually (workspaceDir )
56- if err != nil {
57- fmt .Println (err )
58- sentry .CaptureException (err )
59- return "" , err
60- }
61- return headOID , nil
55+ // If we are here, it means there weren't any special cases. Return the manually found headOID.
56+ return
6257}
6358
6459// Fetches the latest commit hash using the command `git rev-parse HEAD`
@@ -80,3 +75,60 @@ func fetchHeadManually(directoryPath string) (string, error) {
8075 // Trim newline suffix from Commit OID
8176 return strings .TrimSuffix (outStr , "\n " ), nil
8277}
78+
79+ // Handle special cases for GitHub Actions.
80+ func getGitHubActionsCommit (topCommit string ) (headOID string , warning string , err error ) {
81+ // When GITHUB_REF is not set, GITHUB_SHA points to original commit.
82+ // When set, it points to the "latest *merge* commit in the branch".
83+ // Early exit when GITHUB_SHA points to the original commit.
84+ // Ref: https://help.github.com/en/actions/reference/events-that-trigger-workflows#pull-request-event-pull_request
85+ if _ , isRefPresent := os .LookupEnv ("GITHUB_REF" ); ! isRefPresent {
86+ headOID = os .Getenv ("GITHUB_SHA" )
87+ return
88+ }
89+
90+ // Case: Detect Merge commit made by GitHub Actions, which pull_request events are nutorious to make.
91+ // We are anyways going to return `headOID` fetched manually, but want to warn users about the merge commit.
92+
93+ // When ref is not provided during the checkout step, headOID would be the same as GITHUB_SHA
94+ // This confirms the merge commit.
95+ // event names where GITHUB_SHA would be of a merge commit:
96+ // "pull_request",
97+ // "pull_request_review",
98+ // "pull_request_review",
99+ // "pull_request_review_comment",
100+ eventName := os .Getenv ("GITHUB_EVENT_NAME" )
101+ eventCommitSha := os .Getenv ("GITHUB_SHA" )
102+ if strings .HasPrefix (eventName , "pull_request" ) && topCommit == eventCommitSha {
103+ warning = "Warning: Looks like the checkout step is making a merge commit. " +
104+ "Test coverage Analyzer would not run for the reported artifact because the merge commit doesn't exist upstream.\n " +
105+ "Please refer to the docs for required changes. Ref: https://docs.deepsource.com/docs/analyzers-test-coverage#with-github-actions"
106+ }
107+ headOID = topCommit
108+ return
109+ }
110+
111+ // Return PR's HEAD ref set as env variable manually by DeepSource's Test coverage action.
112+ func getTestCoverageActionCommit () (headOID string , err error ) {
113+ // This is kept separate from `getGitHubActionsCommit` because we don't want to run any git command manually
114+ // before this is checked. Since this is guaranteed to be set if artifact is sent using our GitHub action,
115+ // we can reliably send the commit SHA, and no git commands are executed, making the actions work all the time. \o/
116+
117+ // We are setting PR's head commit as default using github context as env variable: "GHA_HEAD_COMMIT_SHA"
118+ headOID = os .Getenv ("GHA_HEAD_COMMIT_SHA" )
119+
120+ return
121+ }
122+
123+ // Handle special case for TravisCI
124+ func getTravisCommit (topCommit string ) (string , string , error ) {
125+ // Travis creates a merge commit for pull requests on forks.
126+ // The head of commit is this merge commit, which does not match the commit of deepsource check.
127+ // Fetch value of pull request SHA. If this is a PR, it will return SHA of HEAD commit of the PR, else "".
128+ // If prSHA is not empty, that means we got an SHA, which is HEAD. Return this.
129+ if prSHA := os .Getenv ("TRAVIS_PULL_REQUEST_SHA" ); len (prSHA ) > 0 {
130+ return prSHA , "" , nil
131+ }
132+
133+ return topCommit , "" , nil
134+ }
0 commit comments