gitlab-skill 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/GITLAB_API_COMPREHENSIVE_GUIDE.md +3885 -0
- package/PRACTICAL_SCRIPTS.md +1351 -0
- package/QUICK_REFERENCE.md +682 -0
- package/README.md +461 -0
- package/SKILL.md +789 -0
- package/SKILL_SETUP.md +50 -0
- package/package.json +42 -0
- package/scripts/install-skill.mjs +119 -0
- package/skill-features/00-auth-and-bootstrap.md +81 -0
- package/skill-features/01-discovery-and-projects.md +73 -0
- package/skill-features/02-repository-and-code.md +101 -0
- package/skill-features/03-issues-and-merge-requests.md +69 -0
- package/skill-features/04-cicd-pipelines-jobs.md +86 -0
- package/skill-features/05-security-and-vulnerabilities.md +125 -0
- package/skill-features/06-graphql-and-glab-playbook.md +68 -0
package/SKILL_SETUP.md
ADDED
|
@@ -0,0 +1,50 @@
|
|
|
1
|
+
# SKILL Setup (Cursor, Claude, OpenClaw)
|
|
2
|
+
|
|
3
|
+
## Estructura recomendada
|
|
4
|
+
|
|
5
|
+
Fuente única en repo:
|
|
6
|
+
|
|
7
|
+
- `SKILL.md` (índice/orquestación)
|
|
8
|
+
- `skill-features/*.md` (módulos por feature)
|
|
9
|
+
- `QUICK_REFERENCE.md`
|
|
10
|
+
- `GITLAB_API_COMPREHENSIVE_GUIDE.md`
|
|
11
|
+
- `PRACTICAL_SCRIPTS.md`
|
|
12
|
+
|
|
13
|
+
Skill activa para Cursor en proyecto:
|
|
14
|
+
|
|
15
|
+
- `.cursor/skills/gitlab-api-operations/SKILL.md`
|
|
16
|
+
|
|
17
|
+
## Instalación por script (Node)
|
|
18
|
+
|
|
19
|
+
```bash
|
|
20
|
+
npm run install:cursor:project
|
|
21
|
+
npm run install:cursor:user
|
|
22
|
+
npm run install:claude:user
|
|
23
|
+
npm run install:openclaw:user
|
|
24
|
+
```
|
|
25
|
+
|
|
26
|
+
Salida personalizada:
|
|
27
|
+
|
|
28
|
+
```bash
|
|
29
|
+
npm run install:custom
|
|
30
|
+
# instala en dist/skill-custom
|
|
31
|
+
```
|
|
32
|
+
|
|
33
|
+
## Targets por defecto
|
|
34
|
+
|
|
35
|
+
- Cursor (project): `.cursor/skills/gitlab-api-operations`
|
|
36
|
+
- Cursor (user): `~/.cursor/skills/gitlab-api-operations`
|
|
37
|
+
- Claude (user): `~/.claude/skills/gitlab-api-operations`
|
|
38
|
+
- OpenClaw (user): `~/.openclaw/skills/gitlab-api-operations`
|
|
39
|
+
|
|
40
|
+
## Uso recomendado en agentes
|
|
41
|
+
|
|
42
|
+
1. Cargar `SKILL.md`.
|
|
43
|
+
2. Cargar módulo de feature requerido (`skill-features/...`).
|
|
44
|
+
3. Si se necesita detalle, consultar `QUICK_REFERENCE.md` o `GITLAB_API_COMPREHENSIVE_GUIDE.md`.
|
|
45
|
+
4. Ejecutar flujos reproducibles desde `PRACTICAL_SCRIPTS.md`.
|
|
46
|
+
|
|
47
|
+
## Notas
|
|
48
|
+
|
|
49
|
+
- Si existe `openapi_v2.yaml`, usarlo como referencia local de precisión para REST.
|
|
50
|
+
- Si no existe en destino, la skill funciona igual con los módulos y guías embebidas.
|
package/package.json
ADDED
|
@@ -0,0 +1,42 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "gitlab-skill",
|
|
3
|
+
"version": "1.0.0",
|
|
4
|
+
"description": "Skill pack para operar GitLab por REST, GraphQL y CLI en Agentes de IA como Cursor/Claude/OpenClaw.",
|
|
5
|
+
"license": "MIT",
|
|
6
|
+
"type": "module",
|
|
7
|
+
"bin": {
|
|
8
|
+
"gitlab-skill-install": "scripts/install-skill.mjs"
|
|
9
|
+
},
|
|
10
|
+
"files": [
|
|
11
|
+
"SKILL.md",
|
|
12
|
+
"SKILL_SETUP.md",
|
|
13
|
+
"README.md",
|
|
14
|
+
"QUICK_REFERENCE.md",
|
|
15
|
+
"GITLAB_API_COMPREHENSIVE_GUIDE.md",
|
|
16
|
+
"PRACTICAL_SCRIPTS.md",
|
|
17
|
+
"skill-features",
|
|
18
|
+
"scripts/install-skill.mjs"
|
|
19
|
+
],
|
|
20
|
+
"keywords": [
|
|
21
|
+
"gitlab",
|
|
22
|
+
"skill",
|
|
23
|
+
"cursor",
|
|
24
|
+
"claude",
|
|
25
|
+
"openclaw",
|
|
26
|
+
"rest-api",
|
|
27
|
+
"graphql",
|
|
28
|
+
"glab"
|
|
29
|
+
],
|
|
30
|
+
"engines": {
|
|
31
|
+
"node": ">=18"
|
|
32
|
+
},
|
|
33
|
+
"scripts": {
|
|
34
|
+
"install:cursor:project": "node scripts/install-skill.mjs --agent cursor --scope project",
|
|
35
|
+
"install:cursor:user": "node scripts/install-skill.mjs --agent cursor --scope user",
|
|
36
|
+
"install:claude:user": "node scripts/install-skill.mjs --agent claude --scope user",
|
|
37
|
+
"install:openclaw:user": "node scripts/install-skill.mjs --agent openclaw --scope user",
|
|
38
|
+
"install:custom": "node scripts/install-skill.mjs --target-dir dist/skill-custom",
|
|
39
|
+
"pack:dry-run": "npm pack --dry-run",
|
|
40
|
+
"publish:public": "npm publish --access public"
|
|
41
|
+
}
|
|
42
|
+
}
|
|
@@ -0,0 +1,119 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
|
|
3
|
+
import fs from "node:fs";
|
|
4
|
+
import path from "node:path";
|
|
5
|
+
import os from "node:os";
|
|
6
|
+
|
|
7
|
+
const SKILL_NAME = "gitlab-api-operations";
|
|
8
|
+
const ROOT = process.cwd();
|
|
9
|
+
|
|
10
|
+
const FILES_TO_COPY = [
|
|
11
|
+
"SKILL.md",
|
|
12
|
+
"README.md",
|
|
13
|
+
"QUICK_REFERENCE.md",
|
|
14
|
+
"GITLAB_API_COMPREHENSIVE_GUIDE.md",
|
|
15
|
+
"PRACTICAL_SCRIPTS.md"
|
|
16
|
+
];
|
|
17
|
+
|
|
18
|
+
const DIRS_TO_COPY = [
|
|
19
|
+
"skill-features"
|
|
20
|
+
];
|
|
21
|
+
|
|
22
|
+
function parseArgs(argv) {
|
|
23
|
+
const out = {};
|
|
24
|
+
for (let i = 0; i < argv.length; i += 1) {
|
|
25
|
+
const a = argv[i];
|
|
26
|
+
if (a === "--agent") out.agent = argv[i + 1];
|
|
27
|
+
if (a === "--scope") out.scope = argv[i + 1];
|
|
28
|
+
if (a === "--target-dir") out.targetDir = argv[i + 1];
|
|
29
|
+
}
|
|
30
|
+
return out;
|
|
31
|
+
}
|
|
32
|
+
|
|
33
|
+
function resolveTarget({ agent, scope, targetDir }) {
|
|
34
|
+
if (targetDir) return path.resolve(ROOT, targetDir);
|
|
35
|
+
|
|
36
|
+
const home = os.homedir();
|
|
37
|
+
const sc = scope || "user";
|
|
38
|
+
|
|
39
|
+
if (agent === "cursor") {
|
|
40
|
+
if (sc === "project") return path.join(ROOT, ".cursor", "skills", SKILL_NAME);
|
|
41
|
+
return path.join(home, ".cursor", "skills", SKILL_NAME);
|
|
42
|
+
}
|
|
43
|
+
|
|
44
|
+
if (agent === "claude") {
|
|
45
|
+
return path.join(home, ".claude", "skills", SKILL_NAME);
|
|
46
|
+
}
|
|
47
|
+
|
|
48
|
+
if (agent === "openclaw") {
|
|
49
|
+
return path.join(home, ".openclaw", "skills", SKILL_NAME);
|
|
50
|
+
}
|
|
51
|
+
|
|
52
|
+
throw new Error("Agente no soportado. Usa --agent cursor|claude|openclaw o --target-dir.");
|
|
53
|
+
}
|
|
54
|
+
|
|
55
|
+
function ensureDir(dir) {
|
|
56
|
+
fs.mkdirSync(dir, { recursive: true });
|
|
57
|
+
}
|
|
58
|
+
|
|
59
|
+
function copyFile(srcRel, destRoot) {
|
|
60
|
+
const src = path.join(ROOT, srcRel);
|
|
61
|
+
const dest = path.join(destRoot, srcRel);
|
|
62
|
+
|
|
63
|
+
if (!fs.existsSync(src)) {
|
|
64
|
+
throw new Error(`No existe archivo requerido: ${srcRel}`);
|
|
65
|
+
}
|
|
66
|
+
ensureDir(path.dirname(dest));
|
|
67
|
+
fs.copyFileSync(src, dest);
|
|
68
|
+
}
|
|
69
|
+
|
|
70
|
+
function copyDir(srcRel, destRoot) {
|
|
71
|
+
const src = path.join(ROOT, srcRel);
|
|
72
|
+
const dest = path.join(destRoot, srcRel);
|
|
73
|
+
|
|
74
|
+
if (!fs.existsSync(src)) {
|
|
75
|
+
throw new Error(`No existe directorio requerido: ${srcRel}`);
|
|
76
|
+
}
|
|
77
|
+
fs.cpSync(src, dest, { recursive: true });
|
|
78
|
+
}
|
|
79
|
+
|
|
80
|
+
function writeManifest(destRoot, meta) {
|
|
81
|
+
const manifest = {
|
|
82
|
+
name: SKILL_NAME,
|
|
83
|
+
installedAt: new Date().toISOString(),
|
|
84
|
+
sourceRoot: ROOT,
|
|
85
|
+
...meta,
|
|
86
|
+
files: FILES_TO_COPY,
|
|
87
|
+
dirs: DIRS_TO_COPY
|
|
88
|
+
};
|
|
89
|
+
fs.writeFileSync(
|
|
90
|
+
path.join(destRoot, "skill-install-manifest.json"),
|
|
91
|
+
JSON.stringify(manifest, null, 2),
|
|
92
|
+
"utf8"
|
|
93
|
+
);
|
|
94
|
+
}
|
|
95
|
+
|
|
96
|
+
function main() {
|
|
97
|
+
const args = parseArgs(process.argv.slice(2));
|
|
98
|
+
const target = resolveTarget(args);
|
|
99
|
+
|
|
100
|
+
ensureDir(target);
|
|
101
|
+
|
|
102
|
+
for (const f of FILES_TO_COPY) {
|
|
103
|
+
copyFile(f, target);
|
|
104
|
+
}
|
|
105
|
+
for (const d of DIRS_TO_COPY) {
|
|
106
|
+
copyDir(d, target);
|
|
107
|
+
}
|
|
108
|
+
|
|
109
|
+
writeManifest(target, {
|
|
110
|
+
agent: args.agent || "custom",
|
|
111
|
+
scope: args.scope || "n/a",
|
|
112
|
+
target
|
|
113
|
+
});
|
|
114
|
+
|
|
115
|
+
console.log(`[ok] Skill instalada en: ${target}`);
|
|
116
|
+
console.log("[ok] Archivos copiados: SKILL + features + referencias extendidas");
|
|
117
|
+
}
|
|
118
|
+
|
|
119
|
+
main();
|
|
@@ -0,0 +1,81 @@
|
|
|
1
|
+
# Auth and Bootstrap
|
|
2
|
+
|
|
3
|
+
## Objetivo
|
|
4
|
+
|
|
5
|
+
Establecer un contexto reproducible para operar GitLab por REST, GraphQL y CLI sin interfaz web.
|
|
6
|
+
|
|
7
|
+
## Variables runtime
|
|
8
|
+
|
|
9
|
+
```bash
|
|
10
|
+
export GITLAB_HOST="https://gitlab.com"
|
|
11
|
+
export GITLAB_TOKEN="<personal_access_token>"
|
|
12
|
+
export GITLAB_USER="<username>"
|
|
13
|
+
export TARGET_PROJECT_PATH="group/project"
|
|
14
|
+
export TARGET_GROUP_PATH="group"
|
|
15
|
+
```
|
|
16
|
+
|
|
17
|
+
## URL encoding de rutas namespaced
|
|
18
|
+
|
|
19
|
+
```bash
|
|
20
|
+
export PROJECT_ENC="$(python - <<'PY'
|
|
21
|
+
import os, urllib.parse
|
|
22
|
+
print(urllib.parse.quote(os.environ['TARGET_PROJECT_PATH'], safe=''))
|
|
23
|
+
PY
|
|
24
|
+
)"
|
|
25
|
+
export GROUP_ENC="$(python - <<'PY'
|
|
26
|
+
import os, urllib.parse
|
|
27
|
+
print(urllib.parse.quote(os.environ['TARGET_GROUP_PATH'], safe=''))
|
|
28
|
+
PY
|
|
29
|
+
)"
|
|
30
|
+
```
|
|
31
|
+
|
|
32
|
+
## REST auth
|
|
33
|
+
|
|
34
|
+
```bash
|
|
35
|
+
curl --request GET \
|
|
36
|
+
--header "PRIVATE-TOKEN: $GITLAB_TOKEN" \
|
|
37
|
+
--url "$GITLAB_HOST/api/v4/metadata"
|
|
38
|
+
```
|
|
39
|
+
|
|
40
|
+
## GraphQL auth
|
|
41
|
+
|
|
42
|
+
```bash
|
|
43
|
+
curl --request POST \
|
|
44
|
+
--url "$GITLAB_HOST/api/graphql" \
|
|
45
|
+
--header "Authorization: Bearer $GITLAB_TOKEN" \
|
|
46
|
+
--header "Content-Type: application/json" \
|
|
47
|
+
--data '{"query":"query { currentUser { id username name } }"}'
|
|
48
|
+
```
|
|
49
|
+
|
|
50
|
+
## glab auth
|
|
51
|
+
|
|
52
|
+
```bash
|
|
53
|
+
export GL_HOST="$GITLAB_HOST"
|
|
54
|
+
export NO_PROMPT=true
|
|
55
|
+
export GITLAB_TOKEN="$GITLAB_TOKEN"
|
|
56
|
+
glab auth status || glab auth login
|
|
57
|
+
```
|
|
58
|
+
|
|
59
|
+
## Health checks minimos
|
|
60
|
+
|
|
61
|
+
```bash
|
|
62
|
+
# API metadata
|
|
63
|
+
curl --request GET --header "PRIVATE-TOKEN: $GITLAB_TOKEN" \
|
|
64
|
+
--url "$GITLAB_HOST/api/v4/metadata"
|
|
65
|
+
|
|
66
|
+
# Usuario autenticado (GraphQL)
|
|
67
|
+
curl --request POST --url "$GITLAB_HOST/api/graphql" \
|
|
68
|
+
--header "Authorization: Bearer $GITLAB_TOKEN" \
|
|
69
|
+
--header "Content-Type: application/json" \
|
|
70
|
+
--data '{"query":"query { currentUser { username } }"}'
|
|
71
|
+
|
|
72
|
+
# CLI
|
|
73
|
+
glab api "/user"
|
|
74
|
+
```
|
|
75
|
+
|
|
76
|
+
## Errores comunes
|
|
77
|
+
|
|
78
|
+
- `401 Unauthorized`: token inválido, expirado o sin scope.
|
|
79
|
+
- `403 Forbidden`: token válido pero sin permisos sobre recurso.
|
|
80
|
+
- `404 Not Found`: path no encoded o recurso fuera de alcance.
|
|
81
|
+
- `429 Too Many Requests`: aplicar backoff y reducir paralelismo.
|
|
@@ -0,0 +1,73 @@
|
|
|
1
|
+
# Discovery and Projects
|
|
2
|
+
|
|
3
|
+
## Objetivo
|
|
4
|
+
|
|
5
|
+
Descubrir alcance (grupos/proyectos accesibles), resolver IDs y leer metadatos para alimentar flujos automáticos.
|
|
6
|
+
|
|
7
|
+
## Endpoints base (REST)
|
|
8
|
+
|
|
9
|
+
- `GET /api/v4/projects`
|
|
10
|
+
- `GET /api/v4/projects/{id}`
|
|
11
|
+
- `GET /api/v4/groups/{id}/projects`
|
|
12
|
+
- `GET /api/v4/groups/{id}/subgroups`
|
|
13
|
+
- `GET /api/v4/groups/{id}/descendant_groups`
|
|
14
|
+
- `GET /api/v4/issues`
|
|
15
|
+
- `GET /api/v4/merge_requests`
|
|
16
|
+
|
|
17
|
+
## Ejemplos operativos
|
|
18
|
+
|
|
19
|
+
### Listar proyectos visibles
|
|
20
|
+
|
|
21
|
+
```bash
|
|
22
|
+
curl --request GET --header "PRIVATE-TOKEN: $GITLAB_TOKEN" \
|
|
23
|
+
--url "$GITLAB_HOST/api/v4/projects?membership=true&order_by=last_activity_at&sort=desc&per_page=100"
|
|
24
|
+
```
|
|
25
|
+
|
|
26
|
+
### Obtener proyecto por path o ID
|
|
27
|
+
|
|
28
|
+
```bash
|
|
29
|
+
curl --request GET --header "PRIVATE-TOKEN: $GITLAB_TOKEN" \
|
|
30
|
+
--url "$GITLAB_HOST/api/v4/projects/$PROJECT_ENC?statistics=true&license=true"
|
|
31
|
+
```
|
|
32
|
+
|
|
33
|
+
### Proyectos de grupo (incluyendo subgrupos)
|
|
34
|
+
|
|
35
|
+
```bash
|
|
36
|
+
curl --request GET --header "PRIVATE-TOKEN: $GITLAB_TOKEN" \
|
|
37
|
+
--url "$GITLAB_HOST/api/v4/groups/$GROUP_ENC/projects?include_subgroups=true&with_security_reports=true&per_page=100"
|
|
38
|
+
```
|
|
39
|
+
|
|
40
|
+
### Jerarquía de grupos
|
|
41
|
+
|
|
42
|
+
```bash
|
|
43
|
+
curl --request GET --header "PRIVATE-TOKEN: $GITLAB_TOKEN" \
|
|
44
|
+
--url "$GITLAB_HOST/api/v4/groups/$GROUP_ENC/subgroups?per_page=100"
|
|
45
|
+
curl --request GET --header "PRIVATE-TOKEN: $GITLAB_TOKEN" \
|
|
46
|
+
--url "$GITLAB_HOST/api/v4/groups/$GROUP_ENC/descendant_groups?per_page=100"
|
|
47
|
+
```
|
|
48
|
+
|
|
49
|
+
### Issues y MRs globales accesibles (usuario autenticado)
|
|
50
|
+
|
|
51
|
+
```bash
|
|
52
|
+
curl --request GET --header "PRIVATE-TOKEN: $GITLAB_TOKEN" \
|
|
53
|
+
--url "$GITLAB_HOST/api/v4/issues?scope=all&state=opened&per_page=100"
|
|
54
|
+
curl --request GET --header "PRIVATE-TOKEN: $GITLAB_TOKEN" \
|
|
55
|
+
--url "$GITLAB_HOST/api/v4/merge_requests?scope=all&state=opened&per_page=100"
|
|
56
|
+
```
|
|
57
|
+
|
|
58
|
+
## Bootstrap para agentes (paso a paso)
|
|
59
|
+
|
|
60
|
+
1. Resolver `GROUP_ENC` y/o `PROJECT_ENC`.
|
|
61
|
+
2. Consultar proyecto `GET /projects/{id}`.
|
|
62
|
+
3. Validar features activas (`issues_enabled`, `merge_requests_enabled`, `jobs_enabled`).
|
|
63
|
+
4. Calcular alcance:
|
|
64
|
+
- proyecto único
|
|
65
|
+
- grupo completo
|
|
66
|
+
- grupo + descendientes
|
|
67
|
+
5. Persistir mapa `{project_id, path_with_namespace, web_url, default_branch}`.
|
|
68
|
+
|
|
69
|
+
## Buenas prácticas
|
|
70
|
+
|
|
71
|
+
- Siempre usar `per_page` explícito.
|
|
72
|
+
- Para conjuntos grandes, seguir header `Link` y paginar.
|
|
73
|
+
- En errores, devolver request URL final sin token.
|
|
@@ -0,0 +1,101 @@
|
|
|
1
|
+
# Repository and Code
|
|
2
|
+
|
|
3
|
+
## Objetivo
|
|
4
|
+
|
|
5
|
+
Inspeccionar y manipular contenido de repositorio: ramas, commits, archivos y comparaciones.
|
|
6
|
+
|
|
7
|
+
## Endpoints clave
|
|
8
|
+
|
|
9
|
+
- `GET /api/v4/projects/{id}/repository/tree`
|
|
10
|
+
- `GET /api/v4/projects/{id}/repository/branches`
|
|
11
|
+
- `GET /api/v4/projects/{id}/repository/branches/{branch}`
|
|
12
|
+
- `POST /api/v4/projects/{id}/repository/branches/{branch}/protect`
|
|
13
|
+
- `POST /api/v4/projects/{id}/repository/branches/{branch}/unprotect`
|
|
14
|
+
- `GET /api/v4/projects/{id}/repository/commits`
|
|
15
|
+
- `GET /api/v4/projects/{id}/repository/commits/{sha}`
|
|
16
|
+
- `GET /api/v4/projects/{id}/repository/commits/{sha}/diff`
|
|
17
|
+
- `GET /api/v4/projects/{id}/repository/compare`
|
|
18
|
+
- `GET|HEAD|POST|PUT|DELETE /api/v4/projects/{id}/repository/files/{file_path}`
|
|
19
|
+
- `GET /api/v4/projects/{id}/repository/files/{file_path}/raw`
|
|
20
|
+
|
|
21
|
+
## Ejemplos
|
|
22
|
+
|
|
23
|
+
### Tree recursivo
|
|
24
|
+
|
|
25
|
+
```bash
|
|
26
|
+
curl --request GET --header "PRIVATE-TOKEN: $GITLAB_TOKEN" \
|
|
27
|
+
--url "$GITLAB_HOST/api/v4/projects/$PROJECT_ENC/repository/tree?ref=main&recursive=true&pagination=keyset&per_page=100"
|
|
28
|
+
```
|
|
29
|
+
|
|
30
|
+
### Branches
|
|
31
|
+
|
|
32
|
+
```bash
|
|
33
|
+
curl --request GET --header "PRIVATE-TOKEN: $GITLAB_TOKEN" \
|
|
34
|
+
--url "$GITLAB_HOST/api/v4/projects/$PROJECT_ENC/repository/branches?search=release&per_page=100"
|
|
35
|
+
|
|
36
|
+
curl --request GET --header "PRIVATE-TOKEN: $GITLAB_TOKEN" \
|
|
37
|
+
--url "$GITLAB_HOST/api/v4/projects/$PROJECT_ENC/repository/branches/main"
|
|
38
|
+
```
|
|
39
|
+
|
|
40
|
+
### Commits y diff
|
|
41
|
+
|
|
42
|
+
```bash
|
|
43
|
+
curl --request GET --header "PRIVATE-TOKEN: $GITLAB_TOKEN" \
|
|
44
|
+
--url "$GITLAB_HOST/api/v4/projects/$PROJECT_ENC/repository/commits?ref_name=main&per_page=100"
|
|
45
|
+
|
|
46
|
+
curl --request GET --header "PRIVATE-TOKEN: $GITLAB_TOKEN" \
|
|
47
|
+
--url "$GITLAB_HOST/api/v4/projects/$PROJECT_ENC/repository/commits/<sha>/diff"
|
|
48
|
+
```
|
|
49
|
+
|
|
50
|
+
### Compare
|
|
51
|
+
|
|
52
|
+
```bash
|
|
53
|
+
curl --request GET --header "PRIVATE-TOKEN: $GITLAB_TOKEN" \
|
|
54
|
+
--url "$GITLAB_HOST/api/v4/projects/$PROJECT_ENC/repository/compare?from=main&to=feature-hardening&straight=false"
|
|
55
|
+
```
|
|
56
|
+
|
|
57
|
+
### Files API
|
|
58
|
+
|
|
59
|
+
```bash
|
|
60
|
+
export FILE_ENC="src%2Fmain.ts"
|
|
61
|
+
|
|
62
|
+
# HEAD metadata
|
|
63
|
+
curl --head --header "PRIVATE-TOKEN: $GITLAB_TOKEN" \
|
|
64
|
+
"$GITLAB_HOST/api/v4/projects/$PROJECT_ENC/repository/files/$FILE_ENC?ref=main"
|
|
65
|
+
|
|
66
|
+
# GET file object
|
|
67
|
+
curl --request GET --header "PRIVATE-TOKEN: $GITLAB_TOKEN" \
|
|
68
|
+
--url "$GITLAB_HOST/api/v4/projects/$PROJECT_ENC/repository/files/$FILE_ENC?ref=main"
|
|
69
|
+
|
|
70
|
+
# GET raw
|
|
71
|
+
curl --request GET --header "PRIVATE-TOKEN: $GITLAB_TOKEN" \
|
|
72
|
+
--url "$GITLAB_HOST/api/v4/projects/$PROJECT_ENC/repository/files/$FILE_ENC/raw?ref=main"
|
|
73
|
+
```
|
|
74
|
+
|
|
75
|
+
### Crear/actualizar/eliminar archivo
|
|
76
|
+
|
|
77
|
+
```bash
|
|
78
|
+
# create
|
|
79
|
+
curl --request POST --header "PRIVATE-TOKEN: $GITLAB_TOKEN" \
|
|
80
|
+
--header "Content-Type: application/json" \
|
|
81
|
+
--data '{"branch":"main","commit_message":"create security note","content":"hardening checklist","encoding":"text"}' \
|
|
82
|
+
"$GITLAB_HOST/api/v4/projects/$PROJECT_ENC/repository/files/docs%2Fsecurity-checklist.md"
|
|
83
|
+
|
|
84
|
+
# update
|
|
85
|
+
curl --request PUT --header "PRIVATE-TOKEN: $GITLAB_TOKEN" \
|
|
86
|
+
--header "Content-Type: application/json" \
|
|
87
|
+
--data '{"branch":"main","commit_message":"update security note","content":"updated checklist","encoding":"text"}' \
|
|
88
|
+
"$GITLAB_HOST/api/v4/projects/$PROJECT_ENC/repository/files/docs%2Fsecurity-checklist.md"
|
|
89
|
+
|
|
90
|
+
# delete
|
|
91
|
+
curl --request DELETE --header "PRIVATE-TOKEN: $GITLAB_TOKEN" \
|
|
92
|
+
--url "$GITLAB_HOST/api/v4/projects/$PROJECT_ENC/repository/files/docs%2Fsecurity-checklist.md?branch=main&commit_message=remove%20note"
|
|
93
|
+
```
|
|
94
|
+
|
|
95
|
+
## Uso autónomo sugerido
|
|
96
|
+
|
|
97
|
+
Para "revisar cambios sensibles":
|
|
98
|
+
1. Obtener commits recientes.
|
|
99
|
+
2. Traer diffs por commit.
|
|
100
|
+
3. Filtrar paths críticos (`auth`, `payments`, `config`, `ci`).
|
|
101
|
+
4. Reportar riesgos y archivos impactados.
|
|
@@ -0,0 +1,69 @@
|
|
|
1
|
+
# Issues and Merge Requests
|
|
2
|
+
|
|
3
|
+
## Objetivo
|
|
4
|
+
|
|
5
|
+
Gestionar trabajo y code review por API: listar, crear y filtrar Issues y MRs a nivel global, grupo y proyecto.
|
|
6
|
+
|
|
7
|
+
## Endpoints clave
|
|
8
|
+
|
|
9
|
+
- Issues:
|
|
10
|
+
- `GET /api/v4/issues`
|
|
11
|
+
- `GET /api/v4/projects/{id}/issues`
|
|
12
|
+
- `POST /api/v4/projects/{id}/issues`
|
|
13
|
+
- `GET /api/v4/groups/{id}/issues`
|
|
14
|
+
- Merge requests:
|
|
15
|
+
- `GET /api/v4/merge_requests`
|
|
16
|
+
- `GET /api/v4/projects/{id}/merge_requests`
|
|
17
|
+
- `POST /api/v4/projects/{id}/merge_requests`
|
|
18
|
+
- `GET /api/v4/groups/{id}/merge_requests`
|
|
19
|
+
|
|
20
|
+
## Issues: ejemplos
|
|
21
|
+
|
|
22
|
+
```bash
|
|
23
|
+
# Issues globales
|
|
24
|
+
curl --request GET --header "PRIVATE-TOKEN: $GITLAB_TOKEN" \
|
|
25
|
+
--url "$GITLAB_HOST/api/v4/issues?scope=all&state=opened&order_by=updated_at&sort=desc&per_page=100"
|
|
26
|
+
|
|
27
|
+
# Issues de proyecto filtrados
|
|
28
|
+
curl --request GET --header "PRIVATE-TOKEN: $GITLAB_TOKEN" \
|
|
29
|
+
--url "$GITLAB_HOST/api/v4/projects/$PROJECT_ENC/issues?state=opened&labels=bug,security&issue_type=issue&per_page=100"
|
|
30
|
+
|
|
31
|
+
# Crear issue
|
|
32
|
+
curl --request POST --header "PRIVATE-TOKEN: $GITLAB_TOKEN" \
|
|
33
|
+
--header "Content-Type: application/json" \
|
|
34
|
+
--data '{"title":"Corregir validación JWT","description":"Se detecta bypass en middleware","labels":["security","backend"],"issue_type":"issue","confidential":true}' \
|
|
35
|
+
"$GITLAB_HOST/api/v4/projects/$PROJECT_ENC/issues"
|
|
36
|
+
```
|
|
37
|
+
|
|
38
|
+
## Merge requests: ejemplos
|
|
39
|
+
|
|
40
|
+
```bash
|
|
41
|
+
# MRs globales
|
|
42
|
+
curl --request GET --header "PRIVATE-TOKEN: $GITLAB_TOKEN" \
|
|
43
|
+
--url "$GITLAB_HOST/api/v4/merge_requests?scope=all&state=opened&per_page=100"
|
|
44
|
+
|
|
45
|
+
# MRs de proyecto
|
|
46
|
+
curl --request GET --header "PRIVATE-TOKEN: $GITLAB_TOKEN" \
|
|
47
|
+
--url "$GITLAB_HOST/api/v4/projects/$PROJECT_ENC/merge_requests?state=opened&scope=all&order_by=updated_at&sort=desc&per_page=100"
|
|
48
|
+
|
|
49
|
+
# Crear MR
|
|
50
|
+
curl --request POST --header "PRIVATE-TOKEN: $GITLAB_TOKEN" \
|
|
51
|
+
--header "Content-Type: application/json" \
|
|
52
|
+
--data '{"title":"fix: harden auth middleware","source_branch":"fix/auth-hardening","target_branch":"main","remove_source_branch":true,"squash":true,"labels":["security","hotfix"]}' \
|
|
53
|
+
"$GITLAB_HOST/api/v4/projects/$PROJECT_ENC/merge_requests"
|
|
54
|
+
```
|
|
55
|
+
|
|
56
|
+
## Filtros útiles para agentes
|
|
57
|
+
|
|
58
|
+
- Issues:
|
|
59
|
+
- `state`, `labels`, `issue_type`, `author_id`, `assignee_id`, `created_after`, `updated_after`, `search`
|
|
60
|
+
- MRs:
|
|
61
|
+
- `state`, `scope`, `author_id`, `reviewer_id`, `source_branch`, `target_branch`, `labels`, `wip`, `search`
|
|
62
|
+
|
|
63
|
+
## Flujo autónomo recomendado
|
|
64
|
+
|
|
65
|
+
Para "priorizar backlog de seguridad":
|
|
66
|
+
1. Listar issues con label `security`.
|
|
67
|
+
2. Ordenar por `updated_at` desc.
|
|
68
|
+
3. Cruzar con MRs abiertos relacionados (`search` por IID/clave).
|
|
69
|
+
4. Proponer plan de cierre (issue -> MR -> pipeline).
|
|
@@ -0,0 +1,86 @@
|
|
|
1
|
+
# CI/CD Pipelines and Jobs
|
|
2
|
+
|
|
3
|
+
## Objetivo
|
|
4
|
+
|
|
5
|
+
Automatizar observabilidad y control de ejecución CI: pipelines, jobs, retries, cancelaciones, traces y variables.
|
|
6
|
+
|
|
7
|
+
## Endpoints clave
|
|
8
|
+
|
|
9
|
+
- `GET /api/v4/projects/{id}/pipelines`
|
|
10
|
+
- `POST /api/v4/projects/{id}/pipeline`
|
|
11
|
+
- `GET /api/v4/projects/{id}/pipelines/{pipeline_id}`
|
|
12
|
+
- `GET /api/v4/projects/{id}/pipelines/{pipeline_id}/jobs`
|
|
13
|
+
- `GET /api/v4/projects/{id}/pipelines/{pipeline_id}/variables`
|
|
14
|
+
- `POST /api/v4/projects/{id}/pipelines/{pipeline_id}/retry`
|
|
15
|
+
- `POST /api/v4/projects/{id}/pipelines/{pipeline_id}/cancel`
|
|
16
|
+
- `GET /api/v4/projects/{id}/jobs`
|
|
17
|
+
- `GET /api/v4/projects/{id}/jobs/{job_id}`
|
|
18
|
+
- `GET /api/v4/projects/{id}/jobs/{job_id}/trace`
|
|
19
|
+
- `POST /api/v4/projects/{id}/jobs/{job_id}/retry`
|
|
20
|
+
- `POST /api/v4/projects/{id}/jobs/{job_id}/cancel`
|
|
21
|
+
- `GET|POST /api/v4/projects/{id}/variables`
|
|
22
|
+
|
|
23
|
+
## Ejemplos de consumo
|
|
24
|
+
|
|
25
|
+
```bash
|
|
26
|
+
# Pipelines fallidos recientes
|
|
27
|
+
curl --request GET --header "PRIVATE-TOKEN: $GITLAB_TOKEN" \
|
|
28
|
+
--url "$GITLAB_HOST/api/v4/projects/$PROJECT_ENC/pipelines?status=failed&order_by=updated_at&sort=desc&per_page=100"
|
|
29
|
+
|
|
30
|
+
# Crear pipeline con variables
|
|
31
|
+
curl --request POST --header "PRIVATE-TOKEN: $GITLAB_TOKEN" \
|
|
32
|
+
--header "Content-Type: application/json" \
|
|
33
|
+
--data '{"ref":"main","variables":[{"key":"SECURITY_SCAN","value":"true","variable_type":"env_var"}]}' \
|
|
34
|
+
"$GITLAB_HOST/api/v4/projects/$PROJECT_ENC/pipeline"
|
|
35
|
+
|
|
36
|
+
# Jobs de pipeline
|
|
37
|
+
curl --request GET --header "PRIVATE-TOKEN: $GITLAB_TOKEN" \
|
|
38
|
+
--url "$GITLAB_HOST/api/v4/projects/$PROJECT_ENC/pipelines/<pipeline_id>/jobs?per_page=100"
|
|
39
|
+
|
|
40
|
+
# Jobs por scope
|
|
41
|
+
curl --request GET --header "PRIVATE-TOKEN: $GITLAB_TOKEN" \
|
|
42
|
+
--url "$GITLAB_HOST/api/v4/projects/$PROJECT_ENC/jobs?scope[]=failed&scope[]=running&per_page=100"
|
|
43
|
+
|
|
44
|
+
# Trace de job
|
|
45
|
+
curl --request GET --header "PRIVATE-TOKEN: $GITLAB_TOKEN" \
|
|
46
|
+
--url "$GITLAB_HOST/api/v4/projects/$PROJECT_ENC/jobs/<job_id>/trace"
|
|
47
|
+
```
|
|
48
|
+
|
|
49
|
+
## Control de ejecución
|
|
50
|
+
|
|
51
|
+
```bash
|
|
52
|
+
# Retry/cancel pipeline
|
|
53
|
+
curl --request POST --header "PRIVATE-TOKEN: $GITLAB_TOKEN" \
|
|
54
|
+
--url "$GITLAB_HOST/api/v4/projects/$PROJECT_ENC/pipelines/<pipeline_id>/retry"
|
|
55
|
+
curl --request POST --header "PRIVATE-TOKEN: $GITLAB_TOKEN" \
|
|
56
|
+
--url "$GITLAB_HOST/api/v4/projects/$PROJECT_ENC/pipelines/<pipeline_id>/cancel"
|
|
57
|
+
|
|
58
|
+
# Retry/cancel job
|
|
59
|
+
curl --request POST --header "PRIVATE-TOKEN: $GITLAB_TOKEN" \
|
|
60
|
+
--url "$GITLAB_HOST/api/v4/projects/$PROJECT_ENC/jobs/<job_id>/retry"
|
|
61
|
+
curl --request POST --header "PRIVATE-TOKEN: $GITLAB_TOKEN" \
|
|
62
|
+
--url "$GITLAB_HOST/api/v4/projects/$PROJECT_ENC/jobs/<job_id>/cancel"
|
|
63
|
+
```
|
|
64
|
+
|
|
65
|
+
## Variables de proyecto
|
|
66
|
+
|
|
67
|
+
```bash
|
|
68
|
+
# Listar
|
|
69
|
+
curl --request GET --header "PRIVATE-TOKEN: $GITLAB_TOKEN" \
|
|
70
|
+
--url "$GITLAB_HOST/api/v4/projects/$PROJECT_ENC/variables"
|
|
71
|
+
|
|
72
|
+
# Crear
|
|
73
|
+
curl --request POST --header "PRIVATE-TOKEN: $GITLAB_TOKEN" \
|
|
74
|
+
--header "Content-Type: application/json" \
|
|
75
|
+
--data '{"key":"DAST_MODE","value":"active","protected":false,"masked":false}' \
|
|
76
|
+
"$GITLAB_HOST/api/v4/projects/$PROJECT_ENC/variables"
|
|
77
|
+
```
|
|
78
|
+
|
|
79
|
+
## Flujo autónomo recomendado
|
|
80
|
+
|
|
81
|
+
Para "diagnosticar fallos de pipeline":
|
|
82
|
+
1. Listar pipelines `status=failed`.
|
|
83
|
+
2. Tomar último `pipeline_id`.
|
|
84
|
+
3. Listar jobs del pipeline y filtrar `status=failed`.
|
|
85
|
+
4. Descargar `trace` del job fallido.
|
|
86
|
+
5. Clasificar causa (test, build, auth, timeout, dependency).
|