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
25 changes: 25 additions & 0 deletions .github/workflows/add-pr-to-devops.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
name: Add PR to DevOps Board

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

jobs:
add_to_project:
runs-on: ubuntu-latest
if: |
github.event.pull_request.base.ref == 'main' ||
github.event.pull_request.base.ref == 'master'
permissions:
contents: read
pull-requests: write
repository-projects: write
organization-projects: write
steps:
- name: Add PR to DevOps Release Board
uses: actions/[email protected]
with:
project-url: https://github.com/orgs/dhwani-ris/projects/##
github-token: ${{ secrets.GITHUB_TOKEN }}

7 changes: 4 additions & 3 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: [master]

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
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
175 changes: 175 additions & 0 deletions .github/workflows/devops-checklist-lock-monitor.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,175 @@
name: DevOps Checklist Lock Monitor

on:
schedule:
# Run every 5 minutes to check and re-lock submitted checklists
- cron: '*/5 * * * *'
workflow_dispatch:
pull_request:
types: [synchronize, reopened, ready_for_review, edited]
issue_comment:
types: [created, edited]

permissions:
pull-requests: write
contents: read

jobs:
monitor-and-relock:
runs-on: ubuntu-latest
steps:
- name: Monitor and re-lock submitted checklists
uses: actions/github-script@v8
with:
github-token: ${{ secrets.GITHUB_TOKEN }}
script: |
const repo = context.repo;
let prNumbers = [];

// If triggered by PR event, check that specific PR
if (context.eventName === 'pull_request') {
prNumbers = [context.payload.pull_request.number];
} else if (context.eventName === 'issue_comment' && context.payload.issue.pull_request) {
prNumbers = [context.payload.issue.number];
} else {
// For scheduled runs, get all open PRs targeting main/master
const { data: prs } = await github.rest.pulls.list({
owner: repo.owner,
repo: repo.repo,
state: 'open',
base: 'main',
per_page: 50
});

const { data: masterPRs } = await github.rest.pulls.list({
owner: repo.owner,
repo: repo.repo,
state: 'open',
base: 'master',
per_page: 50
});

prNumbers = [...prs.map(p => p.number), ...masterPRs.map(p => p.number)];
}

for (const prNumber of prNumbers) {
try {
// Get all comments
const { data: comments } = await github.rest.issues.listComments({
owner: repo.owner,
repo: repo.repo,
issue_number: prNumber,
});

// Find checklist comment
const checklistComment = comments.find(
comment => comment.user.type === 'Bot' &&
comment.body.includes('DevOps Checklist')
);

if (!checklistComment) continue;

// Check if submitted
const isSubmitted = checklistComment.body.includes('CHECKLIST_SUBMITTED_LOCK') ||
checklistComment.body.includes('✅ **CHECKLIST SUBMITTED**');

if (!isSubmitted) continue;

// Get stored checkbox states
let storedStates = null;
for (const comment of comments) {
if (comment.body.includes('CHECKLIST_STATES:')) {
const match = comment.body.match(/CHECKLIST_STATES:(.+)/);
if (match) {
try {
storedStates = JSON.parse(match[1]);
break;
} catch (e) {
console.log('Could not parse stored states');
}
}
}
}

let checklistBody = checklistComment.body;
let needsUpdate = false;

// Restore checkbox states if we have stored states
if (storedStates && storedStates.length > 0) {
const checkboxRegex = /- \[([ x])\] (.+)/g;
let stateIndex = 0;
let restoredBody = checklistBody;

restoredBody = restoredBody.replace(checkboxRegex, (match, checked, text) => {
if (stateIndex < storedStates.length) {
const state = storedStates[stateIndex];
stateIndex++;
const expectedState = state.checked ? 'x' : ' ';
if (checked !== expectedState || text.trim() !== state.text.trim()) {
needsUpdate = true;
return `- [${expectedState}] ${state.text}`;
}
}
return match;
});

if (needsUpdate) {
checklistBody = restoredBody;
}
}

// Ensure lock section is present
if (!checklistBody.includes('🔒 **This checklist is now locked and cannot be modified.**')) {
needsUpdate = true;
const submitterMatch = checklistBody.match(/\*\*Submitted by:\*\* @(\S+)/);
const dateMatch = checklistBody.match(/\*\*Submitted at:\*\* (.+?)(?:\n|UTC)/);
const submitter = submitterMatch ? submitterMatch[1] : 'System';
const submitDate = dateMatch ? dateMatch[1].trim() : new Date().toLocaleString('en-US', {
timeZone: 'UTC',
year: 'numeric',
month: 'long',
day: 'numeric',
hour: '2-digit',
minute: '2-digit',
second: '2-digit',
timeZoneName: 'short'
});

const lockSection = `---

### ✅ **CHECKLIST SUBMITTED**

**Submitted by:** @${submitter}
**Submitted at:** ${submitDate} (UTC)

🔒 **This checklist is now locked and cannot be modified.**

<!-- CHECKLIST_SUBMITTED_LOCK -->

---
**Note:** This checklist was submitted and is final. No further changes can be made.`;

const submitIndex = checklistBody.indexOf('### ✅ **CHECKLIST SUBMITTED**');
if (submitIndex !== -1) {
checklistBody = checklistBody.substring(0, submitIndex) + lockSection;
} else {
checklistBody = checklistBody + '\n\n' + lockSection;
}
}

// Update if needed
if (needsUpdate) {
await github.rest.issues.updateComment({
owner: repo.owner,
repo: repo.repo,
comment_id: checklistComment.id,
body: checklistBody
});

console.log(`Re-locked checklist for PR #${prNumber}`);
}
} catch (error) {
console.log(`Error processing PR #${prNumber}:`, error.message);
}
}

Loading
Loading