[Project 2] #36
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: Add Project from Issue | |
| on: | |
| issues: | |
| types: [labeled] | |
| permissions: | |
| contents: write | |
| issues: write | |
| pull-requests: write | |
| jobs: | |
| restrict-and-add-project: | |
| runs-on: ubuntu-latest | |
| steps: | |
| # Checkout repository | |
| - name: Checkout repository | |
| uses: actions/checkout@v4 | |
| # Define allowed and restricted labels | |
| - name: Define label rules | |
| run: | | |
| echo "RESTRICTED=approved,security,release-ready" >> $GITHUB_ENV | |
| echo "ALLOWED=bug,question,help wanted,enhancement,Music,Video,Chatbot" >> $GITHUB_ENV | |
| echo "MAINTAINERS=arinagrawal05" >> $GITHUB_ENV | |
| # Enforce label restrictions | |
| - name: Enforce label restrictions | |
| env: | |
| GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} | |
| run: | | |
| LABEL="${{ github.event.label.name }}" | |
| SENDER="${{ github.event.sender.login }}" | |
| ISSUE_NUMBER="${{ github.event.issue.number }}" | |
| IFS=',' read -ra RESTRICTED_ARRAY <<< "$RESTRICTED" | |
| IFS=',' read -ra ALLOWED_ARRAY <<< "$ALLOWED" | |
| IFS=',' read -ra MAINTAINERS_ARRAY <<< "$MAINTAINERS" | |
| if [[ " ${RESTRICTED_ARRAY[*]} " =~ " $LABEL " ]] && [[ ! " ${MAINTAINERS_ARRAY[*]} " =~ " $SENDER " ]]; then | |
| echo "Restricted label '$LABEL' added by non-maintainer. Removing..." | |
| gh issue edit $ISSUE_NUMBER --remove-label "$LABEL" | |
| gh issue comment $ISSUE_NUMBER --body "Hi @$SENDER, the label '$LABEL' is restricted to maintainers and has been removed." | |
| exit 0 | |
| fi | |
| if [[ ! " ${RESTRICTED_ARRAY[*]} " =~ " $LABEL " ]] && [[ ! " ${ALLOWED_ARRAY[*]} " =~ " $LABEL " ]]; then | |
| echo "Label '$LABEL' is not allowed. Removing..." | |
| gh issue edit $ISSUE_NUMBER --remove-label "$LABEL" | |
| gh issue comment $ISSUE_NUMBER --body "Hi @$SENDER, the label '$LABEL' is not allowed and has been removed." | |
| exit 0 | |
| fi | |
| # Extract project info | |
| - name: Extract project info | |
| if: ${{ github.event.label.name == 'approved' && contains(env.MAINTAINERS, github.event.sender.login) }} | |
| id: extract | |
| env: | |
| GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} | |
| run: | | |
| echo "Approved label added by maintainer. Processing project..." | |
| ISSUE_BODY=$(gh issue view ${{ github.event.issue.number }} --json body -q '.body') | |
| NAME=$(echo "$ISSUE_BODY" | grep -A1 "Project Name" | tail -n1 | xargs) | |
| REPO=$(echo "$ISSUE_BODY" | grep -A1 "Repository URL" | tail -n1 | xargs) | |
| WEBSITE=$(echo "$ISSUE_BODY" | grep -A1 "Project Website URL" | tail -n1 | xargs) | |
| DESC=$(echo "$ISSUE_BODY" | grep -A1 "Short Description" | tail -n1 | xargs) | |
| CATEGORY=$(echo "$ISSUE_BODY" | grep -A1 "Category" | tail -n1 | xargs) | |
| echo "NAME=$NAME" >> $GITHUB_ENV | |
| echo "REPO=$REPO" >> $GITHUB_ENV | |
| echo "WEBSITE=$WEBSITE" >> $GITHUB_ENV | |
| echo "DESC=$DESC" >> $GITHUB_ENV | |
| echo "CATEGORY=$CATEGORY" >> $GITHUB_ENV | |
| # Update README with extracted info | |
| - name: Update README | |
| if: ${{ github.event.label.name == 'approved' && contains(env.MAINTAINERS, github.event.sender.login) }} | |
| run: | | |
| python3 - <<'PY' | |
| import re | |
| from pathlib import Path | |
| import os | |
| readme = Path("README.md") | |
| text = readme.read_text(encoding="utf-8") if readme.exists() else "" | |
| name = os.environ["NAME"] | |
| repo = os.environ["REPO"] | |
| website = os.environ["WEBSITE"] | |
| desc = os.environ["DESC"] | |
| category = os.environ.get("CATEGORY") or "Other" | |
| website_md = f"[{website}]({website})" if website else "—" | |
| row = f"| {name} | [Repo]({repo}) | {website_md} | {desc} |" | |
| lines = text.splitlines() | |
| cat_header_pattern = re.compile(rf"##\s*{re.escape(category)}", re.I) | |
| header_idx = next((i for i, l in enumerate(lines) if cat_header_pattern.match(l)), None) | |
| if header_idx is not None: | |
| table_header_idx = next((i for i in range(header_idx+1, len(lines)) | |
| if re.search(r"\|\s*Name\s*\|.*\|\s*Repo\s*\|", lines[i])), None) | |
| if table_header_idx is not None: | |
| if any(name in l for l in lines[table_header_idx+2:]): | |
| print(f"Project '{name}' already exists in '{category}'. Skipping insert.") | |
| else: | |
| lines.insert(table_header_idx + 2, row) | |
| else: | |
| insert_at = header_idx + 1 | |
| block = [ | |
| "", | |
| "| Name | Repo | Website | Description |", | |
| "|------|------|---------|-------------|", | |
| row | |
| ] | |
| for offset, l in enumerate(block): | |
| lines.insert(insert_at + offset, l) | |
| else: | |
| if lines and lines[-1].strip() != "": | |
| lines.append("") | |
| lines.append(f"## {category}") | |
| lines.append("") | |
| lines.append("| Name | Repo | Website | Description |") | |
| lines.append("|------|------|---------|-------------|") | |
| lines.append(row) | |
| readme.write_text("\n".join(lines) + "\n", encoding="utf-8") | |
| print(f"Inserted project '{name}' into '{category}'") | |
| PY | |
| # Create Pull Request | |
| - name: Create Pull Request | |
| if: ${{ github.event.label.name == 'approved' && contains(env.MAINTAINERS, github.event.sender.login) }} | |
| id: create_pr | |
| uses: peter-evans/create-pull-request@v7 | |
| with: | |
| branch: add-project-${{ github.event.issue.number }} | |
| title: 'Add project' | |
| body: 'This PR adds a new project from issue #${{ github.event.issue.number }}' | |
| commit-message: "Add project: ${{ env.NAME }}" | |
| token: ${{ secrets.GITHUB_TOKEN }} | |
| delete-branch: true | |
| # Merge PR, delete branch, and close issue | |
| - name: Merge PR, delete branch, and close issue | |
| if: ${{ github.event.label.name == 'approved' && contains(env.MAINTAINERS, github.event.sender.login) }} | |
| env: | |
| GH_TOKEN: ${{ secrets.MERGE_TOKEN }} | |
| run: | | |
| PR_NUMBER=$(gh pr list --state open --head add-project-${{ github.event.issue.number }} --json number -q '.[0].number') | |
| if [ "$PR_NUMBER" != "null" ] && [ -n "$PR_NUMBER" ]; then | |
| echo "Merging PR #$PR_NUMBER..." | |
| gh pr merge $PR_NUMBER --squash --admin --delete-branch | |
| gh issue comment ${{ github.event.issue.number }} --body "Project added, PR merged, branch deleted. 🎉" | |
| gh issue close ${{ github.event.issue.number }} | |
| else | |
| echo "No open PR found for add-project-${{ github.event.issue.number }}" | |
| fi # <-- this was missing | |