Skip to content

refactor(milvus): share lifecycle across stores #5997

refactor(milvus): share lifecycle across stores

refactor(milvus): share lifecycle across stores #5997

name: Owner Notification
on:
pull_request_target:
types: [assigned, opened, reopened, synchronize, ready_for_review]
jobs:
notify-owners:
if: >-
${{
github.repository == 'vllm-project/semantic-router' &&
!github.event.pull_request.draft
}}
runs-on: ubuntu-latest
permissions:
contents: read
pull-requests: write
issues: write
steps:
- name: Checkout code
uses: actions/checkout@v4
with:
repository: ${{ github.repository }}
ref: ${{ github.event.pull_request.base.sha }}
fetch-depth: 0
- name: Get changed files
id: changed-files
uses: actions/github-script@v7
with:
result-encoding: string
script: |
// Retrieve changed files via GitHub API to avoid relying on fork
// refs.
const files = await github.paginate(github.rest.pulls.listFiles, {
owner: context.repo.owner,
repo: context.repo.repo,
pull_number: context.issue.number,
per_page: 100,
});
const filenames = files.map(f => f.filename);
core.setOutput('all_changed_files', filenames.join(' '));
- name: Find owners and notify
uses: actions/github-script@v7
with:
script: |
const fs = require('fs');
const path = require('path');
// Get changed files
const changedFiles =
`${{ steps.changed-files.outputs.all_changed_files }}`.split(' ');
console.log('Changed files:', changedFiles);
function readOwners(ownerPath) {
if (!fs.existsSync(ownerPath)) {
return [];
}
return fs.readFileSync(ownerPath, 'utf8')
.split('\n')
.map(line => line.trim())
.filter(line => line.startsWith('@'));
}
// Find the nearest OWNER file by walking from the changed file's
// directory back toward the repository root.
function findOwnerFile(filePath) {
let currentDir = path.dirname(filePath);
while (currentDir && currentDir !== '.') {
const ownerPath = path.join(currentDir, 'OWNER');
const owners = readOwners(ownerPath);
if (owners.length > 0) {
return { path: currentDir, owners };
}
const parentDir = path.dirname(currentDir);
if (parentDir === currentDir) {
break;
}
currentDir = parentDir;
}
const rootOwners = readOwners('OWNER');
if (rootOwners.length > 0) {
return { path: '.', owners: rootOwners };
}
return null;
}
// Collect all owners for changed files
const ownerMap = new Map();
for (const file of changedFiles) {
if (!file.trim()) continue;
const ownerInfo = findOwnerFile(file);
if (ownerInfo) {
if (!ownerMap.has(ownerInfo.path)) {
ownerMap.set(ownerInfo.path, {
owners: ownerInfo.owners,
files: []
});
}
ownerMap.get(ownerInfo.path).files.push(file);
}
}
if (ownerMap.size === 0) {
console.log('No owners found for changed files');
return;
}
// Collect all unique owners for assignment
const allOwners = new Set();
for (const [, info] of ownerMap) {
for (const owner of info.owners) {
// Remove @ prefix for API call
allOwners.add(owner.replace('@', ''));
}
}
// Assign owners to the PR
if (allOwners.size > 0) {
try {
await github.rest.issues.addAssignees({
owner: context.repo.owner,
repo: context.repo.repo,
issue_number: context.issue.number,
assignees: Array.from(allOwners)
});
console.log(
`Assigned PR to: ${Array.from(allOwners).join(', ')}`
);
} catch (error) {
console.log(`Failed to assign PR: ${error.message}`);
// Continue with comment creation even if assignment fails
}
}
// Create comment content
let commentBody = '## 👥 vLLM Semantic Team Notification\n\n';
commentBody +=
'The following members have been identified for the changed ' +
'files in this PR and have been automatically assigned:\n\n';
for (const [dirPath, info] of ownerMap) {
commentBody +=
`### 📁 \`${dirPath === '.' ? 'Root Directory' : dirPath}\`\n`;
commentBody += `**Owners:** ${info.owners.join(', ')}\n`;
commentBody += `**Files changed:**\n`;
for (const file of info.files) {
commentBody += `- \`${file}\`\n`;
}
commentBody += '\n';
}
commentBody += '---\n';
commentBody += '<div align="center">\n';
commentBody +=
'<img src="https://raw.githubusercontent.com/' +
'vllm-project/semantic-router/main/website/static/' +
'img/repo.png" ' +
'alt="vLLM" width="80%"/>';
commentBody += '</div>\n\n';
commentBody += '## 🎉 Thanks for your contributions!\n\n';
commentBody +=
'*This comment was automatically generated based on the OWNER ' +
'files in the repository.*';
// Get existing comments
const { data: comments } = await github.rest.issues.listComments({
owner: context.repo.owner,
repo: context.repo.repo,
issue_number: context.issue.number,
});
// Check if we already have an owner notification comment
const existingComment = comments.find(comment =>
comment.user.login === 'github-actions[bot]' &&
comment.body.includes('## 👥 vLLM Semantic Team Notification')
);
if (existingComment) {
// Update existing comment
await github.rest.issues.updateComment({
owner: context.repo.owner,
repo: context.repo.repo,
comment_id: existingComment.id,
body: commentBody
});
console.log('Updated existing owner notification comment');
} else {
// Create new comment
await github.rest.issues.createComment({
owner: context.repo.owner,
repo: context.repo.repo,
issue_number: context.issue.number,
body: commentBody
});
console.log('Created new owner notification comment');
}