From 621fb82cc9320e1e6885dd9942f74994a2a9f87a Mon Sep 17 00:00:00 2001 From: "James O. D. Hunt" Date: Fri, 28 Aug 2020 15:23:47 +0100 Subject: [PATCH] action: Require PR porting labels A PR now needs *two* labels to be applied before it can be merged. One label must be a backport label from the list below and the other a forward port label: - backport labels: `needs-backport`, `no-backport-needed`, `backport`. - forward-port labels: `needs-forward-port`, `no-forward-port-needed`, `forward-port`. This is to make the maintainer think carefully before merging a PR and hopefully maximise efficient porting. Related: https://github.com/kata-containers/kata-containers/issues/634 Fixes: #275. Signed-off-by: James O. D. Hunt --- .../workflows/require-pr-porting-labels.yaml | 134 ++++++++++++++++++ 1 file changed, 134 insertions(+) create mode 100644 .github/workflows/require-pr-porting-labels.yaml diff --git a/.github/workflows/require-pr-porting-labels.yaml b/.github/workflows/require-pr-porting-labels.yaml new file mode 100644 index 0000000..73daa7f --- /dev/null +++ b/.github/workflows/require-pr-porting-labels.yaml @@ -0,0 +1,134 @@ +# Copyright (c) 2020 Intel Corporation +# +# SPDX-License-Identifier: Apache-2.0 +# + +name: Ensure PR has required porting labels + +on: + pull_request_target: + types: + - opened + - reopened + - labeled + - unlabeled + +jobs: + check-pr-porting-labels: + runs-on: ubuntu-latest + steps: + - name: Install hub + run: | + HUB_ARCH="amd64" + HUB_VER=$(curl -sL "https://api.github.com/repos/github/hub/releases/latest" |\ + jq -r .tag_name | sed 's/^v//') + curl -sL \ + "https://github.com/github/hub/releases/download/v${HUB_VER}/hub-linux-${HUB_ARCH}-${HUB_VER}.tgz" |\ + tar xz --strip-components=2 --wildcards '*/bin/hub' && \ + sudo install hub /usr/local/bin + + - name: Checkout code to allow hub to communicate with the project + uses: actions/checkout@v2 + with: + token: ${{ secrets.KATA_GITHUB_ACTIONS_TOKEN }} + + - name: Stop PR being merged unless it has atleast one backport label and one forward port label + env: + GITHUB_TOKEN: ${{ secrets.KATA_GITHUB_ACTIONS_TOKEN }} + run: | + pr=${{ github.event.number }} + + # Every PR must have two porting labels before it can be merged. + # This is to ensure it is clear that a reviewer has considered both + # porting directions. + backport_labels=("needs-backport" "no-backport-needed" "backport") + forward_port_labels=("needs-forward-port" "no-forward-port-needed" "forward-port") + + labels=$(hub api "/repos/{owner}/{repo}/labels" | jq -r '.[].name') + + for label in ${backport_labels[@]} ${forward_port_labels[@]} + do + { echo "$labels"| egrep -q "^${label}$"; ret=$?; } || true + + [ $ret -eq 0 ] || { + echo "::error::Expected label '$label' not available in repository ${{ github.repository }}" + exit 1 + } + done + + pr_details=$(hub pr list -f '%I;%L%n' | grep "^${pr}" || true) + + [ -z "$pr_details" ] && { + echo "::error::Cannot determine details for PR $pr" + exit 1 + } + + pr_labels=$(echo "$pr_details"|cut -d';' -f2|tr ',' ' ') + + [ -z "$pr_labels" ] && { + printf "::error::PR %s does not have required porting labels (expected one of '%s' and one of '%s')\n" \ + "$pr" \ + $(echo "$backport_labels" | tr ' ' ',') \ + $(echo "$forward_port_labels" | tr ' ' ',') + exit 1 + } + + backport_labels_found=() + + for label in ${backport_labels[@]} + do + echo "$pr_labels" | grep -qw "$label" \ + && backport_labels_found+=("$label") + done + + [ "${#backport_labels_found[@]}" -eq 0 ] && { + printf "::error::PR %s missing a backport label (expected one of '%s')\n" \ + "$pr" \ + $(echo "$backport_labels" | tr ' ' ',') + exit 1 + } + + [ "${#backport_labels_found[@]}" -gt 1 ] && { + printf "::error::PR %s has too many backport labels (expected one of '%s', found '%s')\n" \ + "$pr" \ + $(echo "$backport_labels" | tr ' ' ',') \ + $(echo "$backport_labels_found" | tr ' ' ',') + exit 1 + } + + forward_port_labels_found=() + + for label in ${forward_port_labels[@]} + do + echo "$pr_labels" | grep -qw "$label" \ + && forward_port_labels_found+=("$label") + done + + [ "${#forward_port_labels_found[@]}" -eq 0 ] && { + printf "::error::PR %s missing a forward port label (expected one of '%s')\n" \ + "$pr" \ + $(echo "$forward_port_labels" | tr ' ' ',') + exit 1 + } + + [ "${#forward_port_labels_found[@]}" -gt 1 ] && { + printf "::error::PR %s has too many forward port labels (expected one of '%s', found '%s')\n" \ + "$pr" \ + $(echo "$forward_port_labels" | tr ' ' ',') \ + $(echo "$forward_port_labels_found" | tr ' ' ',') + exit 1 + } + + [ "$backport_labels_found" = 'backport-pr' ] && \ + [ "$forward_port_labels_found" = 'forward-port-pr' ] && { + printf "::error::PR %s cannot be labelled as both backport ('%s') and forward port ('%s')\n" \ + "$pr" \ + "$backport_labels_found" \ + "$forward_port_labels_found" + exit 1 + } + + printf "::debug::PR %s has required porting labels (backport label '%s', forward port label '%s')\n" \ + "$pr" \ + "$backport_labels_found" \ + "$forward_port_labels_found"