@vv0rkz/js-template 1.7.0 → 1.8.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +224 -150
- package/bin/cli.js +227 -196
- package/bin/init.js +244 -236
- package/package.json +1 -1
- package/templates/.husky/commit-msg +3 -67
- package/templates/.husky/post-commit +3 -25
- package/templates/.husky/pre-push +3 -17
- package/templates/changelog.config.js +16 -9
- package/templates/commitlint.config.js +13 -6
- package/templates/jst.config.js +125 -0
- package/tools-gh/check-demo-for-release.js +36 -30
- package/tools-gh/config.js +126 -0
- package/tools-gh/post-commit-hook.js +40 -0
- package/tools-gh/release.js +120 -102
- package/tools-gh/report-issue.js +32 -0
- package/tools-gh/setup-deps.js +59 -0
- package/tools-gh/setup-labels.js +53 -58
- package/tools-gh/upgrade.js +72 -0
- package/tools-gh/validate-branch.js +33 -0
- package/tools-gh/validate-commit.js +86 -0
package/bin/init.js
CHANGED
|
@@ -1,236 +1,244 @@
|
|
|
1
|
-
#!/usr/bin/env node
|
|
2
|
-
import { execSync, spawnSync } from 'child_process'
|
|
3
|
-
import { copyFileSync, existsSync, mkdirSync, readdirSync, readFileSync, statSync, unlinkSync, writeFileSync } from 'fs'
|
|
4
|
-
import { dirname, join } from 'path'
|
|
5
|
-
import * as readline from 'readline'
|
|
6
|
-
import { fileURLToPath } from 'url'
|
|
7
|
-
|
|
8
|
-
const __dirname = dirname(fileURLToPath(import.meta.url))
|
|
9
|
-
const templateDir = join(__dirname, '../templates')
|
|
10
|
-
const targetDir = process.cwd()
|
|
11
|
-
const toolsDir = join(__dirname, '../tools-gh')
|
|
12
|
-
|
|
13
|
-
console.log('⚡ JS Template by @vv0rkz — Инициализация проекта\n')
|
|
14
|
-
|
|
15
|
-
// Функция для интерактивного вопроса
|
|
16
|
-
function askQuestion(query) {
|
|
17
|
-
const rl = readline.createInterface({
|
|
18
|
-
input: process.stdin,
|
|
19
|
-
output: process.stdout,
|
|
20
|
-
})
|
|
21
|
-
|
|
22
|
-
return new Promise((resolve) =>
|
|
23
|
-
rl.question(query, (ans) => {
|
|
24
|
-
rl.close()
|
|
25
|
-
resolve(ans)
|
|
26
|
-
}),
|
|
27
|
-
)
|
|
28
|
-
}
|
|
29
|
-
|
|
30
|
-
// 0. Проверка git репозитория
|
|
31
|
-
console.log('🔍 Проверка git...')
|
|
32
|
-
const hasGit = existsSync(join(targetDir, '.git'))
|
|
33
|
-
|
|
34
|
-
if (!hasGit) {
|
|
35
|
-
console.log(' ⚠️ Git репозиторий не найден')
|
|
36
|
-
const answer = await askQuestion(' ❓ Инициализировать git репозиторий? (Y/n): ')
|
|
37
|
-
|
|
38
|
-
if (answer.toLowerCase() !== 'n' && answer.toLowerCase() !== 'no') {
|
|
39
|
-
try {
|
|
40
|
-
execSync('git init', { stdio: 'inherit', cwd: targetDir })
|
|
41
|
-
console.log(' ✅ Git репозиторий создан')
|
|
42
|
-
} catch (error) {
|
|
43
|
-
console.log(' ❌ Ошибка создания git репозитория')
|
|
44
|
-
console.log(' Создай вручную: git init')
|
|
45
|
-
}
|
|
46
|
-
} else {
|
|
47
|
-
console.log(' ⏭️ Git пропущен')
|
|
48
|
-
console.log(' ⚠️ Без git некоторые функции могут не работать (husky, gh)')
|
|
49
|
-
}
|
|
50
|
-
} else {
|
|
51
|
-
console.log(' ✅ Git репозиторий найден')
|
|
52
|
-
}
|
|
53
|
-
|
|
54
|
-
// 1. Копирование конфигов с интерактивной перезаписью
|
|
55
|
-
console.log('\n📋 Копирование конфигов...')
|
|
56
|
-
const filesToCopy = [
|
|
57
|
-
{ src: 'gitignore', dest: '.gitignore' },
|
|
58
|
-
{ src: 'changelog.config.js', dest: 'changelog.config.js' },
|
|
59
|
-
{ src: 'commitlint.config.js', dest: 'commitlint.config.js' },
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
const
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
}
|
|
85
|
-
}
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
}
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
const
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
console.log('
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
console.log('
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
|
|
158
|
-
|
|
159
|
-
|
|
160
|
-
|
|
161
|
-
|
|
162
|
-
|
|
163
|
-
|
|
164
|
-
|
|
165
|
-
|
|
166
|
-
|
|
167
|
-
|
|
168
|
-
|
|
169
|
-
|
|
170
|
-
|
|
171
|
-
|
|
172
|
-
|
|
173
|
-
|
|
174
|
-
|
|
175
|
-
|
|
176
|
-
|
|
177
|
-
|
|
178
|
-
|
|
179
|
-
|
|
180
|
-
|
|
181
|
-
|
|
182
|
-
|
|
183
|
-
|
|
184
|
-
|
|
185
|
-
|
|
186
|
-
|
|
187
|
-
|
|
188
|
-
|
|
189
|
-
|
|
190
|
-
}
|
|
191
|
-
|
|
192
|
-
console.log('
|
|
193
|
-
|
|
194
|
-
|
|
195
|
-
|
|
196
|
-
|
|
197
|
-
|
|
198
|
-
|
|
199
|
-
|
|
200
|
-
|
|
201
|
-
|
|
202
|
-
|
|
203
|
-
|
|
204
|
-
|
|
205
|
-
const
|
|
206
|
-
if (
|
|
207
|
-
console.log('
|
|
208
|
-
|
|
209
|
-
|
|
210
|
-
|
|
211
|
-
|
|
212
|
-
|
|
213
|
-
|
|
214
|
-
|
|
215
|
-
|
|
216
|
-
|
|
217
|
-
|
|
218
|
-
|
|
219
|
-
|
|
220
|
-
|
|
221
|
-
|
|
222
|
-
|
|
223
|
-
|
|
224
|
-
|
|
225
|
-
|
|
226
|
-
|
|
227
|
-
|
|
228
|
-
|
|
229
|
-
|
|
230
|
-
|
|
231
|
-
|
|
232
|
-
|
|
233
|
-
npm run _
|
|
234
|
-
|
|
235
|
-
|
|
236
|
-
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
import { execSync, spawnSync } from 'child_process'
|
|
3
|
+
import { copyFileSync, existsSync, mkdirSync, readdirSync, readFileSync, statSync, unlinkSync, writeFileSync } from 'fs'
|
|
4
|
+
import { dirname, join } from 'path'
|
|
5
|
+
import * as readline from 'readline'
|
|
6
|
+
import { fileURLToPath } from 'url'
|
|
7
|
+
|
|
8
|
+
const __dirname = dirname(fileURLToPath(import.meta.url))
|
|
9
|
+
const templateDir = join(__dirname, '../templates')
|
|
10
|
+
const targetDir = process.cwd()
|
|
11
|
+
const toolsDir = join(__dirname, '../tools-gh')
|
|
12
|
+
|
|
13
|
+
console.log('⚡ JS Template by @vv0rkz — Инициализация проекта\n')
|
|
14
|
+
|
|
15
|
+
// Функция для интерактивного вопроса
|
|
16
|
+
function askQuestion(query) {
|
|
17
|
+
const rl = readline.createInterface({
|
|
18
|
+
input: process.stdin,
|
|
19
|
+
output: process.stdout,
|
|
20
|
+
})
|
|
21
|
+
|
|
22
|
+
return new Promise((resolve) =>
|
|
23
|
+
rl.question(query, (ans) => {
|
|
24
|
+
rl.close()
|
|
25
|
+
resolve(ans)
|
|
26
|
+
}),
|
|
27
|
+
)
|
|
28
|
+
}
|
|
29
|
+
|
|
30
|
+
// 0. Проверка git репозитория
|
|
31
|
+
console.log('🔍 Проверка git...')
|
|
32
|
+
const hasGit = existsSync(join(targetDir, '.git'))
|
|
33
|
+
|
|
34
|
+
if (!hasGit) {
|
|
35
|
+
console.log(' ⚠️ Git репозиторий не найден')
|
|
36
|
+
const answer = await askQuestion(' ❓ Инициализировать git репозиторий? (Y/n): ')
|
|
37
|
+
|
|
38
|
+
if (answer.toLowerCase() !== 'n' && answer.toLowerCase() !== 'no') {
|
|
39
|
+
try {
|
|
40
|
+
execSync('git init', { stdio: 'inherit', cwd: targetDir })
|
|
41
|
+
console.log(' ✅ Git репозиторий создан')
|
|
42
|
+
} catch (error) {
|
|
43
|
+
console.log(' ❌ Ошибка создания git репозитория')
|
|
44
|
+
console.log(' Создай вручную: git init')
|
|
45
|
+
}
|
|
46
|
+
} else {
|
|
47
|
+
console.log(' ⏭️ Git пропущен')
|
|
48
|
+
console.log(' ⚠️ Без git некоторые функции могут не работать (husky, gh)')
|
|
49
|
+
}
|
|
50
|
+
} else {
|
|
51
|
+
console.log(' ✅ Git репозиторий найден')
|
|
52
|
+
}
|
|
53
|
+
|
|
54
|
+
// 1. Копирование конфигов с интерактивной перезаписью
|
|
55
|
+
console.log('\n📋 Копирование конфигов...')
|
|
56
|
+
const filesToCopy = [
|
|
57
|
+
{ src: 'gitignore', dest: '.gitignore' },
|
|
58
|
+
{ src: 'changelog.config.js', dest: 'changelog.config.js' },
|
|
59
|
+
{ src: 'commitlint.config.js', dest: 'commitlint.config.js' },
|
|
60
|
+
{ src: 'jst.config.js', dest: 'jst.config.js' },
|
|
61
|
+
]
|
|
62
|
+
|
|
63
|
+
for (const file of filesToCopy) {
|
|
64
|
+
const src = join(templateDir, file.src)
|
|
65
|
+
const dest = join(targetDir, file.dest)
|
|
66
|
+
|
|
67
|
+
if (!existsSync(src)) {
|
|
68
|
+
console.log(` ⚠️ ${file.dest} не найден в template (пропускаем)`)
|
|
69
|
+
continue
|
|
70
|
+
}
|
|
71
|
+
|
|
72
|
+
if (existsSync(dest)) {
|
|
73
|
+
// Файл существует - спрашиваем что делать
|
|
74
|
+
const answer = await askQuestion(` ❓ ${file.dest} уже существует. Перезаписать? (y/N): `)
|
|
75
|
+
|
|
76
|
+
if (answer.toLowerCase() === 'y' || answer.toLowerCase() === 'yes') {
|
|
77
|
+
copyFileSync(src, dest)
|
|
78
|
+
console.log(` ✅ ${file.dest} (перезаписан)`)
|
|
79
|
+
} else {
|
|
80
|
+
console.log(` ⏭️ ${file.dest} (пропущен)`)
|
|
81
|
+
}
|
|
82
|
+
} else {
|
|
83
|
+
copyFileSync(src, dest)
|
|
84
|
+
console.log(` ✅ ${file.dest}`)
|
|
85
|
+
}
|
|
86
|
+
}
|
|
87
|
+
|
|
88
|
+
// 2. Копирование .husky
|
|
89
|
+
console.log('\n🐶 Настройка husky хуков...')
|
|
90
|
+
const huskyDir = join(targetDir, '.husky')
|
|
91
|
+
if (!existsSync(huskyDir)) {
|
|
92
|
+
mkdirSync(huskyDir, { recursive: true })
|
|
93
|
+
}
|
|
94
|
+
|
|
95
|
+
const huskyTemplateDir = join(templateDir, '.husky')
|
|
96
|
+
if (existsSync(huskyTemplateDir)) {
|
|
97
|
+
const copyDir = (src, dest) => {
|
|
98
|
+
if (!existsSync(dest)) {
|
|
99
|
+
mkdirSync(dest, { recursive: true })
|
|
100
|
+
}
|
|
101
|
+
|
|
102
|
+
const entries = readdirSync(src)
|
|
103
|
+
for (const entry of entries) {
|
|
104
|
+
const srcPath = join(src, entry)
|
|
105
|
+
const destPath = join(dest, entry)
|
|
106
|
+
|
|
107
|
+
if (statSync(srcPath).isDirectory()) {
|
|
108
|
+
copyDir(srcPath, destPath)
|
|
109
|
+
} else {
|
|
110
|
+
copyFileSync(srcPath, destPath)
|
|
111
|
+
}
|
|
112
|
+
}
|
|
113
|
+
}
|
|
114
|
+
|
|
115
|
+
copyDir(huskyTemplateDir, huskyDir)
|
|
116
|
+
console.log(' ✅ Хуки скопированы')
|
|
117
|
+
} else {
|
|
118
|
+
console.log(' ⚠️ .husky не найден в template')
|
|
119
|
+
}
|
|
120
|
+
|
|
121
|
+
// 3. НЕ копируем tools-gh
|
|
122
|
+
console.log('\n🔧 GitHub скрипты...')
|
|
123
|
+
console.log(' ✅ Используются из @vv0rkz/js-template (не копируются)')
|
|
124
|
+
|
|
125
|
+
// 4. Добавление скриптов в package.json
|
|
126
|
+
console.log('\n📦 Обновление package.json...')
|
|
127
|
+
const packageJsonPath = join(targetDir, 'package.json')
|
|
128
|
+
if (existsSync(packageJsonPath)) {
|
|
129
|
+
const packageJson = JSON.parse(readFileSync(packageJsonPath, 'utf8'))
|
|
130
|
+
|
|
131
|
+
packageJson.scripts = {
|
|
132
|
+
...packageJson.scripts,
|
|
133
|
+
prepare: 'husky',
|
|
134
|
+
jst: 'jst',
|
|
135
|
+
_: 'jst',
|
|
136
|
+
}
|
|
137
|
+
|
|
138
|
+
if (!packageJson.devDependencies) {
|
|
139
|
+
packageJson.devDependencies = {}
|
|
140
|
+
}
|
|
141
|
+
packageJson.devDependencies['@vv0rkz/js-template'] = '^1.4.0'
|
|
142
|
+
|
|
143
|
+
// Проверка и установка type: module для ES модулей
|
|
144
|
+
if (!packageJson.type || packageJson.type === 'commonjs') {
|
|
145
|
+
packageJson.type = 'module'
|
|
146
|
+
console.log(' ⚙️ Установлен "type": "module" (для ES модулей)')
|
|
147
|
+
}
|
|
148
|
+
|
|
149
|
+
writeFileSync(packageJsonPath, JSON.stringify(packageJson, null, 2))
|
|
150
|
+
console.log(' ✅ Скрипты добавлены')
|
|
151
|
+
console.log(' npm run jst или npm run _')
|
|
152
|
+
}
|
|
153
|
+
|
|
154
|
+
// 5. Установка зависимостей
|
|
155
|
+
console.log('\n📥 Установка зависимостей...')
|
|
156
|
+
try {
|
|
157
|
+
execSync('npm install --save-dev @commitlint/cli @commitlint/config-conventional husky changelogen', {
|
|
158
|
+
stdio: 'inherit',
|
|
159
|
+
cwd: targetDir,
|
|
160
|
+
})
|
|
161
|
+
console.log(' ✅ Зависимости установлены')
|
|
162
|
+
} catch (error) {
|
|
163
|
+
console.error(' ❌ Ошибка установки зависимостей')
|
|
164
|
+
}
|
|
165
|
+
|
|
166
|
+
// 6. Инициализация husky
|
|
167
|
+
console.log('\n🔗 Активация husky...')
|
|
168
|
+
try {
|
|
169
|
+
execSync('npx husky init', { stdio: 'inherit', cwd: targetDir })
|
|
170
|
+
|
|
171
|
+
// Удаляем дефолтный pre-commit с npm test
|
|
172
|
+
const defaultPreCommit = join(targetDir, '.husky', 'pre-commit')
|
|
173
|
+
if (existsSync(defaultPreCommit)) {
|
|
174
|
+
unlinkSync(defaultPreCommit) // ← Теперь без await import
|
|
175
|
+
console.log(' 🧹 Удалён дефолтный pre-commit')
|
|
176
|
+
}
|
|
177
|
+
|
|
178
|
+
console.log(' ✅ Husky активирован')
|
|
179
|
+
} catch (error) {
|
|
180
|
+
console.log(' ⚠️ Husky уже инициализирован')
|
|
181
|
+
}
|
|
182
|
+
|
|
183
|
+
// 7. Настройка GitHub labels
|
|
184
|
+
console.log('\n🏷️ Настройка GitHub labels...')
|
|
185
|
+
try {
|
|
186
|
+
execSync('gh auth status', { stdio: 'ignore' })
|
|
187
|
+
const setupLabels = spawnSync('node', [join(toolsDir, 'setup-labels.js')], { stdio: 'inherit' })
|
|
188
|
+
if (setupLabels.status === 0) {
|
|
189
|
+
console.log(' ✅ Labels настроены')
|
|
190
|
+
}
|
|
191
|
+
} catch (error) {
|
|
192
|
+
console.log(' ⏭️ Пропущено (GitHub CLI не настроен)')
|
|
193
|
+
console.log(' Запусти позже: npm run _ setup-labels')
|
|
194
|
+
}
|
|
195
|
+
|
|
196
|
+
// 8. Настройка автообновления зависимостей
|
|
197
|
+
console.log('\n📦 Настройка автообновления зависимостей...')
|
|
198
|
+
const setupDeps = spawnSync('node', [join(toolsDir, 'setup-deps.js')], { stdio: 'inherit' })
|
|
199
|
+
if (setupDeps.status !== 0) {
|
|
200
|
+
console.log(' ⏭️ Пропущено (измени depUpdater в jst.config.js)')
|
|
201
|
+
}
|
|
202
|
+
|
|
203
|
+
// 9. Инициализация README
|
|
204
|
+
console.log('\n📝 Инициализация README...')
|
|
205
|
+
const initReadme = spawnSync('node', [join(toolsDir, 'init-readme.js')], { stdio: 'inherit' })
|
|
206
|
+
if (initReadme.status === 0) {
|
|
207
|
+
console.log(' ✅ README.md создан')
|
|
208
|
+
}
|
|
209
|
+
// 10. Проверка на версию
|
|
210
|
+
const packageJson = JSON.parse(readFileSync('package.json', 'utf8'))
|
|
211
|
+
|
|
212
|
+
// Проверка версии
|
|
213
|
+
const currentVersion = packageJson.version || '1.0.0'
|
|
214
|
+
if (currentVersion.startsWith('0.')) {
|
|
215
|
+
console.log('\n⚠️ ВНИМАНИЕ: Текущая версия ' + currentVersion + ' (0.x.x)')
|
|
216
|
+
console.log('💡 Рекомендуется начинать с версии 1.0.0 для корректной работы changelogen')
|
|
217
|
+
console.log(' Причина: https://github.com/conventional-changelog/standard-version/issues/539\n')
|
|
218
|
+
|
|
219
|
+
const answer = await askQuestion('Изменить версию на 1.0.0? (Y/n): ')
|
|
220
|
+
|
|
221
|
+
if (answer.toLowerCase() !== 'n' && answer.toLowerCase() !== 'no') {
|
|
222
|
+
packageJson.version = '1.0.0'
|
|
223
|
+
writeFileSync('package.json', JSON.stringify(packageJson, null, 2))
|
|
224
|
+
console.log('✅ Версия изменена на 1.0.0')
|
|
225
|
+
}
|
|
226
|
+
}
|
|
227
|
+
|
|
228
|
+
console.log(`
|
|
229
|
+
🎉 JS Template успешно установлен!
|
|
230
|
+
|
|
231
|
+
📖 БЫСТРЫЕ КОМАНДЫ:
|
|
232
|
+
npm run _ changelog # Создать changelog
|
|
233
|
+
npm run _ release # Полный релиз
|
|
234
|
+
npm run _ tasks # Список задач
|
|
235
|
+
npm run _ create-task # Создать задачу
|
|
236
|
+
|
|
237
|
+
📚 ПОЛНЫЙ СПИСОК:
|
|
238
|
+
npm run _
|
|
239
|
+
|
|
240
|
+
🚀 Начни работу:
|
|
241
|
+
npm run _ create-task "Моя первая задача"
|
|
242
|
+
|
|
243
|
+
💡 ВАЖНО: tools-gh скрипты используются из node_modules, не копируются в проект
|
|
244
|
+
`)
|
package/package.json
CHANGED
|
@@ -1,67 +1,3 @@
|
|
|
1
|
-
#!/usr/bin/env sh
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
# Функция показа подсказки
|
|
6
|
-
show_help() {
|
|
7
|
-
echo ""
|
|
8
|
-
echo "🎯 РАЗРЕШЕННЫЕ ФОРМАТЫ КОММИТОВ:"
|
|
9
|
-
echo "────────────────────────────────────"
|
|
10
|
-
echo "✨ НОВЫЕ ФИЧИ: feat: #номер описание"
|
|
11
|
-
echo " feat(scope): #номер описание"
|
|
12
|
-
echo "🐛 ИСПРАВЛЕНИЯ: fix: #номер описание"
|
|
13
|
-
echo " fix(scope): #номер описание"
|
|
14
|
-
echo "🔧 РЕФАКТОРИНГ: refactor: описание ИЛИ refactor(scope): описание"
|
|
15
|
-
echo "🏗️ ИНФРАСТРУКТУРА: build: описание ИЛИ build(scope): описание"
|
|
16
|
-
echo "🛠️ ТЕХ. ЗАДАЧИ: chore: описание ИЛИ chore(scope): описание"
|
|
17
|
-
echo "📚 ДОКУМЕНТАЦИЯ: docs: описание ИЛИ docs(scope): описание"
|
|
18
|
-
echo "🚀 АВТО-РЕЛИЗЫ: chore(release): vX.X.X"
|
|
19
|
-
echo ""
|
|
20
|
-
echo "📝 ПРИМЕРЫ:"
|
|
21
|
-
echo " feat: #9 добавить нормализацию чисел"
|
|
22
|
-
echo " feat(parser): #9 добавить нормализацию чисел"
|
|
23
|
-
echo " fix: #10 исправить валидацию"
|
|
24
|
-
echo " fix(validator): #10 исправить валидацию операторов"
|
|
25
|
-
echo " refactor: оптимизировать алгоритм"
|
|
26
|
-
echo " docs(observer): добавлен пример redux"
|
|
27
|
-
echo " chore(release): v2.3.0"
|
|
28
|
-
echo "────────────────────────────────────"
|
|
29
|
-
exit 1
|
|
30
|
-
}
|
|
31
|
-
|
|
32
|
-
# ИСКЛЮЧЕНИЕ: разрешаем авто-релизные коммиты от changelogen
|
|
33
|
-
if echo "$COMMIT_MSG" | grep -q "^chore(release): v[0-9]\+\.[0-9]\+\.[0-9]\+$"; then
|
|
34
|
-
echo "✅ Авто-релизный коммит: $COMMIT_MSG"
|
|
35
|
-
exit 0
|
|
36
|
-
fi
|
|
37
|
-
|
|
38
|
-
# СТРОГАЯ ПРОВЕРКА для обычных коммитов
|
|
39
|
-
if ! echo "$COMMIT_MSG" | grep -q -E "^(feat(\(.+\))?: #[0-9]+ .+|fix(\(.+\))?: #[0-9]+ .+|refactor(\(.+\))?: .+|build(\(.+\))?: .+|chore(\(.+\))?: .+|docs(\(.+\))?: .+)"; then
|
|
40
|
-
echo "❌ Неправильный формат коммита: '$COMMIT_MSG'"
|
|
41
|
-
show_help
|
|
42
|
-
fi
|
|
43
|
-
|
|
44
|
-
# Дополнительная проверка: feat/fix должны иметь #номер
|
|
45
|
-
if echo "$COMMIT_MSG" | grep -q "^\(feat\|fix\)"; then
|
|
46
|
-
if ! echo "$COMMIT_MSG" | grep -q "^\(feat\|fix\)\(\(.*\)\)\?: #[0-9]"; then
|
|
47
|
-
echo "❌ Ошибка: feat и fix коммиты должны содержать номер задачи"
|
|
48
|
-
echo "💡 Твой коммит: $COMMIT_MSG"
|
|
49
|
-
echo "✅ Пример: feat: #9 добавить нормализацию чисел"
|
|
50
|
-
exit 1
|
|
51
|
-
fi
|
|
52
|
-
fi
|
|
53
|
-
|
|
54
|
-
# Закрытие issues при fix: #номер
|
|
55
|
-
if echo "$COMMIT_MSG" | grep -q "^fix: #[0-9]"; then
|
|
56
|
-
ISSUE_NUMBER=$(echo "$COMMIT_MSG" | grep -o '#[0-9]*' | sed 's/#//')
|
|
57
|
-
echo "🔧 Закрываю issue #$ISSUE_NUMBER..."
|
|
58
|
-
|
|
59
|
-
COMMIT_HASH=$(git rev-parse --short HEAD)
|
|
60
|
-
REPO_URL=$(git remote get-url origin | sed 's/\.git$//')
|
|
61
|
-
COMMIT_URL="$REPO_URL/commit/$COMMIT_HASH"
|
|
62
|
-
|
|
63
|
-
gh issue close "$ISSUE_NUMBER" --comment "Исправлено в коммите: [$COMMIT_HASH]($COMMIT_URL) - $COMMIT_MSG"
|
|
64
|
-
fi
|
|
65
|
-
|
|
66
|
-
# Запускаем commitlint
|
|
67
|
-
npx --no -- commitlint --edit "$1"
|
|
1
|
+
#!/usr/bin/env sh
|
|
2
|
+
|
|
3
|
+
node ./node_modules/@vv0rkz/js-template/tools-gh/validate-commit.js "$1"
|
|
@@ -1,25 +1,3 @@
|
|
|
1
|
-
#!/usr/bin/env sh
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
COMMIT_HASH=$(git rev-parse --short HEAD)
|
|
5
|
-
REPO_URL=$(git remote get-url origin)
|
|
6
|
-
|
|
7
|
-
# Исправляем URL
|
|
8
|
-
if echo "$REPO_URL" | grep -q "git@github.com"; then
|
|
9
|
-
REPO_URL=$(echo "$REPO_URL" | sed 's/git@github.com:/https:\/\/github.com\//' | sed 's/\.git$//')
|
|
10
|
-
else
|
|
11
|
-
REPO_URL=$(echo "$REPO_URL" | sed 's/\.git$//')
|
|
12
|
-
fi
|
|
13
|
-
|
|
14
|
-
# Пуш коммита
|
|
15
|
-
git push origin HEAD
|
|
16
|
-
|
|
17
|
-
# Закрытие issues при feat: #номер И fix: #номер
|
|
18
|
-
if echo "$COMMIT_MSG" | grep -q "^\(feat\|fix\): #[0-9]"; then
|
|
19
|
-
ISSUE_NUMBER=$(echo "$COMMIT_MSG" | grep -o '#[0-9]*' | sed 's/#//')
|
|
20
|
-
echo "🔧 Закрываю issue #$ISSUE_NUMBER..."
|
|
21
|
-
|
|
22
|
-
COMMIT_LINK="$REPO_URL/commit/$COMMIT_HASH"
|
|
23
|
-
|
|
24
|
-
gh issue close "$ISSUE_NUMBER" --comment "✅ Завершено в коммите: [$COMMIT_HASH]($COMMIT_LINK) - $COMMIT_MSG"
|
|
25
|
-
fi
|
|
1
|
+
#!/usr/bin/env sh
|
|
2
|
+
|
|
3
|
+
node ./node_modules/@vv0rkz/js-template/tools-gh/post-commit-hook.js
|
|
@@ -1,17 +1,3 @@
|
|
|
1
|
-
#!/usr/bin/env sh
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
if [ "$CURRENT_BRANCH" = "main" ]; then
|
|
5
|
-
echo "✅ Разрешённая ветка: $CURRENT_BRANCH"
|
|
6
|
-
exit 0
|
|
7
|
-
fi
|
|
8
|
-
|
|
9
|
-
# Простая проверка: начинается с v и есть дефис
|
|
10
|
-
if ! echo "$CURRENT_BRANCH" | grep -q "^v.*-.*"; then
|
|
11
|
-
echo "❌ Неправильный формат ветки: $CURRENT_BRANCH"
|
|
12
|
-
echo "✅ Должен быть: vX.Y.Z-description"
|
|
13
|
-
echo "📝 Пример: v2.3.0-normalize-operators"
|
|
14
|
-
exit 1
|
|
15
|
-
fi
|
|
16
|
-
|
|
17
|
-
echo "✅ Формат ветки правильный: $CURRENT_BRANCH"
|
|
1
|
+
#!/usr/bin/env sh
|
|
2
|
+
|
|
3
|
+
node ./node_modules/@vv0rkz/js-template/tools-gh/validate-branch.js
|
|
@@ -1,9 +1,16 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
}
|
|
1
|
+
let changelogTypes = {
|
|
2
|
+
feat: { title: '✨ Новые фичи', semver: 'minor' },
|
|
3
|
+
fix: { title: '🐛 Исправления', semver: 'patch' },
|
|
4
|
+
refactor: { title: '♻️ Рефакторинг', semver: 'patch' },
|
|
5
|
+
perf: { title: '⚡ Оптимизация', semver: 'patch' },
|
|
6
|
+
}
|
|
7
|
+
|
|
8
|
+
try {
|
|
9
|
+
const { default: config } = await import('./jst.config.js')
|
|
10
|
+
if (config.changelog?.types) changelogTypes = config.changelog.types
|
|
11
|
+
} catch {}
|
|
12
|
+
|
|
13
|
+
export default {
|
|
14
|
+
types: changelogTypes,
|
|
15
|
+
contributors: false,
|
|
16
|
+
}
|