Skip to content
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

Add github pkg to webhook #1230

Merged
merged 3 commits into from
Nov 2, 2018
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
11 changes: 10 additions & 1 deletion pkg/webhook/constants/constants.go
Original file line number Diff line number Diff line change
Expand Up @@ -17,15 +17,24 @@ limitations under the License.
package constants

const (
// GithubAccessToken is the env variable auth for container-tools-bot is stored in
GithubAccessToken = "GITHUB_ACCESS_TOKEN"
// GithubOwner is the owner of the repository
GithubOwner = "GoogleContainerTools"
// GithubRepo is the name of the repo
GithubRepo = "skaffold"
// GithubEventHeader is the header key used to describe a github event
GithubEventHeader = "X-GitHub-Event"
// PullRequestEvent is the header value for pull requests
// PullRequestEvent is the Github header value for pull requests
PullRequestEvent = "pull_request"
// OpenState is the state of an open PR
OpenState = "open"

// when a PR is closed
ClosedAction = "closed"
// when a PR is labeled
LabeledAction = "labeled"

// DocsLabel kicks off the controller when added to a PR
DocsLabel = "docs-modifications"

Expand Down
77 changes: 77 additions & 0 deletions pkg/webhook/github/github.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,77 @@
/*
Copyright 2018 The Skaffold Authors

Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at

http://www.apache.org/licenses/LICENSE-2.0

Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/

package github

import (
"context"
"log"
"os"

"github.com/GoogleContainerTools/skaffold/pkg/webhook/constants"
"github.com/google/go-github/github"
"github.com/pkg/errors"
"golang.org/x/oauth2"
)

// Client provides the context and client with necessary auth
// for interacting with the Github API
type Client struct {
ctx context.Context
*github.Client
}

// NewClient returns a github client with the necessary auth
func NewClient() *Client {
githubToken := os.Getenv(constants.GithubAccessToken)
// Setup the token for github authentication
ts := oauth2.StaticTokenSource(
&oauth2.Token{AccessToken: githubToken},
)
tc := oauth2.NewClient(context.Background(), ts)

// Return a client instance from github
client := github.NewClient(tc)
return &Client{
Client: client,
ctx: context.Background(),
}
}

// CommentOnPR comments message on the PR
func (g *Client) CommentOnPR(pr *github.PullRequestEvent, message string) error {
comment := &github.IssueComment{
Body: &message,
}

log.Printf("Creating comment on PR %d", pr.PullRequest.GetNumber())
_, _, err := g.Client.Issues.CreateComment(g.ctx, constants.GithubOwner, constants.GithubRepo, pr.PullRequest.GetNumber(), comment)
if err != nil {
return errors.Wrap(err, "creating github comment")
}
log.Printf("Successfully commented on PR %d.", pr.GetNumber())
return nil
}

// RemoveLabelFromPR removes label from pr
func (g *Client) RemoveLabelFromPR(pr *github.PullRequestEvent, label string) error {
_, err := g.Client.Issues.DeleteLabel(g.ctx, constants.GithubOwner, constants.GithubRepo, label)
if err != nil {
return errors.Wrap(err, "deleting label")
}
log.Printf("Successfully deleted label from PR %d", pr.GetNumber())
return nil
}
4 changes: 2 additions & 2 deletions pkg/webhook/kubernetes/deployment.go
Original file line number Diff line number Diff line change
Expand Up @@ -87,7 +87,7 @@ func CreateDeployment(pr *github.PullRequestEvent, svc *v1.Service, externalIP s
{
Name: "server",
Image: constants.DeploymentImage,
Args: []string{"hugo", "server", "--bind=0.0.0.0", "-D", "--baseURL", baseURL(externalIP)},
Args: []string{"hugo", "server", "--bind=0.0.0.0", "-D", "--baseURL", BaseURL(externalIP)},
WorkingDir: docsPath,
VolumeMounts: []v1.VolumeMount{
{
Expand Down Expand Up @@ -126,6 +126,6 @@ func WaitForDeploymentToStabilize(d *appsv1.Deployment) error {
return pkgkubernetes.WaitForDeploymentToStabilize(context.Background(), client, d.Namespace, d.Name, 5*time.Minute)
}

func baseURL(ip string) string {
func BaseURL(ip string) string {
return fmt.Sprintf("http://%s:%d", ip, constants.HugoPort)
}
28 changes: 24 additions & 4 deletions webhook/webhook.go
Original file line number Diff line number Diff line change
Expand Up @@ -18,15 +18,17 @@ package main

import (
"encoding/json"
"fmt"
"log"
"net/http"

"github.com/GoogleContainerTools/skaffold/pkg/webhook/kubernetes"
"github.com/GoogleContainerTools/skaffold/pkg/webhook/labels"
"github.com/google/go-github/github"
"github.com/pkg/errors"

"github.com/GoogleContainerTools/skaffold/pkg/webhook/constants"
"github.com/google/go-github/github"
pkggithub "github.com/GoogleContainerTools/skaffold/pkg/webhook/github"
)

const (
Expand Down Expand Up @@ -69,7 +71,7 @@ func handlePullRequestEvent(event *github.PullRequestEvent) error {

prNumber := event.GetNumber()

if event.PullRequest.GetMerged() || event.PullRequest.ClosedAt == nil {
if event.PullRequest.GetState() != constants.OpenState {
log.Printf("Pull request %d is either merged or closed, skipping docs deployment", prNumber)
return nil
}
Expand All @@ -79,6 +81,12 @@ func handlePullRequestEvent(event *github.PullRequestEvent) error {
return nil
}

// If a PR was relabeled, we need to first cleanup preexisting deployments
if err := kubernetes.CleanupDeployment(event); err != nil {
return errors.Wrap(err, "cleaning up deployment")
}

// Create service for the PR and get the associated external IP
log.Printf("Label %s found on PR %d, creating service", constants.DocsLabel, prNumber)
svc, err := kubernetes.CreateService(event)
if err != nil {
Expand All @@ -90,14 +98,26 @@ func handlePullRequestEvent(event *github.PullRequestEvent) error {
return errors.Wrap(err, "getting external IP")
}

// Create a deployment which maps to the service
log.Printf("Creating deployment for pull request %d", prNumber)
deployment, err := kubernetes.CreateDeployment(event, svc, ip)
if err != nil {
return errors.Wrap(err, "creating deployment")
return errors.Wrapf(err, "creating deployment for PR %d", prNumber)
}
if err := kubernetes.WaitForDeploymentToStabilize(deployment); err != nil {
return errors.Wrapf(err, "waiting for deployment %s to stabilize", deployment.Name)
}
// TODO: priyawadhwa@ to add logic for commenting on Github once the deployment is ready

// Comment on the PR and remove the docs-modifications label
githubClient := pkggithub.NewClient()
baseURL := kubernetes.BaseURL(ip)
msg := fmt.Sprintf("Please visit [%s](%s) to view changes to the docs.", baseURL, baseURL)
if err := githubClient.CommentOnPR(event, msg); err != nil {
return errors.Wrapf(err, "comenting on PR %d", prNumber)
}
if err := githubClient.RemoveLabelFromPR(event, constants.DocsLabel); err != nil {
return errors.Wrapf(err, "removing %s label from PR %d", constants.DocsLabel, prNumber)
}

return nil
}