-
Notifications
You must be signed in to change notification settings - Fork 112
/
Copy pathgithub.go
161 lines (136 loc) · 4.61 KB
/
github.go
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
package service
import (
"bytes"
"context"
"encoding/json"
"errors"
"fmt"
"io"
"strings"
"time"
"github.com/fxamacker/cbor/v2"
http "github.com/taubyte/http"
"github.com/taubyte/tau/core/services/patrick"
patrickSpecs "github.com/taubyte/tau/pkg/specs/patrick"
servicesCommon "github.com/taubyte/tau/services/common"
"github.com/taubyte/utils/id"
"gopkg.in/go-playground/webhooks.v5/github"
)
func (srv *PatrickService) githubCheckHookAndExtractSecret(ctx http.Context) (interface{}, error) {
if servicesCommon.FakeSecret && srv.devMode {
ctx.SetVariable("GithubSecret", "taubyte_secret")
return nil, nil
}
hook_uuid, err := ctx.GetStringVariable("hook")
if err != nil {
return nil, fmt.Errorf("get string context failed with %w", err)
}
hook, err := srv.getHook(hook_uuid)
if err != nil {
return nil, fmt.Errorf("get hook failed with %w", err)
}
github_hook, err := hook.Github()
if err != nil {
return nil, fmt.Errorf("github hook failed with %w", err)
}
ctx.SetVariable("GithubSecret", github_hook.Secret)
return nil, nil
}
func (srv *PatrickService) githubHookHandler(ctx http.Context) (interface{}, error) {
newJob := &patrick.Job{
Status: patrick.JobStatusOpen,
Timestamp: time.Now().Unix(),
Logs: make(map[string]string),
AssetCid: make(map[string]string),
Attempt: 0,
}
secret, err := ctx.GetStringVariable("GithubSecret") // comes from auth
if err != nil {
return nil, err
}
if servicesCommon.DelayJob {
newJob.Delay = &patrick.DelayConfig{
Time: int(servicesCommon.DelayJobTime),
}
}
hook, err := github.New(github.Options.Secret(secret))
if err != nil {
return nil, fmt.Errorf("creating hook failed with %w", err)
}
// FIXME: move this logic to taubyte/http
req := ctx.Request()
req.Body = io.NopCloser(bytes.NewReader(ctx.Body()))
payload, err := hook.Parse(ctx.Request(), github.PushEvent)
if err != nil {
if err == github.ErrEventNotFound {
// ok event wasn't one of the ones asked to be parsed
return nil, errors.New("this is not a push event")
}
return nil, fmt.Errorf("parsing hook failed with %w", err)
}
switch payload.(type) {
case github.PushPayload:
logger.Debugf("Hook triggred. Push: %v", payload)
pl, err := json.Marshal(payload)
if err != nil {
logger.Errorf("new pipeline for payload `%#v` failed with: %s", payload, err.Error())
return nil, errors.New("can't decode push payload")
}
//Unmarshal the needed json fields into the structure
err = json.Unmarshal(pl, &newJob.Meta)
if err != nil {
return nil, fmt.Errorf("failed unmarshalling payload into struct with error: %w", err)
}
job_id := id.Generate(newJob.Meta.Repository.ID)
//Assign fields before marshal
newJob.Meta.Repository.Provider = "github"
newJob.Id = job_id
logger.Info("payload", string(pl))
logger.Info("job:", newJob.Meta)
// Setting current branch and main branch
if newJob.Meta.Repository.MainBranch == "" {
newJob.Meta.Repository.MainBranch = newJob.Meta.Repository.Branch
}
newJob.Meta.Repository.Branch = strings.Replace(newJob.Meta.Ref, "refs/heads/", "", 1)
if newJob.Meta.Repository.MainBranch != newJob.Meta.Repository.Branch && !srv.devMode {
return nil, fmt.Errorf("only builds main branch `%s` got `%s`", newJob.Meta.Repository.MainBranch, newJob.Meta.Repository.Branch)
}
err = srv.RegisterJob(ctx.Request().Context(), newJob)
if err != nil {
return nil, err
}
// Pushing useful information to tns for auth
repoInfo := map[string]string{
"id": fmt.Sprintf("%d", newJob.Meta.Repository.ID),
"ssh": newJob.Meta.Repository.SSHURL,
}
err = srv.tnsClient.Push([]string{"resolve", "repo", "github", fmt.Sprintf("%d", newJob.Meta.Repository.ID)}, repoInfo)
if err != nil {
return nil, fmt.Errorf("failed registering new job repo %d into tns with error: %v", newJob.Meta.Repository.ID, err)
}
return newJob, nil
default:
return nil, fmt.Errorf("this is not a push event. but a %T", payload)
}
}
func (srv *PatrickService) RegisterJob(ctx context.Context, newJob *patrick.Job) error {
job_byte, err := cbor.Marshal(newJob)
if err != nil {
return fmt.Errorf("failed cbor marshall on job structure with err: %w", err)
}
// Store the job inside the database with a generated ID
err = srv.db.Put(ctx, "/jobs/"+newJob.Id, job_byte)
if err != nil {
return fmt.Errorf("failed putting job into database with error: %w", err)
}
err = srv.connectToProject(ctx, newJob)
if err != nil {
return err
}
// Send the job over pub sub
err = srv.node.PubSubPublish(ctx, patrickSpecs.PubSubIdent, job_byte)
if err != nil {
return fmt.Errorf("failed to send over pubsub error: %w", err)
}
return nil
}