Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
15 changes: 15 additions & 0 deletions internal/github/data.go
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ package github

import (
"errors"
"os"

"github.com/rh-ecosystem-edge/gitstream/internal/process"
)
Expand All @@ -14,6 +15,7 @@ type Commit struct {
type BaseData struct {
AppName string
Commit Commit
JobID string
Markup string
UpstreamURL string
}
Expand All @@ -34,3 +36,16 @@ func (is *IssueData) ProcessError() *process.Error {
}

type PRData BaseData

// GetJobID returns the Job ID from environment variables.
// It first tries GITHUB_RUN_ID (GitHub Actions), then falls back to JOB_ID (generic CI).
// Returns empty string if no Job ID is found.
func GetJobID() string {
if jobID, exists := os.LookupEnv("GITHUB_RUN_ID"); exists && jobID != "" {
return jobID
}
if jobID, exists := os.LookupEnv("JOB_ID"); exists && jobID != "" {
return jobID
}
return ""
}
65 changes: 65 additions & 0 deletions internal/github/data_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,65 @@
package github

import (
"os"
"testing"

"github.com/stretchr/testify/assert"
)

func TestGetJobID(t *testing.T) {
tests := []struct {
name string
githubRunID string
jobID string
expectedResult string
}{
{
name: "GitHub Actions environment",
githubRunID: "12345678",
jobID: "",
expectedResult: "12345678",
},
{
name: "Generic CI environment",
githubRunID: "",
jobID: "ci-job-987",
expectedResult: "ci-job-987",
},
{
name: "GitHub Actions takes precedence",
githubRunID: "github-123",
jobID: "generic-456",
expectedResult: "github-123",
},
{
name: "No job ID available",
githubRunID: "",
jobID: "",
expectedResult: "",
},
}

for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
// Clear environment variables
os.Unsetenv("GITHUB_RUN_ID")
os.Unsetenv("JOB_ID")

// Set test environment variables
if tt.githubRunID != "" {
os.Setenv("GITHUB_RUN_ID", tt.githubRunID)
}
if tt.jobID != "" {
os.Setenv("JOB_ID", tt.jobID)
}

result := GetJobID()
assert.Equal(t, tt.expectedResult, result)

// Clean up
os.Unsetenv("GITHUB_RUN_ID")
os.Unsetenv("JOB_ID")
})
}
}
1 change: 1 addition & 0 deletions internal/github/issue.go
Original file line number Diff line number Diff line change
Expand Up @@ -42,6 +42,7 @@ func (ih *IssueHelperImpl) Create(ctx context.Context, err error, upstreamURL st
Message: commit.Message,
SHA: sha,
},
JobID: GetJobID(),
Markup: ih.markup,
UpstreamURL: upstreamURL,
},
Expand Down
79 changes: 79 additions & 0 deletions internal/github/issue_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ import (
"errors"
"fmt"
"net/http"
"os"
"os/exec"
"testing"

Expand All @@ -20,6 +21,14 @@ import (
)

func TestIssueHelper_Create(t *testing.T) {
// Clear any existing job ID environment variables for consistent testing
os.Unsetenv("GITHUB_RUN_ID")
os.Unsetenv("JOB_ID")
defer func() {
os.Unsetenv("GITHUB_RUN_ID")
os.Unsetenv("JOB_ID")
}()

const expectedTitle = "Cherry-picking error for `e3229f3c533ed51070beff092e5c7694a8ee81f0`"

issue := &github.Issue{Number: github.Int(456)}
Expand Down Expand Up @@ -161,6 +170,76 @@ func TestIssueHelper_Create(t *testing.T) {
})
}

func TestIssueHelper_CreateWithJobID(t *testing.T) {
// Set job ID environment variable
testJobID := "test-job-123"
os.Setenv("GITHUB_RUN_ID", testJobID)
defer os.Unsetenv("GITHUB_RUN_ID")

const expectedTitle = "Cherry-picking error for `e3229f3c533ed51070beff092e5c7694a8ee81f0`"

issue := &github.Issue{Number: github.Int(456)}
repoName := &gh.RepoName{Owner: "owner", Repo: "repo"}

commit := &object.Commit{
Hash: plumbing.NewHash("e3229f3c533ed51070beff092e5c7694a8ee81f0"),
Message: "Some commit message\nspanning over two lines.",
}

t.Run("regular error with job ID", func(t *testing.T) {
expectedBodyWithJobID := "gitstream tried to cherry-pick commit `e3229f3c533ed51070beff092e5c7694a8ee81f0` from `some-upstream-url` but was unable to do so.\n" +
"\n" +
"**Job ID**: " + testJobID + "\n\n" +
"Commit message:\n" +
"```\n" +
"Some commit message\n" +
"spanning over two lines.\n" +
"```\n\n" +
"Please cherry-pick the commit manually.\n\n" +
"---\n\n" +
"**Error**:\n" +
"```\n" +
"random error\n" +
"```\n\n\n" +
"---\n\n" +
"Markup: e3229f3c533ed51070beff092e5c7694a8ee81f0"

c := mock.NewMockedHTTPClient(
mock.WithRequestMatchHandler(
mock.PostReposIssuesByOwnerByRepo,
http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
m := make(map[string]interface{})

assert.NoError(
t,
json.NewDecoder(r.Body).Decode(&m),
)

assert.Equal(t, expectedBodyWithJobID, m["body"])
assert.Equal(t, expectedTitle, m["title"])
assert.Contains(t, m["labels"], "gitstream")
assert.NoError(
t,
json.NewEncoder(w).Encode(issue),
)
}),
),
)

gc := github.NewClient(c)

res, err := gh.NewIssueHelper(gc, "Markup", repoName).Create(
context.Background(),
errors.New("random error"),
"some-upstream-url",
commit,
)

assert.NoError(t, err)
assert.Equal(t, issue, res)
})
}

func TestIssueHelper_Assign(t *testing.T) {

issue := &github.Issue{Number: github.Int(456)}
Expand Down
1 change: 1 addition & 0 deletions internal/github/pr.go
Original file line number Diff line number Diff line change
Expand Up @@ -48,6 +48,7 @@ func (ph *PRHelperImpl) Create(ctx context.Context, branch, base, upstreamURL st
Message: commit.Message,
SHA: sha,
},
JobID: GetJobID(),
Markup: ph.markup,
UpstreamURL: upstreamURL,
}
Expand Down
97 changes: 97 additions & 0 deletions internal/github/pr_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ import (
"encoding/json"
"fmt"
"net/http"
"os"
"testing"

"github.com/go-git/go-git/v5/plumbing"
Expand All @@ -16,6 +17,14 @@ import (
)

func TestPRHelperImpl_Create(t *testing.T) {
// Clear any existing job ID environment variables for consistent testing
os.Unsetenv("GITHUB_RUN_ID")
os.Unsetenv("JOB_ID")
defer func() {
os.Unsetenv("GITHUB_RUN_ID")
os.Unsetenv("JOB_ID")
}()

const (
draft = true
expectedBody = "This is an automated cherry-pick by gitstream of `e3229f3c533ed51070beff092e5c7694a8ee81f0` from `some-upstream-url`.\n\n" +
Expand Down Expand Up @@ -95,3 +104,91 @@ func TestPRHelperImpl_Create(t *testing.T) {
assert.NoError(t, err)
assert.Equal(t, pr, res)
}

func TestPRHelperImpl_CreateWithJobID(t *testing.T) {
// Set job ID environment variable
testJobID := "test-job-123"
os.Setenv("GITHUB_RUN_ID", testJobID)
defer os.Unsetenv("GITHUB_RUN_ID")

const (
draft = true
expectedTitle = "Cherry-pick `e3229f3c533ed51070beff092e5c7694a8ee81f0` from upstream"
owner = "owner"
prNumber = 456
repo = "repo"
)

expectedBodyWithJobID := "This is an automated cherry-pick by gitstream of `e3229f3c533ed51070beff092e5c7694a8ee81f0` from `some-upstream-url`.\n\n" +
"**Job ID**: " + testJobID + "\n\n" +
"Commit message:\n" +
"```\n" +
"Some commit message\n" +
"spreading over two lines.\n" +
"```\n\n" +
"---\n\n" +
"Markup: e3229f3c533ed51070beff092e5c7694a8ee81f0"

pr := &github.PullRequest{
Number: github.Int(prNumber),
}

c := mock.NewMockedHTTPClient(
mock.WithRequestMatchHandler(
mock.PostReposPullsByOwnerByRepo,
http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
m := make(map[string]interface{})

assert.NoError(
t,
json.NewDecoder(r.Body).Decode(&m),
)

assert.Equal(t, expectedBodyWithJobID, m["body"])
assert.Equal(t, expectedTitle, m["title"])
assert.Equal(t, draft, m["draft"])

assert.NoError(
t,
json.NewEncoder(w).Encode(pr),
)
}),
),
mock.WithRequestMatchHandler(
mock.PostReposIssuesLabelsByOwnerByRepoByIssueNumber,
http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
m := make([]string, 0)

assert.NoError(
t,
json.NewDecoder(r.Body).Decode(&m),
)

assert.Equal(
t,
fmt.Sprintf("/repos/%s/%s/issues/%d/labels", owner, repo, prNumber),
r.RequestURI,
)

assert.Equal(t, []string{"gitstream"}, m)
}),
),
)

gc := github.NewClient(c)

res, err := gh.NewPRHelper(gc, nil, "Markup", &gh.RepoName{Owner: owner, Repo: repo}).Create(
context.Background(),
"some-branch",
"main",
"some-upstream-url",
&object.Commit{
Hash: plumbing.NewHash("e3229f3c533ed51070beff092e5c7694a8ee81f0"),
Message: "Some commit message\nspreading over two lines.",
},
draft,
)

assert.NoError(t, err)
assert.Equal(t, pr, res)
}
4 changes: 4 additions & 0 deletions internal/github/templates/issue.tmpl
Original file line number Diff line number Diff line change
@@ -1,5 +1,9 @@
{{- /*gotype: github.com/rh-ecosystem-edge/gitstream/internal/github.IssueData*/ -}}
{{ .AppName }} tried to cherry-pick commit `{{ .Commit.SHA }}` from `{{ .UpstreamURL }}` but was unable to do so.
{{- if .JobID }}

**Job ID**: {{ .JobID }}
{{- end }}

Commit message:
```
Expand Down
4 changes: 4 additions & 0 deletions internal/github/templates/pr.tmpl
Original file line number Diff line number Diff line change
@@ -1,5 +1,9 @@
{{- /*gotype: github.com/rh-ecosystem-edge/gitstream/internal/github.PRData*/ -}}
This is an automated cherry-pick by {{ .AppName }} of `{{ .Commit.SHA }}` from `{{ .UpstreamURL }}`.
{{- if .JobID }}

**Job ID**: {{ .JobID }}
{{- end }}

Commit message:
```
Expand Down
Loading