|
name: Auto-Invite New Member |
|
on: |
|
issues: |
|
types: [opened] |
|
|
|
jobs: |
|
invite: |
|
runs-on: ubuntu-latest |
|
|
|
steps: |
|
- name: Checkout repository |
|
uses: actions/checkout@v4 |
|
|
|
- name: Load configuration |
|
id: load_config |
|
run: | |
|
ORG_NAME=$(yq '.org_name' .github/onboarding-config.yml) |
|
TEAM_LIST=$(yq '.team_list' .github/onboarding-config.yml) |
|
PAT_SECRET_NAME=$(yq '.pat_secret_name' .github/onboarding-config.yml) |
|
MENTION_TEAM=$(yq '.mention_team' .github/onboarding-config.yml) |
|
FAILURE_LABEL=$(yq '.failure_label' .github/onboarding-config.yml) |
|
|
|
echo "ORG_NAME=$ORG_NAME" >> $GITHUB_ENV |
|
echo "TEAM_LIST=$TEAM_LIST" >> $GITHUB_ENV |
|
echo "PAT_SECRET_NAME=$PAT_SECRET_NAME" >> $GITHUB_ENV |
|
echo "MENTION_TEAM=$MENTION_TEAM" >> $GITHUB_ENV |
|
echo "FAILURE_LABEL=$FAILURE_LABEL" >> $GITHUB_ENV |
|
|
|
- name: Check if issue is valid onboarding request |
|
id: check |
|
run: | |
|
BODY="${{ github.event.issue.body }}" |
|
if echo "$BODY" | grep -q "GitHub Username" && echo "$BODY" | grep -q "I agree to follow"; then |
|
echo "valid_request=true" >> $GITHUB_ENV |
|
else |
|
echo "::error ::Issue missing required fields. Exiting." |
|
echo "valid_request=false" >> $GITHUB_ENV |
|
fi |
|
|
|
- name: Extract GitHub Username |
|
if: env.valid_request == 'true' |
|
id: extract |
|
run: | |
|
BODY="${{ github.event.issue.body }}" |
|
USERNAME=$(echo "$BODY" | awk '/### GitHub Username/ {flag=1; next} flag && NF {print; exit}' | xargs) |
|
|
|
if [ -z "$USERNAME" ]; then |
|
echo "::error ::No username found after parsing. Exiting." |
|
exit 1 |
|
fi |
|
|
|
echo "USERNAME=$USERNAME" >> $GITHUB_ENV |
|
echo "username=$USERNAME" >> $GITHUB_OUTPUT |
|
|
|
- name: Lookup GitHub user ID |
|
if: env.valid_request == 'true' |
|
id: lookup |
|
run: | |
|
RESPONSE=$(curl -s -H "Authorization: Bearer ${{ secrets[env.PAT_SECRET_NAME] }}" \ |
|
-H "Accept: application/vnd.github+json" \ |
|
https://api.github.com/users/${{ env.USERNAME }}) |
|
|
|
USER_ID=$(echo "$RESPONSE" | jq '.id // empty') |
|
|
|
if [ -z "$USER_ID" ]; then |
|
echo "::error ::GitHub user not found. Exiting." |
|
exit 1 |
|
fi |
|
|
|
echo "Resolved USER_ID: $USER_ID" |
|
echo "USER_ID=$USER_ID" >> $GITHUB_ENV |
|
echo "user_id=$USER_ID" >> $GITHUB_OUTPUT |
|
|
|
- name: Check org and team membership |
|
if: env.valid_request == 'true' |
|
id: check_membership |
|
run: | |
|
echo "Checking if @${{ env.USERNAME }} is already fully onboarded..." |
|
|
|
ORG_MEMBER=$(curl -s -o /dev/null -w "%{http_code}" \ |
|
-H "Authorization: Bearer ${{ secrets[env.PAT_SECRET_NAME] }}" \ |
|
-H "Accept: application/vnd.github+json" \ |
|
https://api.github.com/orgs/${{ env.ORG_NAME }}/members/${{ env.USERNAME }}) |
|
|
|
ALL_TEAMS_OK=true |
|
|
|
IFS=',' read -ra TEAMS <<< "${{ env.TEAM_LIST }}" |
|
for TEAM in "${TEAMS[@]}"; do |
|
TEAM=$(echo "$TEAM" | xargs) |
|
TEAM_MEMBER=$(curl -s -o /dev/null -w "%{http_code}" \ |
|
-H "Authorization: Bearer ${{ secrets[env.PAT_SECRET_NAME] }}" \ |
|
-H "Accept: application/vnd.github+json" \ |
|
https://api.github.com/orgs/${{ env.ORG_NAME }}/teams/${TEAM}/memberships/${{ env.USERNAME }}) |
|
|
|
if [ "$TEAM_MEMBER" -ne 200 ]; then |
|
echo "β Not in team: $TEAM" |
|
ALL_TEAMS_OK=false |
|
else |
|
echo "β
Already in team: $TEAM" |
|
fi |
|
done |
|
|
|
if [ "$ORG_MEMBER" -eq 204 ] && [ "$ALL_TEAMS_OK" == "true" ]; then |
|
echo "β
Fully onboarded." |
|
echo "already_fully_member=true" >> $GITHUB_ENV |
|
else |
|
echo "π§ Needs onboarding." |
|
echo "already_fully_member=false" >> $GITHUB_ENV |
|
fi |
|
|
|
- name: Invite to organization |
|
if: env.valid_request == 'true' && env.already_fully_member == 'false' |
|
run: | |
|
ORG_MEMBER=$(curl -s -o /dev/null -w "%{http_code}" \ |
|
-H "Authorization: Bearer ${{ secrets[env.PAT_SECRET_NAME] }}" \ |
|
-H "Accept: application/vnd.github+json" \ |
|
https://api.github.com/orgs/${{ env.ORG_NAME }}/members/${{ env.USERNAME }}) |
|
|
|
if [ "$ORG_MEMBER" -ne 204 ]; then |
|
echo "Inviting USER_ID=${{ env.USER_ID }} to organization..." |
|
curl -X POST \ |
|
-H "Authorization: Bearer ${{ secrets[env.PAT_SECRET_NAME] }}" \ |
|
-H "Accept: application/vnd.github+json" \ |
|
https://api.github.com/orgs/${{ env.ORG_NAME }}/invitations \ |
|
-d "{\"invitee_id\": ${{ env.USER_ID }}}" |
|
else |
|
echo "Already in organization." |
|
fi |
|
|
|
- name: Add to teams |
|
if: env.valid_request == 'true' && env.already_fully_member == 'false' |
|
id: add_teams |
|
run: | |
|
team_add_failed=false |
|
|
|
echo "Adding @${{ env.USERNAME }} to required teams..." |
|
|
|
IFS=',' read -ra TEAMS <<< "${{ env.TEAM_LIST }}" |
|
for TEAM in "${TEAMS[@]}"; do |
|
TEAM=$(echo "$TEAM" | xargs) |
|
|
|
TEAM_EXISTS=$(curl -s -o /dev/null -w "%{http_code}" \ |
|
-H "Authorization: Bearer ${{ secrets[env.PAT_SECRET_NAME] }}" \ |
|
-H "Accept: application/vnd.github+json" \ |
|
https://api.github.com/orgs/${{ env.ORG_NAME }}/teams/${TEAM}) |
|
|
|
if [ "$TEAM_EXISTS" -ne 200 ]; then |
|
echo "::warning ::Team $TEAM does not exist. Skipping." |
|
team_add_failed=true |
|
continue |
|
fi |
|
|
|
TEAM_MEMBER=$(curl -s -o /dev/null -w "%{http_code}" \ |
|
-H "Authorization: Bearer ${{ secrets[env.PAT_SECRET_NAME] }}" \ |
|
-H "Accept: application/vnd.github+json" \ |
|
https://api.github.com/orgs/${{ env.ORG_NAME }}/teams/${TEAM}/memberships/${{ env.USERNAME }}) |
|
|
|
if [ "$TEAM_MEMBER" -ne 200 ]; then |
|
ADD_RESPONSE=$(curl -s -w "%{http_code}" -o /dev/null \ |
|
-X PUT \ |
|
-H "Authorization: Bearer ${{ secrets[env.PAT_SECRET_NAME] }}" \ |
|
-H "Accept: application/vnd.github+json" \ |
|
https://api.github.com/orgs/${{ env.ORG_NAME }}/teams/${TEAM}/memberships/${{ env.USERNAME }}) |
|
|
|
if [ "$ADD_RESPONSE" -ne 200 ] && [ "$ADD_RESPONSE" -ne 201 ]; then |
|
echo "::warning ::Failed to add ${{ env.USERNAME }} to team $TEAM" |
|
team_add_failed=true |
|
else |
|
echo "Added user to team: $TEAM" |
|
fi |
|
else |
|
echo "Already in team: $TEAM" |
|
fi |
|
done |
|
|
|
echo "team_add_failed=$team_add_failed" >> $GITHUB_ENV |
|
|
|
- name: Comment back on issue |
|
if: env.valid_request == 'true' |
|
run: | |
|
if [ "${{ env.already_fully_member }}" == "true" ]; then |
|
COMMENT_BODY="β
@${{ env.USERNAME }} is already a full member (organization + teams)!" |
|
elif [ "${{ env.team_add_failed }}" == "true" ]; then |
|
COMMENT_BODY="β οΈ ${{ env.MENTION_TEAM }} Attention needed: @${{ env.USERNAME }} was invited, but some team additions failed." |
|
else |
|
COMMENT_BODY="π @${{ env.USERNAME }} has been invited and added to required teams! Welcome aboard!" |
|
fi |
|
|
|
curl -X POST \ |
|
-H "Authorization: Bearer ${{ secrets[env.PAT_SECRET_NAME] }}" \ |
|
-H "Accept: application/vnd.github+json" \ |
|
https://api.github.com/repos/${{ github.repository }}/issues/${{ github.event.issue.number }}/comments \ |
|
-d "{\"body\":\"$COMMENT_BODY\"}" |
|
|
|
- name: Add failure label if configured |
|
if: env.valid_request == 'true' && env.team_add_failed == 'true' && env.FAILURE_LABEL != '' |
|
run: | |
|
echo "Adding failure label '${{ env.FAILURE_LABEL }}'..." |
|
curl -X POST \ |
|
-H "Authorization: Bearer ${{ secrets[env.PAT_SECRET_NAME] }}" \ |
|
-H "Accept: application/vnd.github+json" \ |
|
https://api.github.com/repos/${{ github.repository }}/issues/${{ github.event.issue.number }}/labels \ |
|
-d "{\"labels\": [\"${{ env.FAILURE_LABEL }}\"]}" |
|
|
|
- name: Close the issue |
|
if: env.valid_request == 'true' |
|
run: | |
|
if [ "${{ env.team_add_failed }}" != "true" ]; then |
|
curl -X PATCH \ |
|
-H "Authorization: Bearer ${{ secrets[env.PAT_SECRET_NAME] }}" \ |
|
-H "Accept: application/vnd.github+json" \ |
|
https://api.github.com/repos/${{ github.repository }}/issues/${{ github.event.issue.number }} \ |
|
-d '{"state":"closed"}' |
|
else |
|
echo "Not closing because team additions failed." |
|
fi |