✨ feat: add passthrough for verbatim issue keys#77
Conversation
✅ Changeset detectedLatest commit: f5bd805
If no version change is needed, please add The changes in this PR will be included in the next version bump. This PR includes changesets to release 5 packages
|
|
/canary-publish |
|
@claude review this PR |
Published Canary Packages |
Recognize full tracker keys (Jira/Linear style, e.g. PROJ-123) in the branch and copy them into the commit message unchanged, via a new `passthrough` config ("uppercase" for any uppercase key shape, or an array of project keys). GitHub-style `rules` are unchanged and take precedence when a branch matches both.
Also fix idempotency to detect the resolved reference anywhere in the message, so body-placed templates no longer double-tag on git commit --amend; and evaluate branch protection before the already-tagged check so a pre-tagged message cannot bypass protect.
Ship schema.json in the package for editor autocompletion and validation.
|
/canary-publish |
Published Canary Packages |
|
@djk01281 님, 작업 감사합니다. 혹시 @naverpay/commithelper 쪽에도 동일 작업 부탁드려도 될까요? |
- `passthrough` is now an explicit project-key list (`["PROJ"]`); recognition follows Jigit's rule (<PROJECT>-<1-7 digits>, anywhere in the branch), so a listed project links identically in commithelper and Jigit - fix idempotency whole-token boundary so a reference is not matched inside a longer key (e.g. PROJ-1871 within MY-PROJ-1871) - update schema, README, tests (incl. a Jigit-parity table), and fold the changeset into a single note Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
|
/canary-publish |
넵! 확인했습니다! 🙇🏻 |
Published Canary Packages |
|
@djk01281 혹시 commithelper쪽 작업은 아직 작업 전이신거죠? |
|
@kyungmi 님 네 규칙을 맞추려고 했어서 아직 전이긴 합니다,,! |
kyungmi
left a comment
There was a problem hiding this comment.
main() 에서 순수 코어 processMessage 를 분리하고 resolve/resolvePrefix/resolveKey/alreadyHasRef 로 쪼갠 덕에 테이블 테스트가 촘촘하게 붙은 구조가 좋습니다.
- passthrough 를 allowlist + 프로젝트 키(≥2자)·숫자(1~7자리)로 좁혀 UTF-8/SHA-1 같은 토큰 오탐을 막고, alreadyHasRef 의 토큰 경계 검사로
[PROJ-123]재태깅까지 멱등 처리한 점이 견고합니다. - rules 우선 → passthrough 순서와 Jigit parity 테스트까지 있어 동작 확신이 섭니다.
- [nit] 2건만 남깁니다: 커스텀 template + passthrough 조합에서
{{.Number}}빈 값 /ioutildeprecated 정리. 둘 다 반영은 선택입니다.
| } | ||
| for _, m := range keyPattern.FindAllStringSubmatch(branch, -1) { | ||
| if len(m[2]) <= 7 && allowed[m[1]] { | ||
| return &TemplateData{Prefix: m[0]} |
There was a problem hiding this comment.
[nit] passthrough 경로에서는 Prefix 만 채워서, 커스텀 template 이 {{.Number}}(또는 {{.Repo}})를 참조하면 빈 값이 렌더될 수 있어요.
- 예:
"template": "{{.Message}}\n\nRef. [#{{.Number}}]"설정 시feature/PROJ-123브랜치에서는Ref. [#]로 나옵니다. (rules 경로는Number가 채워져 정상) - 기본 template(
[{{.Prefix}}] {{.Message}})에는 영향이 없어 우선순위는 낮습니다.Number: m[2]정도를 함께 채워두면 기존 template 사용자와의 호환이 깔끔해질 것 같아요.
| if _, err := os.Stat(input); err == nil { | ||
| // Input is a file path | ||
| isFile = true | ||
| commitMessageBytes, err := ioutil.ReadFile(input) |
There was a problem hiding this comment.
[nit] io/ioutil 은 Go 1.16 부터 deprecated 라(현재 go.mod 1.24.4), 이 리팩터링 겸 os/io 로 정리해도 좋을 것 같아요.
ioutil.ReadFile/WriteFile→os.ReadFile/os.WriteFile,ioutil.ReadAll→io.ReadAll- 이 PR 스코프(passthrough)와는 무관해서 별도 정리로 빼도 무방합니다.
There was a problem hiding this comment.
별도로 나중에 수정해보겠습니다! 감사합니다!
resolveKey only set Prefix, so a custom template using {{.Number}}
(e.g. "Ref. [#{{.Number}}]") rendered "[#]" on a passthrough branch.
Set Number to the key's number part; Repo stays empty (a verbatim key
has no repo). The default [{{.Prefix}}] template is unaffected.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>

Before vs After
<prefix>/<number>branches (e.g.feature/123), looked the prefix up inrules, and produced a GitHub reference like#123ororg/repo#123. A branch carrying a full tracker key such asfeature/PROJ-123matched nothing, so the commit stayed untagged.PROJECT-123) for the projects you list, and copies them into the message verbatim. The existingrulesbehavior is unchanged and still wins when a branch matches both.Behavior by case
With this config:
{ "rules": { "feature": null, "qa": "org/repo" }, "passthrough": ["PROJ"], // 명시 필요 "protect": ["main"] }feature/123[#123]qa/45[org/repo#45]feature/PROJ-123[PROJ-123]PROJ-123[PROJ-123]feature/PROJ-123-add-login[PROJ-123]feature/PROJ-123_wip[PROJ-123]feature/OPS-9feature/12-ABC-34[#12]feature/wipmainpassthrough
passthroughlists the project keys to copy verbatim;rules(GitHub prefixes) still take precedence when a branch matches both.["PROJ", …][]Only listed projects are tagged, so unrelated
UPPERCASE-NUMBERtokens (e.g.UTF-8,SHA-1) are never mistaken for issues.Branch recognition
passthroughrecognizes a key shapedPROJECT-NUMBER- an uppercase project ([A-Z][A-Z0-9]+, ≥2 chars), a hyphen, and a 1–7 digit number - appearing anywhere in the branch.For a
passthroughentryPROJ:PROJ-123[PROJ-123]feature/PROJ-123[PROJ-123]feature_PROJ-123[PROJ-123]PROJ-123-add-login[PROJ-123]PROJ-123_wip[PROJ-123]PROJ-123-20260101[PROJ-123]-<number>(date) suffix is ignored tooPROJ-123/anything[PROJ-123]PROJ-12345678PROJ/123-(PROJ-123); the slash form is arulesprefixPROJ_123-proj-123OPS-123OPSis not listedSo name the branch with the key joined by a hyphen —
PROJ-123orfeature/PROJ-123-short-desc.PROJ_123(underscore) andPROJ/123(slash) are not keys; a suffix after the number (-desc,_wip,-20260101,/path) is fine.Configuration example
{ "$schema": "./node_modules/@naverpay/commithelper-go/schema.json", "rules": { "feature": null, "qa": "org/repo" }, "passthrough": ["PROJ"], "protect": ["main", "release/*"], "template": "{{.Message}}\n\nRef. [{{.Prefix}}]" }$schemais optional; it gives editor autocompletion and validation and resolves from the installed package (offline, no CDN).Fixes included
Idempotency (
isAlreadyTagged→alreadyHasRef). The old check treated a message as tagged only when it started with a bracketed reference matching^\[.*?#\d+\]. That was tied to the default format and the#numbershape, so a custom template placing the reference in the body went undetected and was re-added on every amend. It is replaced byalreadyHasRef, which checks whether the branch's resolved reference is already present anywhere in the message as a whole token (so#123is not found in#1234, andPROJ-1871is not found inMY-PROJ-1871). This is template-independent and works for verbatim keys too.On branch
feature/123(resolved reference#123):isAlreadyTaggedalreadyHasRef[#123] fixfixwithRef. [#123]in body[#999] fix(different reference)[#123]fixThe third row is the one intentional behavior change: the old check skipped when the message started with any bracketed reference; the new check skips only when this branch's own reference is present.
Protected branch ordering. Branch protection now runs before the already-tagged check, so a message that already contains a tag can no longer slip past
protect.Tests
resolveKeyis covered by a table that mirrors Jigit's rules (TestResolveKey_JigitParity) - every branch Jigit's docs list as recognized/ignored is asserted here - plus edge cases (8-digit numbers,_/date suffixes, longer-key boundaries, unlisted projects).alreadyHasRefandprocessMessagecover the idempotency and protect behavior above.