Sign in

Search issue titles and bodies, change requests and comments. Private repositories you cannot read are not included.

vole
Clone

Read only, no credentials:

https://rodent.software/vole.git

Write over SSH with a registered key:

git clone ssh://git@rodent.software:2222/vole.git

A free and open-source forge that lives in your Git repo.

#27

Close linked issues when a change request lands

merged · by keenan 13d ago · merged into main at 183d48e5 by keenan 13d ago

keenan opened this 13d ago

Closes #01M5XG8WYZ1566KZFC73WQWGX3.

Why

A change request and the issue it resolves were two records that knew nothing about each other. Landing a request left its issue open, so the issue tracker drifted from the branch history the moment anybody merged, and the only thing keeping them in step was somebody remembering to close the issue afterwards.

What changed

The link is a field, not prose. request.md gains a closes: list of full issue ids. That makes it part of the file a reviewer reads, rather than a Closes #abc convention inside a description that nothing parses. Ids are validated and deduplicated on read and write, and vole change new --closes <id> refuses an id that is not an issue — while the author is still looking at the command, not at the landing they waited on.

The closure happens with the merge, in one commit. metadata.MarkMerged already writes the merged state; it now writes state: closed onto each linked issue in the same CommitFiles transaction. So the two cannot be separated by a crash: a merged request cannot leave its issues open, and an issue cannot be closed by a merge that did not happen. Both sides are validated afterwards and a failure is reported as ErrLandedUnmarked, which already carries “the branch moved, the record did not”.

What is deliberately left alone: an issue that is already closed is not rewritten (somebody closing it deliberately is not overruled), an issue that no longer exists is skipped (a request may outlive the issue), and re-marking an already-merged request closes nothing, so a retried landing is harmless.

Surfaces: vole change new --closes <id> (repeatable, comma lists accepted), the new-change form in the browser, “Closes #…” links on the request page, and vole change merge printing closed issue <id> for each one it closed.

Verification

vole workflow run verify in the pinned image: gofmt, vet, build, govulncheck (0 reachable), packaging, links, go test -race ./... — all pass.

New tests:

  • metadata: the closes list is sorted and deduplicated, and a short or malformed id is refused; MarkMerged closes the linked issue, leaves an unrelated one open, does not rewrite an already-closed one, returns exactly the ids it changed, is a no-op the second time, and CreateRequest refuses a link to an issue that does not exist;
  • forge/landing: landing a request closes the issue it names and nothing else.

One limitation, stated plainly

The closure happens where the request is marked merged — the server-side landing (Land), which is now the supported flow. A request landed the old way, by pushing the approved branch, is not marked by the hook (the hook validates and reports; it does not write metadata), so its issues stay open until the request is merged. That is the same gap that kept a push-landed request showing open and “Already merged” — and running vole change merge on it closes the issues too, because that path re-reads the request and marks it.

Acceptance

  • A change request can name the issues it closes
  • Merging closes them, in the same commit as the merged mark
  • A bad or unknown issue id is refused when the request is written
  • An already-closed or removed issue is left alone
  • CLI, browser form, request page and merge output all show the link
  • The issue’s own record shows it closed, by the same actor, at the same time

Discussion (0)

No discussion yet.