Skip to content

Commit 336e6e3

Browse files
committed
Make backport action accept PR as input instead of using event info
1 parent 5a34130 commit 336e6e3

File tree

4 files changed

+167
-53
lines changed

4 files changed

+167
-53
lines changed

backport/action.yml

Lines changed: 32 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -13,21 +13,38 @@ inputs:
1313
path:
1414
required: false
1515
default: "."
16+
pr_label:
17+
description: If specified, the backport will only be created for this label
18+
required: false
19+
pr_number:
20+
description: The number of the PR to backport
21+
required: false
22+
repo_owner:
23+
description: The owner of the repository the PR is in
24+
required: false
25+
repo_name:
26+
description: The name of the repository the PR is in
27+
required: false
28+
1629
runs:
1730
using: composite
1831
steps:
19-
- shell: bash
20-
env:
21-
GITHUB_TOKEN: ${{inputs.token}}
22-
RELEASE_TAG: ${{inputs.binary_release_tag}}
23-
INPUT_LABELS_TO_ADD: ${{inputs.labels_to_add}}
24-
PR: ${{inputs.pr}}
25-
DIR: ${{ inputs.path }}
26-
run: |
27-
set -e
28-
# Download the action from the store
29-
curl --fail -L -o /tmp/backport https://github.com/grafana/grafana-github-actions-go/releases/download/${RELEASE_TAG}/backport
30-
chmod +x /tmp/backport
31-
cd $DIR
32-
# Execute action
33-
/tmp/backport ${PR}
32+
- shell: bash
33+
env:
34+
GITHUB_TOKEN: ${{inputs.token}}
35+
RELEASE_TAG: ${{inputs.binary_release_tag}}
36+
INPUT_LABELS_TO_ADD: ${{inputs.labels_to_add}}
37+
PR: ${{inputs.pr}}
38+
DIR: ${{ inputs.path }}
39+
PR_LABEL: ${{ inputs.pr_label }}
40+
PR_NUMBER: ${{ inputs.pr_number }}
41+
REPO_OWNER: ${{ inputs.repo_owner }}
42+
REPO_NAME: ${{ inputs.repo_name }}
43+
run: |
44+
set -e
45+
# Download the action from the store
46+
curl --fail -L -o /tmp/backport https://github.com/grafana/grafana-github-actions-go/releases/download/${RELEASE_TAG}/backport
47+
chmod +x /tmp/backport
48+
cd $DIR
49+
# Execute action
50+
/tmp/backport ${PR}

backport/main.go

Lines changed: 23 additions & 26 deletions
Original file line numberDiff line numberDiff line change
@@ -47,35 +47,30 @@ func main() {
4747
}
4848

4949
var (
50-
ctx = context.Background()
51-
token = os.Getenv("GITHUB_TOKEN")
52-
client = github.NewTokenClient(ctx, token)
53-
inputs = GetInputs()
54-
payload = &github.PullRequestTargetEvent{}
50+
ctx = context.Background()
51+
token = os.Getenv("GITHUB_TOKEN")
52+
client = github.NewTokenClient(ctx, token)
53+
inputs = GetInputs()
5554
)
5655

5756
if token == "" {
5857
panic("token can not be empty")
5958
}
6059

61-
if err := UnmarshalEventData(ghctx, &payload); err != nil {
62-
log.Error("error reading github payload", "error", err)
60+
prInfo, err := GetBackportPrInfo(ctx, client, ghctx)
61+
if err != nil {
62+
log.Error("error getting PR info", "error", err)
6363
panic(err)
6464
}
6565

66-
var (
67-
owner = payload.GetRepo().GetOwner().GetLogin()
68-
repo = payload.GetRepo().GetName()
69-
)
70-
71-
log = log.With("pull_request", payload.GetNumber())
72-
branches, err := ghutil.GetReleaseBranches(ctx, client.Repositories, owner, repo)
66+
log = log.With("pull_request", prInfo.Pr.Number)
67+
branches, err := ghutil.GetReleaseBranches(ctx, client.Repositories, prInfo.RepoOwner, prInfo.RepoName)
7368
if err != nil {
7469
log.Error("error getting branches", "error", err)
7570
panic(err)
7671
}
7772

78-
targets, err := BackportTargetsFromPayload(branches, payload)
73+
targets, err := BackportTargetsFromPayload(branches, prInfo)
7974
if err != nil {
8075
if errors.Is(err, ErrorNotMerged) {
8176
log.Warn("pull request is not merged; nothing to do")
@@ -88,28 +83,30 @@ func main() {
8883

8984
for _, target := range targets {
9085
log := log.With("target", target)
91-
mergeBase, err := MergeBase(ctx, client.Repositories, owner, repo, target.Name, *payload.GetPullRequest().Base.Ref)
86+
mergeBase, err := MergeBase(ctx, client.Repositories, prInfo.RepoOwner, prInfo.RepoName, target.Name, prInfo.Pr.GetBase().GetRef())
9287
if err != nil {
9388
log.Error("error finding merge-base", "error", err)
9489
}
9590

9691
opts := BackportOpts{
97-
PullRequestNumber: payload.GetPullRequest().GetNumber(),
98-
SourceSHA: payload.GetPullRequest().GetMergeCommitSHA(),
99-
SourceCommitDate: payload.GetPullRequest().MergedAt.Time,
100-
SourceTitle: payload.GetPullRequest().GetTitle(),
101-
SourceBody: payload.GetPullRequest().GetBody(),
92+
PullRequestNumber: prInfo.Pr.GetNumber(),
93+
SourceSHA: prInfo.Pr.GetMergeCommitSHA(),
94+
SourceCommitDate: prInfo.Pr.GetMergedAt().Time,
95+
SourceTitle: prInfo.Pr.GetTitle(),
96+
SourceBody: prInfo.Pr.GetBody(),
10297
Target: target,
103-
Labels: append(inputs.Labels, payload.GetPullRequest().Labels...),
104-
Owner: owner,
105-
Repository: repo,
98+
Labels: append(inputs.Labels, prInfo.Pr.Labels...),
99+
Owner: prInfo.RepoOwner,
100+
Repository: prInfo.RepoName,
106101
MergeBase: mergeBase,
107102
}
108-
pr, err := Backport(ctx, log, client.PullRequests, client.Issues, client.Issues, NewShellCommandRunner(log), opts)
103+
104+
prOut, err := Backport(ctx, log, client.PullRequests, client.Issues, client.Issues, NewShellCommandRunner(log), opts)
109105
if err != nil {
110106
log.Error("backport failed", "error", err)
111107
continue
112108
}
113-
log.Info("backport successful", "url", pr.GetURL())
109+
110+
log.Info("backport successful", "url", prOut.GetURL())
114111
}
115112
}

backport/pr_info.go

Lines changed: 102 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,102 @@
1+
package main
2+
3+
import (
4+
"context"
5+
"fmt"
6+
"os"
7+
"strconv"
8+
9+
"github.com/google/go-github/v50/github"
10+
"github.com/sethvargo/go-githubactions"
11+
)
12+
13+
type PrInfo struct {
14+
Pr *github.PullRequest
15+
16+
// Contains the relevant labels for the backport.
17+
// When triggered by being labeled, it should be only the applied label.
18+
// When triggered by being closed, it should be all labels on the PR.
19+
Labels []string
20+
21+
RepoOwner string
22+
RepoName string
23+
}
24+
25+
func GetBackportPrInfo(ctx context.Context, client *github.Client, ghctx *githubactions.GitHubContext) (PrInfo, error) {
26+
prLabel := os.Getenv("PR_LABEL")
27+
prNumber, _ := strconv.Atoi(os.Getenv("PR_NUMBER"))
28+
repoOwner := os.Getenv("REPO_OWNER")
29+
repoName := os.Getenv("REPO_NAME")
30+
31+
// First, try to use the API to get the PR info
32+
if prNumber != 0 && repoOwner != "" && repoName != "" {
33+
return getFromApi(ctx, client, prLabel, repoOwner, repoName, prNumber)
34+
}
35+
36+
// Try to use event data if present
37+
eventPath := ghctx.EventPath
38+
if eventPath != "" {
39+
return getFromEvent(ctx, client, ghctx)
40+
}
41+
42+
return PrInfo{}, fmt.Errorf("no PR info found")
43+
}
44+
45+
func getFromEvent(ctx context.Context, client *github.Client, ghctx *githubactions.GitHubContext) (PrInfo, error) {
46+
payload := &github.PullRequestTargetEvent{}
47+
48+
if err := UnmarshalEventData(ghctx, &payload); err != nil {
49+
return PrInfo{}, err
50+
}
51+
52+
if payload.PullRequest == nil {
53+
return PrInfo{}, fmt.Errorf("pull request is nil")
54+
}
55+
56+
pr := payload.GetPullRequest()
57+
prInfo := PrInfo{
58+
Pr: pr,
59+
RepoOwner: payload.GetRepo().GetOwner().GetLogin(),
60+
RepoName: payload.GetRepo().GetName(),
61+
}
62+
63+
switch action := payload.GetAction(); action {
64+
case "labeled":
65+
prInfo.Labels = []string{payload.GetLabel().GetName()}
66+
case "closed":
67+
prInfo.Labels = labelsToStrings(pr.Labels)
68+
default:
69+
return PrInfo{}, fmt.Errorf("unsupported action: %s", action)
70+
}
71+
72+
return prInfo, nil
73+
}
74+
75+
func getFromApi(ctx context.Context, client *github.Client, prLabel, repoOwner, repoName string, prNumber int) (PrInfo, error) {
76+
pr, _, err := client.PullRequests.Get(ctx, repoOwner, repoName, prNumber)
77+
if err != nil {
78+
return PrInfo{}, err
79+
}
80+
81+
prInfo := PrInfo{
82+
Pr: pr,
83+
RepoOwner: repoOwner,
84+
RepoName: repoName,
85+
}
86+
87+
if prLabel != "" {
88+
prInfo.Labels = []string{prLabel}
89+
} else {
90+
prInfo.Labels = labelsToStrings(pr.Labels)
91+
}
92+
93+
return prInfo, nil
94+
}
95+
96+
func labelsToStrings(labels []*github.Label) []string {
97+
strings := make([]string, len(labels))
98+
for i, label := range labels {
99+
strings[i] = label.GetName()
100+
}
101+
return strings
102+
}

backport/release_branches.go

Lines changed: 10 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -10,10 +10,10 @@ import (
1010
"github.com/grafana/grafana-github-actions-go/pkg/ghutil"
1111
)
1212

13-
func BackportTargets(branches []*github.Branch, labels []*github.Label) ([]ghutil.Branch, error) {
13+
func BackportTargets(branches []*github.Branch, labels []string) ([]ghutil.Branch, error) {
1414
targets := []ghutil.Branch{}
1515
for _, label := range labels {
16-
if !strings.HasPrefix(label.GetName(), "backport ") {
16+
if !strings.HasPrefix(label, "backport ") {
1717
continue
1818
}
1919

@@ -31,28 +31,26 @@ func BackportTargets(branches []*github.Branch, labels []*github.Label) ([]ghuti
3131
var (
3232
ErrorNotMerged = errors.New("pull request is not merged; nothing to do")
3333
ErrorBadAction = errors.New("unrecognized action")
34+
ErrorNoLabels = errors.New("no labels found")
3435
)
3536

36-
func BackportTargetsFromPayload(branches []*github.Branch, payload *github.PullRequestTargetEvent) ([]ghutil.Branch, error) {
37-
if !payload.PullRequest.GetMerged() {
37+
func BackportTargetsFromPayload(branches []*github.Branch, prInfo PrInfo) ([]ghutil.Branch, error) {
38+
if !prInfo.Pr.GetMerged() {
3839
return nil, ErrorNotMerged
3940
}
4041

41-
switch payload.GetAction() {
42-
case "labeled":
43-
return BackportTargets(branches, []*github.Label{payload.GetLabel()})
44-
case "closed":
45-
return BackportTargets(branches, payload.GetPullRequest().Labels)
42+
if len(prInfo.Labels) == 0 {
43+
return nil, ErrorNoLabels
4644
}
4745

48-
return nil, ErrorBadAction
46+
return BackportTargets(branches, prInfo.Labels)
4947
}
5048

5149
// BackportTarget finds the most appropriate base branch (target) given the backport label 'label'
5250
// This function takes the label, like `backport v11.2.x`, and finds the most recent `release-` branch
5351
// that matches the pattern.
54-
func BackportTarget(label *github.Label, branches []*github.Branch) (ghutil.Branch, error) {
55-
version := strings.TrimPrefix(label.GetName(), "backport")
52+
func BackportTarget(label string, branches []*github.Branch) (ghutil.Branch, error) {
53+
version := strings.TrimPrefix(label, "backport")
5654
labelString := strings.ReplaceAll(strings.TrimSpace(version), "x", "0")
5755
major, minor, _ := ghutil.MajorMinorPatch(labelString)
5856

0 commit comments

Comments
 (0)