[TEAM] TEAM-KLP #96
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| name: Route Issue to Repo or Team PR | |
| on: | |
| issues: | |
| types: [opened] | |
| permissions: | |
| contents: write | |
| pull-requests: write | |
| jobs: | |
| process_repo_or_team_request: | |
| runs-on: ubuntu-latest | |
| steps: | |
| - name: Checkout Repository | |
| uses: actions/checkout@v4 | |
| - name: Determine Request Type | |
| id: classify | |
| run: | | |
| TITLE="${{ github.event.issue.title }}" | |
| echo "Issue Title: $TITLE" | |
| if [[ "$TITLE" == *"[Repo Request]"* ]]; then | |
| echo "type=repo" >> $GITHUB_OUTPUT | |
| elif [[ "$TITLE" == *"[TEAM]"* ]]; then | |
| echo "type=team" >> $GITHUB_OUTPUT | |
| else | |
| echo "Unsupported issue type, skipping." | |
| echo "type=skip" >> $GITHUB_OUTPUT | |
| fi | |
| - name: Stop if unsupported issue | |
| if: steps.classify.outputs.type == 'skip' | |
| run: echo "No supported issue type found. Exiting." | |
| - name: Process Repo Request | |
| if: steps.classify.outputs.type == 'repo' | |
| run: | | |
| ISSUE_BODY=$(jq -r '.issue.body' "$GITHUB_EVENT_PATH") | |
| # Print the full issue body to debug formatting issues | |
| echo "Full ISSUE_BODY content:" | |
| echo "$ISSUE_BODY" | |
| - name: Parse Issue Details | |
| if: steps.classify.outputs.type == 'repo' | |
| id: parse | |
| run: | | |
| ISSUE_BODY=$(jq -r '.issue.body' "$GITHUB_EVENT_PATH") | |
| # Extract values by looking for the header and getting the next non-empty line | |
| REPO_NAME=$(echo "$ISSUE_BODY" | awk -F'\n' '/^### Repository Name$/{getline; getline; print $0}' | sed 's/^[[:space:]]*//;s/[[:space:]]*$//') | |
| VISIBILITY=$(echo "$ISSUE_BODY" | awk -F'\n' '/^### Visibility$/{getline; getline; print $0}' | sed 's/^[[:space:]]*//;s/[[:space:]]*$//') | |
| BRANCH=$(echo "$ISSUE_BODY" | awk -F'\n' '/^### Default Branch$/{getline; getline; print $0}' | sed 's/^[[:space:]]*//;s/[[:space:]]*$//') | |
| INCLUDE_README=$(echo "$ISSUE_BODY" | awk -F'\n' '/^### Include README$/{getline; getline; print $0}' | sed 's/^[[:space:]]*//;s/[[:space:]]*$//') | |
| # Debugging Output | |
| echo "Extracted Repository Name: '$REPO_NAME'" | |
| echo "Extracted Visibility: '$VISIBILITY'" | |
| echo "Extracted Branch: '$BRANCH'" | |
| echo "Extracted Include README: '$INCLUDE_README'" | |
| # Ensure default values if missing | |
| if [ -z "$REPO_NAME" ]; then echo "Error: Repository Name is required"; exit 1; fi | |
| if [ -z "$BRANCH" ]; then BRANCH="main"; fi | |
| echo "REPO_NAME=$REPO_NAME" >> $GITHUB_ENV | |
| echo "VISIBILITY=$VISIBILITY" >> $GITHUB_ENV | |
| echo "BRANCH=$BRANCH" >> $GITHUB_ENV | |
| echo "INCLUDE_README=$INCLUDE_README" >> $GITHUB_ENV | |
| - name: Set Git Identity | |
| if: steps.classify.outputs.type == 'repo' | |
| run: | | |
| git config --global user.name "github-actions" | |
| git config --global user.email "github-actions@github.com" | |
| - name: Create Repository Structure | |
| if: steps.classify.outputs.type == 'repo' | |
| run: | | |
| mkdir -p repos/${{ env.REPO_NAME }} | |
| cd repos/${{ env.REPO_NAME }} | |
| git init -b ${{ env.BRANCH }} | |
| # Ensure at least one file exists before committing | |
| if [[ "${{ env.INCLUDE_README }}" == "Yes" ]]; then | |
| echo "# ${{ env.REPO_NAME }}" > README.md | |
| else | |
| touch .gitkeep # Create a placeholder file if README is not included | |
| fi | |
| git add . | |
| git commit -m "Initial commit for ${{ env.REPO_NAME }}" | |
| - name: Commit Changes | |
| if: steps.classify.outputs.type == 'repo' | |
| run: | | |
| cd repos/${{ env.REPO_NAME }} | |
| git add . | |
| git commit -m "Add repository structure for ${{ env.REPO_NAME }}" || echo "No changes to commit" | |
| - name: Create Pull Request for Repository | |
| if: steps.classify.outputs.type == 'repo' | |
| uses: peter-evans/create-pull-request@v6 | |
| with: | |
| token: ${{ secrets.GH_PAT }} | |
| title: "Create new repository: ${{ env.REPO_NAME }}" | |
| body: | | |
| Repository Details: | |
| - **Name**: ${{ env.REPO_NAME }} | |
| - **Visibility**: ${{ env.VISIBILITY }} | |
| - **Default Branch**: ${{ env.BRANCH }} | |
| - **Include README**: ${{ env.INCLUDE_README }} | |
| branch: "create-${{ env.REPO_NAME }}" | |
| - name: Process Team Request | |
| if: steps.classify.outputs.type == 'team' | |
| run: | | |
| # Extract issue body from GitHub event | |
| ISSUE_BODY="${{ github.event.issue.body }}" | |
| # Debugging: Print the issue body | |
| echo "Issue Body:" | |
| echo "$ISSUE_BODY" | |
| TEAM_NAME=$(echo "$ISSUE_BODY" | awk '/^### Team Name$/{getline; getline; print}' | sed 's/[`]//g' | xargs) | |
| PARENT_TEAM=$(echo "$ISSUE_BODY" | awk '/^### Parent Team \(optional\)$/{getline; getline; print}' | sed 's/[`]//g' | xargs) | |
| VISIBILITY=$(echo "$ISSUE_BODY" | awk '/^### Visibility$/{getline; getline; print}' | sed 's/[`]//g' | xargs) | |
| PURPOSE=$(echo "$ISSUE_BODY" | awk '/^### Purpose$/{getline; getline; print}' | sed 's/[`]//g' | xargs) | |
| MAINTAINERS=$(echo "$ISSUE_BODY" | awk '/^### Maintainers \(comma-separated\)$/{getline; getline; print}' | sed 's/[`]//g' | xargs) | |
| TEAM_MEMBERS=$(echo "$ISSUE_BODY" | awk '/^### Team Members \(comma-separated\)$/{getline; getline; print}' | sed 's/[`]//g' | xargs) | |
| echo "Extracted Values:" | |
| echo "Team Name: '$TEAM_NAME'" | |
| echo "Visibility: '$VISIBILITY'" | |
| echo "Purpose: '$PURPOSE'" | |
| echo "Maintainers: '$MAINTAINERS'" | |
| echo "Team Members: '$TEAM_MEMBERS'" | |
| echo "parent_team=$PARENT_TEAM" >> "$GITHUB_ENV" | |
| if [[ ! "$TEAM_NAME" =~ ^TEAM-[a-zA-Z0-9_-]{1,20}$ ]]; then | |
| echo "::error::Invalid team name format: '$TEAM_NAME'" | |
| exit 1 | |
| fi | |
| VISIBILITY=${VISIBILITY:-Visible} | |
| PURPOSE=${PURPOSE:-Team created via automation} | |
| MAINTAINERS=${MAINTAINERS:-none} | |
| TEAM_MEMBERS=${TEAM_MEMBERS:-none} | |
| PARENT_TEAM=${PARENT_TEAM:-none} | |
| echo "$TEAM_NAME" > team-name.txt | |
| echo "team_name=$TEAM_NAME" >> "$GITHUB_ENV" | |
| echo "visibility=$VISIBILITY" >> "$GITHUB_ENV" | |
| echo "purpose=$PURPOSE" >> "$GITHUB_ENV" | |
| echo "maintainers=$MAINTAINERS" >> "$GITHUB_ENV" | |
| echo "team_members=$TEAM_MEMBERS" >> "$GITHUB_ENV" | |
| echo "parent_team=$PARENT_TEAM" >> "$GITHUB_ENV" | |
| - name: Debug team info | |
| run: | | |
| echo "Maintainers to validate: $MAINTAINERS" | |
| echo "Team members to validate: $TEAM_MEMBERS" | |
| env: | |
| MAINTAINERS: ${{ env.maintainers }} | |
| TEAM_MEMBERS: ${{ env.team_members }} | |
| - name: Install jq | |
| run: sudo apt-get install -y jq | |
| - name: Validate GitHub usernames | |
| if: env.maintainers != '_No response_' || env.team_members != '_No response_' | |
| shell: bash | |
| run: | | |
| # Function to validate a GitHub username | |
| validate_username() { | |
| local username=$1 | |
| response=$(curl -s -H "Authorization: token $GITHUB_TOKEN" "https://api.github.com/users/$username") | |
| if echo "$response" | grep -q '"login":'; then | |
| echo "✅ Valid GitHub user: $username" | |
| else | |
| echo "::error::❌ Invalid or non-existent GitHub user: $username" | |
| echo "Response: $response" | |
| exit 1 | |
| fi | |
| } | |
| echo "Checking for users to validate..." | |
| # Validate maintainers if defined | |
| if [[ "$MAINTAINERS" != "_No response_" && "$MAINTAINERS" != "none" && -n "$MAINTAINERS" ]]; then | |
| echo "Validating maintainers..." | |
| IFS=',' read -ra MAINTAINER_ARRAY <<< "$MAINTAINERS" | |
| for user in "${MAINTAINER_ARRAY[@]}"; do | |
| trimmed=$(echo "$user" | xargs) | |
| [ -n "$trimmed" ] && validate_username "$trimmed" | |
| done | |
| else | |
| echo "No maintainers to validate" | |
| fi | |
| # Validate team members if defined | |
| if [[ "$TEAM_MEMBERS" != "_No response_" && "$TEAM_MEMBERS" != "none" && -n "$TEAM_MEMBERS" ]]; then | |
| echo "Validating team members..." | |
| IFS=',' read -ra MEMBER_ARRAY <<< "$TEAM_MEMBERS" | |
| for user in "${MEMBER_ARRAY[@]}"; do | |
| trimmed=$(echo "$user" | xargs) | |
| [ -n "$trimmed" ] && validate_username "$trimmed" | |
| done | |
| else | |
| echo "No team members to validate" | |
| fi | |
| env: | |
| GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} | |
| MAINTAINERS: ${{ env.maintainers }} | |
| TEAM_MEMBERS: ${{ env.team_members }} | |
| - name: Create Pull Request for Team | |
| if: steps.classify.outputs.type == 'team' | |
| uses: peter-evans/create-pull-request@v5 | |
| with: | |
| token: ${{ secrets.GH_PAT }} | |
| commit-message: "Add team: ${{ env.team_name }}" | |
| title: "Create team: ${{ env.team_name }}" | |
| body: | | |
| ### Team Creation Request | |
| **Team Name:** ${{ env.team_name }} | |
| **Parent Team:** ${{ env.parent_team }} | |
| **Visibility:** ${{ env.visibility }} | |
| **Purpose:** ${{ env.purpose }} | |
| **Maintainers:** ${{ env.maintainers }} | |
| **Team Members:** ${{ env.team_members }} | |
| Generated from issue #${{ github.event.issue.number }} | |
| branch: "team-request/${{ github.event.issue.number }}" | |
| labels: "team-creation" | |
| paths: | | |
| team-name.txt | |
| - name: Post a message in Slack | |
| uses: slackapi/slack-github-action@v2.0.0 | |
| with: | |
| webhook: ${{ secrets.SLACK_TOKEN }} | |
| webhook-type: incoming-webhook | |
| payload: | | |
| text: "*New Team PR Created: `${{ env.team_name }}`*" | |
| blocks: | |
| - type: section | |
| text: | |
| type: mrkdwn | |
| text: ":tada: A new PR has been created for team *`${{ env.team_name }}`*!\n*Purpose:* ${{ env.purpose }}\n*Maintainers:* ${{ env.maintainers }}\n*Parent:* `${{ env.parent_team }}`\n<https://github.com/${{ github.repository }}/pull/${{ steps.create_pr.outputs.pull-request-number }}|View Pull Request>" | |