Skip to content

Ankit devops

Ankit devops #26

name: DevOps Checklist Reminder
on:
pull_request:
types: [opened, synchronize, reopened, ready_for_review]
permissions:
pull-requests: write
contents: read
jobs:
checklist-reminder:
name: Add DevOps Checklist Reminder
runs-on: ubuntu-latest
if: |
github.event.pull_request.base.ref == 'main' ||
github.event.pull_request.base.ref == 'master'
steps:
- name: Check if deployment notes comment exists
id: check-deployment-notes
uses: actions/github-script@v8
with:
github-token: ${{ secrets.GITHUB_TOKEN }}
script: |
const pr = context.payload.pull_request;
const comments = await github.rest.issues.listComments({
owner: context.repo.owner,
repo: context.repo.repo,
issue_number: pr.number,
});
const botComment = comments.data.find(
comment => comment.user.type === 'Bot' &&
comment.body.includes('Production Deployment Release Document')
);
return { exists: !!botComment, commentId: botComment?.id };
- name: Generate Deployment Notes automatically (Comment 1)
if: steps.check-deployment-notes.outputs.exists != 'true' || github.event.action == 'opened'
uses: actions/github-script@v8
with:
github-token: ${{ secrets.GITHUB_TOKEN }}
script: |
const pr = context.payload.pull_request;
// Get all commits in the PR using GitHub API
let commits = [];
try {
const { data: prCommits } = await github.rest.pulls.listCommits({
owner: context.repo.owner,
repo: context.repo.repo,
pull_number: pr.number
});
commits = prCommits.map(commit => ({
hash: commit.sha.substring(0, 7),
message: commit.commit.message.split('\n')[0],
author: commit.commit.author.name,
date: commit.commit.author.date.split('T')[0]
}));
} catch (e) {
console.log('Error getting commits:', e.message);
}
// Determine release type from commits
let releaseType = 'Patch';
const hasBreaking = commits.some(c =>
c.message.includes('BREAKING') ||
c.message.includes('BREAKING CHANGE') ||
c.message.startsWith('feat!') ||
c.message.match(/^feat\(.+\)!:/)
);
const hasFeature = commits.some(c =>
c.message.startsWith('feat') && !c.message.startsWith('feat!')
);
const hasFix = commits.some(c => c.message.startsWith('fix'));
if (hasBreaking) {
releaseType = 'Major';
} else if (hasFeature) {
releaseType = 'Minor';
} else if (hasFix) {
releaseType = 'Patch';
}
// Get version from latest release or estimate from release type
let version = 'TBA';
try {
const { data: releases } = await github.rest.repos.listReleases({
owner: context.repo.owner,
repo: context.repo.repo,
per_page: 1
});
if (releases.length > 0) {
const latestRelease = releases[0];
const versionMatch = latestRelease.tag_name.match(/v?(\d+\.\d+\.\d+)/);
if (versionMatch) {
const [major, minor, patch] = versionMatch[1].split('.').map(Number);
if (releaseType === 'Major') {
version = `${major + 1}.0.0`;
} else if (releaseType === 'Minor') {
version = `${major}.${minor + 1}.0`;
} else {
version = `${major}.${minor}.${patch + 1}`;
}
}
} else {
// No releases yet, start with 1.0.0
version = releaseType === 'Major' ? '1.0.0' : releaseType === 'Minor' ? '0.1.0' : '0.0.1';
}
} catch (e) {
console.log('Could not determine version:', e.message);
}
// Get reviewers
let reviewers = [];
try {
const { data: reviews } = await github.rest.pulls.listReviews({
owner: context.repo.owner,
repo: context.repo.repo,
pull_number: pr.number
});
const approvedReviewers = reviews
.filter(r => r.state === 'APPROVED')
.map(r => r.user.login)
.filter((v, i, a) => a.indexOf(v) === i); // unique
reviewers = approvedReviewers;
} catch (e) {
console.log('Could not get reviewers:', e.message);
}
// Group commits by type for feature details
const features = commits.filter(c => c.message.startsWith('feat')).map(c => c.message.replace(/^feat(\(.+?\))?:\s*/i, ''));
const fixes = commits.filter(c => c.message.startsWith('fix')).map(c => c.message.replace(/^fix(\(.+?\))?:\s*/i, ''));
const other = commits.filter(c => !c.message.startsWith('feat') && !c.message.startsWith('fix') && !c.message.startsWith('chore') && !c.message.startsWith('ci'));
// Build feature details (without numbering - will be added in formatFeatureDetails)
let featureDetails = [];
if (features.length > 0) {
featureDetails.push(...features);
}
if (fixes.length > 0) {
featureDetails.push(...fixes);
}
if (other.length > 0) {
featureDetails.push(...other.slice(0, 5).map(o => o.message));
}
const today = new Date().toISOString().split('T')[0];
const releaseDate = today.split('-').reverse().join('-'); // Format: DD-MM-YYYY
// Format feature details with sequential numbering
const formatFeatureDetails = (details) => {
if (details.length === 0) return 'See commits above';
return details.map((f, i) => `${i + 1}) ${f}`).join('<br>');
};
const deploymentNotes = `## πŸ“ Production Deployment Release Document
**Release Information:**
- **Version:** \`${version}\`
- **Release Date:** \`${releaseDate}\`
- **Prepared by:** \`${pr.user.login}\`
- **Approved by:** \`${reviewers.length > 0 ? reviewers.join(', ') : 'Pending'}\`
- **Release Type:** \`${releaseType}\`
**Deployment Branches:**
\`\`\`
${pr.base.ref}
\`\`\`
**Overview:**
- Here are the key feature details for this release:
**Repository Details:**
| S.No. | Repository Name | Release Number | Feature Details |
|-------|-----------------|----------------|-----------------|
| 1. | \`${context.repo.repo}\` | \`${pr.base.ref}-release-${version}\` | ${formatFeatureDetails(featureDetails)} |
**Note:** This deployment document was **automatically generated** from PR commits and information. Please review and update the TBD sections before merging.`;
// Check if comment already exists
const comments = await github.rest.issues.listComments({
owner: context.repo.owner,
repo: context.repo.repo,
issue_number: pr.number,
});
const existingComment = comments.data.find(
comment => comment.user.type === 'Bot' &&
comment.body.includes('Production Deployment Release Document')
);
if (existingComment) {
// Update existing comment
await github.rest.issues.updateComment({
owner: context.repo.owner,
repo: context.repo.repo,
comment_id: existingComment.id,
body: deploymentNotes
});
} else {
// Create new comment
await github.rest.issues.createComment({
owner: context.repo.owner,
repo: context.repo.repo,
issue_number: pr.number,
body: deploymentNotes
});
}
- name: Check if checklist comment exists
id: check-comment
uses: actions/github-script@v8
with:
github-token: ${{ secrets.GITHUB_TOKEN }}
script: |
const pr = context.payload.pull_request;
const comments = await github.rest.issues.listComments({
owner: context.repo.owner,
repo: context.repo.repo,
issue_number: pr.number,
});
const botComment = comments.data.find(
comment => comment.user.type === 'Bot' &&
comment.body.includes('DevOps Checklist - Workflow Review')
);
return { exists: !!botComment, commentId: botComment?.id };
- name: Add or update DevOps checklist reminder (Comment 2)
uses: actions/github-script@v8
with:
github-token: ${{ secrets.GITHUB_TOKEN }}
script: |
const pr = context.payload.pull_request;
// Check if comment already exists
const comments = await github.rest.issues.listComments({
owner: context.repo.owner,
repo: context.repo.repo,
issue_number: pr.number,
});
const existingComment = comments.data.find(
comment => comment.user.type === 'Bot' &&
comment.body.includes('DevOps Checklist - Workflow Review')
);
if (existingComment) {
// Check if already submitted (check both visible marker and hidden marker)
if (existingComment.body.includes('βœ… **CHECKLIST SUBMITTED**') ||
existingComment.body.includes('CHECKLIST_SUBMITTED_LOCK')) {
console.log('Checklist already submitted and locked, cannot update');
return;
}
// Don't update existing comment to preserve checkbox states
console.log('DevOps Checklist comment already exists, preserving user checkboxes');
return;
}
// Only create new comment if it doesn't exist
const checklist = `## πŸ”§ DevOps Checklist
πŸ‘‹ **DevOps Team:** Please review and check the items below.
---
### βœ… Pre-Merge Verification
- [ ] All CI/CD workflows passing (check Actions tab)
- [ ] Code quality checks passed (Semgrep, Pre-commit)
- [ ] Security scans passed (no vulnerabilities)
- [ ] No secrets or credentials exposed (manual review)
### πŸ“ Documentation
- [ ] Deployment notes reviewed (see comment above)
- [ ] πŸ”— [Rollback Guidelines](https://dhwaniris1-my.sharepoint.com/:b:/g/personal/technology_dhwaniris_com/IQBZ-x3H8jIjQoliD_JEKHfSAQq2pMXdy8wFAdISg7fInTE?e=gd7dsq) reviewed
---
πŸ’‘ *Click the checkboxes above to mark items as complete.*`;
// Create new comment
await github.rest.issues.createComment({
owner: context.repo.owner,
repo: context.repo.repo,
issue_number: pr.number,
body: checklist
});
console.log('Created new DevOps Checklist comment');