Skip to content

ci: Add Github action to add "has:owner-approval" label for approved PRs #2798

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

Open
wants to merge 8 commits into
base: main
Choose a base branch
from
Open
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
22 changes: 22 additions & 0 deletions .github/workflows/pr-review.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
name: PR review
# This workflow is triggered when a PR review is submitted. It checks if the review is approved and runs a script to add labels to the PR based on the review.
on:
pull_request_review:
types:
- submitted
Comment on lines +3 to +6
Copy link
Member

Choose a reason for hiding this comment

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

Hmm, I think that the pull_request_review trigger only provides a read-only GITHUB_TOKEN - I guess it would not be able to re-label the PR in that case, right? 🤔

Thinking more about it, I'm also wondering if there are some security concerns if we were to give the workflow additional permissions. 🤔

Copy link
Member Author

Choose a reason for hiding this comment

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

We can add permissions by workflow right? that would prevent us to change the default permissions and keep them read only for other workflows


jobs:
add-owner-approved-label:
if: github.event.review.state == 'approved'
runs-on: ubuntu-latest
steps:
- name: Checkout
uses: actions/checkout@v4

- name: Run add-labels-to-reviewed-pr.sh
run: ./.github/workflows/scripts/add-labels-to-reviewed-pr.sh
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
REPO: ${{ github.repository }}
PR: ${{ github.event.number }}

75 changes: 75 additions & 0 deletions .github/workflows/scripts/add-labels-to-reviewed-pr.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,75 @@
#!/usr/bin/env bash
#
# Copyright The OpenTelemetry 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
#
# https://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.
#
# Adds a "has:owner-approval" label to a PR if a reviewer who approved it is a component owner.

set -euo pipefail

if [[ -z "${REPO:-}" || -z "${PR:-}" ]]; then
echo "One or more of REPO and PR have not been set. Please ensure each is set."
exit 0
fi

main () {
CUR_DIRECTORY=$(dirname "$0")

# The latestReviews key returns the latest review for each reviewer cutting out any other reviews.
JSON=$(gh pr view "${PR}" --json "files,author,latestReviews" | tr -dc '[:print:]' | sed -E 's/\\[a-z]//g')
FILES=$(echo -n "${JSON}"| jq -r '.files[].path')
LATEST_REVIEWS=$(echo -n "${JSON}" | jq -c '.latestReviews')

# Fetch components
COMPONENTS=$(bash "${CUR_DIRECTORY}/get-components.sh" | tac) # Reversed so we visit subdirectories first

declare -A PROCESSED_COMPONENTS

for COMPONENT in ${COMPONENTS}; do
COMPONENT_OWNERS=$(COMPONENT="${COMPONENT}" bash "${CUR_DIRECTORY}/get-codeowners.sh")

for FILE in ${FILES}; do
MATCH=$(echo -n "${FILE}" | grep -E "^${COMPONENT}" || true)

if [[ -z "${MATCH}" ]]; then
continue
fi

# If we match a file with a component, skip further processing for this file
if [[ -v PROCESSED_COMPONENTS["${COMPONENT}"] ]]; then
continue
fi
PROCESSED_COMPONENTS["${COMPONENT}"]=true

# Check if updated file is owned by one of the reviewers"
echo "${LATEST_REVIEWS}" | jq -c '.[]' | while IFS= read -r REVIEW; do
REVIEW_AUTHOR=$(echo -n "${REVIEW}"| jq -r '.author.login')
REVIEW_STATE=$(echo -n "${REVIEW}"| jq -r '.state')
if [[ "${REVIEW_STATE}" == "APPROVED" ]]; then
# Review is approved. Checking if reviewer is a component owner
for OWNER in ${COMPONENT_OWNERS}; do
if [[ "${REVIEW_AUTHOR}" == "${OWNER}" ]]; then
echo "Reviewer $REVIEW_AUTHOR is a component owner. Adding 'has:owner-approval' label."
gh pr edit "${PR}" --repo "${REPO}" --add-label "has:owner-approval"
exit 0
fi
done
fi
done
done
done
}

# Ensure the script does not block a PR even if it fails
main || echo "Failed to run $0"
50 changes: 50 additions & 0 deletions .github/workflows/scripts/get-codeowners.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,50 @@
#!/usr/bin/env bash
#
# Copyright The OpenTelemetry 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
#
# https://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.
#
# Gets the owners for a given component from the component_owners.yml file.

# Define the file path
YML_FILE=".github/component_owners.yml"

if [[ -z "${COMPONENT:-}" ]]; then
echo "COMPONENT has not been set, please ensure it is set."
exit 1
fi

FOUND=0

# Parse the YAML file and extract owners for the given component
while IFS= read -r line; do
# Check if the line matches the given component
if [[ "$line" =~ ^[[:space:]]*${COMPONENT}:[[:space:]]*$ ]]; then
FOUND=1
continue
fi

# If the component is found, extract owners
if [[ $FOUND -eq 1 ]]; then
# Stop if we encounter another component or an empty line
if [[ "$line" =~ ^[[:space:]]*[^#]+: || -z "$line" ]]; then
break
fi

# Extract the owner (remove leading spaces and '- ')
if [[ "$line" =~ ^[[:space:]]*-[[:space:]]*[^#]+ ]]; then
OWNER=$(echo "$line" | sed -E 's/^[[:space:]]*-[[:space:]]*([^#]+).*/\1/')
echo "$OWNER"
fi
fi
done < "$YML_FILE"
31 changes: 31 additions & 0 deletions .github/workflows/scripts/get-components.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
#!/usr/bin/env bash
#
# Copyright The OpenTelemetry 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
#
# https://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.
#
# Gets the components from the component_owners.yml file.


# Define the file path
YML_FILE=".github/component_owners.yml"

# Parse the YAML file and extract components and their owners
while IFS= read -r line; do
# Check if the line contains a component (ends with ':')
if [[ "$line" =~ ^[[:space:]]*[^#]+: ]]; then
# Extract the component name (remove leading spaces and trailing ':')
COMPONENT=$(echo "$line" | sed -E 's/^[[:space:]]*([^:]+):.*/\1/')
echo "$COMPONENT"
fi
done < "$YML_FILE"