-
Notifications
You must be signed in to change notification settings - Fork 0
[CHORE] main 브랜치 머지 시 npm 자동 배포 및 버저닝 설정 #86
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Changes from all commits
f4aa5be
06c32c8
5cccbd8
0b6ff7d
416db69
56cf88f
cc75c0a
6491be5
a3e0c91
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,168 @@ | ||
| name: Auto Bump Version on Merge to main | ||
|
|
||
| on: | ||
| pull_request: | ||
| types: | ||
| - closed | ||
|
|
||
| permissions: | ||
| contents: write | ||
|
|
||
| jobs: | ||
| bump-version: | ||
| if: > | ||
| github.event.pull_request.merged == true && | ||
| github.event.pull_request.base.ref == 'main' && | ||
| github.actor != 'github-actions[bot]' | ||
| runs-on: ubuntu-latest | ||
| steps: | ||
| - name: Checkout main | ||
| uses: actions/checkout@v4 | ||
| with: | ||
| ref: main | ||
|
|
||
| - name: Setup Node | ||
| uses: actions/setup-node@v4 | ||
| with: | ||
| node-version: '20' | ||
| registry-url: 'https://registry.npmjs.org' | ||
|
|
||
| - name: Detect if package.json version changed in PR | ||
| id: ver_changed | ||
| uses: actions/github-script@v7 | ||
| with: | ||
| script: | | ||
| const pr = context.payload.pull_request.number; | ||
| const files = await github.paginate(github.rest.pulls.listFiles, { | ||
| owner: context.repo.owner, | ||
| repo: context.repo.repo, | ||
| pull_number: pr, | ||
| per_page: 100 | ||
| }); | ||
| const touched = files.some(f => f.filename === 'package.json' && /"version"\s*:/.test(f.patch || '')); | ||
| core.setOutput('changed', touched ? 'true' : 'false'); | ||
|
Comment on lines
+30
to
+43
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. 🧹 Nitpick | 🔵 Trivial Line 41: 버전 변경 감지 로직 개선 - 정확성 고려 현재 정규식 패턴 patch 컨텐츠에서 이전 버전과 새 버전의 실제 semver 문자열을 추출하여 비교하면 더 정확합니다: const versionMatch = (f.patch || '').match(/^-.*"version"\s*:\s*"([^"]+)"[\s,]/m);
const newVersionMatch = (f.patch || '').match(/^\+.*"version"\s*:\s*"([^"]+)"[\s,]/m);
const touched = versionMatch && newVersionMatch && versionMatch[1] !== newVersionMatch[1];🤖 Prompt for AI Agents |
||
|
|
||
| - name: Detect if new UI folder added | ||
| id: new_ui_folder | ||
| uses: actions/github-script@v7 | ||
| with: | ||
| script: | | ||
| const pr = context.payload.pull_request.number; | ||
| const files = await github.paginate(github.rest.pulls.listFiles, { | ||
| owner: context.repo.owner, | ||
| repo: context.repo.repo, | ||
| pull_number: pr, | ||
| per_page: 100 | ||
| }); | ||
|
|
||
| const addedDirs = new Set(); | ||
| for (const f of files) { | ||
| if (f.status === 'added' && f.filename.startsWith('src/shared/ui/')) { | ||
| const parts = f.filename.split('/'); | ||
| if (parts.length > 3) { | ||
| addedDirs.add(parts.slice(0, 4).join('/')); // 예: src/shared/ui/Button | ||
| } | ||
| } | ||
| } | ||
|
|
||
| core.setOutput('new_ui_folder', addedDirs.size > 0 ? 'true' : 'false'); | ||
| console.log('New UI folders detected:', Array.from(addedDirs)); | ||
|
|
||
| - name: Bump version based on PR type | ||
| if: steps.ver_changed.outputs.changed != 'true' | ||
| run: | | ||
| node -e " | ||
| const fs = require('fs'); | ||
| const pr_title = process.env.PR_TITLE; | ||
| const is_new_ui = process.env.NEW_UI_FOLDER === 'true'; | ||
| const pkg = JSON.parse(fs.readFileSync('package.json', 'utf8')); | ||
| const [a, b, c] = pkg.version.split('.').map(Number); | ||
| let new_version; | ||
|
|
||
| if (is_new_ui) { | ||
| new_version = [a + 1, 0, 0].join('.'); | ||
| console.log('Major bump (new UI folder added)'); | ||
| } else if (pr_title.toLowerCase().startsWith('feat')) { | ||
| new_version = [a, b + 1, 0].join('.'); | ||
| console.log('Minor bump (feat detected)'); | ||
| } else { | ||
| new_version = [a, b, c + 1].join('.'); | ||
| console.log('Patch bump (default)'); | ||
| } | ||
|
|
||
| pkg.version = new_version; | ||
| fs.writeFileSync('package.json', JSON.stringify(pkg, null, 2) + '\n'); | ||
| console.log('Bumped to', pkg.version); | ||
| " | ||
| env: | ||
| PR_TITLE: ${{ github.event.pull_request.title }} | ||
| NEW_UI_FOLDER: ${{ steps.new_ui_folder.outputs.new_ui_folder }} | ||
|
|
||
| - name: Install dependencies | ||
| run: npm ci | ||
|
|
||
| - name: Sync exports to src/shared/index.ts (Revised) | ||
| run: | | ||
| node -e " | ||
| const fs = require('fs'); | ||
| const path = require('path'); | ||
| const root = 'src/shared'; | ||
| const indexPath = path.join(root, 'index.ts'); | ||
| const indexContent = fs.existsSync(indexPath) ? fs.readFileSync(indexPath, 'utf8') : ''; | ||
| const existingExports = new Set( | ||
| (indexContent.match(/from\\s+['\\\"](\\.\\/|\\.\\.\\/)([^'\\\"]+)['\\\"]/g) || []) | ||
| .map(line => line.match(/from\\s+['\\\"]([^'\\\"]+)['\\\"]/)[1]) | ||
| ); | ||
| const adds = []; | ||
| const uiRoot = path.join(root, 'ui'); | ||
| const componentFiles = []; | ||
| if (fs.existsSync(uiRoot)) { | ||
| fs.readdirSync(uiRoot, { withFileTypes: true }) | ||
| .filter(d => d.isDirectory()) | ||
| .forEach(dir => { | ||
| const dirPath = path.join(uiRoot, dir.name); | ||
| const innerItems = fs.readdirSync(dirPath, { withFileTypes: true }); | ||
| for (const item of innerItems) { | ||
| if (item.isFile() && (item.name.endsWith('.ts') || item.name.endsWith('.tsx')) && item.name !== 'index.ts') { | ||
| componentFiles.push(path.join(dir.name, item.name)); | ||
| } | ||
| } | ||
| }); | ||
| } | ||
|
|
||
| for (const relativeFilePath of componentFiles) { | ||
| const componentName = path.basename(relativeFilePath, path.extname(relativeFilePath)); | ||
| const exportPath = './ui/' + relativeFilePath.replace(path.extname(relativeFilePath), ''); | ||
| if (existingExports.has(exportPath)) continue; | ||
| const line = \`export { \${componentName} } from '\${exportPath}'\`; | ||
|
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. export 라인 템플릿에 세미콜론 누락 Line 137의 export 문 끝에 세미콜론이 없습니다: const line = \`export { \${componentName} } from '\${exportPath}'\`;
// ↑ 세미콜론 필요Line 142에서 - const line = \`export { \${componentName} } from '\${exportPath}'\`;
+ const line = \`export { \${componentName} } from '\${exportPath}';\`;🤖 Prompt for AI Agents |
||
| adds.push(line); | ||
| } | ||
|
Comment on lines
+112
to
+139
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. export 감지 정규식 패턴이 제한적 - 오류 위험 존재 Lines 113-115의 정규식이 특정 형식만 감지하며, 예상치 못한 형식에서 (indexContent.match(/from\\s+['\\\"](\\.\\/|\\.\\.\\/)([^'\\\"]+)['\\\"]/g) || [])
.map(line => line.match(/from\\s+['\\\"]([^'\\\"]+)['\\\"]/)[1])매칭이 null인 경우를 안전하게 처리하도록 개선하세요: const existingExports = new Set(
- (indexContent.match(/from\\s+['\\\"](\\.\\/|\\.\\.\\/)([^'\\\"]+)['\\\"]/g) || [])
- .map(line => line.match(/from\\s+['\\\"]([^'\\\"]+)['\\\"]/)[1])
+ (indexContent.match(/from\s+['"]([^'"]+)['"]/g) || [])
+ .map(line => {
+ const match = line.match(/from\s+['"]([^'"]+)['"]/);
+ return match ? match[1] : null;
+ })
+ .filter(Boolean)
);또한 Line 136의 중복 검사 로직도 개선이 필요합니다. 현재 🤖 Prompt for AI Agents |
||
|
|
||
| if (adds.length) { | ||
| const next = (indexContent.trim() ? indexContent.trim() + '\\n' : '') + adds.join(';\\n') + ';\\n'; | ||
| fs.writeFileSync(indexPath, next); | ||
| console.log('Added exports to index.ts:', adds); | ||
| } else { | ||
| console.log('No new files found to export.'); | ||
| } | ||
| " | ||
|
|
||
| - name: Build package | ||
| run: npm run build | ||
|
|
||
| - name: Commit & Push | ||
| run: | | ||
| if git diff --quiet; then | ||
| echo "No changes to commit." | ||
| exit 0 | ||
| fi | ||
| git config user.name "github-actions[bot]" | ||
| git config user.email "github-actions[bot]@users.noreply.github.com" | ||
| git add package.json src/shared/index.ts || true | ||
| git commit -m "chore: bump version and sync shared exports [skip ci]" | ||
| git push | ||
|
|
||
| - name: Publish to npm | ||
| run: npm publish | ||
| env: | ||
| NODE_AUTH_TOKEN: ${{ secrets.NPM_TOKEN }} | ||
|
Comment on lines
+165
to
+168
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. 🧹 Nitpick | 🔵 Trivial Lines 132-135: npm publish 조건 검토 - 변경사항 없을 때 동작 npm publish 단계가 이전 "Commit & Push" 단계의 조건부 로직과 독립적으로 항상 실행됩니다. 변경사항이 없어서 Commit & Push에서 변경사항이 있을 때만 publish하도록 보호하세요. 예를 들어, Commit & Push에서 성공 여부를 변수로 저장 후 publish 단계에서 조건 확인: - name: Commit & Push
id: commit_push
run: |
if git diff --quiet; then
echo "changed=false" >> $GITHUB_OUTPUT
exit 0
fi
git config user.name "github-actions[bot]"
git config user.email "github-actions[bot]@users.noreply.github.com"
git add package.json src/shared/index.ts || true
git commit -m "chore: bump version and sync shared exports [skip ci]"
git push
echo "changed=true" >> $GITHUB_OUTPUT
- name: Publish to npm
if: steps.commit_push.outputs.changed == 'true'
run: npm publish
env:
NODE_AUTH_TOKEN: ${{ secrets.NPM_TOKEN }}🤖 Prompt for AI Agents |
||
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
🧩 Analysis chain
버전 변경 감지 로직이 키 존재 여부만 확인 - 실제 값 변경 미감지
현재 정규식
/"version"\s*:/.test(f.patch || '')는"version"키가 있는지만 확인하고, 실제로 버전 값이 변경되었는지는 검증하지 않습니다. JSON 포매팅 변경이나 다른 필드 수정으로도 거짓 양성이 발생할 수 있습니다.patch 컨텐츠에서 이전/새 버전값을 직접 추출하여 비교하도록 개선하세요:
🏁 Script executed:
Length of output: 1827
🏁 Script executed:
Length of output: 479
🏁 Script executed:
Length of output: 769
라인 42의 버전 변경 감지 로직이 키 존재 여부만 확인 - 실제 값 변경 미감지
현재 정규식
/"version"\s*:/.test(f.patch || '')는"version"키가 diff의 어디든 나타나면 참을 반환합니다. GitHub API의 patch 형식은 변경사항(-,+)뿐만 아니라 컨텍스트 라인(변경 없는 라인)도 포함하므로, 버전 필드가 diff 컨텍스트에 나타나기만 해도 거짓 양성이 발생합니다.실제 버전 값 변경을 감지하도록 개선하세요:
🤖 Prompt for AI Agents