Skip to content

Use modern patch syntax for first spec patch - #846

Merged
opohorel merged 2 commits into
packit:mainfrom
opohorel:patch_format
Sep 30, 2026
Merged

opohorel merged 2 commits into
packit:mainfrom
opohorel:patch_format

Conversation

@opohorel

@opohorel opohorel commented Sep 24, 2026 •

Copy link
Copy Markdown
Collaborator

Default new explicit patch applications to %patch -P N when a spec has no prior patches. Preserve established conventions and normalize first-patch inheritance without changing shipped patch files.

Resolves: PACKIT-5480
Related: #842

Assisted-by: GPT-6 Codex

@qodo-for-packit

Copy link
Copy Markdown

PR Summary by Qodo

Use modern syntax for first RPM spec patch applications

✨ Enhancement 🧪 Tests 🕐 20-40 Minutes

Grey Divider

AI Description

• Defaults first explicit RPM patch applications to %patch -P N.
• Preserves existing spec conventions and automatic %autosetup or %autopatch behavior.
• Normalizes inherited first patches before validation, with focused regression coverage.
Diagram

graph TD
    A["Backport Prompts"] --> B["Adaptation Agent"] --> C["Target Spec"] --> D["Syntax Normalizer"] --> E["Inheritance Validator"]
    F["Original Spec"] --> D
Loading
High-Level Assessment

The combined approach is appropriate: prompt guidance handles generated backports, while deterministic post-processing protects inherited adaptations from inconsistent model output. A prompt-only solution would be nondeterministic, and parser-level macro reconstruction could unnecessarily alter surrounding spec formatting; the targeted line rewrite better preserves existing files.

Files changed (8) +130 / -1

Enhancement (2) +42 / -0
backport_agent.pyNormalize inherited first-patch syntax before validation +10/-0

Normalize inherited first-patch syntax before validation

• Loads the original target spec after inheritance adaptation and normalizes newly inherited explicit patch applications before running safety validation.

ymir/agents/backport_agent.py

ystream_inherit.pyAdd targeted inherited patch syntax normalization +32/-0

Add targeted inherited patch syntax normalization

• Introduces a normalizer that detects whether the original spec already declared patches and rewrites only newly inherited '%patchN' applications in '%prep' to '%patch -P N'. It preserves whitespace, macro options, unrelated references, existing conventions, and automatic patch workflows.

ymir/agents/ystream_inherit.py

Tests (2) +71 / -1
test_jinja2_templates.pyVerify first-patch guidance in rendered prompts +13/-0

Verify first-patch guidance in rendered prompts

• Adds assertions that standard, z-stream, and inheritance prompts communicate explicit first-patch numbering and convention-preservation rules.

ymir/agents/tests/unit/test_jinja2_templates.py

test_ystream_inherit.pyCover selective first-patch normalization +58/-1

Cover selective first-patch normalization

• Tests conversion of inherited '%patchN' macros, preservation of indentation and options, automatic application behavior, existing declarations, conditional patches, and patch lists. Extends the inheritance workflow test to verify normalized syntax remains valid.

ymir/agents/tests/unit/test_ystream_inherit.py

Other (4) +17 / -0
_self_review.j2Add first-patch syntax to backport self-review +2/-0

Add first-patch syntax to backport self-review

• Requires self-review to confirm that a spec's first explicit patch uses '%patch -P N', while later patches retain the established format.

ymir/agents/prompts/backport/_self_review.j2

instructions.j2Guide standard backports toward modern first-patch syntax +4/-0

Guide standard backports toward modern first-patch syntax

• Instructs the backport agent to use explicit '-P' numbering for a spec's first patch and preserve existing or automatic application conventions.

ymir/agents/prompts/backport/instructions.j2

instructions_inherit.j2Prioritize target conventions during patch inheritance +6/-0

Prioritize target conventions during patch inheritance

• Directs inherited adaptations to use modern syntax only when introducing the target's first patch. Existing target conventions take precedence over source-spec spelling.

ymir/agents/prompts/backport/instructions_inherit.j2

instructions_zstream.j2Guide z-stream backports toward modern patch syntax +5/-0

Guide z-stream backports toward modern patch syntax

• Adds first-patch formatting rules for z-stream spec changes while preserving established syntax and automatic patch application.

ymir/agents/prompts/backport/instructions_zstream.j2

@qodo-for-packit

qodo-for-packit Bot commented Sep 24, 2026 •

Copy link
Copy Markdown

Code Review by Qodo

🐞 Bugs (0) 📘 Rule violations (0) 📜 Skill insights (0)

Grey Divider


Remediation recommended

1. Inherited first patches keep old syntax ✓ Resolved
Description
normalize_first_inherited_patch_applications only matches a patch number joined directly to
%patch, leaving the supported %patch 0 -p1 form unchanged. When an inheritance adaptation uses
that repository-supported form for a spec with no previous patches, validation accepts the
application but the promised %patch -P 0 normalization never occurs.
Code

ymir/agents/ystream_inherit.py[R442-444]

+                match = re.match(r"(\s*)%patch(\d+)(?=\s|$)", line)
+                if match and int(match.group(2)) in patch_numbers:
+                    prep[index] = f"{match.group(1)}%patch -P {match.group(2)}{line[match.end() :]}"
Relevance

●●● Strong

Supported spaced syntax bypasses promised normalization; similar regex robustness fixes were
accepted.

PR-#510
PR-#477

ⓘ Recommendations generated based on similar findings in past PRs

Evidence
The new inheritance instructions require %patch -P N for a target spec's first explicit patch,
while the normalizer's regular expression only accepts digits immediately following %patch. The
repository's specfile tests demonstrate that %patch 0 is a supported individual application form,
and inheritance validation parses such applications through PatchMacro, so no later check enforces
the intended normalization.

ymir/agents/prompts/backport/instructions_inherit.j2[17-21]
ymir/agents/ystream_inherit.py[431-444]
ymir/agents/ystream_inherit.py[383-410]
ymir/tools/unprivileged/tests/unit/test_specfile.py[231-239]

Agent prompt
The issue below was found during a code review. Follow the provided context and guidance below and implement a solution

## Issue description
`normalize_first_inherited_patch_applications` recognizes `%patch0` but not the supported `%patch 0` form, allowing first inherited patch applications to retain old syntax.

## Fix Focus Areas
- ymir/agents/ystream_inherit.py[442-444]
- ymir/agents/tests/unit/test_ystream_inherit.py[252-286]

## Recommended Fix
Extend the matcher and replacement logic to recognize both `%patchN` and `%patch N` while preserving indentation and all trailing options. Add a parameterized test covering `%patch 0 -p1` and confirming it becomes `%patch -P 0 -p1`.

ⓘ Copy this prompt and use it to remediate the issue with your preferred AI generation tools


Grey Divider

Context sources
✅ Compliance rules (platform): 5 rules
Review mode: 🚀 Fast: This is a small, localized regex normalization change with a focused regression test and no high-risk or broad behavioral impact.

Grey Divider

Tip of the day
💡 Did you know, you can route each severity your way: inline, summary, both, or drop

More tips ↗ | Customize Qodo ↗ | Qodo docs ↗

Grey Divider

Previous reviews

Review updated until commit 7470a7c

Results up to commit 8216def ⚖️ Balanced


🐞 Bugs (0) 📘 Rule violations (0) 📎 Requirement gaps (0) 🎨 UX issues (0) 🔗 Cross-repo conflicts (0) 📜 Skill insights (0)


Remediation recommended
1. Inherited first patches keep old syntax ✓ Resolved
Description
normalize_first_inherited_patch_applications only matches a patch number joined directly to
%patch, leaving the supported %patch 0 -p1 form unchanged. When an inheritance adaptation uses
that repository-supported form for a spec with no previous patches, validation accepts the
application but the promised %patch -P 0 normalization never occurs.
Code

ymir/agents/ystream_inherit.py[R442-444]

+                match = re.match(r"(\s*)%patch(\d+)(?=\s|$)", line)
+                if match and int(match.group(2)) in patch_numbers:
+                    prep[index] = f"{match.group(1)}%patch -P {match.group(2)}{line[match.end() :]}"
Relevance

●●● Strong

Supported spaced syntax bypasses promised normalization; similar regex robustness fixes were
accepted.

PR-#510
PR-#477

ⓘ Recommendations generated based on similar findings in past PRs

Evidence
The new inheritance instructions require %patch -P N for a target spec's first explicit patch,
while the normalizer's regular expression only accepts digits immediately following %patch. The
repository's specfile tests demonstrate that %patch 0 is a supported individual application form,
and inheritance validation parses such applications through PatchMacro, so no later check enforces
the intended normalization.

ymir/agents/prompts/backport/instructions_inherit.j2[17-21]
ymir/agents/ystream_inherit.py[431-444]
ymir/agents/ystream_inherit.py[383-410]
ymir/tools/unprivileged/tests/unit/test_specfile.py[231-239]

Agent prompt
The issue below was found during a code review. Follow the provided context and guidance below and implement a solution

## Issue description
`normalize_first_inherited_patch_applications` recognizes `%patch0` but not the supported `%patch 0` form, allowing first inherited patch applications to retain old syntax.

## Fix Focus Areas
- ymir/agents/ystream_inherit.py[442-444]
- ymir/agents/tests/unit/test_ystream_inherit.py[252-286]

## Recommended Fix
Extend the matcher and replacement logic to recognize both `%patchN` and `%patch N` while preserving indentation and all trailing options. Add a parameterized test covering `%patch 0 -p1` and confirming it becomes `%patch -P 0 -p1`.

ⓘ Copy this prompt and use it to remediate the issue with your preferred AI generation tools


Grey Divider

Qodo Logo

Comment thread ymir/agents/ystream_inherit.py Outdated
@opohorel

Copy link
Copy Markdown
Collaborator Author

/agentic_review

@qodo-for-packit

Copy link
Copy Markdown

Code review by qodo was updated up to the latest commit 18473d4

@lbarcziova lbarcziova left a comment

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

LGTM, can you please link #842 in commit/PR description?

@opohorel
opohorel force-pushed the patch_format branch 2 times, most recently from ba6b4af to 45f2905 Compare September 30, 2026 08:24
Default new explicit patch applications to %patch -P N when a spec has no prior patches. Preserve established conventions and normalize first-patch inheritance without changing shipped patch files.

Resolves: PACKIT-5480

Related: packit#842

Assisted-by: GPT-6 Codex
Recognize %patch N alongside %patchN when adding a spec first inherited patch, preserving strip and backup options.

Assisted-by: GPT-6 Codex
@opohorel
opohorel merged commit 90ae027 into packit:main Sep 30, 2026
15 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants