Conversation
Summary of ChangesHello @dasosann, I'm Gemini Code Assist1! I'm currently reviewing this pull request and will post my feedback shortly. In the meantime, here's a summary to help you and other reviewers quickly get up to speed! 이 PR은 디자인 토큰 관리 방식을 개선하여, 디자인 시스템의 유지보수성과 일관성을 높이는 것을 목표로 합니다. Highlights
Using Gemini Code AssistThe full guide for Gemini Code Assist can be found on our documentation page, here are some quick tips. Invoking Gemini You can request assistance from Gemini at any point by creating a comment using either
Customization To customize Gemini Code Assist for GitHub experience, repository maintainers can create a configuration file and/or provide a custom code review style guide (such as PEP-8 for Python) by creating and adding files to a Limitations & Feedback Gemini Code Assist may make mistakes. Please leave feedback on any instances where its feedback is incorrect or counter productive. You can react with 👍 and 👎 on @gemini-code-assist comments. If you're interested in giving your feedback about your experience with Gemini Code Assist for Github and other Google products, sign up here. You can also get AI-powered code generation, chat, as well as code reviews directly in the IDE at no cost with the Gemini Code Assist IDE Extension. Footnotes
|
There was a problem hiding this comment.
Code Review
이번 PR은 token.json에서 디자인 토큰을 자동으로 생성하는 스크립트를 도입하고, 이를 활용한 테스트 페이지를 구현하는 중요한 개선 작업을 포함하고 있습니다. 전반적으로 디자인 시스템의 기반을 마련하는 좋은 시도입니다. 다만, 코드의 유지보수성과 확장성을 높이기 위해 몇 가지 개선점을 제안합니다. generate-tokens.js 스크립트의 중복 코드를 제거하고, 동적으로 토큰을 처리하도록 리팩토링하는 것이 필요해 보입니다. 또한, page.tsx에서 버튼 스타일을 적용하는 방식에 오류가 있어 수정이 필요합니다. 자세한 내용은 각 파일에 남긴 코드 리뷰 코멘트를 참고해주세요.
| if (colors.Pink) { | ||
| Object.entries(colors.Pink).forEach(([key, value]) => { | ||
| if (key.startsWith("color-pink-")) { | ||
| cssVariables.push(` --${sanitizeKey(key)}: ${value.$value};`); | ||
| } | ||
| }); | ||
| } | ||
| if (colors.Flame) { | ||
| Object.entries(colors.Flame).forEach(([key, value]) => { | ||
| if (key.startsWith("color-flame-")) { | ||
| cssVariables.push(` --${sanitizeKey(key)}: ${value.$value};`); | ||
| } | ||
| }); | ||
| } | ||
| if (colors.Orange) { | ||
| Object.entries(colors.Orange).forEach(([key, value]) => { | ||
| if (key.startsWith("color-orange-")) { | ||
| cssVariables.push(` --${sanitizeKey(key)}: ${value.$value};`); | ||
| } | ||
| }); | ||
| } |
There was a problem hiding this comment.
Pink, Flame, Orange 색상 그룹을 처리하는 로직이 중복되고 있습니다. 코드 중복은 유지보수를 어렵게 만듭니다. colors 객체를 순회하며 동적으로 CSS 변수를 생성하도록 리팩토링하는 것을 권장합니다. 이렇게 하면 새로운 색상 그룹이 추가되어도 스크립트를 수정할 필요가 없습니다.
if (colors) {
for (const colorGroup of Object.values(colors)) {
for (const [key, token] of Object.entries(colorGroup)) {
if (key.startsWith("color-")) {
cssVariables.push(` --${sanitizeKey(key)}: ${token.$value};`);
}
}
}
}References
- 중복 코드를 발견하면 재사용 가능한 유틸리티나 컴포넌트로 추출할 것을 제안하세요. (link)
| function resolveValue(value, depth = 0) { | ||
| if (depth > 10 || typeof value !== "string") return value; | ||
|
|
||
| const match = value.match(/^\{(.+)\}$/); | ||
| if (!match) return value; | ||
|
|
||
| const ref = match[1]; | ||
|
|
||
| // Grayscale 참조 | ||
| if (ref.startsWith("Grayscale.")) { | ||
| const key = ref.replace("Grayscale.", ""); | ||
| return `var(--${key})`; | ||
| } | ||
|
|
||
| // Colors 참조 | ||
| if (ref.startsWith("Colors.Pink.")) { | ||
| const key = ref.replace("Colors.Pink.", ""); | ||
| return `var(--${key})`; | ||
| } | ||
| if (ref.startsWith("Colors.Flame.")) { | ||
| const key = ref.replace("Colors.Flame.", ""); | ||
| return `var(--${key})`; | ||
| } | ||
| if (ref.startsWith("Colors.Orange.")) { | ||
| const key = ref.replace("Colors.Orange.", ""); | ||
| return `var(--${key})`; | ||
| } | ||
|
|
||
| // Transparent 참조 | ||
| if (ref.startsWith("Transparent.")) { | ||
| const key = ref.replace("Transparent.", ""); | ||
| return `var(--${key})`; | ||
| } | ||
|
|
||
| // System/Mode 1의 Colors 참조 | ||
| if (ref.startsWith("Colors.")) { | ||
| const key = ref.replace("Colors.", ""); | ||
| return `var(--${key})`; | ||
| } | ||
|
|
||
| return value; | ||
| } |
There was a problem hiding this comment.
resolveValue 함수에서 각 토큰 그룹(Grayscale, Colors.Pink 등)에 대한 참조를 처리하는 로직이 반복적으로 작성되어 있습니다. 이로 인해 새로운 토큰 그룹이 추가될 때마다 코드를 수정해야 하는 번거로움이 있습니다. 참조 경로를 동적으로 해석하는 방식으로 일반화하여 코드 중복을 줄이고 확장성을 높이는 것이 좋습니다.
function resolveValue(value, depth = 0) {
if (depth > 10 || typeof value !== "string") return value;
const match = value.match(/^\{(.+)\}$/);
if (!match) return value;
const ref = match[1];
const refParts = ref.split('.');
// e.g., {Grayscale.color-gray-64} -> var(--color-gray-64)
const key = refParts[refParts.length - 1];
return `var(--${sanitizeKey(key)})`;
}References
- 중복 코드를 발견하면 재사용 가능한 유틸리티나 컴포넌트로 추출할 것을 제안하세요. (link)
app/page.tsx
Outdated
| <button className="btn-primary text-16-600 px-8 py-3 transition-opacity hover:opacity-90"> | ||
| Primary Button | ||
| </button> | ||
| <button className="btn-slate text-brand-black border-light text-16-600 rounded-2xl border px-8 py-3"> |
There was a problem hiding this comment.
이 버튼의 className이 다소 길고 복잡합니다. 스타일 가이드 51번에 따라, 이렇게 여러 유틸리티 클래스가 조합되는 경우 cva (class-variance-authority)를 사용하거나, @layer components에 @apply를 사용하여 btn-secondary와 같은 컴포넌트 클래스로 추상화하는 것을 고려해볼 수 있습니다. 이렇게 하면 코드 가독성이 향상되고 재사용이 용이해집니다.
References
- Tailwind 클래스가 너무 길거나 복잡하면
class-variance-authority (cva)또는 논리적 그룹핑을 제안하세요. (link)
| tailwindUtilities.push(`${className} { | ||
| font-size: ${size}px; | ||
| font-weight: ${weight}; | ||
| line-height: 1.5; |
| import fs from "fs"; | ||
| import path from "path"; | ||
| import { fileURLToPath } from "url"; | ||
|
|
||
| const __filename = fileURLToPath(import.meta.url); | ||
| const __dirname = path.dirname(__filename); | ||
|
|
||
| // token.json 읽기 | ||
| const tokensPath = path.join(__dirname, "../app/token.json"); | ||
| const tokens = JSON.parse(fs.readFileSync(tokensPath, "utf-8")); | ||
|
|
||
| // Semantic tokens에서 실제 색상값 추출 | ||
| const semanticMode1 = tokens["Sementic/Mode 1"] || {}; | ||
| const systemMode1 = tokens["System/Mode 1"] || {}; | ||
|
|
||
| // Grayscale, Colors, Transparent 값 추출 | ||
| const grayscale = semanticMode1.Grayscale || {}; | ||
| const colors = semanticMode1.Colors || {}; | ||
| const transparent = semanticMode1.Transparent || {}; | ||
|
|
||
| // CSS 변수 생성 | ||
| let cssVariables = []; | ||
|
|
||
| // 키 정제 함수 (공백을 하이픈으로 변경) | ||
| function sanitizeKey(key) { | ||
| return key.replace(/\s+/g, "-").toLowerCase(); | ||
| } | ||
|
|
||
| // Grayscale 색상 | ||
| Object.entries(grayscale).forEach(([key, value]) => { | ||
| if (key.startsWith("color-gray-")) { | ||
| cssVariables.push(` --${sanitizeKey(key)}: ${value.$value};`); | ||
| } | ||
| }); | ||
|
|
||
| // Colors (Pink, Flame, Orange) | ||
| if (colors.Pink) { | ||
| Object.entries(colors.Pink).forEach(([key, value]) => { | ||
| if (key.startsWith("color-pink-")) { | ||
| cssVariables.push(` --${sanitizeKey(key)}: ${value.$value};`); | ||
| } | ||
| }); | ||
| } | ||
| if (colors.Flame) { | ||
| Object.entries(colors.Flame).forEach(([key, value]) => { | ||
| if (key.startsWith("color-flame-")) { | ||
| cssVariables.push(` --${sanitizeKey(key)}: ${value.$value};`); | ||
| } | ||
| }); | ||
| } | ||
| if (colors.Orange) { | ||
| Object.entries(colors.Orange).forEach(([key, value]) => { | ||
| if (key.startsWith("color-orange-")) { | ||
| cssVariables.push(` --${sanitizeKey(key)}: ${value.$value};`); | ||
| } | ||
| }); | ||
| } | ||
|
|
||
| // Transparent | ||
| Object.entries(transparent).forEach(([key, value]) => { | ||
| cssVariables.push(` --${sanitizeKey(key)}: ${value.$value};`); | ||
| }); | ||
|
|
||
| // System tokens | ||
| if (systemMode1.Colors) { | ||
| Object.entries(systemMode1.Colors).forEach(([key, value]) => { | ||
| if (value.$type === "color") { | ||
| const finalValue = resolveValue(value.$value); | ||
| cssVariables.push(` --${sanitizeKey(key)}: ${finalValue};`); | ||
| } | ||
| }); | ||
| } | ||
|
|
||
| // Radius | ||
| if (systemMode1.Radius) { | ||
| Object.entries(systemMode1.Radius).forEach(([key, value]) => { | ||
| const varName = key.replace("radius-", ""); | ||
| cssVariables.push(` --radius-${sanitizeKey(varName)}: ${value.$value}px;`); | ||
| }); | ||
| } | ||
|
|
||
| // Border | ||
| if (systemMode1.Border) { | ||
| Object.entries(systemMode1.Border).forEach(([key, value]) => { | ||
| const varName = key.replace("border-width-", ""); | ||
| cssVariables.push(` --border-${sanitizeKey(varName)}: ${value.$value}px;`); | ||
| }); | ||
| } | ||
|
|
||
| // Opacity | ||
| if (systemMode1.Opacity) { | ||
| Object.entries(systemMode1.Opacity).forEach(([key, value]) => { | ||
| const varName = key.replace("opacity-", ""); | ||
| cssVariables.push(` --opacity-${sanitizeKey(varName)}: ${value.$value}%;`); | ||
| }); | ||
| } | ||
|
|
||
| // 토큰 참조 해석 | ||
| function resolveValue(value, depth = 0) { | ||
| if (depth > 10 || typeof value !== "string") return value; | ||
|
|
||
| const match = value.match(/^\{(.+)\}$/); | ||
| if (!match) return value; | ||
|
|
||
| const ref = match[1]; | ||
|
|
||
| // Grayscale 참조 | ||
| if (ref.startsWith("Grayscale.")) { | ||
| const key = ref.replace("Grayscale.", ""); | ||
| return `var(--${key})`; | ||
| } | ||
|
|
||
| // Colors 참조 | ||
| if (ref.startsWith("Colors.Pink.")) { | ||
| const key = ref.replace("Colors.Pink.", ""); | ||
| return `var(--${key})`; | ||
| } | ||
| if (ref.startsWith("Colors.Flame.")) { | ||
| const key = ref.replace("Colors.Flame.", ""); | ||
| return `var(--${key})`; | ||
| } | ||
| if (ref.startsWith("Colors.Orange.")) { | ||
| const key = ref.replace("Colors.Orange.", ""); | ||
| return `var(--${key})`; | ||
| } | ||
|
|
||
| // Transparent 참조 | ||
| if (ref.startsWith("Transparent.")) { | ||
| const key = ref.replace("Transparent.", ""); | ||
| return `var(--${key})`; | ||
| } | ||
|
|
||
| // System/Mode 1의 Colors 참조 | ||
| if (ref.startsWith("Colors.")) { | ||
| const key = ref.replace("Colors.", ""); | ||
| return `var(--${key})`; | ||
| } | ||
|
|
||
| return value; | ||
| } | ||
|
|
||
| // Font Size - text-{size}-{weight} 형태로 생성 | ||
| const fontSizes = systemMode1?.Font || {}; | ||
| const weights = ["400", "500", "600", "700"]; | ||
| let tailwindUtilities = []; | ||
|
|
||
| Object.entries(fontSizes).forEach(([key, value]) => { | ||
| if (key.startsWith("font-size-")) { | ||
| const size = value.$value; | ||
| weights.forEach((weight) => { | ||
| const className = `.text-${size}-${weight}`; | ||
| tailwindUtilities.push(`${className} { | ||
| font-size: ${size}px; | ||
| font-weight: ${weight}; | ||
| line-height: 1.5; | ||
| }`); | ||
| }); | ||
| } | ||
| }); | ||
|
|
||
| // CSS 파일 생성 | ||
| const cssContent = `/* Auto-generated from token.json */ | ||
| /* Run: node scripts/generate-tokens.js to regenerate */ | ||
|
|
||
| @layer base { | ||
| :root { | ||
| ${cssVariables.join("\n")} | ||
| } | ||
| } | ||
|
|
||
| @layer utilities { | ||
| /* Text utilities: text-{size}-{weight} */ | ||
| ${tailwindUtilities.join("\n\n")} | ||
|
|
||
| /* Background utilities */ | ||
| .bg-surface-base { background-color: var(--color-surface-base); } | ||
| .bg-brand-secondary-pink { background-color: var(--color-brand-secondary-pink); } | ||
| .bg-brand-primary-orange { background-color: var(--color-brand-primary-orange); } | ||
| .bg-disabled { background-color: var(--color-background-disabled); } | ||
|
|
||
| /* Button utilities */ | ||
| .bg-button-primary { | ||
| background: linear-gradient(135deg, var(--color-brand-primary-flame), var(--color-brand-primary-orange)); | ||
| } | ||
|
|
||
| .bg-button-disabled { | ||
| background-color: var(--color-background-disabled); | ||
| } | ||
|
|
||
| .bg-button-slate { | ||
| background-color: var(--color-gray-0-a30); | ||
| } | ||
|
|
||
| /* Border utilities */ | ||
| .border-light { border-color: var(--color-border-light); } | ||
|
|
||
| /* Text color utilities */ | ||
| .text-white { color: var(--color-text-white); } | ||
| .text-disabled { color: var(--color-text-disabled); } | ||
| .text-brand-black { color: var(--color-brand-black); } | ||
| } | ||
| `; | ||
|
|
||
| // tokens.css 파일로 저장 | ||
| const outputPath = path.join(__dirname, "../app/tokens.css"); | ||
| fs.writeFileSync(outputPath, cssContent, "utf-8"); | ||
|
|
||
| console.log("✅ Tokens generated successfully!"); | ||
| console.log(`📝 Output: ${outputPath}`); | ||
| console.log("\nNext steps:"); | ||
| console.log("1. Import tokens.css in your globals.css:"); | ||
| console.log(' @import "./tokens.css";'); | ||
| console.log("\n2. Use utilities in your components:"); | ||
| console.log(' <div className="bg-surface-base text-16-500">Hello</div>'); |
There was a problem hiding this comment.
스크립트 파일의 길이가 200줄을 초과합니다. 가이드라인에 따라 파일을 더 작은 모듈로 분리하는 것을 고려해볼 수 있습니다. 예를 들어, 토큰 종류별(색상, 타이포그래피, 간격 등) 파싱 로직을 별도의 함수나 파일로 분리하면 코드의 가독성과 유지보수성이 향상됩니다. 앞서 제안한 중복 코드 리팩토링을 적용하면 파일 크기를 줄이는 데 도움이 될 것입니다.
References
- 컴포넌트 파일이 200줄을 초과하면 더 작은 서브 컴포넌트로 분리할 것을 권장하세요. (link)
There was a problem hiding this comment.
/describe --pr_description.generate_title=true
There was a problem hiding this comment.
scripts/generate-tokens.js 파일의 길이가 여전히 200줄을 초과하고 있습니다. 코드의 가독성과 유지보수성을 높이기 위해 토큰 종류별(색상, 타이포그래피, 간격 등) 파싱 로직을 별도의 함수나 파일로 분리하는 것을 다시 한번 고려해 보시는 것이 좋습니다. 이전에 제안드렸던 중복 코드 리팩토링을 적용하시면 파일 크기를 줄이는 데도 도움이 될 것입니다.
There was a problem hiding this comment.
Ask❓
@gemini-code-assist review
Answer:
전반적으로 “token.json → tokens.css(CSS 변수/유틸) → globals.css import” 파이프라인이 잘 잡혀 있고, @layer base / utilities로 Tailwind와 공존시키려는 방향도 좋습니다. 다만 현재 스크립트/산출물에는 유지보수성과 정확성 측면에서 몇 가지 개선 포인트가 보여요.
1) 스크립트 구조(200줄 초과) 분리 제안 (gemini bot 코멘트 동의)
scripts/generate-tokens.js가 “파일 I/O + 토큰 파싱 + 참조 해석 + CSS 템플릿 생성”을 한 파일에서 전부 담당하고 있어요. 아래처럼 역할 기준으로 함수/모듈 분리하면 가독성과 확장성이 좋아집니다.
readTokens(tokensPath)extractSemantic(tokens)/extractSystem(tokens)buildCssVariables({grayscale, colors, transparent, systemMode1})buildTypographyUtilities(systemMode1.Font)buildUtilities()(bg/text/border/button 등)writeCss(outputPath, cssContent)
또한 Pink/Flame/Orange 처리 로직은 거의 동일하므로 공통 함수로 중복 제거가 가능합니다.
예: pushColorGroup(colors, "Pink", "color-pink-")
2) token.json 경로 및 파일 이동 이슈 가능성
스크립트는 ../app/token.json을 읽도록 되어 있는데,
diff에서는 app/src/token.json이 삭제된 것으로 보이고, app/token.json의 추가는 보이지 않습니다.
- 실제로 token.json이
app/token.json에 존재하는지 확인 필요 - 만약 경로가 바뀐 거라면 스크립트 경로도 함께 수정하거나, CLI 인자로 받는 형태가 안전합니다.
- 예:
node scripts/generate-tokens.js --input app/src/token.json --output app/tokens.css
- 예:
3) 키/참조 해석 로직의 일관성 문제 (sanitizeKey / resolveValue)
- CSS 변수명은
sanitizeKey()로 lower-case 및 공백→하이픈 처리합니다. - 그런데
resolveValue()에서 참조를var(--${key})로 만들 때는 sanitize를 적용하지 않습니다. - 현재 token.json 참조는
"{Grayscale.color-gray-64}"처럼 이미 CSS 변수에 가까운 키라서 운 좋게 맞지만,
opacity-subtle 2처럼 공백이 포함된 키(실제로 token에 있음)는--opacity-subtle-2로 생성되는데, 참조 해석은 공백을 포함한 채var(--opacity-subtle 2)가 될 위험이 있습니다(지금은 Opacity는 참조 해석을 안 해서 우연히 피해간 상태).
개선:
resolveValue()에서 반환하는 변수명에도sanitizeKey()를 적용- 그리고
depth파라미터가 선언만 있고 재귀 호출이 없어 의미가 없습니다. 참조가 연쇄되는 경우를 대비해 재귀로 풀거나(필요하다면) depth 제거가 더 명확합니다.
4) 토큰 스펠링/키 안정성: "Sementic/Mode 1"
코드에서 tokens["Sementic/Mode 1"]를 사용 중인데, 일반적으로 “Semantic” 오타로 보입니다.
- 현재 token.json의 최상위 키가 실제로
Sementic/Mode 1라면 동작은 하겠지만, 추후 수정/도구 연동 시 깨지기 쉬운 지점입니다. - 가능하면 소스 토큰 키를
Semantic/Mode 1로 정정하고, 스크립트도 함께 맞추는 것을 추천합니다. - 혹은 하위호환으로
tokens["Semantic/Mode 1"] ?? tokens["Sementic/Mode 1"] ?? {}처럼 방어코드를 두는 것도 방법입니다.
5) 생성된 CSS 품질(포맷/일관성)
app/tokens.css를 보면 :root 내부 들여쓰기/정렬이 다소 깨져 있습니다(변수 라인이 :root {와 같은 레벨처럼 보임).
- 현재 스크립트가
cssVariables에 이미" --..."(2칸) 들여쓰기를 넣고, 템플릿에서도 들여쓰기를 또 하고 있어 결과가 애매해졌습니다. - “템플릿에서만 들여쓰기” 또는 “데이터에는 들여쓰기 제거” 중 하나로 일관성을 맞추는 것이 좋습니다.
- Prettier 적용(스크립트에서
prettier.format사용 또는 CI에서 포맷)을 고려하면 산출물 품질이 안정적입니다.
6) page.tsx에서 사용하는 클래스와 tokens.css의 불일치
page.tsx에는 btn-primary, btn-slate, btn-disabled를 사용하지만,
tokens.css에는 .bg-button-primary, .bg-button-slate, .bg-button-disabled만 생성됩니다.
- 이 상태면 버튼 스타일이 기대대로 적용되지 않습니다.
- 해결안:
- page에서
bg-button-*클래스를 사용하도록 수정하거나 - generator에서
.btn-primary등 버튼 컴포넌트용 유틸도 같이 생성(텍스트색/보더/라운드 포함)하도록 확장
- page에서
7) VSCode 설정 변경(css.lint.unknownAtRules ignore)
@layer, @theme 등으로 경고가 뜨는 문제를 해결하려는 의도는 이해됩니다. 다만 저장소 공용 설정에 넣을 때는 팀 컨센서스가 필요할 수 있어요(개인 환경에선 괜찮지만, repo에 포함되면 모두에게 적용).
- 대안:
.vscode/settings.json유지하되, 문서에 이유를 간단히 남기거나, stylelint 도입 시 룰로 관리
정리하면: 스크립트 모듈화 + 경로/키 안정성 + sanitize/resolve 일관성 + page에서 사용하는 클래스 불일치 해결 이 4가지만 잡아도, 토큰 파이프라인이 훨씬 견고해질 것 같습니다.
|
PR Description updated to latest commit (354fd18)
|
There was a problem hiding this comment.
File Walkthrough
Enhancement
| |||
Configuration changes
| |||
| Miscellaneous |
Co-authored-by: gemini-code-assist[bot] <176961590+gemini-code-assist[bot]@users.noreply.github.com>
PR Type
Enhancement
Description
디자인 토큰 자동 생성 스크립트 추가
token.json에서 CSS 변수로 변환하는 파이프라인 구축
타이포그래피, 색상, 반경 등 토큰 시스템 정의
홈페이지를 토큰 테스트 페이지로 리뉴얼
Diagram Walkthrough
File Walkthrough
generate-tokens.js
토큰 자동 생성 스크립트 구현scripts/generate-tokens.js
globals.css
토큰 CSS 파일 임포트 추가app/globals.css
page.tsx
홈페이지를 토큰 테스트 페이지로 리뉴얼app/page.tsx
tokens.css
생성된 디자인 토큰 CSS 파일app/tokens.css
settings.json
CSS 린트 설정 업데이트.vscode/settings.json
token.json
토큰 파일 위치 변경app/src/token.json
✨ Describe tool usage guide:
Overview:
The
describetool scans the PR code changes, and generates a description for the PR - title, type, summary, walkthrough and labels. The tool can be triggered automatically every time a new PR is opened, or can be invoked manually by commenting on a PR.When commenting, to edit configurations related to the describe tool (
pr_descriptionsection), use the following template:With a configuration file, use the following template:
Enabling\disabling automation
meaning the
describetool will run automatically on every PR.the tool will replace every marker of the form
pr_agent:marker_namein the PR description with the relevant content, wheremarker_nameis one of the following:type: the PR type.summary: the PR summary.walkthrough: the PR walkthrough.diagram: the PR sequence diagram (if enabled).Note that when markers are enabled, if the original PR description does not contain any markers, the tool will not alter the description at all.
Custom labels
The default labels of the
describetool are quite generic: [Bug fix,Tests,Enhancement,Documentation,Other].If you specify custom labels in the repo's labels page or via configuration file, you can get tailored labels for your use cases.
Examples for custom labels:
Main topic:performance- pr_agent:The main topic of this PR is performanceNew endpoint- pr_agent:A new endpoint was added in this PRSQL query- pr_agent:A new SQL query was added in this PRDockerfile changes- pr_agent:The PR contains changes in the DockerfileThe list above is eclectic, and aims to give an idea of different possibilities. Define custom labels that are relevant for your repo and use cases.
Note that Labels are not mutually exclusive, so you can add multiple label categories.
Make sure to provide proper title, and a detailed and well-phrased description for each label, so the tool will know when to suggest it.
Inline File Walkthrough 💎
For enhanced user experience, the
describetool can add file summaries directly to the "Files changed" tab in the PR page.This will enable you to quickly understand the changes in each file, while reviewing the code changes (diffs).
To enable inline file summary, set
pr_description.inline_file_summaryin the configuration file, possible values are:'table': File changes walkthrough table will be displayed on the top of the "Files changed" tab, in addition to the "Conversation" tab.true: A collapsable file comment with changes title and a changes summary for each file in the PR.false(default): File changes walkthrough will be added only to the "Conversation" tab.Utilizing extra instructions
The
describetool can be configured with extra instructions, to guide the model to a feedback tailored to the needs of your project.Be specific, clear, and concise in the instructions. With extra instructions, you are the prompter. Notice that the general structure of the description is fixed, and cannot be changed. Extra instructions can change the content or style of each sub-section of the PR description.
Examples for extra instructions:
Use triple quotes to write multi-line instructions. Use bullet points to make the instructions more readable.
More PR-Agent commands
See the describe usage page for a comprehensive guide on using this tool.