Skip to content
Closed
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
15 changes: 15 additions & 0 deletions .github/workflows/lint.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -33,3 +33,18 @@ jobs:
echo "Run './tools/generate-codeowners.sh' and submit your changes"
exit 1
fi
members:
if: github.repository == 'cilium/community'
name: Validate
runs-on: ubuntu-latest
environment: team-management
steps:
- uses: actions/checkout@5a4ac9002d0be2fb38bd78e4b4dbde5606d7042f
with:
persist-credentials: false
fetch-depth: '0'
# Lint team membership files for org members
- name: Run tools/lint_members.sh
run: tools/lint_members.sh ladder/teams cilium
env:
GITHUB_TOKEN: ${{ secrets.TM_READ_ORG_TOKEN }}
Copy link
Member

Choose a reason for hiding this comment

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

Might need to rethink this access token. Pull requests aren't going to be able to access secrets in the organization.

163 changes: 163 additions & 0 deletions tools/lint_members.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,163 @@
#!/usr/bin/env bash
# Copyright Authors of Cilium
# SPDX-License-Identifier: Apache-2.0

##
# This script is used to lint team membership
# file based on a directory of yaml files of the
# form team-name.yaml
# This tool is used as part of team-management automation
##

set -eu
set -o pipefail

# $1 - teams directory
# $2 - org name
if [ $# -ne 2 ]; then
echo "Usage: $0 <TEAMS_DIRECTORY> <GITHUB_ORG>"
echo "Organization read token in envvar GITHUB_TOKEN"
exit 1
fi

>&2 echo "> Linting $2 teams from $1/*.yaml"
CDIR=`pwd`
cd "$1"

# Use GitHub API with paging to recover Org member login list
Copy link
Member

Choose a reason for hiding this comment

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

nit: It'd be nice to structure this a bit more formally with functions, just to make it easier to track the structure of the execution.

url="https://api.github.com/orgs/$2/members"
page=1
flag=true
logins=()
check_org_members=true
while $flag; do
status=$(curl --head --location --connect-timeout 5 --write-out %{http_code} --silent --output /dev/null -H "Authorization: Bearer $GITHUB_TOKEN" ${url}?page=${page})
if [[ "$status" -gt 399 ]] ; then
echo "GitHub API Org Membership Retrieval Failure with Status Code: $status"
flag=false
check_org_members=false
fi
if $flag; then
response=$( curl -s -I -H "Authorization: Bearer $GITHUB_TOKEN" "${url}?page=${page}" )
# Append to logins array
logins+=( `curl --no-progress-meter -L \
-H "Accept: application/vnd.github+json" \
-H "Authorization: Bearer $GITHUB_TOKEN" \
-H "X-GitHub-Api-Version: 2022-11-28" \
${url}?page=${page} | jq -r '.[].login'` )

# Check to see if there is a next page to grab
set +o pipefail
next_page=$(echo "$response" | grep -s 'rel="next"' | sed 's/.*<//' | sed 's/>.*//')
set -o pipefail

if [[ -z "$next_page" ]]; then
flag=false
fi

page=$((page + 1))
fi
done
if $check_org_members; then
>&2 echo "Org Members:"
for login in "${logins[@]}"; do
>&2 echo "$login"
done
fi
>&2 echo ""

status=0
for file in *.yaml; do
Copy link
Member

Choose a reason for hiding this comment

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

Rather than running per file, this should probably list all members (tools/list-members) and validate from there. This would reduce duplicate API calls for the same usernames.

>&2 echo -e "\n>> Linting members from $file"
f="${file%.*}"
cd "$CDIR"; cd "$1"
set +e
members=$(yq -e -o t '.members' $file 2>/dev/null)
ret=$?
set -e
if [ $ret -ne 0 ]; then
continue
fi
for member in ${members[@]}; do
if [ -n "$member" ]; then

#>&2 echo "checking team member: $member"
# Checking to see if team member login is cased correctly
http_status=`curl --header "Authorization: Bearer $GITHUB_TOKEN" --head --location --connect-timeout 5 --write-out %{http_code} --silent --output /dev/null --no-progress-meter "https://api.github.com/users/${member}"`
Copy link
Member

Choose a reason for hiding this comment

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

nit: Idly wondering whether it could be simpler to use gh api ... or similar GitHub CLI commands rather than curl. Not sure it makes a big difference.

if [[ "$http_status" -gt 399 ]] ; then
>&2 echo "Error: Member: ${member} :: GitHub API Status Code: $http_status"
status=1
else
login=`curl --header "Authorization: Bearer $GITHUB_TOKEN" --no-progress-meter "https://api.github.com/users/${member}" | jq -r .login`
if [ "$login" == "$member" ] ; then
found=1
else
>&2 echo "Team $f Member: $member case mistatch should be : $login"
status=1
fi
fi

# Checking to see if team member login is in org membership
if $check_org_members; then
found=0
for login in "${logins[@]}"; do
if [ "$login" == "$member" ] ; then
found=1
fi
done
if [ $found -eq 0 ] ; then
>&2 echo "Team $f Member: $member not found in Org: $2"
status=1
fi
fi
fi
done
>&2 echo -e "\n>> Linting mentors from $file"

set +e
mentors=$(yq -e -o t '.mentors' $file 2>/dev/null)
ret=$?
set -e
if [ $ret -ne 0 ]; then
continue
fi
for mentor in ${mentors[@]}; do
Copy link
Member

Choose a reason for hiding this comment

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

This could do with some DRY by defining a function that takes the list as input and iterating over it. Seems like the next 40 or so LoC are very similar to the previous check.

if [ -n "$mentor" ]; then
>&2 echo "checking team mentor: $mentor"
# Checking to see if team mentor login is cased correctly
http_status=`curl --header "Authorization: Bearer $GITHUB_TOKEN" --head --location --connect-timeout 5 --write-out %{http_code} --silent --output /dev/null --no-progress-meter "https://api.github.com/users/${mentor}"`
if [[ "$http_status" -gt 399 ]] ; then
>&2 echo "Error: Mentor: ${mentor} :: GitHub API Status Code: $http_status"
status=1
else
login=`curl --header "Authorization: Bearer $GITHUB_TOKEN" --no-progress-meter "https://api.github.com/users/${mentor}" | jq -r .login`
if [ "$login" == "$mentor" ] ; then
found=1
else
>&2 echo "Team $f Mentor: $mentor case mistatch should be : $login"
status=1
fi
fi

# Checking to see if team mentor login is in org membership
if $check_org_members; then
found=0
for login in "${logins[@]}"; do
if [ "$login" == "$mentor" ] ; then
found=1
fi
done
if [ $found -eq 0 ] ; then
>&2 echo "Team $f Mentor: $mentor not found in Org: $2"
status=1
fi
fi
fi
done
done
if [ $status -eq 1 ] ; then
>&2 echo -e "\n> At least one team member or mentor missing from org $2: exiting"
exit 1
fi


Loading