fix(migrate): backfill identifier aliases for renamed legacy prefixes

Migration 131 normalizes each workspace's legacy issue_prefix into a
Space key satisfying ^[A-Z][A-Z0-9]{0,6}$, but a prefix longer than 7
chars, digit-first, or punctuated gets rewritten and never went
through the alias-writing path in UpdateIssue (no issue actually
changed space_id, so no move-triggered alias was recorded). Old
links, CLI/API identifier lookups, and GitHub auto-linking for those
workspaces would 404/silently skip forever.

Backfill issue_identifier_alias for exactly the workspaces where the
normalized key diverges from the original prefix, and widen the
GitHub identifier regex back to {0,9} (matching the old prefix length
cap) so 8-10 char legacy prefixes are still extracted as candidates
before the DB/alias lookup decides validity.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
This commit is contained in:
Naiyuan Qing
2026-07-09 13:54:48 +08:00
parent f94d98b0de
commit c5a5d9eb74
2 changed files with 27 additions and 3 deletions

View File

@@ -581,8 +581,12 @@ func (h *Handler) ListPullRequestsForIssue(w http.ResponseWriter, r *http.Reques
// because branch names are conventionally lowercase but issue prefixes are
// uppercase. Word boundary on the left prevents matching inside email-style
// strings (e.g. "abc@MUL-1") and the digit anchor on the right rules out
// version numbers like "v1.2-3".
var identifierRe = regexp.MustCompile(`(?i)\b([a-z][a-z0-9]{0,6})-(\d+)\b`)
// version numbers like "v1.2-3". The key group allows up to 9 chars (not the
// Space key's 7-char cap) because legacy issue_prefix values up to 10 chars
// still resolve via the issue_identifier_alias backfill (see migration 134);
// extraction only needs to find a candidate, the DB lookup (current key,
// then alias) decides validity.
var identifierRe = regexp.MustCompile(`(?i)\b([a-z][a-z0-9]{0,9})-(\d+)\b`)
// closingIdentifierRe extracts identifiers that appear immediately after a
// GitHub-style closing keyword ("close[sd]?", "fix(e[sd])?", "resolve[sd]?"),
@@ -594,7 +598,7 @@ var identifierRe = regexp.MustCompile(`(?i)\b([a-z][a-z0-9]{0,6})-(\d+)\b`)
// title prefixes like "MUL-1: ..." link the PR (via identifierRe) but
// never auto-close.
var closingIdentifierRe = regexp.MustCompile(
`(?i)\b(?:close[sd]?|fix(?:e[sd])?|resolve[sd]?)[:\s]+([a-z][a-z0-9]{0,6})-(\d+)\b`,
`(?i)\b(?:close[sd]?|fix(?:e[sd])?|resolve[sd]?)[:\s]+([a-z][a-z0-9]{0,9})-(\d+)\b`,
)
// HandleGitHubWebhook (POST /api/webhooks/github) is GitHub's destination for

View File

@@ -14,3 +14,23 @@ CREATE TABLE issue_identifier_alias (
);
CREATE INDEX idx_issue_identifier_alias_issue ON issue_identifier_alias(issue_id);
-- Backfill aliases for the renaming migration 131 already performed. 131
-- normalized every workspace's legacy issue_prefix into a Space key
-- satisfying ^[A-Z][A-Z0-9]{0,6}$ (uppercase, strip non-alnum, truncate to 7).
-- Legacy prefixes longer than 7 chars, digit-first, or punctuated therefore
-- diverge from the key their issues now resolve under, and — unlike a
-- runtime move-to-space — that rename never went through the alias-writing
-- path above, since no issue actually changed space_id. Old links/CLI/GitHub
-- references using the pre-migration prefix would otherwise 404 forever.
-- workspace.issue_prefix is untouched by 131/132 (kept intentionally; see
-- 132's header comment), so the original value is still available here.
INSERT INTO issue_identifier_alias (workspace_id, space_key_lower, number, issue_id)
SELECT i.workspace_id, lower(btrim(w.issue_prefix)), i.number, i.id
FROM issue i
JOIN workspace w ON w.id = i.workspace_id
JOIN workspace_space wt ON wt.id = i.space_id
WHERE w.issue_prefix IS NOT NULL
AND btrim(w.issue_prefix) <> ''
AND lower(btrim(w.issue_prefix)) <> lower(wt.key)
ON CONFLICT DO NOTHING;