mirror of
https://github.com/slsdetectorgroup/slsDetectorPackage.git
synced 2026-09-03 03:00:44 +02:00
259 lines
7.9 KiB
YAML
259 lines
7.9 KiB
YAML
# This reusable workflow detects detector labels for pull requests. This workflow is ignored for Infrastructure Prs. It checks whole word matching of detector names in server folders, changed code and PR title/description. If a detector is detected, the corresponding label is added to the PR. Existing labels are left untouched. Detector labels are never removed automatically.
|
|
name: PR Detector Labels
|
|
|
|
on:
|
|
workflow_call:
|
|
inputs:
|
|
pr_number:
|
|
required: true
|
|
type: number
|
|
|
|
permissions:
|
|
pull-requests: write
|
|
issues: read
|
|
|
|
jobs:
|
|
detector-labels:
|
|
name: Detect detector labels
|
|
runs-on: ubuntu-latest
|
|
|
|
steps:
|
|
- name: Detect detector labels
|
|
uses: actions/github-script@v8
|
|
with:
|
|
script: |
|
|
const prNumber = ${{ inputs.pr_number }};
|
|
|
|
const { data: pr } =
|
|
await github.rest.pulls.get({
|
|
owner: context.repo.owner,
|
|
repo: context.repo.repo,
|
|
pull_number: prNumber
|
|
});
|
|
|
|
|
|
/*
|
|
* Infrastructure PRs do not receive detector labels.
|
|
*/
|
|
const body = pr.body || '';
|
|
|
|
const infrastructureSelected =
|
|
/-\s*\[[xX]\]\s*Infrastructure\b/.test(body);
|
|
|
|
if (infrastructureSelected) {
|
|
core.info(
|
|
'Infrastructure PR detected. Skipping detector label detection.'
|
|
);
|
|
return;
|
|
}
|
|
core.info(
|
|
`Not an infrastructure PR. Proceeding with detector label detection.`
|
|
);
|
|
|
|
/*
|
|
* Known detector labels.
|
|
*/
|
|
const detectorLabels = [
|
|
'Ctb',
|
|
'Eiger',
|
|
'Moench',
|
|
'Mythen3',
|
|
'Jungfrau',
|
|
'Gotthard2',
|
|
'Matterhorn',
|
|
'Xilinx_ctb'
|
|
];
|
|
|
|
|
|
/*
|
|
* Check whether a detector name appears as a
|
|
* complete word, case-insensitively.
|
|
*/
|
|
function containsDetector(text, detector) {
|
|
const regex = new RegExp(
|
|
`\\b${detector}\\b`,
|
|
'i'
|
|
);
|
|
|
|
return regex.test(text);
|
|
}
|
|
|
|
/*
|
|
* Detectors detected by any detection method.
|
|
*/
|
|
const detectedDetectors = new Set();
|
|
|
|
/*
|
|
* --------------------------------------------------
|
|
* 1. Get all files changed by the PR
|
|
* --------------------------------------------------
|
|
*/
|
|
const files = await github.paginate(
|
|
github.rest.pulls.listFiles,
|
|
{
|
|
owner: context.repo.owner,
|
|
repo: context.repo.repo,
|
|
pull_number: prNumber,
|
|
per_page: 100
|
|
}
|
|
);
|
|
|
|
core.info(
|
|
`Found ${files.length} changed files.`
|
|
);
|
|
|
|
/*
|
|
* --------------------------------------------------
|
|
* 2. Detect detector from detector-server folders
|
|
* --------------------------------------------------
|
|
*
|
|
* Examples:
|
|
*
|
|
* slsDetectorServers/eigerDetectorServer/...
|
|
* ↓
|
|
* Eiger
|
|
*
|
|
* slsDetectorServers/xilinx_ctbDetectorServer/...
|
|
* ↓
|
|
* Xilinx_ctb
|
|
*/
|
|
for (const file of files) {
|
|
const match = file.filename.match(
|
|
/^slsDetectorServers\/([^/]+)DetectorServer\//
|
|
);
|
|
|
|
if (!match) {
|
|
continue;
|
|
}
|
|
|
|
const detectorName = match[1];
|
|
|
|
/*
|
|
* Remove "DetectorServer" and capitalize
|
|
* the first character.
|
|
*/
|
|
const detector =
|
|
detectorName.charAt(0).toUpperCase() +
|
|
detectorName.slice(1);
|
|
|
|
if (detectorLabels.includes(detector)) {
|
|
detectedDetectors.add(detector);
|
|
|
|
core.info(
|
|
`Detected ${detector} from detector-server path: ${file.filename}`
|
|
);
|
|
}
|
|
}
|
|
|
|
/*
|
|
* --------------------------------------------------
|
|
* 3. Detect detector from changed code
|
|
* --------------------------------------------------
|
|
*
|
|
* Only the PR patch is searched.
|
|
*
|
|
* Therefore, text that already existed elsewhere
|
|
* in an unchanged file does not trigger a label.
|
|
*/
|
|
for (const file of files) {
|
|
if (!file.patch) {
|
|
continue;
|
|
}
|
|
|
|
for (const detector of detectorLabels) {
|
|
if (
|
|
containsDetector(
|
|
file.patch,
|
|
detector
|
|
)
|
|
) {
|
|
detectedDetectors.add(detector);
|
|
|
|
core.info(
|
|
`Detected ${detector} in changed code: ${file.filename}`
|
|
);
|
|
}
|
|
}
|
|
}
|
|
|
|
/*
|
|
* --------------------------------------------------
|
|
* 4. Detect detector from PR title/description
|
|
* --------------------------------------------------
|
|
*/
|
|
const prText = [
|
|
pr.title || '',
|
|
pr.body || ''
|
|
].join('\n');
|
|
|
|
for (const detector of detectorLabels) {
|
|
if (
|
|
containsDetector(
|
|
prText,
|
|
detector
|
|
)
|
|
) {
|
|
detectedDetectors.add(detector);
|
|
|
|
core.info(
|
|
`Detected ${detector} in PR title or description.`
|
|
);
|
|
}
|
|
}
|
|
|
|
|
|
/*
|
|
* --------------------------------------------------
|
|
* 5. Get current PR labels
|
|
* --------------------------------------------------
|
|
*/
|
|
const { data: currentLabels } =
|
|
await github.rest.issues.listLabelsOnIssue({
|
|
owner: context.repo.owner,
|
|
repo: context.repo.repo,
|
|
issue_number: prNumber
|
|
});
|
|
|
|
const currentLabelNames =
|
|
currentLabels.map(label => label.name);
|
|
|
|
/*
|
|
* --------------------------------------------------
|
|
* 6. Add detected detector labels
|
|
* --------------------------------------------------
|
|
*
|
|
* Existing labels are left untouched.
|
|
*
|
|
* Detector labels are NEVER removed automatically.
|
|
*/
|
|
for (const detector of detectedDetectors) {
|
|
if (!currentLabelNames.includes(detector)) {
|
|
await github.rest.issues.addLabels({
|
|
owner: context.repo.owner,
|
|
repo: context.repo.repo,
|
|
issue_number: prNumber,
|
|
labels: [detector]
|
|
});
|
|
|
|
core.info(
|
|
`Added detector label: ${detector}`
|
|
);
|
|
} else {
|
|
core.info(
|
|
`Detector label already exists: ${detector}`
|
|
);
|
|
}
|
|
}
|
|
|
|
/*
|
|
* --------------------------------------------------
|
|
* 9. Summary
|
|
* --------------------------------------------------
|
|
*/
|
|
core.info(
|
|
`Detected detectors: ${
|
|
detectedDetectors.size > 0
|
|
? [...detectedDetectors].join(', ')
|
|
: 'none'
|
|
}`
|
|
); |