1 package project
2
3 import (
4 "context"
5 "fmt"
6
7 "edge-infra.dev/pkg/lib/logging"
8
9 "github.com/google/go-github/v47/github"
10 "github.com/shurcooL/githubv4"
11
12 "edge-infra.dev/pkg/f8n/devinfra/jack/constants"
13 gs "edge-infra.dev/pkg/f8n/devinfra/jack/guest_services"
14 "edge-infra.dev/pkg/f8n/devinfra/jack/plugin"
15 )
16
17 func addIssueToProject(hp plugin.HandlerParams, event github.IssuesEvent, id int64) error {
18 log := hp.Log
19 ctx := hp.Ctx
20 client := hp.Client
21 clientv4 := hp.ClientV4
22
23 log.Info("Adding a new issue to the default project")
24
25 labels := gs.NewLabels(event.Issue.Labels)
26
27
28 if labels.Kind == constants.KindIncident {
29 return nil
30 }
31
32
33 org := event.GetRepo().GetOwner().GetLogin()
34 issueID := event.GetIssue().GetNodeID()
35 orgs, _, err := client.Organizations().ListProjects(ctx, org, &github.ProjectListOptions{})
36 if err != nil {
37 log.Error(err, "Failed to get orgs")
38 return err
39 }
40
41
42 project := github.Project{}
43 for _, x := range orgs {
44 if int64(x.GetNumber()) == id {
45 project = *x
46 }
47 }
48
49
50
51 if (github.Project{}) == project {
52 log.Info("cant find project associated with the given number")
53 log.Info("trying the v4 api")
54
55 betaProjID, err := attemptV4Connection(ctx, clientv4, org, id, log, issueID)
56 if err != nil {
57 log.Error(err, "v4 connection failed")
58 return err
59 }
60 log.Info("added via v4 api -- card nodeid " + betaProjID)
61 return nil
62 }
63
64
65 projects, _, err := client.Projects().GetProject(ctx, project.GetID())
66 if err != nil {
67 log.Error(err, "Failed to get the orgs projects")
68 return err
69 }
70
71
72 columns, _, err := client.Projects().ListProjectColumns(ctx, projects.GetID(), &github.ListOptions{})
73 if err != nil {
74 log.Error(err, "Failed to get the projects columns")
75 return err
76 }
77
78
79 if len(columns) <= 0 {
80 log.Info("not enough columns on the given project")
81 return nil
82 }
83
84
85
86 projectColumnID := columns[0].GetID()
87 githubProjectCard := &github.ProjectCardOptions{ContentID: event.GetIssue().GetID(), ContentType: "Issue"}
88 _, _, err = client.Projects().CreateProjectCard(ctx, projectColumnID, githubProjectCard)
89 if err != nil {
90 log.Error(err, fmt.Sprintf("Failed to create a new project card for project %s", projects.GetName()))
91 return err
92 }
93
94 log.Info(fmt.Sprintf("issue %v was added to the %v project", event.GetIssue().GetNumber(), projects.GetName()))
95
96 return nil
97 }
98
99
100
101 func attemptV4Connection(ctx context.Context, c plugin.GithubV4ClientInterface, org string, id int64, log logging.EdgeLogger, inid string) (string, error) {
102 pnid, err := fetchProjectNodeID(ctx, c, org, id)
103 if err != nil {
104 log.Error(err, "Failed to get orgs")
105 return "", err
106 }
107 return addIssueToV4Project(ctx, c, pnid, inid)
108 }
109
110
111
112 func fetchProjectNodeID(ctx context.Context, c plugin.GithubV4ClientInterface, org string, id int64) (string, error) {
113 var q struct {
114 Organization struct {
115 Project struct {
116 ID string
117 } `graphql:"projectNext(number: $id)"`
118 } `graphql:"organization(login: $org)"`
119 }
120
121 variables := map[string]interface{}{
122 "org": githubv4.String(org),
123 "id": githubv4.Int(id),
124 }
125
126 err := c.Query(ctx, &q, variables)
127 return q.Organization.Project.ID, err
128 }
129
130
131
132 func addIssueToV4Project(ctx context.Context, c plugin.GithubV4ClientInterface, pnid string, inid string) (string, error) {
133 var m struct {
134 AddProjectV2ItemByID struct {
135 Item struct {
136 ID string
137 }
138 } `graphql:"AddProjectV2ItemById(input: $input)"`
139 }
140
141 input := githubv4.AddProjectV2ItemByIdInput{
142 ProjectID: githubv4.ID(pnid),
143 ContentID: githubv4.ID(inid),
144 }
145
146 err := c.Mutate(ctx, &m, input, nil)
147 if err != nil {
148 return "", err
149 }
150 return m.AddProjectV2ItemByID.Item.ID, nil
151 }
152
View as plain text