Patch check
Does each composer patch still apply to the release a site installed, and is
its fix already in that release? Verdicts come from git apply --check
against the release tag in the project's bare clone. For a merge request URL,
the merge request state is read too.
POST /v1/patch/check
{"items": [
{"project": "redirect", "version": "1.13.0",
"patch": "https://git.drupalcode.org/project/redirect/-/merge_requests/45.patch",
"title": "Guide users who enter path aliases"},
{"project": "drupal", "version": "11.4.5", "patch": "<inline unified diff>"}
],
"reroll": false,
"target_core": "11.4.5"}
At most 50 items and 32 MB.
| Field | What it holds |
|---|---|
project |
The drupal.org machine name. drupal or core for Drupal core. |
version |
The installed composer version: 1.13.0, 8.x-1.13, 2.0.0-beta4, 11.4.5. |
patch |
Unified diff text, up to 16 MB, or a URL on www.drupal.org/files/issues/, or on git.drupalcode.org under /project/<name>/-/merge_requests/<n> or /project/<name>/-/commit/<sha>, ending .patch or .diff. |
title |
Optional. Echoed back. |
base |
Optional. The release the site runs: a commit sha, or a composer version. A re-roll of a patch without index lines tries it first as the merge base, before the newest tags. |
reroll |
Top-level. true also returns a 3-way re-roll for every item that ends conflicts. Each one costs a scratch merge and can be large. |
target_core |
The core version the added code is checked against, 11.4.5. Defaults to the lock's drupal/core, else the version of a drupal item. |
Or send the site's own files in place of items:
{"composer_json": "<composer.json text>",
"composer_lock": "<composer.lock text>",
"patch_files": {"patches/webform.patch": "<diff text>"}}
Every extra.patches entry is then checked at its installed version.
patch_files holds the text of each local patch, keyed by its path.
missing_files in the response lists the local patches the body did not
include.
GET /v1/patch/check
One URL item: ?project=redis&version=1.11.0&patch=https://www.drupal.org/files/issues/….patch.
Add &reroll=1 for the re-roll. Cached for one hour.
Response
{count, results}, one result per item in input order.
| Field | What it holds |
|---|---|
tag |
The release tag matched, or unknown_version. |
sha |
The commit the verdict was taken at. Present only when the version was a branch; a tag fixes its own commit. |
applies_at |
The -p level at which git apply --check passes (1, 0, 2, 4 tried in that order), or null. |
fuzzy |
True when it applied only with one context line, whitespace ignored and hunk counts recomputed. Review the result. |
hunks_failed |
[{file, line, reason}] at the most plausible level, at most 10. |
reverse_applies |
True when the patched lines are already in the tag. |
hunks_shipped |
[{file, line, reason}]: the hunks the release already has verbatim, when only part of the patch landed. On a conflicts row, check whether the rest is still needed before re-rolling. Evidence, not a verdict. |
files_shipped |
The files whose whole change is already in the release. |
mr |
{state, target_branch, merged_at, merge_commit_sha, squash_commit_sha, head_sha, detailed_merge_status} for a merge request URL. |
merged_in_version |
True when the merged request's squash or merge commit is an ancestor of the tag, or every From <sha> of a format-patch series is. False for an open request. Null when nothing could be checked. |
suggested |
The verdict: merged, applies, conflicts, or unknown. |
reroll |
Only with reroll: true on a conflicts item: {status, level, patch, conflicts: [{file, regions}], truncated, error}. See below. |
core_references |
What the added code references in core, at target_core. See below. |
error |
Why a verdict is missing or partial. |
reroll
| Field | What it holds |
|---|---|
status |
clean: install patch as the new patch. conflicts: patch has `<<<<<<< release / |
base |
The tag the merge ran from, when it was not the patch's own index lines. It is the item's base when the patch applies there, else the newest tag it applies to. |
patch |
The re-rolled diff. Paths are relative to the repository root: contrib at -p1, core under core/ at -p2 from web/core. Cut at 16 MB. |
syntax_errors |
PHP files that do not parse after the merge, path: message. verified is false then: the diff applies, the result is not valid PHP. Send resolutions whose text makes those files parse. |
core_references
{target, checked, flagged, flagged_more, deprecated, unresolved, note}.
| Field | What it holds |
|---|---|
flagged |
[{symbol, kind, via, file, line, reference, issue, site_arguments, target_parameters, since, change_record, replacement}]. |
flagged[].kind |
removed; moved (a live class has the name elsewhere); signature (the argument count is outside the declared parameters). |
flagged[].via |
For parent::__construct and new: the walk to the nearest core ancestor whose constructor was checked. |
deprecated |
[{fqn, deprecated_in, removal_in}]. |
note |
Why the references could not be checked, for a patch that does not apply. |
Scope: added lines and direct references only (extends, implements, trait use, new, static calls, parent::__construct). Read from the re-rolled diff when a clean re-roll produced one.
Errors
400 for a bad batch. 413 above 32 MB. 503 with Retry-After when the service
is busy. 502 when it is unreachable.