Skip to content

Conversation

Skarlso
Copy link
Member

@Skarlso Skarlso commented Jul 20, 2018

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?

@Skarlso
Copy link
Member Author

Skarlso commented Jul 21, 2018

@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:

screen shot 2018-07-21 at 09 40 27

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.

sontaran

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
Copy link
Member Author

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. 😊

Copy link
Member

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)
Copy link
Member Author

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.

Copy link
Member

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 😃

// 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)
Copy link
Member Author

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?

Copy link
Member

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"
Copy link
Member Author

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?

Copy link
Member

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?

Copy link
Member Author

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?

Copy link
Member

@michelvocks michelvocks left a 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?

// 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)
Copy link
Member

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"
Copy link
Member

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?

@rmb938
Copy link
Contributor

rmb938 commented Jul 21, 2018

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..
This would also allow us to add a "Generic" hook that someone could just call from curl or something.

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.

@Skarlso
Copy link
Member Author

Skarlso commented Jul 21, 2018

@rmb938 @michelvocks Thanks guys. This is all very good feedback and I agree with the both of you. :)

@Skarlso
Copy link
Member Author

Skarlso commented Jul 21, 2018

@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.

@michelvocks
Copy link
Member

@Skarlso Yes sure. Just let me know where I can help explicitly.

@Skarlso
Copy link
Member Author

Skarlso commented Jul 22, 2018

So, what I'm going to do in this Pr is the following... @michelvocks @rmb938.

  • Not going to save the git token as there is, for now, no reason for it. It's only used once, and that's when the pipeline is created and the hook is sent.
  • Modify the UI to have a checkbox that the user want's a webhook, and if it's checked, popup a field where a github TOKEN is requested. ( make apparent that it's not saved at this time ). (( I imagine that this would be a different set of fields for a bitbucket hook. For git a token is enough )).
  • This means deleting a hook is not handled currently ( that will be a future feature after we save the token in the form of issue Secret store for passwords, tokens, api keys and more #51 (handling secrets via a vault).
  • Modify the auto-updater to be opt-in and save a flag for a pipeline saying (autoupdate - true) because maybe you don't always want all your pipeline to update. Thoughts on this?
  • Add a flag called hostname to use for the callback url.

I think that's all.

@codecov-io
Copy link

codecov-io commented Jul 22, 2018

Codecov Report

Merging #48 into master will increase coverage by 0.47%.
The diff coverage is 70.5%.

Impacted file tree graph

@@            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
Impacted Files Coverage Δ
security/vault.go 76.69% <0%> (ø) ⬆️
handlers/handler.go 85.13% <100%> (+1.07%) ⬆️
pipeline/create_pipeline.go 50% <28.57%> (-2.84%) ⬇️
handlers/hook.go 62.5% <62.5%> (ø)
pipeline/git.go 69.33% <79.41%> (+8.22%) ⬆️

Continue to review full report at Codecov.

Legend - Click here to learn more
Δ = absolute <relative> (impact), ø = not affected, ? = missing data
Powered by Codecov. Last update 312ae68...ee8b7b5. Read the comment docs.

@Skarlso
Copy link
Member Author

Skarlso commented Jul 22, 2018

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:

screen shot 2018-07-22 at 23 00 43

screen shot 2018-07-22 at 23 00 36

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 secret which brings us back to #51. :/

@michelvocks?

@Skarlso
Copy link
Member Author

Skarlso commented Jul 22, 2018

Yeah so I think this pr is blocked until I can inject a secret from a managed secret store via #51.

@Skarlso Skarlso changed the title [POC][WIP] Automatically update pipelines webhook [BLOCKED][WIP] Automatically update pipelines webhook Jul 23, 2018
@michelvocks
Copy link
Member

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 secret which brings us back to #51. :/

What do you mean exactly with "pipeline errors out"?
Especially when an error happened during the create pipeline step, the github token should not be stored at all.

Not going to save the git token as there is, for now, no reason for it. It's only used once, and that's when the pipeline is created and the hook is sent.

I like that a lot until we have #51 implemented! 🤗

Modify the UI to have a checkbox that the user want's a webhook, and if it's checked, popup a field where a github TOKEN is requested. ( make apparent that it's not saved at this time ). (( I imagine that this would be a different set of fields for a bitbucket hook. For git a token is enough )).

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 👍 ).

This means deleting a hook is not handled currently ( that will be a future feature after we save the token in the form of issue #51 (handling secrets via a vault).

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.

Modify the auto-updater to be opt-in and save a flag for a pipeline saying (autoupdate - true) because maybe you don't always want all your pipeline to update. Thoughts on this?

Like that. We somehow need to integrate that into the create pipeline view. 😄

Add a flag called hostname to use for the callback url.

Perfect. ❤️

@Skarlso
Copy link
Member Author

Skarlso commented Jul 23, 2018

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.

Oh f*ck. :D That didn't occur to me before. :)

@rmb938
Copy link
Contributor

rmb938 commented Jul 24, 2018

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.

@rmb938
Copy link
Contributor

rmb938 commented Jul 24, 2018

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.

@Skarlso
Copy link
Member Author

Skarlso commented Jul 26, 2018

@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.

@rmb938
Copy link
Contributor

rmb938 commented Jul 26, 2018

Makes sense :)

I don't really have a strong preference one way or another tbh.

@michelvocks
Copy link
Member

I agree with @Skarlso 😄
We cannot 100% rely on the detection. And if there is an error or a user has a problem, we can always point to this parameter. 🤗

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.

@Skarlso Skarlso changed the title [BLOCKED][WIP] Automatically update pipelines webhook Automatically update pipelines webhook Aug 2, 2018
@Skarlso Skarlso added the Needs Work The PR still requires some work from the submitter. label Aug 2, 2018
@Skarlso Skarlso requested a review from michelvocks August 14, 2018 16:12
@bidhan-a
Copy link
Contributor

Correct me if I'm wrong but this PR doesn't support non-Github webhooks?

@Skarlso
Copy link
Member Author

Skarlso commented Aug 14, 2018

@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. :)

Copy link
Member

@michelvocks michelvocks left a 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")
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

what does exp mean? 😄

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Example. :D

Copy link
Member

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? 😄

Copy link
Member Author

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>
Copy link
Member

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

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Sure thing. :) Thanks! :)

@Skarlso
Copy link
Member Author

Skarlso commented Aug 15, 2018

@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.

@Skarlso
Copy link
Member Author

Skarlso commented Aug 15, 2018

@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

@Skarlso
Copy link
Member Author

Skarlso commented Aug 15, 2018

To be fair running it with --race only failed once out of 10 runs. :/ Which is quiet shitty. But it still failed. So we'll have to take care of that. But to be faire, I'm not going to do this in this pr if you don't mind.

@Skarlso Skarlso force-pushed the automatically_update_pipelines_webhook branch from 35e95ea to 7b69b60 Compare August 15, 2018 19:52
@Skarlso Skarlso force-pushed the automatically_update_pipelines_webhook branch from 7b69b60 to 030a068 Compare August 15, 2018 20:03
@Skarlso Skarlso added Needs Work The PR still requires some work from the submitter. and removed needs review labels Aug 16, 2018
@Skarlso
Copy link
Member Author

Skarlso commented Aug 16, 2018

I'm getting invalid signature on the real deal.. I need to investigate why. :/

@Skarlso
Copy link
Member Author

Skarlso commented Aug 16, 2018

Everything works!! Yiiss!!

Couple of things:

  • Password generated wasn't accepted because it had special characters.
  • The pipeline was actually not being built because it didn't select the branch which was selected
  • The webhook URL was not open to github. It's open now which is safe as it has it's own authentication procedures using secret and header checks.

@Skarlso
Copy link
Member Author

Skarlso commented Aug 16, 2018

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

screen shot 2018-08-16 at 08 42 26

That image is from the webhook's webpage in github. It shows that it successfully sent a push event request. I'm using ngrok to create and open tunnel to the local service.

@Skarlso Skarlso added Ready To Merge PR is ready to be merged into master Needs Work The PR still requires some work from the submitter. and removed Needs Work The PR still requires some work from the submitter. Ready To Merge PR is ready to be merged into master labels Aug 16, 2018
@Skarlso Skarlso force-pushed the automatically_update_pipelines_webhook branch from 90e32d5 to 61938f4 Compare August 16, 2018 08:58
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(""))
Copy link
Member

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)
Copy link
Member

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())
Copy link
Member

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())
Copy link
Member

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())

@Skarlso Skarlso dismissed michelvocks’s stale review August 18, 2018 13:59

Addressed Comments.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Ready To Merge PR is ready to be merged into master
Projects
None yet
Development

Successfully merging this pull request may close these issues.

5 participants