azure-pr-manager 2.0.0 → 2.0.5
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 +1 -1
- package/src/git.js +21 -0
- package/src/index.js +108 -12
package/package.json
CHANGED
package/src/git.js
CHANGED
|
@@ -172,3 +172,24 @@ export function fetchOrigin() {
|
|
|
172
172
|
// fetch pode falhar se nao tiver acesso, prosseguir
|
|
173
173
|
}
|
|
174
174
|
}
|
|
175
|
+
|
|
176
|
+
/**
|
|
177
|
+
* Lista os commits da branch atual que nao estao na target
|
|
178
|
+
* Util para gerar descricao do PR baseada nos commits
|
|
179
|
+
* @param {string} targetBranch
|
|
180
|
+
* @returns {string[]} Lista de mensagens de commit (formato "hash - mensagem")
|
|
181
|
+
*/
|
|
182
|
+
export function getCommitsBetween(targetBranch) {
|
|
183
|
+
try {
|
|
184
|
+
const log = exec(`log origin/${targetBranch}..HEAD --format="%h - %s"`);
|
|
185
|
+
return log ? log.split("\n").filter(Boolean) : [];
|
|
186
|
+
} catch {
|
|
187
|
+
try {
|
|
188
|
+
// Fallback: tenta sem origin/
|
|
189
|
+
const log = exec(`log ${targetBranch}..HEAD --format="%h - %s"`);
|
|
190
|
+
return log ? log.split("\n").filter(Boolean) : [];
|
|
191
|
+
} catch {
|
|
192
|
+
return [];
|
|
193
|
+
}
|
|
194
|
+
}
|
|
195
|
+
}
|
package/src/index.js
CHANGED
|
@@ -8,12 +8,70 @@ import { AzureDevOpsApi } from "./api.js";
|
|
|
8
8
|
import { loadConfig, saveConfig, getDefaultConfig } from "./config.js";
|
|
9
9
|
import * as git from "./git.js";
|
|
10
10
|
|
|
11
|
+
// ==================== BANNER ====================
|
|
12
|
+
const BANNER_WIDTH = 64;
|
|
13
|
+
const BORDER = "═".repeat(BANNER_WIDTH);
|
|
14
|
+
const EMPTY = " ".repeat(BANNER_WIDTH);
|
|
15
|
+
|
|
16
|
+
function stripAnsi(str) {
|
|
17
|
+
return str.replace(/\x1b\[[0-9;]*m/g, "");
|
|
18
|
+
}
|
|
19
|
+
|
|
20
|
+
function centerText(text) {
|
|
21
|
+
const len = stripAnsi(text).length;
|
|
22
|
+
const pad = Math.max(0, BANNER_WIDTH - len);
|
|
23
|
+
const left = Math.floor(pad / 2);
|
|
24
|
+
const right = pad - left;
|
|
25
|
+
return " ".repeat(left) + text + " ".repeat(right);
|
|
26
|
+
}
|
|
27
|
+
|
|
28
|
+
function rightPad(text) {
|
|
29
|
+
const len = stripAnsi(text).length;
|
|
30
|
+
const pad = Math.max(0, BANNER_WIDTH - len);
|
|
31
|
+
return text + " ".repeat(pad);
|
|
32
|
+
}
|
|
33
|
+
|
|
34
|
+
function showBanner(subtitle) {
|
|
35
|
+
const c = chalk.cyan;
|
|
36
|
+
const w = chalk.bold.white;
|
|
37
|
+
|
|
38
|
+
const art = [
|
|
39
|
+
" ____ ____ __ __ ",
|
|
40
|
+
" | _ \\| _ \\ | \\/ | __ _ _ __ __ _ __ _ ___ _ __ ",
|
|
41
|
+
" | |_) | |_) | | |\\/| |/ _` | '_ \\ / _` |/ _` |/ _ \\ '__|",
|
|
42
|
+
" | __/| _ < | | | | (_| | | | | (_| | (_| | __/ | ",
|
|
43
|
+
" |_| |_| \\_\\ |_| |_|\\__,_|_| |_|\\__,_|\\__, |\\___|_| ",
|
|
44
|
+
" |___/ ",
|
|
45
|
+
];
|
|
46
|
+
|
|
47
|
+
console.log();
|
|
48
|
+
console.log(c(" ╔" + BORDER + "╗"));
|
|
49
|
+
console.log(c(" ║") + EMPTY + c("║"));
|
|
50
|
+
|
|
51
|
+
for (const line of art) {
|
|
52
|
+
console.log(c(" ║") + rightPad(" " + w(line)) + c("║"));
|
|
53
|
+
}
|
|
54
|
+
|
|
55
|
+
console.log(c(" ║") + EMPTY + c("║"));
|
|
56
|
+
console.log(c(" ║") + centerText(chalk.gray("Azure DevOps Pull Request Automation")) + c("║"));
|
|
57
|
+
console.log(c(" ║") + centerText(chalk.gray("v2.0.5 — Desenvolvido por ") + chalk.white("Higor Santos")) + c("║"));
|
|
58
|
+
console.log(c(" ║") + EMPTY + c("║"));
|
|
59
|
+
|
|
60
|
+
if (subtitle) {
|
|
61
|
+
console.log(c(" ║") + centerText(chalk.bold.yellow(subtitle)) + c("║"));
|
|
62
|
+
console.log(c(" ║") + EMPTY + c("║"));
|
|
63
|
+
}
|
|
64
|
+
|
|
65
|
+
console.log(c(" ╚" + BORDER + "╝"));
|
|
66
|
+
console.log();
|
|
67
|
+
}
|
|
68
|
+
|
|
11
69
|
const program = new Command();
|
|
12
70
|
|
|
13
71
|
program
|
|
14
72
|
.name("azure-pr")
|
|
15
73
|
.description("CLI para criar Pull Requests no Azure DevOps automaticamente")
|
|
16
|
-
.version("2.0.
|
|
74
|
+
.version("2.0.5")
|
|
17
75
|
.addHelpText("after", "\n Desenvolvido por Higor Santos");
|
|
18
76
|
|
|
19
77
|
// ==================== INIT ====================
|
|
@@ -21,8 +79,7 @@ program
|
|
|
21
79
|
.command("init")
|
|
22
80
|
.description("Inicializa a configuracao do projeto (.prmanager.json)")
|
|
23
81
|
.action(async () => {
|
|
24
|
-
|
|
25
|
-
console.log(chalk.gray(" Desenvolvido por ") + chalk.white("Higor Santos\n"));
|
|
82
|
+
showBanner("Configuração");
|
|
26
83
|
|
|
27
84
|
const existing = await loadConfig();
|
|
28
85
|
const defaults = existing || getDefaultConfig();
|
|
@@ -286,8 +343,7 @@ program
|
|
|
286
343
|
process.exit(1);
|
|
287
344
|
}
|
|
288
345
|
|
|
289
|
-
|
|
290
|
-
console.log(chalk.gray(" Desenvolvido por ") + chalk.white("Higor Santos\n"));
|
|
346
|
+
showBanner("Criação de Pull Request");
|
|
291
347
|
|
|
292
348
|
// ── ETAPA 1: Verificar repositorio git ──
|
|
293
349
|
if (!git.isGitRepo()) {
|
|
@@ -681,11 +737,15 @@ program
|
|
|
681
737
|
);
|
|
682
738
|
console.log(
|
|
683
739
|
chalk.gray(" │") +
|
|
684
|
-
"
|
|
740
|
+
" Escolha como gerar a descricao do seu Pull Request."
|
|
741
|
+
);
|
|
742
|
+
console.log(
|
|
743
|
+
chalk.gray(" │") +
|
|
744
|
+
" Voce pode usar os commits como descricao, escrever"
|
|
685
745
|
);
|
|
686
746
|
console.log(
|
|
687
747
|
chalk.gray(" │") +
|
|
688
|
-
"
|
|
748
|
+
" sua propria mensagem, ou deixar sem descricao."
|
|
689
749
|
);
|
|
690
750
|
console.log(
|
|
691
751
|
chalk.gray(
|
|
@@ -693,15 +753,51 @@ program
|
|
|
693
753
|
)
|
|
694
754
|
);
|
|
695
755
|
|
|
696
|
-
|
|
756
|
+
let description = "";
|
|
757
|
+
|
|
758
|
+
const { descMode } = await inquirer.prompt([
|
|
697
759
|
{
|
|
698
|
-
type: "
|
|
699
|
-
name: "
|
|
700
|
-
message: "Descricao do PR
|
|
701
|
-
|
|
760
|
+
type: "list",
|
|
761
|
+
name: "descMode",
|
|
762
|
+
message: "Descricao do PR:",
|
|
763
|
+
choices: [
|
|
764
|
+
{
|
|
765
|
+
name: "Usar lista de commits como descricao",
|
|
766
|
+
value: "commits",
|
|
767
|
+
},
|
|
768
|
+
{
|
|
769
|
+
name: "Escrever manualmente",
|
|
770
|
+
value: "manual",
|
|
771
|
+
},
|
|
772
|
+
{
|
|
773
|
+
name: "Sem descricao",
|
|
774
|
+
value: "empty",
|
|
775
|
+
},
|
|
776
|
+
],
|
|
702
777
|
},
|
|
703
778
|
]);
|
|
704
779
|
|
|
780
|
+
if (descMode === "commits") {
|
|
781
|
+
const commits = git.getCommitsBetween(targetBranch);
|
|
782
|
+
if (commits.length > 0) {
|
|
783
|
+
description = "## Commits\n\n" + commits.map((c) => `- ${c}`).join("\n");
|
|
784
|
+
console.log(chalk.green(`\n ${commits.length} commit(s) adicionado(s) a descricao:\n`));
|
|
785
|
+
commits.forEach((c) => console.log(chalk.gray(` ${c}`)));
|
|
786
|
+
console.log();
|
|
787
|
+
} else {
|
|
788
|
+
console.log(chalk.yellow("\n Nenhum commit encontrado entre as branches. Descricao ficara vazia.\n"));
|
|
789
|
+
}
|
|
790
|
+
} else if (descMode === "manual") {
|
|
791
|
+
const { manualDesc } = await inquirer.prompt([
|
|
792
|
+
{
|
|
793
|
+
type: "input",
|
|
794
|
+
name: "manualDesc",
|
|
795
|
+
message: "Descricao (pode usar Markdown):",
|
|
796
|
+
},
|
|
797
|
+
]);
|
|
798
|
+
description = manualDesc || "";
|
|
799
|
+
}
|
|
800
|
+
|
|
705
801
|
// Draft / Auto-complete
|
|
706
802
|
const isDraft =
|
|
707
803
|
opts.draft !== undefined
|