Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
14 changes: 14 additions & 0 deletions .github/CODEOWNERS
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
# CODEOWNERS file
# This file defines code owners for the repository
# See: https://docs.github.com/en/repositories/managing-your-repositorys-settings-and-features/customizing-your-repository/about-code-owners

# DevOps team owns all files
* @dhwani-ris/dhwani-devops

# GitHub workflows - DevOps team
/.github/workflows/ @dhwani-ris/dhwani-devops

# Configuration files - DevOps team
/.github/ @dhwani-ris/dhwani-devops
/.releaserc @dhwani-ris/dhwani-devops

152 changes: 152 additions & 0 deletions .github/workflows/add-pr-to-devops.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,152 @@
name: Add PR to DevOps Board

on:
pull_request:
types: [opened, reopened, synchronize]
branches: [main, master, develop, development]

jobs:
add_to_project:
runs-on: ubuntu-latest
if: |
github.event.pull_request.base.ref == 'main' ||
github.event.pull_request.base.ref == 'master' ||
github.event.pull_request.base.ref == 'develop' ||
github.event.pull_request.base.ref == 'development'
permissions:
contents: read
pull-requests: write
repository-projects: write
organization-projects: write
steps:
- name: Add PR to DevOps Release Board
uses: actions/github-script@v8
with:
github-token: ${{ secrets.PROJECT_TOKEN || secrets.GITHUB_TOKEN }}
script: |
const prNodeId = context.payload.pull_request.node_id;
const prNumber = context.payload.pull_request.number;
const prUrl = context.payload.pull_request.html_url;

console.log(`Processing PR #${prNumber} (Node ID: ${prNodeId})`);

try {
// Get organization projects
const { data: projects } = await github.rest.projects.listForOrg({
org: 'dhwani-ris',
state: 'open'
});

console.log(`Found ${projects.length} organization projects`);

if (projects.length === 0) {
console.log('⚠️ No organization projects found. Check permissions.');
return;
}

// Log all project names for debugging
console.log('Available projects:', projects.map(p => `"${p.name}" (ID: ${p.id})`).join(', '));

// Find the DevOps Release & QC Board project - try exact match first
// Project name from UI: "Dhwani – DevOps Release & QC Board" (with en-dash)
let devopsProject = projects.find(p => {
const name = p.name.toLowerCase();
// Try exact match with various dash characters (hyphen, en-dash, em-dash)
return name === 'dhwani - devops release & qc board' ||
name === 'dhwani – devops release & qc board' || // en-dash (U+2013)
name === 'dhwani — devops release & qc board' || // em-dash (U+2014)
name === 'dhwani - devops release and qc board' ||
name === 'dhwani – devops release and qc board' ||
(name.includes('dhwani') && name.includes('devops') && name.includes('release') && name.includes('qc')) ||
(name.includes('dhwani') && name.includes('devops') && name.includes('release') && name.includes('board')) ||
(name.includes('devops') && name.includes('release') && name.includes('qc')) ||
(name.includes('devops') && name.includes('release') && name.includes('board')) ||
(name.includes('devops') && name.includes('release')) ||
(name.includes('devops') && name.includes('qc'));
});

// If not found, try just "devops"
if (!devopsProject) {
devopsProject = projects.find(p =>
p.name.toLowerCase().includes('devops')
);
}

if (!devopsProject) {
console.log('❌ DevOps Release & QC Board project not found');
console.log('Available project names:', projects.map(p => `"${p.name}"`).join(', '));
console.log('Searched for: "Dhwani – DevOps Release & QC Board" (with en-dash)');
console.log('Please check:');
console.log(' 1. Project name matches: "DevOps", "Release", or "QC"');
console.log(' 2. Project is in the dhwani-ris organization');
console.log(' 3. GITHUB_TOKEN has organization project access');
console.log(' 4. Consider using PROJECT_TOKEN secret with "project" scope');
return;
}

console.log(`✅ Found project: "${devopsProject.name}" (ID: ${devopsProject.id})`);

// Get project columns
const { data: columns } = await github.rest.projects.listColumns({
project_id: devopsProject.id
});

if (columns.length === 0) {
console.log('❌ No columns found in project');
return;
}

console.log(`Found ${columns.length} columns:`, columns.map(c => `"${c.name}"`).join(', '));

// Find the first column (usually "To do", "In progress", or "Backlog")
const firstColumn = columns[0];
console.log(`Adding PR to column: "${firstColumn.name}"`);

// Check if PR is already in the project (check all columns)
let alreadyAdded = false;
for (const column of columns) {
const { data: cards } = await github.rest.projects.listCards({
column_id: column.id
});
alreadyAdded = cards.some(card =>
card.content_url && card.content_url.includes(`/pulls/${prNumber}`)
);
if (alreadyAdded) {
console.log(`✅ PR #${prNumber} is already in the project (column: ${column.name})`);
break;
}
}

if (!alreadyAdded) {
// Add PR to the first column
await github.rest.projects.createCard({
column_id: firstColumn.id,
content_id: prNodeId,
content_type: 'PullRequest'
});

console.log(`✅ Successfully added PR #${prNumber} to DevOps Release & QC Board`);
console.log(` Project: "${devopsProject.name}"`);
console.log(` Column: "${firstColumn.name}"`);
console.log(` PR URL: ${prUrl}`);
}
} catch (error) {
console.log('❌ Error adding PR to project:', error.message);
console.log('Error details:', JSON.stringify(error, null, 2));

if (error.status === 403) {
console.log('⚠️ Permission denied (403). GITHUB_TOKEN may not have organization project access.');
console.log(' Solution: Use a Personal Access Token (PAT) with "project" scope.');
console.log(' 1. Create PAT at: https://github.com/settings/tokens');
console.log(' 2. Add it as secret: PROJECT_TOKEN');
console.log(' 3. Update workflow to use: ${{ secrets.PROJECT_TOKEN }}');
} else if (error.status === 404) {
console.log('⚠️ Not found (404). Check project name and permissions.');
} else if (error.status === 401) {
console.log('⚠️ Unauthorized (401). Token may be invalid or expired.');
}

// Don't fail the workflow, just log the error
console.log('⚠️ Continuing workflow despite error...');
}

56 changes: 38 additions & 18 deletions .github/workflows/auto-reviewer.yml
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,8 @@ name: Auto Request Review

on:
pull_request:
types: [opened, synchronize, reopened, ready_for_review]
types: [opened, synchronize, reopened, ready_for_review, closed]
branches: [main, master, develop, development]

permissions:
pull-requests: write
Expand All @@ -13,8 +14,8 @@ jobs:
name: Request Review from Default Reviewer
runs-on: ubuntu-latest
if: |
github.event.pull_request.base.ref == 'main' ||
github.event.pull_request.base.ref == 'master'
(github.event.action == 'opened' || github.event.action == 'reopened' || github.event.action == 'synchronize' || github.event.action == 'ready_for_review') &&
(github.event.pull_request.base.ref == 'main' || github.event.pull_request.base.ref == 'master')

steps:
- name: Request review from default reviewer
Expand Down Expand Up @@ -46,27 +47,46 @@ jobs:

console.log('Current reviewers:', JSON.stringify(currentReviews, null, 2));

// Check if reviewer is already requested
const isAlreadyRequested = currentReviews.users?.some(
// Check if DevOps team is already requested
const devopsTeam = 'dhwani-ris/dhwani-devops';
const isTeamRequested = currentReviews.teams?.some(
team => `${team.organization.login}/${team.slug}` === devopsTeam
);

// Check if individual reviewer is already requested
const isUserRequested = currentReviews.users?.some(
user => user.login.toLowerCase() === reviewer.toLowerCase()
) || currentReviews.teams?.some(
team => team.slug.toLowerCase() === reviewer.toLowerCase()
);

if (isAlreadyRequested) {
console.log(`✅ Review already requested from ${reviewer}`);
return;
// Request review from DevOps team (from CODEOWNERS)
if (!isTeamRequested) {
try {
await github.rest.pulls.requestReviewers({
owner: context.repo.owner,
repo: context.repo.repo,
pull_number: pr.number,
team_reviewers: ['dhwani-devops'],
});
console.log(`✅ Successfully requested review from ${devopsTeam}`);
} catch (teamError) {
console.log(`⚠️ Could not request review from team ${devopsTeam}:`, teamError.message);
}
} else {
console.log(`✅ Review already requested from ${devopsTeam}`);
}

// Request review from default reviewer
await github.rest.pulls.requestReviewers({
owner: context.repo.owner,
repo: context.repo.repo,
pull_number: pr.number,
reviewers: [reviewer],
});

console.log(`✅ Successfully requested review from ${reviewer}`);
if (!isUserRequested) {
await github.rest.pulls.requestReviewers({
owner: context.repo.owner,
repo: context.repo.repo,
pull_number: pr.number,
reviewers: [reviewer],
});
console.log(`✅ Successfully requested review from ${reviewer}`);
} else {
console.log(`✅ Review already requested from ${reviewer}`);
}
} catch (error) {
console.error(`❌ Error requesting review from ${reviewer}:`, error);
console.error('Error details:', JSON.stringify(error, null, 2));
Expand Down
3 changes: 2 additions & 1 deletion .github/workflows/bot-handler.yml
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,8 @@ on:
issue_comment:
types: [created, edited]
pull_request:
types: [opened, synchronize, reopened]
types: [opened, synchronize, reopened, closed]
branches: [master]

permissions:
contents: write
Expand Down
Loading
Loading