From 5f192c80a30bee1e027c73953fa2c9f42b5668a1 Mon Sep 17 00:00:00 2001 From: Himanshu Singhal Date: Tue, 5 Aug 2025 18:24:17 +0530 Subject: [PATCH] AIRA-64: Project Automation Action Update --- .github/workflows/project-automation.yml | 168 ++++++++++++----------- 1 file changed, 86 insertions(+), 82 deletions(-) diff --git a/.github/workflows/project-automation.yml b/.github/workflows/project-automation.yml index e2f1858..08d72df 100644 --- a/.github/workflows/project-automation.yml +++ b/.github/workflows/project-automation.yml @@ -325,105 +325,70 @@ jobs: return issues; } - // Helper function to find issue by AIRA number (REST API fallback) + // Helper function to find issue by AIRA number (REST API primary) async function findIssueByAiraNumber(airaNumber) { try { - // First try GraphQL search - console.log(` 🔍 Searching for AIRA-${airaNumber} using GraphQL...`); + // Use REST API as primary method (GraphQL search has been problematic) + console.log(` 🔍 Searching for AIRA-${airaNumber} using REST API...`); - const query = ` - query($searchQuery: String!) { - search(query: $searchQuery, type: ISSUE, first: 10) { - nodes { - ... on Issue { - number - title - state - id - } - } - } - } - `; - - const searchQuery = `repo:${context.repo.owner}/${context.repo.repo} AIRA-${airaNumber} in:title`; - console.log(` 🔍 GraphQL search query: ${searchQuery}`); - - const result = await github.graphql(query, { - searchQuery + const searchResponse = await github.rest.search.issuesAndPullRequests({ + q: `repo:${context.repo.owner}/${context.repo.repo} AIRA-${airaNumber} in:title type:issue`, + per_page: 10 }); - const issues = result.search.nodes.filter(node => - node.title.includes(`AIRA-${airaNumber}`) - ); + console.log(` 🔍 REST API found ${searchResponse.data.total_count} results`); - if (issues.length > 0) { - console.log(` ✅ Found issue via GraphQL: #${issues[0].number} - ${issues[0].title}`); - return issues[0]; + if (searchResponse.data.items && searchResponse.data.items.length > 0) { + const matchingIssues = searchResponse.data.items.filter(issue => + issue.title && issue.title.includes(`AIRA-${airaNumber}`) + ); + + if (matchingIssues.length > 0) { + const issue = matchingIssues[0]; + console.log(` ✅ Found issue via REST API: #${issue.number} - ${issue.title} (State: ${issue.state})`); + return { + number: issue.number, + title: issue.title, + state: issue.state, + id: issue.node_id + }; + } } - console.log(` ❌ No results from GraphQL search, trying REST API...`); + console.log(` ❌ No matching issues found in search results`); - } catch (graphqlError) { - console.log(` ❌ GraphQL search failed: ${graphqlError.message}`); - console.log(` 🔄 Falling back to REST API search...`); + } catch (restError) { + console.log(` ❌ REST API search failed: ${restError.message}`); } try { - // Fallback to REST API search - const searchResponse = await github.rest.search.issuesAndPullRequests({ - q: `repo:${context.repo.owner}/${context.repo.repo} AIRA-${airaNumber} in:title type:issue`, - per_page: 10 - }); + // Fallback: Direct lookup if AIRA number matches issue number + console.log(` 🔄 Fallback: checking if AIRA-${airaNumber} corresponds to issue #${airaNumber}...`); - console.log(` 🔍 REST API found ${searchResponse.data.total_count} results`); - - const matchingIssues = searchResponse.data.items.filter(issue => - issue.title.includes(`AIRA-${airaNumber}`) - ); + const issueResponse = await github.rest.issues.get({ + owner: context.repo.owner, + repo: context.repo.repo, + issue_number: airaNumber + }); - if (matchingIssues.length > 0) { - const issue = matchingIssues[0]; - console.log(` ✅ Found issue via REST API: #${issue.number} - ${issue.title}`); + if (issueResponse.data.title && issueResponse.data.title.includes(`AIRA-${airaNumber}`)) { + console.log(` ✅ Found by direct lookup: #${issueResponse.data.number} - ${issueResponse.data.title} (State: ${issueResponse.data.state})`); return { - number: issue.number, - title: issue.title, - state: issue.state, - id: issue.node_id + number: issueResponse.data.number, + title: issueResponse.data.title, + state: issueResponse.data.state, + id: issueResponse.data.node_id }; } else { - console.log(` ❌ No matching issues found for AIRA-${airaNumber}`); - return null; + console.log(` ❌ Issue #${airaNumber} exists but doesn't match AIRA-${airaNumber}`); } - } catch (restError) { - console.log(` ❌ REST API search also failed: ${restError.message}`); - - // Last resort: try to find by issue number if AIRA number matches - try { - console.log(` 🔄 Last resort: checking if AIRA-${airaNumber} corresponds to issue #${airaNumber}...`); - - const issueResponse = await github.rest.issues.get({ - owner: context.repo.owner, - repo: context.repo.repo, - issue_number: airaNumber - }); - - if (issueResponse.data.title.includes(`AIRA-${airaNumber}`)) { - console.log(` ✅ Found by direct lookup: #${issueResponse.data.number} - ${issueResponse.data.title}`); - return { - number: issueResponse.data.number, - title: issueResponse.data.title, - state: issueResponse.data.state, - id: issueResponse.data.node_id - }; - } - } catch (directError) { - console.log(` ❌ Direct lookup failed: ${directError.message}`); - } - - return null; + } catch (directError) { + console.log(` ❌ Direct lookup failed: ${directError.message}`); } + + console.log(` ❌ Could not find issue for AIRA-${airaNumber}`); + return null; } // Main automation logic @@ -534,7 +499,16 @@ jobs: // Find the actual GitHub issue const issue = await findIssueByAiraNumber(airaNumber); - if (issue && issue.state === 'open') { + if (!issue) { + console.log(` ❌ Could not find GitHub issue for AIRA-${airaNumber}`); + continue; + } + + console.log(` 📋 Found issue #${issue.number}: "${issue.title}" (State: ${issue.state})`); + + if (issue.state === 'open') { + console.log(` 🔄 Issue is open, proceeding to close it...`); + // Close the issue await github.rest.issues.update({ owner: context.repo.owner, @@ -543,20 +517,50 @@ jobs: state: 'closed' }); + console.log(` ✅ Closed issue #${issue.number}`); + // Move to Done in project let linkedItemId = await getProjectItemId(issue.id); if (!linkedItemId) { + console.log(` 🔄 Adding issue to project...`); linkedItemId = await addToProject(issue.id); } if (linkedItemId) { await updateItemStatus(linkedItemId, 'Done'); + console.log(` ✅ Moved issue to Done in project`); + } else { + console.log(` ❌ Could not add issue to project`); } console.log(`✅ Auto-closed and moved AIRA-${airaNumber} (issue #${issue.number}) to Done`); - } else if (issue) { - console.log(`â„šī¸ Issue AIRA-${airaNumber} already closed`); + + } else if (issue.state === 'closed') { + console.log(` â„šī¸ Issue AIRA-${airaNumber} (issue #${issue.number}) is already closed, skipping closure`); + + // Still move to Done in project if not already there + let linkedItemId = await getProjectItemId(issue.id); + + if (!linkedItemId) { + console.log(` 🔄 Adding closed issue to project...`); + linkedItemId = await addToProject(issue.id); + } + + if (linkedItemId) { + const currentStatus = await getCurrentItemStatus(linkedItemId); + if (currentStatus && currentStatus.toLowerCase() !== 'done') { + await updateItemStatus(linkedItemId, 'Done'); + console.log(` ✅ Moved already-closed issue to Done in project`); + } else { + console.log(` â„šī¸ Issue already in Done status`); + } + } + + console.log(`✅ Verified AIRA-${airaNumber} (issue #${issue.number}) is closed and in Done status`); + + } else { + console.log(` âš ī¸ Issue AIRA-${airaNumber} has unexpected state: ${issue.state}`); } } catch (error) { console.log(`❌ Failed to process AIRA-${airaNumber}:`, error.message);