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/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).