mirror of
https://github.com/openfoodfoundation/openfoodnetwork
synced 2026-02-01 21:47:16 +00:00
Merge pull request #13546 from openfoodfoundation/task/13521-move-dependabot-to-code-review
Automate Dependabot PRs to Code Review column via GitHub Action
This commit is contained in:
15
.github/test-events/dependabot-pr.json
vendored
Normal file
15
.github/test-events/dependabot-pr.json
vendored
Normal file
@@ -0,0 +1,15 @@
|
||||
{
|
||||
"pull_request": {
|
||||
"number": 13545,
|
||||
"title": "Bump test from 7.0.4 to 7.0.8",
|
||||
"user": {
|
||||
"login": "dependabot[bot]"
|
||||
}
|
||||
},
|
||||
"repository": {
|
||||
"owner": {
|
||||
"login": "openfoodfoundation"
|
||||
},
|
||||
"name": "openfoodnetwork"
|
||||
}
|
||||
}
|
||||
152
.github/workflows/move-dependency-pr-to-code-review.yml
vendored
Normal file
152
.github/workflows/move-dependency-pr-to-code-review.yml
vendored
Normal file
@@ -0,0 +1,152 @@
|
||||
name: Auto-move Dependabot PRs to Code Review
|
||||
permissions:
|
||||
contents: read
|
||||
pull-requests: read
|
||||
project: write
|
||||
|
||||
on:
|
||||
pull_request:
|
||||
types: [opened]
|
||||
|
||||
jobs:
|
||||
move-pr-to-code-review:
|
||||
runs-on: ubuntu-latest
|
||||
if: github.event.pull_request.user.login == 'dependabot[bot]' || startsWith(github.event.pull_request.title, 'Bump')
|
||||
steps:
|
||||
- name: Generate GitHub App Token
|
||||
id: app-token
|
||||
uses: tibdex/github-app-token@v2
|
||||
with:
|
||||
app_id: ${{ secrets.DEPENDABOT_PR_APP_ID }}
|
||||
private_key: ${{ secrets.DEPENDABOT_PR_APP_PRIVATE_KEY }}
|
||||
installation_retrieval_mode: id
|
||||
installation_retrieval_payload: ${{ secrets.DEPENDABOT_PR_APP_INSTALLATION_ID }}
|
||||
|
||||
- name: Move PR to Code Review in Project v2
|
||||
uses: actions/github-script@v7
|
||||
with:
|
||||
github-token: ${{ steps.app-token.outputs.token }}
|
||||
script: |
|
||||
const projectNumber = 8; // for "OFN Delivery board"
|
||||
const org = "openfoodfoundation";
|
||||
const repo = context.repo.repo;
|
||||
const prNumber = context.payload.pull_request.number;
|
||||
const statusFieldName = "Status";
|
||||
const statusValue = "Code review 🔎";
|
||||
|
||||
// ---- Helper: Get PR Node ID ----
|
||||
async function getPrNodeId(owner, repo, number) {
|
||||
const res = await github.graphql(`
|
||||
query($owner: String!, $repo: String!, $number: Int!) {
|
||||
repository(owner: $owner, name: $repo) {
|
||||
pullRequest(number: $number) {
|
||||
id
|
||||
number
|
||||
title
|
||||
}
|
||||
}
|
||||
}
|
||||
`, { owner, repo, number });
|
||||
return res.repository.pullRequest.id;
|
||||
}
|
||||
|
||||
console.log("🚀 Starting ProjectV2 automation...");
|
||||
|
||||
// ---- Step 1: Get Project and Fields ----
|
||||
const projectRes = await github.graphql(`
|
||||
query($org: String!, $number: Int!) {
|
||||
organization(login: $org) {
|
||||
projectV2(number: $number) {
|
||||
id
|
||||
title
|
||||
fields(first: 50) {
|
||||
nodes {
|
||||
... on ProjectV2Field {
|
||||
id
|
||||
name
|
||||
}
|
||||
... on ProjectV2SingleSelectField {
|
||||
id
|
||||
name
|
||||
options {
|
||||
id
|
||||
name
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
`, { org, number: projectNumber });
|
||||
|
||||
const project = projectRes.organization.projectV2;
|
||||
if (!project) throw new Error(`❌ Project #${projectNumber} not found`);
|
||||
|
||||
console.log(`✅ Found project: ${project.title} (${project.id})`);
|
||||
|
||||
const statusField = project.fields.nodes.find(f => f.name === statusFieldName);
|
||||
if (!statusField) throw new Error(`❌ Field '${statusFieldName}' not found`);
|
||||
|
||||
const option = statusField.options.find(o => o.name === statusValue);
|
||||
if (!option) throw new Error(`❌ Option '${statusValue}' not found in '${statusFieldName}'`);
|
||||
|
||||
console.log(`✅ Found field '${statusFieldName}' and option '${statusValue}'`);
|
||||
|
||||
// ---- Step 2: Get PR Node ID ----
|
||||
const prNodeId = await getPrNodeId(org, repo, prNumber);
|
||||
console.log(`✅ PR #${prNumber} node ID: ${prNodeId}`);
|
||||
|
||||
// ---- Step 3: Check if PR is already in Project ----
|
||||
const itemRes = await github.graphql(`
|
||||
query($prId: ID!) {
|
||||
node(id: $prId) {
|
||||
... on PullRequest {
|
||||
projectItems(first: 50) {
|
||||
nodes {
|
||||
id
|
||||
project { id title }
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
`, { prId: prNodeId });
|
||||
|
||||
let projectItem = itemRes.node.projectItems.nodes.find(i => i.project.id === project.id);
|
||||
|
||||
if (!projectItem) {
|
||||
console.log("ℹ️ PR not yet in project, adding...");
|
||||
const addRes = await github.graphql(`
|
||||
mutation($projectId: ID!, $contentId: ID!) {
|
||||
addProjectV2ItemById(input: {projectId: $projectId, contentId: $contentId}) {
|
||||
item { id }
|
||||
}
|
||||
}
|
||||
`, { projectId: project.id, contentId: prNodeId });
|
||||
projectItem = addRes.addProjectV2ItemById.item;
|
||||
console.log(`✅ Added PR to project: ${projectItem.id}`);
|
||||
} else {
|
||||
console.log(`ℹ️ PR already in project: ${projectItem.id}`);
|
||||
}
|
||||
|
||||
// ---- Step 4: Update Status ----
|
||||
await github.graphql(`
|
||||
mutation($projectId: ID!, $itemId: ID!, $fieldId: ID!, $optionId: String!) {
|
||||
updateProjectV2ItemFieldValue(input: {
|
||||
projectId: $projectId,
|
||||
itemId: $itemId,
|
||||
fieldId: $fieldId,
|
||||
value: { singleSelectOptionId: $optionId }
|
||||
}) {
|
||||
projectV2Item { id }
|
||||
}
|
||||
}
|
||||
`, {
|
||||
projectId: project.id,
|
||||
itemId: projectItem.id,
|
||||
fieldId: statusField.id,
|
||||
optionId: option.id,
|
||||
});
|
||||
|
||||
console.log(`🎉 Moved PR #${prNumber} → '${statusValue}'`);
|
||||
1
.gitignore
vendored
1
.gitignore
vendored
@@ -59,3 +59,4 @@ yarn-debug.log*
|
||||
|
||||
/config/credentials.yml.enc
|
||||
/config/master.key
|
||||
.secrets
|
||||
|
||||
4
.secrets.example
Normal file
4
.secrets.example
Normal file
@@ -0,0 +1,4 @@
|
||||
# .secrets file define github secrets value locally
|
||||
DEPENDABOT_PR_APP_ID=123456
|
||||
DEPENDABOT_PR_APP_INSTALLATION_ID=123456
|
||||
DEPENDABOT_PR_APP_PRIVATE_KEY="-----BEGIN RSA PRIVATE KEY-----\n....\n-----END RSA PRIVATE KEY-----"
|
||||
Reference in New Issue
Block a user