Skip to content

feat(backport-fix-imports): rewrite module paths on backports to older module majors - #329

Merged
Piotr1215 merged 7 commits into
mainfrom
devops-1648/backport-fix-imports
Oct 26, 2026
Merged

Piotr1215 merged 7 commits into
mainfrom
devops-1648/backport-fix-imports

Conversation

@vcauesantos

@vcauesantos vcauesantos commented Oct 22, 2026 •

Copy link
Copy Markdown
Contributor

Summary

  • New action backport-fix-imports. It fixes Go module paths on a backport branch when the target release line is on an older module major than main. Example: loft-enterprise main is on loft/v5 and api/v5, while release-4.x is still on v4.
  • It reads the paths the repo owns from go.mod on both branches. It moves files added under a v5 staging folder, resolves conflicts made only of import lines, and rewrites the paths in the changed .go files. Then it pushes one fix commit.
  • Conflicts in real code are left alone, and the reason output says how many files are left for review. The action never fails the job.
  • This PR does not wire the action into backport.yaml. That is feat(backport): wire backport-fix-imports behind fix-imports with a sticky pr comment #332, behind a flag.

Flow

flowchart TD
    A[Bot opens a backport PR] --> B{Does main use a newer module version than the release branch?}
    B -->|No| S[Stop: nothing to fix]
    B -->|Yes| C[Move new files into the old version's folder]
    C --> D[Fix conflicts that are only import lines]
    D --> E[Change v5 import paths to v4 in the changed files]
    E --> F{Did anything change?}
    F -->|No| U[Nothing to rewrite]
    F -->|Yes| G[Format, commit and push one fix commit]
    G --> H{Any conflicts left in real code?}
    U --> H
    H -->|No| Done[PR is ready for review]
    H -->|Yes| Next[Left for a person]
Loading

If any step fails, nothing is pushed and the backport PR stays as the bot opened it.

Test plan

  • make test-backport-fix-imports: 63 pytest tests with throwaway git repos and a local bare remote, no network.
  • actionlint, zizmor, make check-bats-jobs and make check-docs are clean.
  • Replayed the logic on the bot's first commit of six real loft-enterprise backports and compared with the merged result:
    • #8643, #8727, #8630, #8719: every file matches the human fix. #8719 includes 2 resolved import conflicts.
    • #8808: 19 of 23 files match, with 18 import conflicts resolved. The other 4 need real code changes because pkg/tenancy does not exist on 4.12.
    • #8629: the Go files match. A YAML conflict is left for review.
  • Full replay of all 54 bot backports to 4.x since the v5 change, with go vet on every package the script changed: 43 had nothing to fix and 9 got a fix commit. None of the script's changes caused a compile error. In 3 of the 9, go vet still failed on code that needs something missing on the older branch. That is a real code change, left for a person.
  • Real run on loft-enterprise with five backports, script and AI pass together: see feat(backport): run backport-fix-imports with an ai pass gated on go vet #330, section Real run on loft-enterprise.

Related to DEVOPS-1648
Related to DEVOPS-1671

@loft-bot loft-bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Panel review: 2 blocking, 3 quality notes, 9 lanes.

Blocking concerns

  • .github/actions/backport-fix-imports/src/fix.py:176: the usage check counts obj.config.X as a use of package config, so an unused import stays in and breaks the build.
  • .github/actions/backport-fix-imports/src/fix.py:321: skipped and failed runs leave conflicts-remaining empty, so the documented != '0' gate fires.

What was checked. Checked: correctness, security, test-quality, operability, reuse, architecture, typos, infra (CI workflow), PR metadata. Skipped: dead-code, e2e, gap analysis, entry-point fidelity, layout (nothing deleted, no e2e or Go test files, no linked customer bug, not a restructure).

Quality notes (non-blocking)

  • consider: fix.py:179. Could we keep the backported side's blank lines when merging an import hunk? Dropping them lets gofmt fold stdlib and module imports into one group (reproduced locally), and goimports-style lint flags that. This becomes blocking if the target repo's lint enforces import grouping.
  • nit: fix.py:302. Could git() name the subcommand instead of args[0]? A failed commit currently reports git -c failed.
  • nit: fix.py:292. Could the warning drop "outside import blocks"? It also fires for YAML files, where import resolution never ran.

Comment thread .github/actions/backport-fix-imports/src/fix.py Outdated
Comment thread .github/actions/backport-fix-imports/src/fix.py
@vcauesantos

Copy link
Copy Markdown
Contributor Author

The three quality notes are fixed in 0173056 too: blank lines between import groups are kept, git errors name the real command, and the warning no longer says "outside import blocks".

@vcauesantos
vcauesantos marked this pull request as ready for review October 22, 2026 17:42
@vcauesantos
vcauesantos requested a review from a team as a code owner October 22, 2026 17:42
@Piotr1215
Piotr1215 merged commit a3d77d1 into main Oct 26, 2026
8 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