Skip to content

Project Request: Open SWE #72

Project Request: Open SWE

Project Request: Open SWE #72

name: Project Request
on:
issues:
types: [opened, edited]
env:
GH_TOKEN: ${{ secrets.AGENT_TOKEN }}
jobs:
process-project-request:
if: contains(github.event.issue.title, 'Project Request:')
runs-on: ubuntu-latest
steps:
- name: Checkout repository
uses: actions/checkout@v3
- name: Set up Python
uses: actions/setup-python@v4
with:
python-version: '3.10'
- name: Install dependencies
run: pip install -r requirements.txt
- name: Parse issue body
id: parse-issue
uses: actions/github-script@v6
with:
script: |
const issueBody = context.payload.issue.body;
const issueAuthorId = context.payload.issue.user.login;
// First remove HTML comments from the issue body
const bodyWithoutComments = issueBody.replace(/<!--[\s\S]*?-->/g, '');
// Extract Project Information
// Project name
const projectNameMatch = bodyWithoutComments.match(/- Project name:([^\n]+)/i);
const projectName = projectNameMatch ? projectNameMatch[1].trim() : null;
// Github URL
const githubUrlMatch = bodyWithoutComments.match(/- Github URL:([^\n]+)/i);
const githubUrl = githubUrlMatch ? githubUrlMatch[1].trim() : null;
// Homepage URL
const homepageUrlMatch = bodyWithoutComments.match(/- Homepage URL:([^\n]+)/i);
const homepageUrl = homepageUrlMatch ? homepageUrlMatch[1].trim() : null;
// Logo URL
const logoUrlMatch = bodyWithoutComments.match(/- Logo URL:([^\n]+)/i);
const logoUrl = logoUrlMatch ? logoUrlMatch[1].trim() : null;
// Logo Name (optional)
const logoNameMatch = bodyWithoutComments.match(/- Logo Name:([^\n]+)/i);
const logoName = logoNameMatch ? logoNameMatch[1].trim() : null;
// Extract Category - Find the first checked box with [x] and its parent category
let category = null;
const lines = bodyWithoutComments.split('\n');
let parentCategory = null;
for (let i = 0; i < lines.length; i++) {
const line = lines[i].trim();
// Check if this is a main category line
if (line.startsWith('- ') && !line.includes('[')) {
parentCategory = line.substring(2).trim();
}
// Check if this is a checked subcategory
if (line.match(/- \[x\] (.+)/)) {
const subcategory = line.match(/- \[x\] (.+)/)[1].trim();
if (parentCategory) {
category = `${parentCategory}/${subcategory}`;
break;
} else {
category = subcategory;
break;
}
}
}
// Set outputs
core.setOutput('repo-url', githubUrl);
core.setOutput('project-name', projectName);
core.setOutput('category', category);
core.setOutput('logo-url', logoUrl);
core.setOutput('logo-name', logoName);
core.setOutput('homepage-url', homepageUrl);
core.setOutput("author-id", issueAuthorId);
// Log the extracted information
console.log(`Github URL: ${githubUrl}`);
console.log(`Project Name: ${projectName}`);
console.log(`Homepage URL: ${homepageUrl}`);
console.log(`Logo URL: ${logoUrl}`);
console.log(`Logo Name: ${logoName}`);
console.log(`Category: ${category}`);
console.log(`Author ID: ${issueAuthorId}`);
// Define README_ONLY_CATEGORIES
const README_ONLY_CATEGORIES = ["MCP/MCP Server", "MCP/MCP Client"];
// Check if the category is in README_ONLY_CATEGORIES
const isReadmeOnly = README_ONLY_CATEGORIES.some(c => c.toLowerCase() === category?.toLowerCase());
// Check if we have all required information
if (!githubUrl || !projectName || !category) {
core.setFailed('Missing required information in the issue');
await github.rest.issues.createComment({
issue_number: context.issue.number,
owner: context.repo.owner,
repo: context.repo.repo,
body: '❌ Could not process this request. Please make sure you have provided the GitHub repo URL, project name, and selected a category.'
});
return false;
}
// For non-README_ONLY_CATEGORIES, check for homepage_url
if (!isReadmeOnly && !homepageUrl) {
core.setFailed('Missing required information in the issue');
await github.rest.issues.createComment({
issue_number: context.issue.number,
owner: context.repo.owner,
repo: context.repo.repo,
body: `❌ Could not process this request. Please make sure you have provided the homepage URL.`
});
return false;
}
return true;
- name: Check for existing PR
if: steps.parse-issue.outputs.result == 'true'
id: check-pr
uses: actions/github-script@v6
with:
github-token: ${{ secrets.AGENT_TOKEN }}
script: |
const { owner, repo } = context.repo;
const issueNumber = context.issue.number;
const branchName = `add-project-issue-${issueNumber}`;
// Search for existing PRs that reference this issue
const prs = await github.rest.pulls.list({
owner,
repo,
state: 'open'
});
// Look for PRs with the expected branch name or that reference this issue
let existingPR = null;
for (const pr of prs.data) {
if (pr.head.ref === branchName || pr.body.includes(`fixes #${issueNumber}`)) {
existingPR = pr;
break;
}
}
if (existingPR) {
console.log(`Found existing PR #${existingPR.number} for issue #${issueNumber}`);
core.setOutput('pr-exists', 'true');
core.setOutput('pr-number', existingPR.number.toString());
} else {
console.log(`No existing PR found for issue #${issueNumber}`);
core.setOutput('pr-exists', 'false');
}
// Always set the branch name for later steps
core.setOutput('branch-name', branchName);
- name: Create or update branch
if: steps.parse-issue.outputs.result == 'true'
run: |
git config --global user.name "InftyAI-Agent"
git config --global user.email "[email protected]"
BRANCH_NAME="${{ steps.check-pr.outputs.branch-name }}"
# Check if the branch already exists on remote
if git ls-remote --heads origin $BRANCH_NAME | grep -q $BRANCH_NAME; then
echo "Branch $BRANCH_NAME already exists on remote, updating it"
git fetch origin
git checkout $BRANCH_NAME || git checkout -b $BRANCH_NAME --track origin/$BRANCH_NAME
# Reset to main to get latest changes and avoid conflicts
git reset --hard origin/main
else
echo "Creating new branch $BRANCH_NAME"
git checkout -b $BRANCH_NAME
fi
echo "BRANCH_NAME=$BRANCH_NAME" >> $GITHUB_ENV
- name: Run project_request.py script
run: |
# Define README_ONLY_CATEGORIES
README_ONLY_CATEGORIES=("MCP/MCP Server" "MCP/MCP Client")
CATEGORY="${{ steps.parse-issue.outputs.category }}"
# Check if category is in README_ONLY_CATEGORIES
IS_README_ONLY=false
for c in "${README_ONLY_CATEGORIES[@]}"; do
if [ "${c,,}" = "${CATEGORY,,}" ]; then
IS_README_ONLY=true
break
fi
done
# Build command based on category type
CMD="python project_request.py \
--category \"$CATEGORY\" \
--repo_url \"${{ steps.parse-issue.outputs.repo-url }}\" \
--name \"${{ steps.parse-issue.outputs.project-name }}\""
# Add logo_url and homepage_url if provided or required
if [ "$IS_README_ONLY" = false ] || [ -n "${{ steps.parse-issue.outputs.logo-url }}" ]; then
CMD="$CMD --logo_url \"${{ steps.parse-issue.outputs.logo-url }}\""
fi
if [ "$IS_README_ONLY" = false ] || [ -n "${{ steps.parse-issue.outputs.homepage-url }}" ]; then
CMD="$CMD --homepage_url \"${{ steps.parse-issue.outputs.homepage-url }}\""
fi
# Add logo_name if provided
if [ -n "${{ steps.parse-issue.outputs.logo-name }}" ]; then
CMD="$CMD --logo_name \"${{ steps.parse-issue.outputs.logo-name }}\""
fi
echo "Running command: $CMD"
eval $CMD
- name: Commit changes
env:
ISSUE_AUTHOR: ${{ steps.parse-issue.outputs.author-id }}
run: |
git add .
git commit -m "Add ${{ steps.parse-issue.outputs.repo-url }} to ${{ steps.parse-issue.outputs.category }} category
Co-authored-by: $ISSUE_AUTHOR <[email protected]>"
git remote set-url origin https://x-access-token:${GH_TOKEN}@github.com/InftyAI/Awesome-LLMOps.git
# Check if we need to force push (if branch already exists)
if git ls-remote --heads origin $BRANCH_NAME | grep -q $BRANCH_NAME; then
git push --force origin $BRANCH_NAME
else
git push --set-upstream origin $BRANCH_NAME
fi
- name: Create or Update Pull Request
uses: actions/github-script@v6
with:
github-token: ${{ secrets.AGENT_TOKEN }}
script: |
const { owner, repo } = context.repo;
const issueNumber = context.issue.number;
const branchName = process.env.BRANCH_NAME;
const prExists = '${{ steps.check-pr.outputs.pr-exists }}' === 'true';
const existingPrNumber = '${{ steps.check-pr.outputs.pr-number }}';
const repoUrl = '${{ steps.parse-issue.outputs.repo-url }}';
const category = '${{ steps.parse-issue.outputs.category }}';
// Get the repository name from the URL
const repoName = repoUrl.split('/').pop();
// Get the user who created the issue
const issue = await github.rest.issues.get({
owner,
repo,
issue_number: issueNumber
});
const issueAuthor = issue.data.user.login;
let pr;
if (prExists) {
// PR already exists, no need to create a new one
console.log(`Using existing PR #${existingPrNumber}`);
// Add comment to the PR about the update
await github.rest.issues.createComment({
issue_number: parseInt(existingPrNumber),
owner,
repo,
body: `♻️ PR updated with latest changes from issue #${issueNumber}`
});
// Add comment to the issue
await github.rest.issues.createComment({
issue_number: issueNumber,
owner,
repo,
body: `βœ… Pull Request #${existingPrNumber} has been updated with your changes`
});
} else {
// Create a new PR
pr = await github.rest.pulls.create({
owner,
repo,
title: `Add ${repoName} to ${category}`,
body: `fixes #${issueNumber},
Co-authored-by: @${issueAuthor}`,
head: branchName,
base: 'main'
});
// Add comment to the issue
await github.rest.issues.createComment({
issue_number: issueNumber,
owner,
repo,
body: `βœ… Pull Request created: #${pr.data.number}`
});
}