I comment /test all
on a Pull Request (PR). In response, GitHub posts my comment to Prow, via a webhook. See examples for webhook payloads here.
Prow's Kubernetes cluster uses an ingress resource for terminating TLS, and routing traffic to the hook service resource. This document describes the configuration for the ingress resource. The ingress resource sends traffic to the "hook" service. This document describes the configuration for the "hook" service.
The "hook" service routes traffic to the "hook" application. This deployment resource defines the pods that "hook" is comprised of.
The pods for "hook" run the "Hook" executable. "hook" listens for incoming http requests and translates them to "GitHub event objects". Afterwards, "hook" broadcasts these events to Prow Plugins. In the case of my /test all
comment, "hook" builds an "Issue Comment Event".
Prow plugins receive 2 objects: 1) a GitHub event object, and 2) a "client agent object". The Client agent object contains 7 clients: GitHub, Prow jobs, Kubernetes, Git, Slack, Owners, and Bugzilla. These 7 clients are initialized by "hook", during start-up. This is what "client agent objects" look like:
type ClientAgent struct {
GitHubClient github.Client
ProwJobClient prowv1.ProwJobInterface
KubernetesClient kubernetes.Interface
GitClient *git.Client
SlackClient *slack.Client
OwnersClient *repoowners.Client
BugzillaClient bugzilla.Client
}
"hook" multiplexes events by looking at "X-GitHub-Event", a custom http header. Afterwards, a PluginAgent object, initialized during Hook's startup, selects plugins to handle events. See events.go for more details, and check plugins.yaml for a list of plugins per repo.
"hook" delivers an event that represents my /test all
comment to the Trigger plugin. The Trigger plugin validates the PR before running tests. One such validation is, for instance, that the author is a member of the organization or that the PR is labeled ok-to-test
. The function called handleGenericCommentEvent
(implemented by handleGenericComment
) describes Trigger's logic.
Finally, handleGenericComment
determines presubmit jobs to run. The list of jobs supplied by the Config
object, in the PluginClient
object, will be used to find suitable jobs.
Next, the trigger plugin talks to the Kubernetes API server and creates a ProwJob Custom Resource with the information from the issue comment.
Pod details aside, the resulting Prow job looks like this:
apiVersion: prow.k8s.io/v1
kind: ProwJob
metadata:
name: 32456927-35d9-11e7-8d95-0a580a6c1504
spec:
job: pull-test-infra-bazel
decorate: true
pod_spec:
containers:
- image: gcr.io/k8s-testimages/bazelbuild:0.11
refs:
base_ref: master
base_sha: 064678510782db5b382df478bb374aaa32e577ea
org: kubernetes
pulls:
- author: ixdy
number: 2716
sha: dc32ccc9ea3672ccc523b7cbaa8b00360b4183cd
repo: test-infra
type: presubmit
status:
startTime: 2017-05-10T23:34:22.567457715Z
state: triggered
Every thirty seconds, cmd/plank
runs Sync
. Sync
runs syncKubernetesJob
for each Prow job and pod. Because the above Prow job lacks a corresponding Kubernetes pod, Sync
creates one in the test-pods
namespace. Finally, Sync
updates the status line on the PR with a link to Gubernator. Gubernator handles real-time logs and results.
When the Prow job ends, the syncKubernetesJob
method updates the ProwJob status to success and sets the status line on GitHub to success. The status update makes a green check-mark show up on the PR.
A day later, cmd/sinker
notices that the job and pod are a day old and deletes them from the Kubernetes API server.