Skip to content

Dependency Dashboard #1493

Dependency Dashboard

Dependency Dashboard #1493

Workflow file for this run

name: Issue Labeler
on:
issues:
types: [opened, edited]
permissions:
issues: write
jobs:
label-issue:
runs-on: ubuntu-latest
concurrency:
group: issue-${{ github.event.issue.number }}
cancel-in-progress: false
steps:
- name: Apply Area and Namespace Labels
uses: actions/github-script@3a2844b7e9c422d3c10d287c895573f7108da1b3 # v9.0.0
with:
github-token: ${{ github.token }}
script: |
const { owner, repo } = context.repo;
const issueNumber = context.payload.issue?.number;
if (!issueNumber) return core.setFailed('No issue number in payload');
const { data: issue } = await github.rest.issues.get({ owner, repo, issue_number: issueNumber });
const currentLabels = (issue.labels || []).map(l => typeof l === 'string' ? l : l.name);
const currentLower = currentLabels.map(s => s.toLowerCase());
core.startGroup('Diagnostics');
core.info(`Issue #${issue.number}`);
core.info(`Current labels: ${currentLabels.join(', ') || '(none)'}`);
core.endGroup();
// Gate: only proceed if bug/enhancement label is present
if (!currentLower.includes('bug') && !currentLower.includes('enhancement')) {
core.info('Gate not met (requires "bug" or "enhancement"); skipping.');
return;
}
const body = issue.body || '';
core.startGroup('Body preview');
core.info(`Length: ${body.length}`);
core.info(`First 400 chars: ${body.slice(0, 400).replace(/\r?\n/g, '\\n')}`);
core.endGroup();
// Extract the Component value from Issue Forms ("### Component" section)
function getByHeading(text, title) {
const esc = title.replace(/[.*+?^${}()|[\]\\]/g, '\\$&');
const re = new RegExp(
`(?:^|\\r?\\n)#{2,}\\s*${esc}\\s*\\r?\\n+([\\s\\S]*?)(?=\\r?\\n#{2,}\\s|\\r?\\n<!--|$)`,
'i'
);
const m = text.match(re);
if (!m) return '';
const lines = m[1].split(/\r?\n/).map(s => s.trim());
for (const ln of lines) {
if (!ln) continue;
const cleaned = ln.replace(/^>+\s*/, '').replace(/^[-*]\s*/, '');
if (/^no response$/i.test(cleaned)) continue;
if (/^```/.test(cleaned)) continue; // skip code fences
return cleaned;
}
return '';
}
// Try "### Component" first; fall back to inline "Component: X" or "otel_component: X"
let component = getByHeading(body, 'Component');
if (!component) {
let m = body.match(/(?:^|\r?\n)\s*(?:component|otel[_\s-]*component)\s*[:\-–]\s*(.+)/i);
if (m) component = m[1].trim();
}
core.info(`Extracted component: "${component || '(empty)'}"`);
if (!component) {
return core.setFailed('Gate met, but component not found. Ensure the form has a "Component" field with a value.');
}
const sanitize = s => s.toLowerCase().replace(/\s+/g, ':').replace(/:+$/,'').trim();
let area = '';
let ns = '';
let m;
if ((m = component.match(/^detector\s*[:\-–]\s*(.+)$/i))) {
area = 'area: detector';
ns = `detector: ${sanitize(m[1])}`;
} else if ((m = component.match(/^instrumentation\s*[:\-–]\s*(.+)$/i))) {
area = 'area: instrumentation';
ns = `instrumentation: ${sanitize(m[1])}`;
} else if ((m = component.match(/^propagator\s*[:\-–]\s*(.+)$/i))) {
area = 'area: propagators';
ns = `propagator: ${sanitize(m[1])}`;
} else if ((m = component.match(/^sampler\s*[:\-–]\s*(.+)$/i))) {
area = 'area: sampler';
ns = `sampler: ${sanitize(m[1])}`;
} else if (/^autoexporter$/i.test(component.trim())) {
area = 'area: exporter';
ns = 'exporter: autoexport';
} else if (/^zpages$/i.test(component.trim())) {
area = 'area: zpages';
ns = 'zpages';
} else if (/^config$/i.test(component.trim())) {
area = 'area: file-config';
ns = '';
}
core.info(`Computed area: "${area || '(none)'}", namespace: "${ns || '(none)'}"`);
const toAdd = [area, ns].filter(Boolean).filter(l => !currentLower.includes(l.toLowerCase()));
core.info(`Labels to add: ${toAdd.join(', ') || '(none)'}`);
if (!toAdd.length) {
return core.setFailed('Gate met but no labels computed (unrecognized component) or labels already present.');
}
// Ensure labels exist; fail if missing (so we get an explicit error)
const existing = await github.paginate(github.rest.issues.listLabelsForRepo, { owner, repo, per_page: 100 });
const existingSet = new Set(existing.map(l => l.name.toLowerCase()));
const missing = toAdd.filter(l => !existingSet.has(l.toLowerCase()));
if (missing.length) {
return core.setFailed(`Required labels do not exist in the repository: ${missing.join(', ')}. Create them and re-run.`);
}
// Add labels
await github.rest.issues.addLabels({ owner, repo, issue_number: issue.number, labels: toAdd });
// Verify
const updated = await github.rest.issues.get({ owner, repo, issue_number: issue.number });
const updatedSet = new Set(updated.data.labels.map(l => l.name.toLowerCase()));
const stillMissing = toAdd.filter(l => !updatedSet.has(l.toLowerCase()));
if (stillMissing.length) {
core.setFailed(`Attempted to add labels but they are missing after update: ${stillMissing.join(', ')}`);
} else {
core.info(`Labels added successfully: ${toAdd.join(', ')}`);
}