-
Notifications
You must be signed in to change notification settings - Fork 244
Automatically update pipelines webhook #48
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Automatically update pipelines webhook #48
Conversation
@michelvocks Okay, so I went with the easiest solution here and the least possible impact in either the workflow or the user experience. I'm using a github token which the user needs to provide for now as an environment property later on from a secret file of some sort or maybe both. Right now everything is hardcoded as I was testing if the authentication and the creation is working fine. Here you can see that the hook is created for said repository: This also means that I have to provide a callback url. Which means I will need to be able to determine where and under what address gaia is currently deployed at. Which I'm sure I can. :) Also pinging @rmb938 for the glory of the Sontaran Empire. And to see if you are satisfied with the approach laid out. :) |
Makefile
Outdated
@@ -4,7 +4,7 @@ GO_LDFLAGS_STATIC=-ldflags "-s -w -extldflags -static" | |||
default: dev | |||
|
|||
dev: | |||
go run ./cmd/gaia/main.go -homepath=${PWD}/tmp -dev=true -poll=true |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I haven't noticed that I put this in. 😊
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I guess you can leave that in. Especially when you do pipeline testing this is really helpful! 😄
handlers/hook.go
Outdated
return c.JSON(400, e) | ||
} | ||
|
||
gaia.Cfg.Logger.Info("received: ", h.Event) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Actually, I don't care about the event at all. And in any other case, I'm thinking it's only enough to verify the signature. Since the hook is only for one event, this data here is meaningless. The hook will only ever be called on a push. If there is an event, we build the specific pipeline.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Right. We just have to make sure that this event triggers the right pipeline 😃
pipeline/create_pipeline.go
Outdated
// TODO: Add repo VCS type information? | ||
// TODO: Q: Also, save the webhook so we can later find the pipeline associated with it? | ||
// A: Don't think so, because the hook will contain the name of the repository. | ||
subscribeRepoWebhook(&p.Pipeline.Repo) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@michelvocks This also means that webhook automatic building will never be available for drop-in pipelines as this needs repository information. Are you okay with this? Or shall we try and do some workaround magic?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
No, this is absolutely fine! If you just drop your pipeline binary into the pipeline folder, this pipeline cannot use the poll functionality as well as the webhook. 👍
pipeline/git.go
Outdated
) | ||
tc := oauth2.NewClient(ctx, ts) | ||
config := make(map[string]interface{}) | ||
config["url"] = "https://example.com/callback" |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
So, unless echo is running and a request was received I can't determine where gaia is deployed at from the back-end side. Maybe the admin site can't, I'm not big on NPM. However, that leaves me with config options maybe. :/ Which further convolutes the huge configuration flags by adding -host=example.com
or something like that.
I see the config refactoring approaching ever faster. :) What say you?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Good point. I know from many tools (gitlab for example) that you have to provide the domain name where the application is accessible from. So I guess adding a configuration flag is fine here.
I actually think we should do both. The admin can provide the domain name (which will be used for sure) and if it's not provided we try to determine it after the first request came in. What do you think?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I agree that admin can provide a hostname which overwrites the one provided by the flag. I guess we can try. The first request would be a user login?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Good job so far! 🤗
This is really nice for github users. But I think we should also support non-github users. So we should also provide the end-user just an URL and a secret and that's it. 😄
I'm also not a fan of providing the github token via environment variable/flag etc. What happens if you have multiple github accounts?
I think it should be possible to provide a github token per pipeline via the UI. What do you think?
pipeline/create_pipeline.go
Outdated
// TODO: Add repo VCS type information? | ||
// TODO: Q: Also, save the webhook so we can later find the pipeline associated with it? | ||
// A: Don't think so, because the hook will contain the name of the repository. | ||
subscribeRepoWebhook(&p.Pipeline.Repo) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
No, this is absolutely fine! If you just drop your pipeline binary into the pipeline folder, this pipeline cannot use the poll functionality as well as the webhook. 👍
pipeline/git.go
Outdated
) | ||
tc := oauth2.NewClient(ctx, ts) | ||
config := make(map[string]interface{}) | ||
config["url"] = "https://example.com/callback" |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Good point. I know from many tools (gitlab for example) that you have to provide the domain name where the application is accessible from. So I guess adding a configuration flag is fine here.
I actually think we should do both. The admin can provide the domain name (which will be used for sure) and if it's not provided we try to determine it after the first request came in. What do you think?
Looks good so far! I do have a few nitpicks though (of course lol). Since this webhook is specific to github could we have it under the /pipeline/github/hook path? I.e someone may want to add in the future a gitlab hook, or a bitbucket hook, ect.. Actually thinking about it maybe put it under pipeline/github/build-hook or something since the hook is specific to rebuilding the code vs triggering a pipeline 🤷♂️ Also I don't know if we actually need to register the hook in github during pipeline creation, doing that kinda locks us to github specifically and will probably add some more config options for github creds. Unless we want to have this be a global config option to say which git system we are using. |
@rmb938 @michelvocks Thanks guys. This is all very good feedback and I agree with the both of you. :) |
@michelvocks I agree with you on the admin thingy. And I probably need you help with that since I'm not very big on front-end stuff and vue. :D Also yeah on the UI github token and the separation of github. @rmb938 Also also agree on the whole github thing being restricted into it's own environment. And also, also, also on the fact that it might not should create a hook on pipeline create. The UI should probably have a flag for that or something like Michel is saying. |
@Skarlso Yes sure. Just let me know where I can help explicitly. |
So, what I'm going to do in this Pr is the following... @michelvocks @rmb938.
I think that's all. |
Codecov Report
@@ Coverage Diff @@
## master #48 +/- ##
==========================================
+ Coverage 64.07% 64.55% +0.47%
==========================================
Files 21 22 +1
Lines 1751 1879 +128
==========================================
+ Hits 1122 1213 +91
- Misses 512 535 +23
- Partials 117 131 +14
Continue to review full report at Codecov.
|
So this works right now: 2018/07/22 23:08:47 hook created: "web" 201 Created
2018/07/22 23:08:47 hook url: https://api.github.com/repos/Skarlso/go-example/hooks/39614928 button: The only two problems are that the token is saved if the pipeline errors out and second, I still have no way of providing and saving a |
Yeah so I think this pr is blocked until I can inject a secret from a managed secret store via #51. |
What do you mean exactly with "pipeline errors out"?
I like that a lot until we have #51 implemented! 🤗
Awesome! Maybe move the button next to the "Add credentials" button and change the icon (I know this is fine tuning and will be done later 👍 ).
That's fine I guess. We also have to think about what happens when the flag "hostname" is changed? We might need to update all webhooks in this case.
Like that. We somehow need to integrate that into the create pipeline view. 😄
Perfect. ❤️ |
Oh f*ck. :D That didn't occur to me before. :) |
Well like jenkins, drone ci, ect... if the admin updates the hostname the hooks just break. No one is trying to fix that (because it's hard) so I don't think we should try to. |
Also I don't think we need a hostname flag, I know gin has a middleware for getting the request's hostname https://github.com/gin-contrib/location so I'm sure echo has it/won't be hard to add it. |
@rmb938 It does, it just feels hacky to place such a thing on the first whatever request that gets fired off. I don't think it's easily testable, or maintainable. What if the end-point gets moved and the person moving it doesn't realize that there is a critical thing in there for the webhooks. Namely, detect the host and set it. Or even worse, they put it into a different location but that happens to be after a request for webhook creation is fired off. I think it's just easier and cleaner to have a setting where you explicitly set it, and that's that. No magic, no fuss, no muss. Clean. That's how I feel about it at least. |
Makes sense :) I don't really have a strong preference one way or another tbh. |
I agree with @Skarlso 😄 But I actually like that we don't support the update stuff for the webhooks. If the hostname changes, all webhooks are broken. Updating can be hard for sure. |
Correct me if I'm wrong but this PR doesn't support non-Github webhooks? |
@bidhan-a You are not wrong. Since non-github webhook require a complete different way of registering them with a different library and api, this PR deals with github only. Other hooks, like gitlab and bitbucket will be in a separate PR. :) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Just a few remarks 🤗 Looks already good!
cmd/gaia/main.go
Outdated
@@ -37,6 +37,7 @@ func init() { | |||
// command line arguments | |||
flag.StringVar(&gaia.Cfg.ListenPort, "port", "8080", "Listen port for gaia") | |||
flag.StringVar(&gaia.Cfg.HomePath, "homepath", "", "Path to the gaia home folder") | |||
flag.StringVar(&gaia.Cfg.Hostname, "hostname", "https://localhost", "The host's name under which gaia is deployed at exp: https://gaia-pipeline.com") |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
what does exp mean? 😄
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Example. :D
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
maybe e.g.? or for example? 😄
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Yeah that's definitely better. :D
@@ -32,6 +32,12 @@ | |||
</span> | |||
<span>Add credentials</span> | |||
</a> | |||
<a class="button is-primary" v-on:click="showGitHubWebHookModal"> | |||
<span class="icon"> | |||
<i class="fa fa-certificate"></i> |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Would be awesome if you could change the icon for user experience 😃 see https://fontawesome.com/icons?d=gallery most of them are available
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Sure thing. :) Thanks! :)
@michelvocks Before doing anything I wanted to run a quick manual. Turns out I had a few bugs in there.. One, I was generating the password at a wrong location. :/ Second, I was sending off the wrong URL for the webhook callback. 🗡 Unfortunately, because I needed the API version I had to shift the constant into gaia.go where the other constants are lying. That's why there are now more edits. |
@michelvocks umm... dude... The scheduler threw a data race. :/ 2018-08-15T21:47:24.501+0200 [DEBUG] Gaia: error during job execution: error="job failed" job="{2296842551 Job1 [] running}"
panic: send on closed channel
goroutine 13 [running]:
github.com/gaia-pipeline/gaia/scheduler.(*Scheduler).resolveDependencies(0xc420020f00, 0x89e70aca, 0x11e6932, 0x4, 0x0, 0x0, 0xc42000e2d0, 0x1, 0x1, 0x11ea8ba, ...)
.../golang/src/github.com/gaia-pipeline/gaia/scheduler/scheduler.go:376 +0x2f0
github.com/gaia-pipeline/gaia/scheduler.(*Scheduler).resolveDependencies(0xc420020f00, 0x8ae70c5d, 0x11e6936, 0x4, 0x0, 0x0, 0xc42000e2d8, 0x1, 0x1, 0x11ea8ba, ...)
.../golang/src/github.com/gaia-pipeline/gaia/scheduler/scheduler.go:358 +0x223
created by github.com/gaia-pipeline/gaia/scheduler.(*Scheduler).executeScheduler
...golang/src/github.com/gaia-pipeline/gaia/scheduler/scheduler.go:429 +0x2c9 |
To be fair running it with |
35e95ea
to
7b69b60
Compare
…so fixed the url it was sending.
7b69b60
to
030a068
Compare
I'm getting invalid signature on the real deal.. I need to investigate why. :/ |
Everything works!! Yiiss!! Couple of things:
|
2018-08-16T08:39:55.517+0200 [DEBUG] Gaia: checking pipeline: : asdf=<unknown>
2018-08-16T08:39:55.517+0200 [DEBUG] Gaia: selected branch : : refs/heads/dependson=<unknown>
2018-08-16T08:39:56.709+0200 [DEBUG] Gaia: updating pipeline: : asdf=<unknown>
2018-08-16T08:39:58.052+0200 [DEBUG] Gaia: successfully updated: : asdf=<unknown> POST /api/v1/pipeline/githook 200 OK That image is from the webhook's webpage in github. It shows that it successfully sent a push event request. I'm using |
90e32d5
to
61938f4
Compare
pipeline/git.go
Outdated
return err | ||
} | ||
gaia.Cfg.Logger.Info("hook created: ", github.Stringify(hook.Name), resp.Status) | ||
gaia.Cfg.Logger.Info("hook url: ", hook.Geturl("")) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
should be gaia.Cfg.Logger.Info("hook url ", "url", hook.Geturl(""))
Otherwise we get ugly log output like hook url: : asdf=<unknown>
😄
It's always (initial_log_message, key=string, value)
pipeline/git.go
Outdated
}) | ||
if err != nil { | ||
// It's also an error if the repo is already up to date so we just move on. | ||
gaia.Cfg.Logger.Error("error while doing a pull request : ", err.Error()) | ||
message := "error while doing a pull request: " + err.Error() | ||
gaia.Cfg.Logger.Error(message) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
gaia.Cfg.Logger.Error("error while doing a pull request", "error", err.Error())
pipeline/git.go
Outdated
func createGithubWebhook(token string, repo *gaia.GitRepo, gitRepo GithubRepoService) error { | ||
vault, err := services.VaultService(nil) | ||
if err != nil { | ||
gaia.Cfg.Logger.Error("unable to initialize vault: " + err.Error()) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
gaia.Cfg.Logger.Error("unable to initialize vault", "error", err.Error())
pipeline/git.go
Outdated
|
||
err = vault.LoadSecrets() | ||
if err != nil { | ||
gaia.Cfg.Logger.Error("unable to open vault: " + err.Error()) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
gaia.Cfg.Logger.Error("unable to open vault", "error", err.Error())
This currently a working end-point for accepting and parsing the webhooks. I'm opening a PR for conversation purposes. I'm debating whether to make the user create a webhook or have that authentication process in Gaia complete with callback.
I'm all for making it as easy as possible for a user and probably a user would say the same thing. Which means Gaia will have to redirect and ask for access to the repository in order to send a create webhook request to Github.
Thoughts?