@ndiinginc/commit 1.0.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/package.json +24 -0
- package/src/commit.js +202 -0
package/package.json
ADDED
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "@ndiinginc/commit",
|
|
3
|
+
"version": "1.0.0",
|
|
4
|
+
"description": "",
|
|
5
|
+
"main": "./src/commit.js",
|
|
6
|
+
"scripts": {
|
|
7
|
+
"test": "nodemon --exec \"node -e \\\"require('@ndiinginc/test')(require('path').join(process.cwd(),'tests'),{verbose:true})\\\"\"",
|
|
8
|
+
"dev": "nodemon src/index.js",
|
|
9
|
+
"prettier": "npx prettier . --write",
|
|
10
|
+
"commit": "node scripts/commit.js",
|
|
11
|
+
"npm:dry-run": "npm publish --dry-run",
|
|
12
|
+
"npm:login": "npm login",
|
|
13
|
+
"npm:publish": "npm publish --access public",
|
|
14
|
+
"tsc": "npx tsc"
|
|
15
|
+
},
|
|
16
|
+
"keywords": [],
|
|
17
|
+
"author": "",
|
|
18
|
+
"license": "ISC",
|
|
19
|
+
"type": "commonjs",
|
|
20
|
+
"devDependencies": {
|
|
21
|
+
"@types/jest": "^30.0.0",
|
|
22
|
+
"jest": "^30.5.2"
|
|
23
|
+
}
|
|
24
|
+
}
|
package/src/commit.js
ADDED
|
@@ -0,0 +1,202 @@
|
|
|
1
|
+
const { execSync } = require("child_process");
|
|
2
|
+
const fs = require("fs");
|
|
3
|
+
const path = require("path");
|
|
4
|
+
const readline = require("readline");
|
|
5
|
+
|
|
6
|
+
const rl = readline.createInterface({
|
|
7
|
+
input: process.stdin,
|
|
8
|
+
output: process.stdout,
|
|
9
|
+
});
|
|
10
|
+
|
|
11
|
+
const ask = (query) => new Promise((resolve) => rl.question(query, resolve));
|
|
12
|
+
|
|
13
|
+
// Warna buat console
|
|
14
|
+
const colors = {
|
|
15
|
+
green: "\x1b[32m",
|
|
16
|
+
blue: "\x1b[36m",
|
|
17
|
+
red: "\x1b[31m",
|
|
18
|
+
yellow: "\x1b[33m",
|
|
19
|
+
reset: "\x1b[0m",
|
|
20
|
+
bold: "\x1b[1m",
|
|
21
|
+
};
|
|
22
|
+
|
|
23
|
+
const log = {
|
|
24
|
+
info: (msg) => console.log(`${colors.blue}ℹ️ ${msg}${colors.reset}`),
|
|
25
|
+
success: (msg) => console.log(`${colors.green}${msg}${colors.reset}`),
|
|
26
|
+
error: (msg) => console.log(`${colors.red}${msg}${colors.reset}`),
|
|
27
|
+
warn: (msg) => console.log(`${colors.yellow}⚠️ ${msg}${colors.reset}`),
|
|
28
|
+
title: (msg) => console.log(`\n${colors.bold}${colors.blue}${msg}${colors.reset}\n`),
|
|
29
|
+
};
|
|
30
|
+
|
|
31
|
+
// Template commit types dengan emoji
|
|
32
|
+
const commitTypes = {
|
|
33
|
+
feat: { emoji: "✨", desc: "New feature" },
|
|
34
|
+
fix: { emoji: "🐛", desc: "Bug fix" },
|
|
35
|
+
docs: { emoji: "📝", desc: "Documentation" },
|
|
36
|
+
chore: { emoji: "🔧", desc: "Chore/maintenance" },
|
|
37
|
+
refactor: { emoji: "♻️", desc: "Code refactoring" },
|
|
38
|
+
test: { emoji: "🧪", desc: "Testing" },
|
|
39
|
+
perf: { emoji: "⚡", desc: "Performance improvement" },
|
|
40
|
+
style: { emoji: "💄", desc: "Code style/formatting" },
|
|
41
|
+
ci: { emoji: "👷", desc: "CI/CD configuration" },
|
|
42
|
+
build: { emoji: "📦", desc: "Build system/dependencies" },
|
|
43
|
+
revert: { emoji: "⏪", desc: "Revert changes" },
|
|
44
|
+
};
|
|
45
|
+
|
|
46
|
+
// Cek status git
|
|
47
|
+
function checkGitStatus() {
|
|
48
|
+
try {
|
|
49
|
+
const status = execSync("git status --porcelain").toString().trim();
|
|
50
|
+
if (!status) {
|
|
51
|
+
log.warn("No changes to commit!");
|
|
52
|
+
return false;
|
|
53
|
+
}
|
|
54
|
+
|
|
55
|
+
const files = status.split("\n").length;
|
|
56
|
+
log.info(`${files} file(s) changed:`);
|
|
57
|
+
console.log(status);
|
|
58
|
+
return true;
|
|
59
|
+
} catch (error) {
|
|
60
|
+
log.error("Not a git repository!");
|
|
61
|
+
return false;
|
|
62
|
+
}
|
|
63
|
+
}
|
|
64
|
+
|
|
65
|
+
// Preview commit
|
|
66
|
+
function previewCommit(type, scope, message, version) {
|
|
67
|
+
const emoji = commitTypes[type]?.emoji || "📌";
|
|
68
|
+
const scopeStr = scope ? `(${scope})` : "";
|
|
69
|
+
const fullMsg = `${type}${scopeStr}: ${message}`;
|
|
70
|
+
|
|
71
|
+
console.log(`\n${colors.bold}Commit Preview:${colors.reset}`);
|
|
72
|
+
console.log(` ${colors.yellow}Version:${colors.reset} v${version}`);
|
|
73
|
+
console.log(` ${colors.yellow}Type:${colors.reset} ${emoji} ${type} (${commitTypes[type]?.desc || "Unknown"})`);
|
|
74
|
+
if (scope) console.log(` ${colors.yellow}Scope:${colors.reset} ${scope}`);
|
|
75
|
+
console.log(` ${colors.yellow}Message:${colors.reset} ${message}`);
|
|
76
|
+
console.log(`\n ${colors.blue}git commit -m "${fullMsg}"${colors.reset}`);
|
|
77
|
+
console.log(` ${colors.blue}git tag -a v${version} -m "Release v${version}"${colors.reset}\n`);
|
|
78
|
+
}
|
|
79
|
+
|
|
80
|
+
// Main function
|
|
81
|
+
async function release() {
|
|
82
|
+
try {
|
|
83
|
+
log.title("RELEASE SCRIPT");
|
|
84
|
+
|
|
85
|
+
// 1. Cek git status
|
|
86
|
+
if (!checkGitStatus()) {
|
|
87
|
+
rl.close();
|
|
88
|
+
return;
|
|
89
|
+
}
|
|
90
|
+
|
|
91
|
+
// 2. Baca package.json
|
|
92
|
+
const pkg = JSON.parse(fs.readFileSync(path.join(process.cwd(),"package.json"), "utf-8"));
|
|
93
|
+
let [major, minor, patch] = pkg.version.split(".").map(Number);
|
|
94
|
+
|
|
95
|
+
console.log(`\n${colors.bold}Current version:${colors.reset} ${colors.green}v${pkg.version}${colors.reset}`);
|
|
96
|
+
|
|
97
|
+
// 3. Ask inputs dengan default value
|
|
98
|
+
const bumpType = (await ask(`Bump type (${colors.yellow}patch${colors.reset} | minor | major) [patch]: `)) || "patch";
|
|
99
|
+
const commitType = (await ask(`Commit type (${colors.yellow}chore${colors.reset} | feat | fix | docs | refactor | test | perf) [chore]: `)) || "chore";
|
|
100
|
+
const scope = (await ask("Scope (e.g. auth, user, api) [none]: ")) || "";
|
|
101
|
+
const message = await ask("Commit message: ");
|
|
102
|
+
|
|
103
|
+
// 4. Validasi input
|
|
104
|
+
if (!message.trim()) {
|
|
105
|
+
log.error("Commit message is required!");
|
|
106
|
+
rl.close();
|
|
107
|
+
return;
|
|
108
|
+
}
|
|
109
|
+
|
|
110
|
+
if (!commitTypes[commitType]) {
|
|
111
|
+
log.warn(`Unknown commit type: ${commitType}, using "chore"`);
|
|
112
|
+
}
|
|
113
|
+
|
|
114
|
+
// 5. Versioning
|
|
115
|
+
switch (bumpType.toLowerCase()) {
|
|
116
|
+
case "major":
|
|
117
|
+
major++;
|
|
118
|
+
minor = 0;
|
|
119
|
+
patch = 0;
|
|
120
|
+
break;
|
|
121
|
+
case "minor":
|
|
122
|
+
minor++;
|
|
123
|
+
patch = 0;
|
|
124
|
+
break;
|
|
125
|
+
case "patch":
|
|
126
|
+
default:
|
|
127
|
+
patch++;
|
|
128
|
+
}
|
|
129
|
+
|
|
130
|
+
const newVersion = `${major}.${minor}.${patch}`;
|
|
131
|
+
const finalCommitType = commitTypes[commitType] ? commitType : "chore";
|
|
132
|
+
const finalScope = scope ? `(${scope})` : "";
|
|
133
|
+
const finalMsg = message.trim();
|
|
134
|
+
const commitFull = `${finalCommitType}${finalScope}: ${finalMsg}`;
|
|
135
|
+
|
|
136
|
+
// 6. Preview
|
|
137
|
+
previewCommit(finalCommitType, scope, finalMsg, newVersion);
|
|
138
|
+
|
|
139
|
+
// 7. Confirmation
|
|
140
|
+
const confirm = (await ask(`\nProceed with release? (${colors.green}y${colors.reset}/${colors.red}n${colors.reset}) [y]: `)) || "y";
|
|
141
|
+
|
|
142
|
+
if (confirm.toLowerCase() !== "y") {
|
|
143
|
+
log.warn("Release cancelled");
|
|
144
|
+
rl.close();
|
|
145
|
+
return;
|
|
146
|
+
}
|
|
147
|
+
|
|
148
|
+
// 8. Execute
|
|
149
|
+
console.log(`\n${colors.blue}Releasing v${newVersion}...${colors.reset}\n`);
|
|
150
|
+
|
|
151
|
+
// Update package.json
|
|
152
|
+
pkg.version = newVersion;
|
|
153
|
+
fs.writeFileSync("package.json", JSON.stringify(pkg, null, 2));
|
|
154
|
+
log.info("Updated package.json");
|
|
155
|
+
|
|
156
|
+
// Git add
|
|
157
|
+
execSync("git add -A", { stdio: "inherit" });
|
|
158
|
+
log.info("Staged changes");
|
|
159
|
+
|
|
160
|
+
// Git commit
|
|
161
|
+
execSync(`git commit -m "${commitFull}"`, { stdio: "inherit" });
|
|
162
|
+
log.info("Committed changes");
|
|
163
|
+
|
|
164
|
+
// Git tag
|
|
165
|
+
execSync(`git tag -a v${newVersion} -m "Release v${newVersion}"`, { stdio: "inherit" });
|
|
166
|
+
log.info("Created tag");
|
|
167
|
+
|
|
168
|
+
// Push
|
|
169
|
+
const branch = execSync("git rev-parse --abbrev-ref HEAD").toString().trim();
|
|
170
|
+
execSync(`git push origin ${branch} --tags`, { stdio: "inherit" });
|
|
171
|
+
log.info(`Pushed to ${branch}`);
|
|
172
|
+
|
|
173
|
+
// bagian release
|
|
174
|
+
|
|
175
|
+
// 9. Success
|
|
176
|
+
console.log(`\n${colors.green}${colors.bold}Successfully released v${newVersion}!${colors.reset}\n`);
|
|
177
|
+
|
|
178
|
+
// 10. Show next steps
|
|
179
|
+
console.log(`${colors.blue}Next steps:${colors.reset}`);
|
|
180
|
+
console.log(` 1. Check deployment: ${colors.yellow}npm run deploy${colors.reset}`);
|
|
181
|
+
console.log(` 2. View logs: ${colors.yellow}npm run pm2:logs${colors.reset}`);
|
|
182
|
+
console.log(` 3. Monitor: ${colors.yellow}npm run pm2:monit${colors.reset}\n`);
|
|
183
|
+
} catch (error) {
|
|
184
|
+
console.error(`\n${colors.red}${colors.bold}Release failed:${colors.reset}`, error.message);
|
|
185
|
+
|
|
186
|
+
// Helpful error messages
|
|
187
|
+
if (error.message.includes("not a git repository")) {
|
|
188
|
+
log.error("Make sure you are in a git repository!");
|
|
189
|
+
} else if (error.message.includes("no changes added to commit")) {
|
|
190
|
+
log.error("No changes to commit!");
|
|
191
|
+
} else if (error.message.includes("failed to push")) {
|
|
192
|
+
log.error("Push failed! Check your connection and permissions.");
|
|
193
|
+
}
|
|
194
|
+
|
|
195
|
+
process.exit(1);
|
|
196
|
+
} finally {
|
|
197
|
+
rl.close();
|
|
198
|
+
}
|
|
199
|
+
}
|
|
200
|
+
|
|
201
|
+
// Run
|
|
202
|
+
release();
|