Add labeler-dependabot.yml to auto-label Dependabot PRs by update type#81
Add labeler-dependabot.yml to auto-label Dependabot PRs by update type#81
Conversation
Co-authored-by: felickz <1760475+felickz@users.noreply.github.com> Agent-Logs-Url: https://github.com/advanced-security/reusable-workflows/sessions/7ba7ce0f-aeb4-4230-9150-936e39e1fe67
|
@copilot i enabled https://api.github.com/repos/dependabot/fetch-metadata/ in your firewall I need you to test this against a version PR: #80 and advanced-security/component-detection-dependency-submission-action#184 and a security pr: advanced-security/component-detection-dependency-submission-action#174 metadata looks like this which doesnt appear to help with security vs version: There is a comment in the PR that might distinguish though:
|
Co-authored-by: felickz <1760475+felickz@users.noreply.github.com> Agent-Logs-Url: https://github.com/advanced-security/reusable-workflows/sessions/83d35be1-c195-43a7-9da0-17c5c3838521
Good catch — Fixed in f71a111. The workflow now detects update type via PR body text:
Changes made:
|
|
@copilot - how does this version look? any paradigms we can borrow for our script? (ex the check on existing labels first to short circuit?) |
…le, dual-signal detection Co-authored-by: felickz <1760475+felickz@users.noreply.github.com> Agent-Logs-Url: https://github.com/advanced-security/reusable-workflows/sessions/8c837435-8f96-4ab1-b719-665956287a5b
... Adopted all the paradigms from your snippet in 90f9e3e:
|
Dependency ReviewThe following issues were found:
Snapshot WarningsEnsure that dependencies are being submitted on PR branches and consider enabling retry-on-snapshot-warnings. See the documentation for more information and troubleshooting advice. License Issues.github/workflows/labeler-dependabot.yml
OpenSSF Scorecard
Scanned Files
|
There was a problem hiding this comment.
Pull request overview
Adds a GitHub Actions workflow to automatically label Dependabot pull requests as either security updates or version updates, enabling label differentiation that isn’t possible within a single dependabot.yml ecosystem block.
Changes:
- Introduces
.github/workflows/labeler-dependabot.ymlto detect Dependabot PR type and applydependabot-security-updatevsdependabot-version-update. - Adds optional label auto-creation controlled by
ENSURE_LABELS_EXIST.
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
|
|
||
| permissions: | ||
| contents: read | ||
| pull-requests: write |
There was a problem hiding this comment.
github.rest.issues.* endpoints (label creation + applying labels) require the issues: write permission on GITHUB_TOKEN. With only pull-requests: write, these API calls can fail with 403 in repos where issues write isn’t implicitly granted. Add issues: write (and keep/remove pull-requests as needed).
| pull-requests: write | |
| pull-requests: write | |
| issues: write |
| await github.rest.issues.createLabel({ | ||
| owner: context.repo.owner, | ||
| repo: context.repo.repo, | ||
| name: label | ||
| }); |
There was a problem hiding this comment.
issues.createLabel is missing required fields (notably color). As written, label creation will fail when the labels don’t already exist. Provide a color (and optionally description) when creating the labels.
| const existing = await github.rest.issues.listLabelsForRepo({ | ||
| owner: context.repo.owner, | ||
| repo: context.repo.repo, | ||
| per_page: 100 | ||
| }); | ||
| const existingNames = existing.data.map(l => l.name); | ||
|
|
||
| for (const label of labels) { | ||
| if (!existingNames.includes(label)) { | ||
| await github.rest.issues.createLabel({ | ||
| owner: context.repo.owner, | ||
| repo: context.repo.repo, | ||
| name: label | ||
| }); | ||
| core.info(`Created label: ${label}`); |
There was a problem hiding this comment.
listLabelsForRepo is limited to per_page: 100 with no pagination. If the repo has >100 labels, an existing label may not be found, leading to a failing createLabel call. Consider using issues.getLabel per label, paginate, or catch/ignore the “already exists” error (422).
| const existing = await github.rest.issues.listLabelsForRepo({ | |
| owner: context.repo.owner, | |
| repo: context.repo.repo, | |
| per_page: 100 | |
| }); | |
| const existingNames = existing.data.map(l => l.name); | |
| for (const label of labels) { | |
| if (!existingNames.includes(label)) { | |
| await github.rest.issues.createLabel({ | |
| owner: context.repo.owner, | |
| repo: context.repo.repo, | |
| name: label | |
| }); | |
| core.info(`Created label: ${label}`); | |
| // Fetch all labels with pagination to avoid the 100-label per-page limit. | |
| const existingLabels = await github.paginate( | |
| github.rest.issues.listLabelsForRepo, | |
| { | |
| owner: context.repo.owner, | |
| repo: context.repo.repo, | |
| per_page: 100 | |
| } | |
| ); | |
| const existingNames = existingLabels.map(l => l.name); | |
| for (const label of labels) { | |
| if (!existingNames.includes(label)) { | |
| try { | |
| await github.rest.issues.createLabel({ | |
| owner: context.repo.owner, | |
| repo: context.repo.repo, | |
| name: label | |
| }); | |
| core.info(`Created label: ${label}`); | |
| } catch (error) { | |
| // Ignore "already exists" errors (HTTP 422), rethrow others. | |
| if (error.status === 422) { | |
| core.info(`Label already exists, skipping creation: ${label}`); | |
| } else { | |
| throw error; | |
| } | |
| } |
| runs-on: ubuntu-latest | ||
| # Only run for Dependabot PRs that have not already been labeled | ||
| if: >- | ||
| github.actor == 'dependabot[bot]' && |
There was a problem hiding this comment.
The job filter uses github.actor == 'dependabot[bot]'. That ties execution to who triggered the event, not who authored the PR, so Dependabot PRs may not get labeled on event types initiated by humans (e.g., edited) or when re-running the workflow. Prefer checking github.event.pull_request.user.login == 'dependabot[bot]' (and/or the PR author association) to ensure it always targets Dependabot PRs.
| github.actor == 'dependabot[bot]' && | |
| github.event.pull_request.user.login == 'dependabot[bot]' && |
| core.info(`PR #${context.payload.pull_request.number} is ${isSecurityUpdate ? '' : 'not '}a security update — adding label: ${label}`); | ||
|
|
||
| await github.rest.issues.addLabels({ | ||
| owner: context.repo.owner, | ||
| repo: context.repo.repo, | ||
| issue_number: context.payload.pull_request.number, | ||
| labels: [label] | ||
| }); |
There was a problem hiding this comment.
When ENSURE_LABELS_EXIST is set to 'false' and the labels don’t exist, issues.addLabels will fail with a generic API error. Consider handling that case explicitly (e.g., check label existence before labeling or catch the error and emit a clear message explaining how to create the missing labels).
| core.info(`PR #${context.payload.pull_request.number} is ${isSecurityUpdate ? '' : 'not '}a security update — adding label: ${label}`); | |
| await github.rest.issues.addLabels({ | |
| owner: context.repo.owner, | |
| repo: context.repo.repo, | |
| issue_number: context.payload.pull_request.number, | |
| labels: [label] | |
| }); | |
| const prNumber = context.payload.pull_request.number; | |
| core.info(`PR #${prNumber} is ${isSecurityUpdate ? '' : 'not '}a security update — adding label: ${label}`); | |
| try { | |
| await github.rest.issues.addLabels({ | |
| owner: context.repo.owner, | |
| repo: context.repo.repo, | |
| issue_number: prNumber, | |
| labels: [label] | |
| }); | |
| } catch (error) { | |
| const ensureLabels = process.env.ENSURE_LABELS_EXIST; | |
| const hint = ensureLabels === 'false' | |
| ? "The label may not exist because ENSURE_LABELS_EXIST is set to 'false'. Create the label in the repository's Labels settings, or set ENSURE_LABELS_EXIST to 'true' so this workflow can create it automatically." | |
| : "Ensure the label exists in the repository's Labels settings, or set ENSURE_LABELS_EXIST to 'true' so this workflow can create it automatically."; | |
| core.setFailed(`Failed to add label '${label}' to PR #${prNumber}. ${hint} Original error: ${error.message}`); | |
| } |
| on: | ||
| pull_request: | ||
|
|
There was a problem hiding this comment.
PR description states the workflow (a) runs on pull_request “all event types” and (b) follows the documented dependabot/fetch-metadata pattern, but the workflow currently uses default pull_request event types and doesn’t call dependabot/fetch-metadata. Either update the workflow to match (e.g., specify types: and/or add fetch-metadata) or adjust the PR description to reflect the implemented approach.
dependabot.ymlcannot apply different labels to security update PRs vs. version update PRs within the same ecosystem block. This workflow fills that gap without requiring a PAT.Changes
.github/workflows/labeler-dependabot.yml— new workflow that:pull_request(all event types), scoped todependabot[bot]onlyENSURE_LABELS_EXISTenv var toggle (defaults to'true'; set to'false'when labels are managed centrally)[Security Alerts page]orYou can disable automated security fix PRs; version update PRs never contain either phrasedependabot-security-updatefor security update PRs,dependabot-version-updatefor version update PRs using the GitHub APIPermissions
pull-requests: writeDetection approach
dependabot/fetch-metadata'salert-lookupfeature (which populatesghsa-id) requires a fine-grained PAT — it does not work withGITHUB_TOKEN, soghsa-idis always empty with the standard token. Security vs. version update detection instead relies on phrases present in all Dependabot security update PR bodies:[Security Alerts page]orYou can disable automated security fix PRsThis was verified against real PRs: a security update PR and two version update PRs.
Original prompt
Create a pull request in repository
advanced-security/reusable-workflowsthat adds a new GitHub Actions workflow named.github/workflows/labeler-dependabot.ymlto automatically label Dependabot pull requests by type.Requirements:
dependabot/fetch-metadataplus label application logic.labeler-dependabot.ymlbecause the repository already has a different labeler for another paradigm.dependabot-security-updatedependabot-version-updatePlease also address the case where the labels do not yet exist on the repository:
Expected deliverables:
The following is the prior conversation context from the user's chat exploration (may be truncated):
User: how to distinguish between a dependabot security pr vs a dependabot version update pr?
can you do a custom label per type via dependabot.yml ?
Assistant: Yes:
dependabot.yml(daily/weekly/monthly). About Dependabot pull requestsAnd for your second question: not directly per PR type with separate
labelskeys in the same update block. Thelabels:setting on anupdates:entry can apply to both version updates and security updates for that ecosystem, rather than letting you define one label set for security PRs and a different label set for version PRs in that same block. Customizing pull requests for Dependabot security updates About Dependabot pull requestsHow to distinguish them in practice
dependabot.yml.schedule,open-pull-requests-limit, andtarget-branchwhere configured. About Dependabot pull requestsAbout custom labels per type
GitHub docs show
groupssupportsapplies-to: security-updatesorapplies-to: version-updates, but that selector is for grouping behavior, not for separatelabelsblocks per type. Customizing pull requests for Dependabot security updatesSo if you want truly different labels like:
dependencies-securitydependencies-versionyou generally can’t express that purely in
dependabot.ymltoday with separate label rules by PR type in one ecosystem block, based on the docs above. Customizing pull requests for Dependabot security updatesTypical workaround
Use a GitHub Actions workflow that watches Dependabot PRs and applies labels based on whether the PR is a security update or a version update.
If you want, I can draft a GitHub Actions workflow that auto-labels:
dependencies-securitydependencies-versionUser: ok is there an action that does this workaround already?
Assistant: Yes — the main e...
This pull request was created from Copilot chat.
📍 Connect Copilot coding agent with Jira, Azure Boards or Linear to delegate work to Copilot in one click without leaving your project management tool.