Webhook remediation PR processing fields
This page describes PR processing results, language package update details, PR operation events, and problems that stop writes in webhook remediation plans. See Remediation plan overview for the overall structure.
When PR creation is enabled and a remediation plan exists, pull_request_summary and pull_requests are emitted if there are processing targets, operations if there are undelivered operation events, and problems if there are problems that stop writes.
operations and problems can also be emitted when pull_requests is absent.
Field names in each table are relative to the object named before the table. The notation in “When there is no value” follows Report fields.
PR processing fields
remediation has the following fields for PR processing.
| Field | Type | Meaning | When there is no value |
|---|---|---|---|
pull_request_summary |
object | PR processing item counts by status | omitted when there are no processing targets |
pull_requests |
array of objects | PR processing results for each update target | omitted when there are no processing targets |
operations |
array of objects | Undelivered PR operation events described in PR operation event fields | omitted |
problems |
array of objects | Problems that stop PR writes, as described in Write-blocking problem fields | omitted |
See Item counts for how to read the keys and counts in pull_request_summary and how zero counts are handled.
See PR status values for status definitions.
Matching update targets to PRs
Each element of pull_requests[] is the processing result for targets updated together in the same repository and base branch.
How targets are grouped depends on kind.
An element contains information about the PR created or the PR corresponding to the same update. An element is emitted even when a PR could not be created, so the number of elements does not equal the number of PRs created.
Use repo and number together to identify a PR.
pull_requests[] has the following fields in each element.
| Field | Type | Meaning | When there is no value |
|---|---|---|---|
kind |
string | Update target type, as described in Update target kinds | omitted when updating Compose tags |
key |
string | Identifier of the processing unit that groups update targets | — |
repo |
string | owner/name of the repository to update |
— |
base_branch |
string | Branch into which the PR is to be merged | — |
path |
string | Path within the repository of the file representing the update target | — |
services |
array of strings | List of service names or workloads to update | [] |
workloads |
array of strings | Target workload keys, as described in Image name updates | omitted |
also_running |
array of objects | Information about Services running the same image but not included in the update | omitted |
current_ref |
string | Image name before the update | "" |
candidate_tag |
string | Tag of the update candidate image | omitted |
candidate_digest |
string | Manifest or image index digest of the update candidate image | omitted |
status |
string | PR processing status from PR status values | — |
reason |
string | Reason for the PR processing result from Reason codes | omitted |
detail |
string | Explanatory text supplementing the PR processing result | omitted |
number |
integer | Number of the associated PR | omitted when 0 |
url |
string | URL of the associated PR | omitted |
state |
string | Recorded state of the associated PR from PR status values | omitted |
user_modified |
boolean | Whether changes differing from the creation record were found in the PR | omitted when false |
target_key |
string | Value identifying the combination of file and locations to edit | omitted |
update_key |
string | Value identifying the update contents for the same edit target | omitted |
attempt_key |
string | Value identifying the update contents and inputs to the commit to be created | omitted |
fix_target_count |
integer | Number of fix targets before truncation | 0 |
fix_targets |
array of objects | Fix targets resolved by this update | omitted |
fix_targets_truncated |
boolean | Whether the fix target list was truncated to 100 entries | omitted when false |
replaced_by |
integer | Number of the newer PR that replaced this PR | omitted when 0 |
replacing |
array of objects | Progress of PR replacement for each older PR this PR replaces | omitted |
replaced |
array of integers | Numbers of older PRs whose replacement by this PR is complete | omitted |
item_key |
string | key of the associated element in language_items[] |
omitted |
language |
object | Language package update details | omitted |
The following fields have additional notes.
key- An identifier determined before querying GitHub, separate from the PR number
- Use it to match the same processing target across notifications, without assuming it matches
items[].keyordockerfile_items[].key
item_key- Match against
language_items[].keywhenkindislanguage
- Match against
target_key- Identifies the update kind, repository, base branch, file, and edit locations, and stays the same for the same edit target even if the versions before and after the update change
- Match
pull_requests[].target_keyacross notifications to associate proposals for the same edit target
update_key- Distinguishes the previous reference and candidate tag and digest for image updates, or adopted versions and dependency file changes for language package updates
- Also distinguishes the set of affected workloads for Kubernetes manifest, Kustomize, and Helm values updates
- Match
pull_requests[].update_keyacross notifications to associate proposals for the same update
attempt_key- Changes when the base commit or file contents before or after the edit change, even for the same update
- Stays the same when processing resumes from the same inputs, so do not use it to count executions
- Match against
operations[].attempt_keyto group operations related to creating that PR
target_key,update_key,attempt_key- Values are 64-character hexadecimal strings representing SHA-256 hashes; compare the received strings as they are
- If processing stops partway through, keys that have not yet been determined are omitted
also_running- Includes services without a Compose mapping and workloads outside the Kubernetes mappings or the set of affected workloads
user_modifiedtruewhen the PR head commit, base, head repository, or similar information differs from the creation record
replaced_by,replacing,replaced- PR numbers belong to the repository in this element's
repo replacingandreplacedare not truncated by entry count when emitted in the webhook
- PR numbers belong to the repository in this element's
Update target kinds
kind uses the following values.
| Value | Meaning |
|---|---|
| omitted | Compose tag update, grouping services in the same file that use the same image reference |
kubernetes |
Kubernetes manifest tag update, grouping containers in the same file that use the same image reference |
kustomize |
Updates one Kustomize images entry |
helm_values |
Updates one configured key in Helm values |
dockerfile |
Updates one FROM in a Dockerfile |
language |
Updates packages together for one dependency file directory |
The following fields have additional notes.
path- The Compose file for Compose, the manifest for
kubernetes, the kustomization file forkustomize, or the values file forhelm_values - The Dockerfile for
dockerfile - For
language, the dependency file representing the update target:package-lock.jsonfor npm,pnpm-lock.yamlfor pnpm,uv.lockfor uv,requirements.txtfor pip,go.modfor Go, the rootpom.xmlfor Maven, orgradle.lockfilefor Gradle - Language package PRs may also change dependency files other than
path
- The Compose file for Compose, the manifest for
services- For Compose, service names in the Compose file being edited
- For
kubernetes,kustomize, andhelm_values, workload keys as described in Image name updates - For
dockerfileandlanguage, a list of names extracted from each workload key, with duplicates removed - The extracted name is the service name for Compose, workload name for Kubernetes, container name for Docker containers with an unknown workload, or Pod name for Kubernetes containers with an unknown workload
current_ref- For Compose,
kubernetes,kustomize, andhelm_values, the running image reference used by the update targets - For
dockerfile, the base image reference specified in the targetFROM ""forlanguage
- For Compose,
candidate_tag,candidate_digest- Omitted for
language
- Omitted for
Fix targets
Each element of pull_requests[].fix_targets[] represents a vulnerability resolved in a package at a particular location.
Its fields are as follows.
| Field | Type | Meaning | When there is no value |
|---|---|---|---|
location |
string | Edit location or location within a dependency file to which the fix target belongs | — |
vuln_id |
string | ID of the vulnerability resolved | — |
package |
string | Name of the package to fix | — |
ecosystem |
string | Type of the package to fix, as described in Packages | omitted |
The following fields have additional notes.
location- For Compose,
services.<service>.image - For
kubernetes,<Kind>/<namespace>/<name>/<container>, whereKindandnameidentify the mapped object in the file andnamespaceis the workload namespace - For
kustomize,images[<name>].newTag - For
helm_values, the configuredhelm_values.key - For
dockerfile,stages[<number>]using a zero-based stage number, with:<name>appended in lowercase if the stage has a name - For
language, the matched package location within a dependency file, or the path of the dependency file to update if no location is available
- For Compose,
package- For language packages, this may be the normalized name used for matching against dependency files
Helm values use the configured key for both mapping and string forms.
For example, if helm_values.key is image, location is image, not image.tag, even when changing the tag in mapping form.
The list contains at most 100 entries.
Check pull_requests[].fix_target_count for the full count; pull_requests[].fix_targets_truncated is true when there are more than 100 entries.
The count distinguishes locations and packages rather than grouping only by vulnerability ID. Base image updates also count targets separately when the sets of layers containing the findings differ.
Layer information is not emitted in this array, so receivers must not remove elements as duplicates merely because their visible fields are identical.
PR replacement
Each element of pull_requests[].replacing[] represents the progress of replacing an older PR with this PR.
| Field | Type | Meaning | When there is no value |
|---|---|---|---|
old_number |
integer | Number of the older PR to replace | — |
state |
string | State of the process for replacing the older PR | — |
state uses the following values.
| Value | Meaning |
|---|---|
pending |
Replacement has been decided, but no operation has been sent yet |
commented |
The older PR has a comment announcing the replacement |
closed |
The close operation has been sent, but its result has not been confirmed |
done |
The older PR has been recorded as replaced |
abandoned |
Replacement conditions are no longer met, and the process has been abandoned |
A replacing[].state of closed does not necessarily mean that closure has been confirmed.
replaced[] contains the numbers for which the replacement process is done and the older PR's state has also been confirmed as replaced.
See Replacing older PRs for replacement conditions.
PR processing examples
The following example shows the summary and PR processing result excerpted from the output after creating a base image update PR.
{
"remediation": {
"pull_request_summary": {
"pr_created": 1
},
"pull_requests": [
{
"kind": "dockerfile",
"key": "dockerfile|ex/app|main|docker/Dockerfile|stages[0]:runtime",
"repo": "ex/app",
"base_branch": "main",
"path": "docker/Dockerfile",
"services": ["app"],
"workloads": ["compose/shop/app"],
"current_ref": "python:3.12.3-slim",
"candidate_tag": "3.12.5-slim",
"status": "pr_created",
"number": 7,
"url": "https://github.com/ex/app/pull/7",
"state": "open",
"fix_target_count": 2,
"fix_targets": [
{
"location": "stages[0]:runtime",
"vuln_id": "CVE-2031-0001",
"package": "libc"
},
{
"location": "stages[0]:runtime",
"vuln_id": "CVE-2031-0002",
"package": "libc"
}
]
}
]
}
}
The following example shows fields describing the target, excerpted from one element of pull_requests[] for a language package update.
{
"kind": "language",
"key": "language|ex/app|main|package-lock.json",
"repo": "ex/app",
"base_branch": "main",
"path": "package-lock.json",
"services": ["api", "web"],
"workloads": ["compose/shop/api", "compose/shop/web"],
"current_ref": ""
}
Language package update details
pull_requests[].language describes the packages updated by the PR and the changes to dependency files.
Its fields are as follows.
| Field | Type | Meaning | When there is no value |
|---|---|---|---|
manager |
string | Package manager that handles the dependency files | — |
root |
string | Directory of the dependency files within the repository | — |
packages |
array of objects | Packages to update | [] |
manifest_edits |
array of objects | Version specification changes in dependency files | omitted |
chain |
array of objects | Direct dependencies updated along with the targets for re-resolution | omitted |
remaining |
array of objects | Packages excluded from the PR update | omitted |
manager uses the following values.
| Value | Meaning |
|---|---|
npm |
npm |
pnpm |
pnpm |
uv |
uv |
pip |
pip |
go |
Go modules |
maven |
Maven |
gradle |
Gradle |
root is . when it refers to the repository root.
See Supported input formats for supported dependency file formats.
Packages to update
pull_requests[].language.packages[] has the following fields in each element.
| Field | Type | Meaning | When there is no value |
|---|---|---|---|
name |
string | Name of the package to update | — |
ecosystem |
string | Type of the package to update, as described in Packages | — |
relation |
string | Dependency relationship classification from the project's perspective | omitted |
from |
string | Running version of the package to update | — |
to |
string | Update version adopted by the PR | — |
major |
boolean | Whether the change from from to to is a major version change |
omitted when false |
through |
array of strings | Names of direct dependencies updated along with this package to enable its update | omitted |
relation uses the following values.
| Value | Meaning |
|---|---|
direct |
Dependency required directly by the project |
transitive |
Dependency reached through another package |
mixed |
A mixture of direct dependencies and dependencies reached through other packages |
The following fields have additional notes.
from- In a cycle matched to an existing PR, the running version confirmed in that cycle's plan
major- Also
truefor minor version changes in0.x - Also omitted when versions cannot be parsed and compared, so do not judge the safety of a change from omission alone
- Also
through- Check the entry with the same name in
pull_requests[].language.chain[]for the versions before and after the update
- Check the entry with the same name in
Version specification changes in dependency files
pull_requests[].language.manifest_edits[] has the following fields in each element.
| Field | Type | Meaning | When there is no value |
|---|---|---|---|
file |
string | Path within the repository of the file whose version specification is rewritten | — |
section |
string | Dependency declaration section containing the version specification | — |
name |
string | Name of the package whose version specification is rewritten | — |
from |
string | Version specification before the change | — |
to |
string | Version specification after the change | — |
major |
boolean | Whether the new version specification no longer allows the major version allowed by the old specification | omitted when false |
section contains a section within a dependency file, such as dependencies or project.dependencies.
from and to are version specifications such as ^4.17.15; check pull_requests[].language.packages[].to for the version actually adopted.
Direct dependencies updated along with the targets
pull_requests[].language.chain[] has the following fields in each element.
| Field | Type | Meaning | When there is no value |
|---|---|---|---|
name |
string | Name of the direct dependency updated along with the targets | — |
from |
string | Version of the direct dependency before the change | "" |
to |
string | Version of the direct dependency after the change | "" |
held |
string | Name of the package subject to a requirement for an older version | omitted |
held_range |
string | Version specification that blocked the update | omitted |
held_by |
string | Name of the package between the direct dependency and held that required an older version |
omitted |
held_by is omitted when the direct dependency itself requires the older version.
See Re-resolution check conditions for re-resolution conditions.
Packages excluded from the PR update
pull_requests[].language.remaining[] has the following fields in each element.
| Field | Type | Meaning | When there is no value |
|---|---|---|---|
name |
string | Name of the package excluded from the PR update | — |
ecosystem |
string | Type of the excluded package, as described in Packages | — |
relation |
string | Dependency relationship classification from the project's perspective, as described in Packages to update | omitted |
from |
string | Running version of the excluded package | — |
target |
string | Planned lower bound for the update version | "" |
reason |
string | Reason for exclusion from the update from Reason codes | — |
detail |
string | Explanatory text supplementing the exclusion reason | omitted |
maven_bom |
object | BOM information for excluded packages identifying a version that reaches the update lower bound | omitted |
In a cycle matched to an existing PR, exclusion information from pull_requests[].language.remaining[] supplements language_items[].packages[] entries with the same name and ecosystem.
language_items[].packages[] may include left_out: true, action: "manual", and reason even when language_items[].update_executed and language_items[].post_update_check_executed are false.
Additional details are also reflected in language_items[].packages[].detail when available, and applicable BOM information in language_items[].packages[].maven_bom.
Packages with the reason global_node_modules are excluded from this supplementation.
See Partial PRs for interpreting partial updates.
BOM information for excluded packages
pull_requests[].language.remaining[].maven_bom has the following fields.
| Field | Type | Meaning | When there is no value |
|---|---|---|---|
bom |
string | groupId:artifactId of the BOM |
— |
property |
string | Name of the property specifying the BOM version | omitted |
from |
string | BOM version imported by the project | — |
to |
string | Candidate BOM version that manages the target package at or above the update lower bound | — |
manages |
string | Version of the target package managed by the BOM at to |
— |
This object is emitted when pull_requests[].language.remaining[].reason is maven_bom_series_unreached and BOM candidate information is available.
Use from and to for BOM versions and manages for the target package version.
See Version sources and edits and Version declarations and edits for the meaning of the candidate.
Language package update example
The following example shows the output of pull_requests[].language.
{
"manager": "npm",
"root": ".",
"packages": [
{
"name": "lodash",
"ecosystem": "node-pkg",
"relation": "direct",
"from": "4.17.15",
"to": "4.17.21"
},
{
"name": "minimist",
"ecosystem": "node-pkg",
"relation": "transitive",
"from": "1.2.5",
"to": "1.2.6"
}
],
"manifest_edits": [
{
"file": "package.json",
"section": "dependencies",
"name": "lodash",
"from": "4.17.15",
"to": "4.17.21"
}
]
}
Partial PR example
A partial PR updates only some of the packages that were intended to be updated together.
The following example extracts only the main fields from a payload containing a partial PR. Check where the successfully updated package and the package excluded from the update are recorded.
- The successfully updated
example-ais recorded only inlanguage_items[].packages[]in this example - The excluded
example-bis recorded inlanguage_items[].packages[]withleft_out: trueand also inpull_requests[].language.remaining[]
{
"remediation": {
"language_items": [
{
"category": "pr_candidate",
"update_executed": true,
"post_update_check_executed": true,
"packages": [
{
"name": "example-a",
"ecosystem": "node-pkg",
"installed": "1.0.0",
"adopted_version": "1.0.1",
"action": "update",
"reason": "update_verified"
},
{
"name": "example-b",
"ecosystem": "node-pkg",
"installed": "2.0.0",
"selection_lower_bound": "2.0.1",
"action": "manual",
"reason": "target_not_updated",
"left_out": true
}
]
}
],
"pull_requests": [
{
"kind": "language",
"language": {
"remaining": [
{
"name": "example-b",
"ecosystem": "node-pkg",
"from": "2.0.0",
"target": "2.0.1",
"reason": "target_not_updated"
}
]
}
}
]
}
}
See Partial PR conditions for adoption conditions.
PR operation event fields
operations[] emits PR operation events that have not yet been recorded as delivered, in ascending sequence number order.
The record before sending an operation, its result, and any result confirmed later are separate events for that operation.
operations[] has the following fields in each element.
| Field | Type | Meaning | When there is no value |
|---|---|---|---|
seq |
integer | Event sequence number that increases within the same saved PR processing records | — |
id |
string | Identifier linking the phases of the same operation | — |
at |
string | Time the event was recorded, in UTC RFC 3339 format | — |
phase |
string | Value indicating which phase of the operation the event records | — |
kind |
string | Kind of write operation on GitHub | — |
repo |
string | owner/name of the repository targeted by the operation |
— |
attempt_key |
string | Value identifying the contents of the related PR creation attempt | omitted |
number |
integer | Number of the PR targeted by the operation | omitted when 0 |
result |
string | Operation result | omitted |
error |
string | Explanatory text supplementing an error or the confirmation of an outcome | omitted |
phase uses the following values.
| Value | Meaning |
|---|---|
intent |
The intention to perform the operation was recorded before sending it |
result |
The result obtained after sending the operation was recorded |
settled |
An operation with an unknown outcome was checked in a later cycle, and its handling was settled |
kind uses the following values.
| Value | Meaning |
|---|---|
create_blob |
Creates Git file contents |
create_tree |
Creates a Git file tree |
create_commit |
Creates a commit |
create_ref |
Creates a branch for a PR |
create_pull |
Creates a PR |
create_comment |
Creates a comment on a PR announcing its replacement |
close_pull |
Closes the PR being replaced |
result uses the following values.
| Value | Meaning |
|---|---|
ok |
The operation was confirmed to have succeeded |
failed |
The operation was confirmed to have failed or the intended change was confirmed not to have taken effect |
unknown |
Whether the operation succeeded cannot be determined |
The following fields have additional notes.
seq- Increases across all PR processing that shares the same saved records, rather than separately for each repository
- The same event has the same value when redelivered
id- Uses the form
op-<sequence number>, with the sequence number of the first event - Shared by
intent,result, andsettledfor the same operation, while each event has a differentseq
- Uses the form
attempt_key- Can be matched against
pull_requests[].attempt_key, with one value corresponding to theidvalues of multiple operations - Because undelivered events from earlier cycles are also included, a matching entry may not exist in that notification's
pull_requests[]
- Can be matched against
number- The target PR number for comment creation and closure; it may be omitted from PR creation events even after success
phaseintentalone does not confirm that the operation was sent to GitHub- Even with
settled,resultstaysunknownwhen processing restarts without using Git file contents, trees, or commits whose creation could not be confirmed
error- Explanatory text rather than a fixed code; for
settled, it may contain confirmation details even whenresultisok
- Explanatory text rather than a fixed code; for
To deduplicate events at the receiver, use seq within the same saved records from the same sender.
Deduplicating by id or attempt_key alone would discard results and later confirmation events for the same operation.
seq and id are reused after the saved records are initialized.
The webhook contains no value that uniquely identifies the sender or identifies initialization of the saved records, and neither environment.kind nor environment.name is guaranteed to be unique.
Received data alone cannot reliably distinguish events from multiple senders or events before and after initialization. Operational measures are required, such as using a separate receiving URL for each sender and switching the receiver's deduplication records when the saved records are initialized.
See Remediation plan redelivery for delivery and redelivery behavior.
Write-blocking problem fields
problems[] represents problems that stop PR writes.
A problem is included in each cycle's plan while it persists, with one entry per combination of code, repo, and target in the same plan.
problems[] has the following fields in each element.
| Field | Type | Meaning | When there is no value |
|---|---|---|---|
code |
string | Classification of the problem that stops writes | — |
repo |
string | owner/name of the repository with the problem |
omitted when the problem concerns all repositories |
target |
string | Display string identifying the file and target locations with the problem | omitted when the problem is not limited to a target |
reason |
string | Specific cause of the problem from Reason codes | omitted |
detail |
string | Explanatory text supplementing the problem | omitted |
code uses the following values.
| Value | Meaning |
|---|---|
write_blocked |
Writes stopped because of a mismatch between records and GitHub state, a processing setup failure, or a similar problem |
storage_failed |
Writes stopped because the remediation plan or PR processing records could not be saved |
storage_full |
New writes stopped because space could not be made available for operation events |
records_unverified |
Writes stopped because PR records could not be verified |
code is the broad problem classification, and reason is its cause.
For example, when code is write_blocked, reason distinguishes causes such as branch_not_ours and attempt_unsettled.
The following fields have additional notes.
repo- When present, match against
pull_requests[].repo
- When present, match against
target- Uses the format
<file path> (<target location>, <target location>), with only one location inside the parentheses when there is one target location - Compare the file path with
pull_requests[].pathand the target locations for Compose, Kubernetes, Kustomize, Helm values, and Dockerfile updates withpull_requests[].fix_targets[].location - For language package updates, the target location is the dependency file directory and corresponds to
pull_requests[].language.root - Not a matching key that equals
pull_requests[].keyorpull_requests[].target_key - Because
fix_targetsmay be omitted or truncated and processing targets may change, the corresponding element ofpull_requests[]may not be identifiable from that notification alone - If
repois present andtargetis absent, the problem concerns the entire repository
- Uses the format
See Stopping writes for stop conditions.