@dami_deleon/rikudo 2.0.1 → 2.0.2

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.
@@ -117,11 +117,18 @@ server.registerTool("shift_left_start", {
117
117
  }),
118
118
  }, async ({ ticketId, branchName, targetBranch, isWip }) => {
119
119
  try {
120
- await git.checkout(targetBranch);
121
- await git.pull("origin", targetBranch);
122
- await git.checkoutLocalBranch(branchName);
123
- await git.commit("chore: init #" + ticketId, ["--allow-empty"]);
124
- await git.push(["-u", "origin", branchName]);
120
+ const branches = await git.branchLocal();
121
+ const branchExists = branches.all.includes(branchName);
122
+ if (branchExists) {
123
+ await git.checkout(branchName);
124
+ }
125
+ else {
126
+ await git.checkout(targetBranch);
127
+ await git.pull("origin", targetBranch);
128
+ await git.checkoutLocalBranch(branchName);
129
+ await git.commit("chore: init #" + ticketId, ["--allow-empty"]);
130
+ await git.push(["-u", "origin", branchName]);
131
+ }
125
132
  const ticket = await getIssueDetails(ticketId);
126
133
  const prTitle = isWip
127
134
  ? `WIP: ${ticket?.subject || `Ticket #${ticketId}`}`
@@ -136,7 +143,7 @@ server.registerTool("shift_left_start", {
136
143
  });
137
144
  if (!prResult.success) {
138
145
  return {
139
- content: [{ type: "text", text: `Rama '${branchName}' creada y empujada a origin. Error al crear PR: ${prResult.error}` }],
146
+ content: [{ type: "text", text: `Rama '${branchName}' lista. Error al crear PR: ${prResult.error}` }],
140
147
  isError: true,
141
148
  };
142
149
  }
@@ -148,9 +155,12 @@ server.registerTool("shift_left_start", {
148
155
  success: true,
149
156
  branch: branchName,
150
157
  targetBranch,
158
+ branchCreated: !branchExists,
151
159
  prUrl: prResult.url,
152
160
  prNumber: prResult.number,
153
- message: `Entorno preparado en rama '${branchName}'. Draft PR creado: ${prResult.url}`,
161
+ message: branchExists
162
+ ? `Rama '${branchName}' verificada. Draft PR creado: ${prResult.url}`
163
+ : `Rama '${branchName}' creada. Draft PR creado: ${prResult.url}`,
154
164
  }, null, 2),
155
165
  },
156
166
  ],
@@ -44,3 +44,18 @@ export async function getProjectId() {
44
44
  }
45
45
  return projectId;
46
46
  }
47
+ export async function getGitRemoteInfo() {
48
+ const remote = await git.remote(["get-url", "origin"]);
49
+ if (!remote) {
50
+ throw new Error("No se pudo obtener el remote de Git");
51
+ }
52
+ const cleanRemote = remote.trim().replace(".git", "");
53
+ const url = new URL(cleanRemote);
54
+ const pathParts = url.pathname.split("/").filter(Boolean);
55
+ if (pathParts.length < 2) {
56
+ throw new Error("Formato de remote no válido. Expected: https://gitea.host/owner/repo.git");
57
+ }
58
+ const owner = pathParts[pathParts.length - 2];
59
+ const repo = pathParts[pathParts.length - 1];
60
+ return { owner, repo };
61
+ }
@@ -1,32 +1,41 @@
1
1
  import axios, { AxiosError } from "axios";
2
- const getGiteaConfig = () => {
3
- return {
4
- url: process.env.RIKUDO_GITEA_URL || "",
5
- token: process.env.RIKUDO_GITEA_TOKEN || "",
6
- owner: process.env.RIKUDO_GITEA_OWNER || "",
7
- repo: process.env.RIKUDO_GITEA_REPO || "",
8
- };
2
+ import { getGitRemoteInfo } from "./git.js";
3
+ const getGiteaConfig = async () => {
4
+ const url = process.env.RIKUDO_GITEA_URL || "";
5
+ const token = process.env.RIKUDO_GITEA_TOKEN || "";
6
+ let owner = process.env.RIKUDO_GITEA_OWNER || "";
7
+ let repo = process.env.RIKUDO_GITEA_REPO || "";
8
+ if (!owner || !repo) {
9
+ try {
10
+ const remoteInfo = await getGitRemoteInfo();
11
+ owner = owner || remoteInfo.owner;
12
+ repo = repo || remoteInfo.repo;
13
+ }
14
+ catch {
15
+ // Remote info not available, will be validated later
16
+ }
17
+ }
18
+ return { url, token, owner, repo };
9
19
  };
10
- const getGiteaClient = () => {
11
- const config = getGiteaConfig();
20
+ const getGiteaClient = (url, token) => {
12
21
  return axios.create({
13
- baseURL: config.url,
22
+ baseURL: url,
14
23
  headers: {
15
- Authorization: `token ${config.token}`,
24
+ Authorization: `token ${token}`,
16
25
  "Content-Type": "application/json",
17
26
  },
18
27
  });
19
28
  };
20
29
  export const createPullRequest = async (payload) => {
21
- const config = getGiteaConfig();
30
+ const config = await getGiteaConfig();
22
31
  if (!config.url || !config.token || !config.owner || !config.repo) {
23
32
  return {
24
33
  success: false,
25
- error: "Faltan variables de entorno de Gitea (RIKUDO_GITEA_URL, RIKUDO_GITEA_TOKEN, RIKUDO_GITEA_OWNER, RIKUDO_GITEA_REPO)",
34
+ error: "Faltan variables de entorno de Gitea (RIKUDO_GITEA_URL, RIKUDO_GITEA_TOKEN, RIKUDO_GITEA_OWNER, RIKUDO_GITEA_REPO) o no se pudo obtener el remote de Git",
26
35
  };
27
36
  }
28
37
  try {
29
- const client = getGiteaClient();
38
+ const client = getGiteaClient(config.url, config.token);
30
39
  const endpoint = `/api/v1/repos/${config.owner}/${config.repo}/pulls`;
31
40
  const response = await client.post(endpoint, {
32
41
  title: payload.title,
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@dami_deleon/rikudo",
3
- "version": "2.0.1",
3
+ "version": "2.0.2",
4
4
  "description": "El Sabio de los Commits: AI Assistant con integración a Redmine",
5
5
  "main": "dist/index.js",
6
6
  "type": "module",