This is the multi-page printable view of this section.
Click here to print.
Return to the regular view of this page.
Plugins
Plugins are sub-components of hook
that consume GitHub webhooks related to their function and can be individually enabled per repo or org.
All plugin specific configuration is stored in plugins.yaml
.
The Configuration
golang struct holds all the config fields organized into substructures by plugin. See its GoDoc for up-to-date descriptions of every config option.
Most plugins lack README’s but instead generate PluginHelp
structs on demand that include general explanations and help information in addition to details about the current configuration.
Please see https://prow.k8s.io/plugins for a list of all plugins deployed on the Kubernetes Prow instance, what they do, and what commands they offer.
For an alternate view, please see https://prow.k8s.io/command-help to see all of the commands offered by the deployed plugins.
How to enable a plugin on a repo
Add an entry to plugins.yaml. If you misspell the name then a
unit test will fail. If you have updateconfig plugin
deployed then the config will be automatically updated once the PR is merged,
else you will need to run make update-plugins
. This does not require
redeploying the binaries, and will take effect within a minute.
External Plugins
External plugins offer an alternative to compiling a plugin into the hook
binary. Any web endpoint that can properly handle GitHub webhooks can be configured as an external plugin that hook
will forward webhooks to. External plugin endpoints are specified per org or org/repo in plugins.yaml
under the external_plugins
field. Specific event types may be optionally specified to filter which events are forwarded to the endpoint.
External plugins are well suited for:
- Slow operations that would impact the performance of other plugins if run as part of
hook
.
- Components that need to be triggered or notified of events beside GitHub webhooks.
- Isolating a more or less privileged plugin or a plugin that executes PR code.
- Integrating existing GitHub services with Prow.
Examples of external plugins can be found in the prow/external-plugins
directory. The following is an example external plugin configuration that would live in plugins.yaml
.
external_plugins:
org-foo/repo-bar:
- name: refresh-remote
endpoint: https://my-refresh-plugin.com
events:
- issue_comment
- name: needs-rebase
# No endpoint specified implies "http://{{name}}".
events:
- pull_request
# Dispatching issue_comment events to the needs-rebase plugin is optional. If enabled, this may cost up to two token per comment on a PR. If `ghproxy`
# is in use, these two tokens are only needed if the PR or its mergeability changed.
- issue_comment
- name: cherrypick
# No events specified implies all event types.
How to test a plugin
See “Building, Testing, and Updating Prow”.
1.1 - Reviewers and Approvers
Questions this Doc Seeks To Answer
- What are reviewers, approvers, and the OWNERS files?
- How does the reviewer selection mechanism work? approver selection mechanism work?
- How does an approver know which PR s/he has to approve?
Overview
Every GitHub directory which is a unit of independent code contains a file named “OWNERS”. The file lists reviewers and approvers for the directory. Approvers (or previously called assignees) are owners of the codes.
Approvers:
- have contributed substantially to the repo
- can provide an approval (
/approve
) indicating whether a change to a directory or subdirectory should be accepted
- Approval is done on a per directory basis and subdirectories inherit their parents directory’s approvers
Reviewers:
- generally a larger set of current and past contributors
- They are responsible for a more thorough code review, discussing the implementation details and style
- Provide an
/lgtm
when they are satisfied with the Pull Request. The /lgtm
must be renewed whenever the Pull Request changes.
An example of the OWNERS file is listed below:
reviewers:
- jack
- ken
- lina
approvers:
- jack
- ken
- lina
Note that items in the OWNERS files can be GitHub usernames, or aliases defined in OWNERS_ALIASES files. An OWNERS_ALIASES file is another co-existed file that delivers a mechanism for defining groups. However, GitHub Team names are not supported. We do not use them because there is no audit log for changes to the GitHub Teams. This way we have an audit log.
Blunderbuss And Reviewers
lgtm Label
LGTM is abbreviation for “looks good to me”. The lgtm label is normally given when the code has been thoroughly reviewed. Getting it means the PR is one step away from getting merged. Reviewers of the PR give the label to a PR by typing /lgtm
in a comment, or retract it by typing /lgtm cancel
(at the beginning of a comment line). Authors of the PR cannot give the label, but they can cancel it. The bot retracts the label automatically if someone updates the PR with a new commit.
Any collaborator on the repo may use the /lgtm
command, whether or not they are selected as a reviewer or approver by this plugin. (See the next section for reviewer and approver selection algorithm.)
Blunderbuss Selection Mechanism
Blunderbuss provides statistical means to select a subset of approvers found in OWNERS files for approving a PR. A PR consists of changes on one or more files, in which each file has different number of lines of codes changed. Blunderbuss determines the magnitude of code change within a PR using total number of lines of codes changed across various files. Number of reviewers selected for each PR is 2.
Algorithm for selecting reviewers is as follows:
-
determine potential reviewers of a file by going over all reviewers found in the OWNERS files for current and parent directories of the file (deduplication involved)
-
assign each changed file with a weightage based on number of lines of codes changed
-
assign each potential reviewer with a weightage by summing up weightages of all changed files in which s/he is a reviewer
-
randomly select 2 reviewers based on their weightage
Approval Handler and the Approved Label
approved Label
A PR cannot be merged into the repo without the approved label. In order for the approved label to be applied, every file modified by the PR must be approved (via /approve
) by an approver from the OWNERs files. Note, this does not necessarily require multiple approvers. The process is best illustrated in the example below.
Approval Selection Mechanism
First, it is important to understand that ALL approvers in an OWNERS file can approve any file in that directory AND its subdirectories. Second, it is important to understand the somewhat-competing goals of the bot when selecting approvers:
-
Provide a subset of approvers that can approve all files in the PR
-
Provide a small subset of approvers and suggest the same reviewers as blunderbuss if possible (people can be both reviewers and approvers)
-
Do not always suggest the same set of people to approve and do not consistently suggest people from the root OWNERS file
The exact algorithm for selecting approvers is somewhat complex; it is an set cover approximation with consideration for existing assignees. To read it in depth, check out the approvers source code linked at the end of the README.
Example
Suppose files in directories E and G are changed in a PR created by PRAuthor. Any combination of approver(s) listed below can approve the PR in order to get it merged:
-
approvers found in OWNERS files for leaf (current) directories E and G
-
approvers found in OWNERS files for parent directories B and C
-
approvers found in OWNERS files for root directory A
Note someone can be both a reviewer found in OWNERS files for directory A and E. If s/he is selected as an approver and gives approval, it approves entire PR because s/he is also a reviewer for the root directory A.
Step 1:
K8s-bot creates a comment that suggests the selected approvers and shows a list of OWNERS file(s) where the approvers can be found.
[APPROVALNOTIFIER] This PR is **NOT APPROVED**
This pull-request has been approved by: *PRAuthor*
We suggest the following additional approvers: **approver1,** **approver2**
If they are not already assigned, you can assign the PR to them by writing `/assign @approver1 @approver2` in a comment when ready.
∇ Details
Needs approval from an approver in each of these OWNERS Files:
* /A/B/E/OWNERS
* /A/C/G/OWNERS
You can indicate your approval by writing `/approve` in a comment
You can cancel your approval by writing `/approve cancel` in a comment
A selected approver such as approver1 can be notified by typing /assign @approver1
in a comment.
Step 2:
approver1 is in the E OWNERS file. S/he writes /approve
K8s-bot updates comment:
[APPROVALNOTIFIER] This PR is **NOT APPROVED**
This pull-request has been approved by: *approver1, PRAuthor*
We suggest the following additional approver: **approver2**
If they are not already assigned, you can assign the PR to them by writing /assign @approver2 in a comment when ready.
∇ Details
Needs approval from an approver in each of these OWNERS Files:
* ~/A/B/E/OWNERS~ [approver1]
* /A/C/G/OWNERS
You can indicate your approval by writing `/approve` in a comment
You can cancel your approval by writing `/approve cancel` in a comment
Step 3:
approver3 (an approver for D) is NOT an approver for any of the affected directories. S/he writes /approve
K8s-bot updates comment:
[APPROVALNOTIFIER] This PR is **NOT APPROVED**
This pull-request has been approved by: *approver1, approver3, PRAuthor*
We suggest the following additional approvers: **approver2**
If they are not already assigned, you can assign the PR to them by writing /assign @approver1 @approver2 in a comment when ready.
∇ Details
Needs approval from an approver in each of these OWNERS Files:
* ~/A/B/E/OWNERS~ [approver1]
* /A/C/G/OWNERS
You can indicate your approval by writing `/approve` in a comment
You can cancel your approval by writing `/approve cancel` in a comment
Step 4:
approver1 is an approver of the PR. S/he writes /lgtm
K8s-bot updates comment:
[APPROVALNOTIFIER] This PR is **NOT APPROVED**
This pull-request has been approved by: *approver1, approver3, PRAuthor*
We suggest the following additional approver: **approver2**
If they are not already assigned, you can assign the PR to them by writing /assign @approver2 in a comment when ready.
∇ Details
Needs approval from an approver in each of these OWNERS Files:
* ~/A/B/E/OWNERS~ [approver1]
* /A/C/G/OWNERS
You can indicate your approval by writing `/approve` in a comment
You can cancel your approval by writing `/approve cancel` in a comment
The lgtm label is immediately added to the PR.
Step 5:
approver2 (who in the C OWNERS file, which is a parent to G) writes /approve
K8s-bot updates comment:
[APPROVALNOTIFIER] This PR is **APPROVED**
The following people have approved this PR: *approver1, approver2, approver3, PRAuthor*
∇ Details
Needs approval from an approver in each of these OWNERS Files:
* ~/A/B/E/OWNERS~ [approver1]
* ~/A/C/G/OWNERS~ [approver2]
You can indicate your approval by writing `/approve` in a comment
You can cancel your approval by writing `/approve cancel` in a comment
The PR is now unblocked from merging. If Tide is configured, the K8s-bot merges the PR, because it has both the lgtm and approved. It K8s-bot still needs to wait its turn in submit queue and pass tests.
Configuration options
See the Approve go struct for documentation of the options for this plugin.
See also the Lgtm go struct for documentation of the LGTM plugin’s options.
Final Notes
Obtaining approvals from selected approvers is the last step towards merging a PR. The approvers approve a PR by typing /approve
in a comment, or retract it by typing /approve cancel
.
Algorithm for getting the status is as follow:
-
run through all comments to obtain latest intention of approvers
-
put all approvers into an approver set
-
determine whether a file has at least one approver in the approver set
-
add the status to the PR if all files have been approved
If an approval is cancelled, the bot will delete the status added to the PR and remove the approver from the approver set. If someone who is not an approver in the OWNERS file types /approve
in a comment, the PR will not be approved. If someone who is an approver in the OWNERS file and s/he does not get selected, s/he can still type /approve
or /lgtm
in a comment, pushing the PR forward.
Code Implementation Links
Blunderbuss:
prow/plugins/blunderbuss/blunderbuss.go
LGTM:
prow/plugins/lgtm/lgtm.go
Approve:
prow/plugins/approve/approve.go
prow/plugins/approve/approvers/owners.go
2 - branchcleaner
The branchcleaner
plugin automatically deletes source branches for merged PRs between two branches
on the same repository. This is helpful to keep repos that don’t allow forking clean.
Usage
Enable the branchcleaner
in the desired repos via the plugins.yaml
:
plugins:
org/repo:
- branchcleaner
4 - updateconfig
updateconfig
allows prow to update configmaps when files in a repo change.
updateconfig
also supports glob match, or multi-key updates.
Usage
Update your plugins.yaml
file to something along the following lines:
plugins:
my-github/repo:
plugins:
- config-updater
config_updater:
maps:
# Update the thing-config configmap whenever thing changes
path/to/some/other/thing:
name: thing-config
# If cluster and namespace configuration are unset, it will be put into the default cluster in the prowjob namespace
path/to/some/other/thing2:
name: thing2-config
# Specify the clusters and namespaces that the configmap targets
# which requires that the --kubeconfig arg is enabled for Hook
# https://docs.prow.k8s.io/docs/getting-started-deploy/#run-test-pods-in-different-clusters
# if not set or empty, it uses the cluster where prow components are running
# and the specified namespace(s)
clusters:
others:
- namespace1
# Update the config configmap whenever config.yaml changes
config/prow/config.yaml:
name: config
# Update the plugin configmap whenever plugins.yaml changes
config/prow/plugins.yaml:
name: plugin
# Update the `this` or/and `that` key in the `data` configmap whenever `data.yaml` or/and `other-data.yaml` changes
some/data.yaml:
name: data
key: this
some/other-data.yaml:
name: data
key: that
# Update the fejtaverse configmap whenever any `.yaml` file under `fejtaverse` changes
fejtaverse/**/*.yaml:
name: fejtaverse