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.
Files changed (3) hide show
  1. package/package.json +1 -1
  2. package/src/git.js +21 -0
  3. package/src/index.js +108 -12
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "azure-pr-manager",
3
- "version": "2.0.0",
3
+ "version": "2.0.5",
4
4
  "description": "CLI para criar Pull Requests no Azure DevOps automaticamente, com fluxo git completo (commit, push, publish branch)",
5
5
  "main": "src/index.js",
6
6
  "bin": {
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.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
- console.log(chalk.cyan("\n Azure PR Manager - Configuracao"));
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
- console.log(chalk.cyan("\n Azure PR Manager - Criar Pull Request"));
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
- " Descreva o que foi feito neste PR. Pode usar Markdown."
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
- " Deixe vazio e pressione Enter para pular."
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
- const { description } = await inquirer.prompt([
756
+ let description = "";
757
+
758
+ const { descMode } = await inquirer.prompt([
697
759
  {
698
- type: "input",
699
- name: "description",
700
- message: "Descricao do PR (ou Enter para vazio):",
701
- default: "",
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