GitLab教程(17): API使用与自动化

GitLab提供了强大的REST API和GraphQL API,可以实现各种自动化操作。本文将介绍GitLab API的使用方法。

API认证

# 创建个人访问令牌
# User Settings > Access Tokens > Add new token

# 选择权限范围
# api: 完整API访问
# read_api: 只读API访问
# read_user: 读取用户信息
# read_repository: 读取仓库
# write_repository: 写入仓库
# read_registry: 读取容器镜像
# write_registry: 写入容器镜像
# sudo: 以其他用户身份执行

# 令牌格式
glpat-xxxxxxxxxxxxxxxxxxxx

# 认证方式1: Header
curl --header "PRIVATE-TOKEN: glpat-xxxxxxxxxxxxxxxxxxxx" \
  "https://gitlab.example.com/api/v4/projects"

# 认证方式2: OAuth2 Header
curl --header "Authorization: Bearer glpat-xxxxxxxxxxxxxxxxxxxx" \
  "https://gitlab.example.com/api/v4/projects"

# 认证方式3: Query参数 (不推荐)
curl "https://gitlab.example.com/api/v4/projects?private_token=glpat-xxxxxxxxxxxxxxxxxxxx"

项目API

# 列出项目
curl --header "PRIVATE-TOKEN: $TOKEN" \
  "https://gitlab.example.com/api/v4/projects"

# 响应
[
  {
    "id": 42,
    "name": "my-project",
    "path": "my-project",
    "path_with_namespace": "mygroup/my-project",
    "http_url_to_repo": "https://gitlab.example.com/mygroup/my-project.git",
    "ssh_url_to_repo": "git@gitlab.example.com:mygroup/my-project.git",
    "visibility": "private",
    "default_branch": "main"
  }
]

# 获取单个项目
curl --header "PRIVATE-TOKEN: $TOKEN" \
  "https://gitlab.example.com/api/v4/projects/42"

# 使用路径获取项目 (URL编码)
curl --header "PRIVATE-TOKEN: $TOKEN" \
  "https://gitlab.example.com/api/v4/projects/mygroup%2Fmy-project"

# 创建项目
curl --request POST \
  --header "PRIVATE-TOKEN: $TOKEN" \
  --header "Content-Type: application/json" \
  --data '{
    "name": "new-project",
    "description": "项目描述",
    "visibility": "private",
    "initialize_with_readme": true
  }' \
  "https://gitlab.example.com/api/v4/projects"

# 删除项目
curl --request DELETE \
  --header "PRIVATE-TOKEN: $TOKEN" \
  "https://gitlab.example.com/api/v4/projects/42"

Issue API

# 列出项目Issue
curl --header "PRIVATE-TOKEN: $TOKEN" \
  "https://gitlab.example.com/api/v4/projects/42/issues"

# 带过滤条件
curl --header "PRIVATE-TOKEN: $TOKEN" \
  "https://gitlab.example.com/api/v4/projects/42/issues?state=opened&labels=bug"

# 创建Issue
curl --request POST \
  --header "PRIVATE-TOKEN: $TOKEN" \
  --header "Content-Type: application/json" \
  --data '{
    "title": "登录功能Bug",
    "description": "## 问题描述\n登录按钮无响应",
    "labels": "bug,priority::high",
    "assignee_id": 5,
    "milestone_id": 10
  }' \
  "https://gitlab.example.com/api/v4/projects/42/issues"

# 响应
{
  "id": 123,
  "iid": 42,
  "title": "登录功能Bug",
  "state": "opened",
  "labels": ["bug", "priority::high"],
  "web_url": "https://gitlab.example.com/mygroup/my-project/-/issues/42"
}

# 更新Issue
curl --request PUT \
  --header "PRIVATE-TOKEN: $TOKEN" \
  --data "state_event=close" \
  "https://gitlab.example.com/api/v4/projects/42/issues/42"

# 添加评论
curl --request POST \
  --header "PRIVATE-TOKEN: $TOKEN" \
  --data "body=问题已修复,请验证" \
  "https://gitlab.example.com/api/v4/projects/42/issues/42/notes"

合并请求API

# 创建合并请求
curl --request POST \
  --header "PRIVATE-TOKEN: $TOKEN" \
  --header "Content-Type: application/json" \
  --data '{
    "source_branch": "feature/login",
    "target_branch": "main",
    "title": "feat: 添加登录功能",
    "description": "## 变更说明\n实现了用户登录功能\n\nCloses #42",
    "remove_source_branch": true
  }' \
  "https://gitlab.example.com/api/v4/projects/42/merge_requests"

# 列出合并请求
curl --header "PRIVATE-TOKEN: $TOKEN" \
  "https://gitlab.example.com/api/v4/projects/42/merge_requests?state=opened"

# 审批合并请求
curl --request POST \
  --header "PRIVATE-TOKEN: $TOKEN" \
  "https://gitlab.example.com/api/v4/projects/42/merge_requests/1/approve"

# 合并
curl --request PUT \
  --header "PRIVATE-TOKEN: $TOKEN" \
  --data "merge_when_pipeline_succeeds=true" \
  "https://gitlab.example.com/api/v4/projects/42/merge_requests/1/merge"

Pipeline API

# 触发Pipeline
curl --request POST \
  --header "PRIVATE-TOKEN: $TOKEN" \
  --form "ref=main" \
  --form "variables[DEPLOY_ENV]=production" \
  "https://gitlab.example.com/api/v4/projects/42/pipeline"

# 响应
{
  "id": 1234,
  "sha": "abc123",
  "ref": "main",
  "status": "pending",
  "web_url": "https://gitlab.example.com/mygroup/my-project/-/pipelines/1234"
}

# 使用Pipeline触发器Token
curl --request POST \
  --form "token=TRIGGER_TOKEN" \
  --form "ref=main" \
  --form "variables[DEPLOY_ENV]=staging" \
  "https://gitlab.example.com/api/v4/projects/42/trigger/pipeline"

# 列出Pipeline
curl --header "PRIVATE-TOKEN: $TOKEN" \
  "https://gitlab.example.com/api/v4/projects/42/pipelines?status=success"

# 获取Pipeline详情
curl --header "PRIVATE-TOKEN: $TOKEN" \
  "https://gitlab.example.com/api/v4/projects/42/pipelines/1234"

# 列出Pipeline的Job
curl --header "PRIVATE-TOKEN: $TOKEN" \
  "https://gitlab.example.com/api/v4/projects/42/pipelines/1234/jobs"

# 重试Pipeline
curl --request POST \
  --header "PRIVATE-TOKEN: $TOKEN" \
  "https://gitlab.example.com/api/v4/projects/42/pipelines/1234/retry"

# 取消Pipeline
curl --request POST \
  --header "PRIVATE-TOKEN: $TOKEN" \
  "https://gitlab.example.com/api/v4/projects/42/pipelines/1234/cancel"

用户和组API

# 获取当前用户
curl --header "PRIVATE-TOKEN: $TOKEN" \
  "https://gitlab.example.com/api/v4/user"

# 列出用户 (管理员)
curl --header "PRIVATE-TOKEN: $TOKEN" \
  "https://gitlab.example.com/api/v4/users"

# 创建用户 (管理员)
curl --request POST \
  --header "PRIVATE-TOKEN: $TOKEN" \
  --header "Content-Type: application/json" \
  --data '{
    "email": "user@example.com",
    "username": "newuser",
    "name": "New User",
    "password": "SecurePass123!",
    "skip_confirmation": true
  }' \
  "https://gitlab.example.com/api/v4/users"

# 列出组
curl --header "PRIVATE-TOKEN: $TOKEN" \
  "https://gitlab.example.com/api/v4/groups"

# 添加成员到组
curl --request POST \
  --header "PRIVATE-TOKEN: $TOKEN" \
  --data "user_id=5&access_level=30" \
  "https://gitlab.example.com/api/v4/groups/10/members"

# access_level:
# 10 = Guest
# 20 = Reporter
# 30 = Developer
# 40 = Maintainer
# 50 = Owner

GraphQL API

# GraphQL端点
# https://gitlab.example.com/api/graphql

# 查询示例
curl --request POST \
  --header "PRIVATE-TOKEN: $TOKEN" \
  --header "Content-Type: application/json" \
  --data '{
    "query": "query { currentUser { username name email } }"
  }' \
  "https://gitlab.example.com/api/graphql"

# 响应
{
  "data": {
    "currentUser": {
      "username": "zhangsan",
      "name": "张三",
      "email": "zhangsan@example.com"
    }
  }
}

# 查询项目和Issue
curl --request POST \
  --header "PRIVATE-TOKEN: $TOKEN" \
  --header "Content-Type: application/json" \
  --data '{
    "query": "query { project(fullPath: \"mygroup/my-project\") { name description issues(first: 5, state: opened) { nodes { iid title state labels { nodes { title } } } } } }"
  }' \
  "https://gitlab.example.com/api/graphql"

# 使用GraphQL Explorer
# https://gitlab.example.com/-/graphql-explorer

Webhook

# 配置Webhook
# Project > Settings > Webhooks

URL: https://your-server.com/webhook
Secret Token: your-secret-token
Trigger: 
  [x] Push events
  [x] Merge request events
  [x] Pipeline events
  [x] Issue events

# Webhook请求示例 (Push事件)
POST /webhook HTTP/1.1
X-Gitlab-Event: Push Hook
X-Gitlab-Token: your-secret-token

{
  "object_kind": "push",
  "ref": "refs/heads/main",
  "before": "abc123...",
  "after": "def456...",
  "user_name": "zhangsan",
  "project": {
    "name": "my-project",
    "web_url": "https://gitlab.example.com/mygroup/my-project"
  },
  "commits": [
    {
      "id": "def456",
      "message": "Update README",
      "author": { "name": "zhangsan", "email": "zhangsan@example.com" }
    }
  ]
}

# 处理Webhook的服务器示例 (Node.js)
const express = require('express');
const crypto = require('crypto');
const app = express();

app.use(express.json());

app.post('/webhook', (req, res) => {
  const token = req.headers['x-gitlab-token'];
  if (token !== 'your-secret-token') {
    return res.status(401).send('Unauthorized');
  }
  
  const event = req.headers['x-gitlab-event'];
  console.log(`Received ${event}:`, req.body);
  
  // 处理事件...
  
  res.status(200).send('OK');
});

app.listen(3000);

自动化脚本示例

#!/bin/bash
# gitlab-release.sh - 自动创建发布

GITLAB_URL="https://gitlab.example.com"
TOKEN="$GITLAB_TOKEN"
PROJECT_ID="42"
VERSION="$1"

if [ -z "$VERSION" ]; then
  echo "Usage: $0 "
  exit 1
fi

# 创建标签
echo "Creating tag v$VERSION..."
curl --request POST \
  --header "PRIVATE-TOKEN: $TOKEN" \
  --data "tag_name=v$VERSION" \
  --data "ref=main" \
  --data "message=Release v$VERSION" \
  "$GITLAB_URL/api/v4/projects/$PROJECT_ID/repository/tags"

# 创建发布
echo "Creating release v$VERSION..."
curl --request POST \
  --header "PRIVATE-TOKEN: $TOKEN" \
  --header "Content-Type: application/json" \
  --data "{
    \"name\": \"v$VERSION\",
    \"tag_name\": \"v$VERSION\",
    \"description\": \"Release v$VERSION\\n\\nSee CHANGELOG.md for details.\"
  }" \
  "$GITLAB_URL/api/v4/projects/$PROJECT_ID/releases"

echo "Release v$VERSION created!"

总结

本文介绍了GitLab API的使用方法,包括REST API、GraphQL API和Webhook。通过API可以实现各种自动化操作,提高开发效率。

下一篇我们将学习GitLab与外部服务集成。

发表回复

后才能评论