Skip to content

Commit e4d40ad

Browse files
authored
Merge pull request #86 from COW-dev/feat/#84
[CHORE] main 브랜치 머지 시 npm 자동 배포 및 버저닝 설정
2 parents b025dfe + a3e0c91 commit e4d40ad

File tree

1 file changed

+168
-0
lines changed

1 file changed

+168
-0
lines changed
Lines changed: 168 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,168 @@
1+
name: Auto Bump Version on Merge to main
2+
3+
on:
4+
pull_request:
5+
types:
6+
- closed
7+
8+
permissions:
9+
contents: write
10+
11+
jobs:
12+
bump-version:
13+
if: >
14+
github.event.pull_request.merged == true &&
15+
github.event.pull_request.base.ref == 'main' &&
16+
github.actor != 'github-actions[bot]'
17+
runs-on: ubuntu-latest
18+
steps:
19+
- name: Checkout main
20+
uses: actions/checkout@v4
21+
with:
22+
ref: main
23+
24+
- name: Setup Node
25+
uses: actions/setup-node@v4
26+
with:
27+
node-version: '20'
28+
registry-url: 'https://registry.npmjs.org'
29+
30+
- name: Detect if package.json version changed in PR
31+
id: ver_changed
32+
uses: actions/github-script@v7
33+
with:
34+
script: |
35+
const pr = context.payload.pull_request.number;
36+
const files = await github.paginate(github.rest.pulls.listFiles, {
37+
owner: context.repo.owner,
38+
repo: context.repo.repo,
39+
pull_number: pr,
40+
per_page: 100
41+
});
42+
const touched = files.some(f => f.filename === 'package.json' && /"version"\s*:/.test(f.patch || ''));
43+
core.setOutput('changed', touched ? 'true' : 'false');
44+
45+
- name: Detect if new UI folder added
46+
id: new_ui_folder
47+
uses: actions/github-script@v7
48+
with:
49+
script: |
50+
const pr = context.payload.pull_request.number;
51+
const files = await github.paginate(github.rest.pulls.listFiles, {
52+
owner: context.repo.owner,
53+
repo: context.repo.repo,
54+
pull_number: pr,
55+
per_page: 100
56+
});
57+
58+
const addedDirs = new Set();
59+
for (const f of files) {
60+
if (f.status === 'added' && f.filename.startsWith('src/shared/ui/')) {
61+
const parts = f.filename.split('/');
62+
if (parts.length > 3) {
63+
addedDirs.add(parts.slice(0, 4).join('/')); // 예: src/shared/ui/Button
64+
}
65+
}
66+
}
67+
68+
core.setOutput('new_ui_folder', addedDirs.size > 0 ? 'true' : 'false');
69+
console.log('New UI folders detected:', Array.from(addedDirs));
70+
71+
- name: Bump version based on PR type
72+
if: steps.ver_changed.outputs.changed != 'true'
73+
run: |
74+
node -e "
75+
const fs = require('fs');
76+
const pr_title = process.env.PR_TITLE;
77+
const is_new_ui = process.env.NEW_UI_FOLDER === 'true';
78+
const pkg = JSON.parse(fs.readFileSync('package.json', 'utf8'));
79+
const [a, b, c] = pkg.version.split('.').map(Number);
80+
let new_version;
81+
82+
if (is_new_ui) {
83+
new_version = [a + 1, 0, 0].join('.');
84+
console.log('Major bump (new UI folder added)');
85+
} else if (pr_title.toLowerCase().startsWith('feat')) {
86+
new_version = [a, b + 1, 0].join('.');
87+
console.log('Minor bump (feat detected)');
88+
} else {
89+
new_version = [a, b, c + 1].join('.');
90+
console.log('Patch bump (default)');
91+
}
92+
93+
pkg.version = new_version;
94+
fs.writeFileSync('package.json', JSON.stringify(pkg, null, 2) + '\n');
95+
console.log('Bumped to', pkg.version);
96+
"
97+
env:
98+
PR_TITLE: ${{ github.event.pull_request.title }}
99+
NEW_UI_FOLDER: ${{ steps.new_ui_folder.outputs.new_ui_folder }}
100+
101+
- name: Install dependencies
102+
run: npm ci
103+
104+
- name: Sync exports to src/shared/index.ts (Revised)
105+
run: |
106+
node -e "
107+
const fs = require('fs');
108+
const path = require('path');
109+
const root = 'src/shared';
110+
const indexPath = path.join(root, 'index.ts');
111+
const indexContent = fs.existsSync(indexPath) ? fs.readFileSync(indexPath, 'utf8') : '';
112+
const existingExports = new Set(
113+
(indexContent.match(/from\\s+['\\\"](\\.\\/|\\.\\.\\/)([^'\\\"]+)['\\\"]/g) || [])
114+
.map(line => line.match(/from\\s+['\\\"]([^'\\\"]+)['\\\"]/)[1])
115+
);
116+
const adds = [];
117+
const uiRoot = path.join(root, 'ui');
118+
const componentFiles = [];
119+
if (fs.existsSync(uiRoot)) {
120+
fs.readdirSync(uiRoot, { withFileTypes: true })
121+
.filter(d => d.isDirectory())
122+
.forEach(dir => {
123+
const dirPath = path.join(uiRoot, dir.name);
124+
const innerItems = fs.readdirSync(dirPath, { withFileTypes: true });
125+
for (const item of innerItems) {
126+
if (item.isFile() && (item.name.endsWith('.ts') || item.name.endsWith('.tsx')) && item.name !== 'index.ts') {
127+
componentFiles.push(path.join(dir.name, item.name));
128+
}
129+
}
130+
});
131+
}
132+
133+
for (const relativeFilePath of componentFiles) {
134+
const componentName = path.basename(relativeFilePath, path.extname(relativeFilePath));
135+
const exportPath = './ui/' + relativeFilePath.replace(path.extname(relativeFilePath), '');
136+
if (existingExports.has(exportPath)) continue;
137+
const line = \`export { \${componentName} } from '\${exportPath}'\`;
138+
adds.push(line);
139+
}
140+
141+
if (adds.length) {
142+
const next = (indexContent.trim() ? indexContent.trim() + '\\n' : '') + adds.join(';\\n') + ';\\n';
143+
fs.writeFileSync(indexPath, next);
144+
console.log('Added exports to index.ts:', adds);
145+
} else {
146+
console.log('No new files found to export.');
147+
}
148+
"
149+
150+
- name: Build package
151+
run: npm run build
152+
153+
- name: Commit & Push
154+
run: |
155+
if git diff --quiet; then
156+
echo "No changes to commit."
157+
exit 0
158+
fi
159+
git config user.name "github-actions[bot]"
160+
git config user.email "github-actions[bot]@users.noreply.github.com"
161+
git add package.json src/shared/index.ts || true
162+
git commit -m "chore: bump version and sync shared exports [skip ci]"
163+
git push
164+
165+
- name: Publish to npm
166+
run: npm publish
167+
env:
168+
NODE_AUTH_TOKEN: ${{ secrets.NPM_TOKEN }}

0 commit comments

Comments
 (0)