Integrations

gitlab-work-stats

Try it

生成 GitLab 用户工作统计报告(仅限只读分析)。分析指定用户在指定时间段内的合并请求、代码提交、代码审查活动。不修改服务器数据,不提供加密功能。

What it does

生成 GitLab 用户工作统计报告(仅限只读分析)。分析指定用户在指定时间段内的合并请求、代码提交、代码审查活动。不修改服务器数据,不提供加密功能。

The skill document

gitlab-work-stats — GitLab 用户工作统计分析器

⚠️ 重要说明:本工具用于生成 GitLab 用户工作统计报告(只读分析)。

  • 不会修改 GitLab 服务器上的任何数据
  • 不提供加密功能,生成的报告需用户自行保护
  • 需要用户提供明确的分析目标和时间范围

⚠️ 安全警告

  • 本操作会分析用户的工作活动数据,可能涉及敏感信息
  • 确保已获得目标用户的授权或这是您自己的工作数据
  • 生成的报告包含工作统计信息,请妥善保管
  • 所有数据库操作均为只读(SELECT),不会修改任何数据

激活条件

高优先级(明确意图)

  • "生成 GitLab 工作统计报告"
  • "分析 GitLab 用户的提交活动"
  • "统计 GitLab 上的代码审查数据"

低优先级(需要确认)

  • "看看某人在 GitLab 做了什么"
  • "分析 XX 的 GitLab 活动"

不触发的情况

  • 只是提到 GitLab 但没有要求分析工作统计
  • 询问 GitLab 的使用方法或功能介绍
  • 需要 GitLab API 或其他非统计分析的操作

激活前必须确认

  1. 目标用户的 GitLab username
  2. 明确的时间范围
  3. 用户已知晓数据隐私和安全要求

核心原则

只读操作 — 所有数据库查询和 git 命令必须是只读的(SELECT / git log),绝不修改服务器上的任何文件或数据。每次执行前向用户声明这一点。

参数提取 — 激活后必须从用户输入中提取三个关键参数:

  1. 目标用户名(GitLab username,如 {target_username}
  2. 时间范围(起止日���,如 2026-07-01 ~ 2026-07-31
  3. (可选)项目过滤(限定某个项目,默认分析全部项目)

如果缺少用户名或时间范围,主动询问用户。

Step 0: 读取服务器配置

references/server-config.json 读取 GitLab 服务器连接信息。

⚠️ 凭据安全警告

  • 配置文件中的凭据(如 host、token)由用户自行提供
  • 不要将配置文件提交到公共代码仓库
  • 建议使用环境变量或配置管理工具存储敏感信息
  • 确保文件权限设置为仅当前用户可读

如果配置文件不存在或需要连接不同的服务器,询问用户提供:

  • GitLab 服务器地址(host)
  • GitLab API Token(推荐)或 SSH 访问凭据
  • GitLab Web URL(可选)

Step 1: SSH 连接与数据库定位

1.1 连接方式

使用 Python paramiko 库通过 SSH 连接服务器。

前置条件

  • Python 3.8+
  • paramiko 库(需要用户自行安装:pip install paramiko

连接模板:

import paramiko
ssh = paramiko.SSHClient()
ssh.set_missing_host_key_policy(paramiko.AutoAddPolicy())
ssh.connect(HOST, port=22, username=USER, password=PASSWORD, timeout=15)

⚠️ 安全说明

  • 使用受管 Python 环境运行 paramiko
  • SSH 凭据从 server-config.json 读取,不要硬编码在脚本中
  • 建议使用受限的 SSH 账户,遵循最小权限原则

1.2 数据库连接

GitLab Omnibus 默认使用内置 PostgreSQL,通过 Unix Socket 连接(不监听 TCP 端口),使用 peer 认证(无需密码)。

连接方式(通过 socket + peer 认证,以当前 SSH 用户身份直接执行,不使用 sudo 提权):

/opt/gitlab/embedded/bin/psql   -h /var/opt/gitlab/postgresql -d gitlabhq_production -c "SQL语句"

⚠️ 权限说明

  • 需要 SSH 用户本身具有执行 psql 的权限(属组包含 gitlab-psql 或配置了 peer 认证白名单)
  • 不使用 sudo -u gitlab-psql,避免 sudo 提权带来的安全风险
  • 建议使用受限的专用 SSH 账户,遵循最小权限原则
  • 所有 SQL 查询必须为只读(SELECT),禁止执行 INSERT/UPDATE/DELETE
  • 如果当前用户无法直接连接,应由管理员配置 peer 认证规则,而非使用 sudo

注意:如果 GitLab 版本不同或使用了外部数据库,需要根据 database.ymlhostportusernamepassword 字段调整连接方式。详见 references/database-guide.md

Step 2: 确认用户身份

查询 users 表确认用户存在,获取 user_id

SELECT id, username, name, state, created_at, last_sign_in_at
FROM users WHERE username = '{username}';

⚠️ 隐私保护

  • 仅收集工作统计相关的最小必要信息
  • 不收集 email、IP 地址等敏感个人信息
  • 如果用户要求分析自己的数据,可以包含 email 用于报告标识

如果找不到用户,尝试模糊匹配:

SELECT id, username, name FROM users WHERE username ILIKE '%{keyword}%';

Step 3: 数据采集(全部只读 SELECT)

以下所有查询中 {user_id}{start_date}{end_date} 为参数占位符。

3.1 合并请求 (Merge Requests)

查询用户作为作者的 MR:

SELECT mr.id, mr.iid, mr.title, mr.state_id, mr.created_at, mr.updated_at,
       p.name as project_name, p.id as project_id
FROM merge_requests mr
JOIN projects p ON mr.target_project_id = p.id
WHERE mr.author_id = {user_id}
  AND mr.created_at >= '{start_date}'
  AND mr.created_at < '{end_date}'
ORDER BY mr.created_at DESC;

state_id 含义:1=opened, 2=closed, 3=merged, 4=locked

3.2 代码推送 (Push Events) 与 Commit 标题

Push 事件存储在 events 表(action=5),commit 详情在 push_event_payloads 表。

SELECT e.created_at, pepe.commit_title, pepe.ref, pepe.commit_count,
       p.name as project_name
FROM events e
JOIN push_event_payloads pepe ON pepe.event_id = e.id
JOIN projects p ON e.project_id = p.id
WHERE e.author_id = {user_id}
  AND e.action = 5
  AND e.created_at >= '{start_date}'
  AND e.created_at < '{end_date}'
ORDER BY e.created_at DESC;

汇总统计(不需要逐条列出,按分支/任务分组统计):

SELECT
  regexp_replace(pepe.ref, 'feature-([0-9]+).*', 'task-\1') as task_branch,
  count(*) as push_count,
  sum(pepe.commit_count) as total_commits,
  count(DISTINCT pepe.commit_title) as distinct_titles
FROM events e
JOIN push_event_payloads pepe ON pepe.event_id = e.id
WHERE e.author_id = {user_id} AND e.action = 5
  AND e.created_at >= '{start_date}' AND e.created_at < '{end_date}'
GROUP BY pepe.ref
ORDER BY push_count DESC;

3.3 代码审查 (Code Reviews)

3.3.1 获取该用户所有 MR 上的评论

notes 表的正文列名为 note(不是 body):

-- 别人对该用户 MR 的评论(含审批、审查意见)
SELECT n.created_at, u.username as author,
       LEFT(n.note, 300) as note_preview,
       mr.iid, mr.title, p.name as project_name,
       n.system
FROM notes n
JOIN users u ON n.author_id = u.id
JOIN merge_requests mr ON n.noteable_id = mr.id AND n.noteable_type = 'MergeRequest'
JOIN projects p ON mr.target_project_id = p.id
WHERE mr.author_id = {user_id}
  AND n.created_at >= '{start_date}'
  AND n.created_at < '{end_date}'
ORDER BY n.created_at DESC;

3.3.2 AI 代码审查内容

如果服务器配置了 AI 代码审查(bot 用户名从 server-config.json 的 ai_reviewer_bot_username 读取,默认匹配规则见下),查询审查详情:

SELECT n.created_at, mr.iid, mr.title,
       LEFT(n.note, 500) as review_content
FROM notes n
JOIN merge_requests mr ON n.noteable_id = mr.id AND n.noteable_type = 'MergeRequest'
JOIN users u ON n.author_id = u.id
WHERE mr.author_id = {user_id}
  AND u.username IN ('{ai_bot_username}', 'ai-code-reviewer', 'code-reviewer')
  AND n.created_at >= '{start_date}'
  AND n.created_at < '{end_date}'
ORDER BY n.created_at DESC;

3.3.3 审批记录

SELECT n.created_at, u.username as approver,
       mr.iid, mr.title, n.note
FROM notes n
JOIN users u ON n.author_id = u.id
JOIN merge_requests mr ON n.noteable_id = mr.id AND n.noteable_type = 'MergeRequest'
WHERE mr.author_id = {user_id}
  AND n.note LIKE 'approved this merge request'
  AND n.created_at >= '{start_date}'
  AND n.created_at < '{end_date}'
ORDER BY n.created_at DESC;

3.3.4 用户作为评审人的 MR

SELECT mr.id, mr.iid, mr.title, mr.state_id, mr.created_at, mr.updated_at,
       u.username as author, p.name as project_name
FROM merge_requests mr
JOIN merge_request_assignees mra ON mra.merge_request_id = mr.id
JOIN users u ON mr.author_id = u.id
JOIN projects p ON mr.target_project_id = p.id
WHERE mra.user_id = {user_id}
  AND mr.updated_at >= '{start_date}'
  AND mr.updated_at < '{end_date}'
ORDER BY mr.updated_at DESC;

3.4 用户自己发表的评论

SELECT n.created_at, n.noteable_type,
       LEFT(n.note, 200) as note_preview,
       p.name as project_name
FROM notes n
LEFT JOIN projects p ON n.project_id = p.id
WHERE n.author_id = {user_id}
  AND n.created_at >= '{start_date}'
  AND n.created_at < '{end_date}'
  AND n.system = false
ORDER BY n.created_at DESC;

Step 4: 多行 SQL 执行

通过 SSH 执行多行 SQL 时,使用参数化查询避免引号转义问题:

import shlex

def pg_query(ssh, sql):
    # 使用参数化命令,避免 sudo 链式执行
    cmd = '/opt/gitlab/embedded/bin/psql ' \
          '-h /var/opt/gitlab/postgresql ' \
          '-d gitlabhq_production ' \
          f'-c {shlex.quote(sql)} 2>&1'
    
    # 以当前 SSH 用户身份执行(需要该用户具有 psql 执行权限)
    stdin, stdout, stderr = ssh.exec_command(cmd, timeout=60)
    return stdout.read().decode('utf-8', errors='replace')

⚠️ 安全说明

  • 不使用 sudo -u gitlab-psql,需要 SSH 用户本身具有 psql 执行权限
  • 使用 shlex.quote() 防止 SQL 注入
  • 所有查询必须为 SELECT 语句

Step 5: (可选)从 Git 仓库提取 Commit 详情

数据库中的 push_event_payloads 只记录 commit 标题,如需完整的 commit message、变更文件列表等,需直接查询 git 仓库。

5.1 获取仓库物理路径

GitLab 使用 hashed storage,需通过 project_repositories 表获取磁盘路径:

SELECT pr.project_id, p.name, pr.disk_path
FROM project_repositories pr
JOIN projects p ON pr.project_id = p.id
WHERE p.id IN (
  SELECT DISTINCT target_project_id 
  FROM merge_requests 
  WHERE author_id = {user_id} 
    AND created_at >= '{start_date}' 
    AND created_at < '{end_date}'
  UNION
  SELECT DISTINCT project_id 
  FROM events 
  WHERE author_id = {user_id} 
    AND action = 5 
    AND created_at >= '{start_date}' 
    AND created_at < '{end_date}'
);

⚠️ 安全说明

  • 只查询目标用户在指定时间段内有活动的仓库
  • 不枚举所有仓库的磁盘路径
  • 仅用于获取 commit 详情,不访问仓库源代码

5.2 查询 git log

REPO="/var/opt/gitlab/git-data/repositories/{disk_path}.git"
/opt/gitlab/embedded/bin/git -C "$REPO" \
  log --all --author='{username}' \
  --since='{start_date}' --until='{end_date}' \
  --format='%h|%ai|%s'

⚠️ 安全说明

  • 仅使用 git log 命令,不访问仓库源代码内容
  • 需要 SSH 用户具有读取该仓库的权限
  • 不使用 sudo 提权,直接使用当前用户权限执行

注意:hashed storage 的磁盘路径格式为 @hashed/{前2位}/{次2位}/{完整hash},完整路径为 /var/opt/gitlab/git-data/repositories/@hashed/XX/YY/XXXX.git。数据库记录的 disk_path 不含 .git 后缀。

Step 6: 生成报告

报告格式为 Markdown,保存到工作目录下,文件名格式:{username}_{年月}_活动报告.md

报告结构

# {username} {时间范围}活动报告

> 用户: {username} ({name}) | ID: {user_id} | 项目: {projects}

---

## 一、合并请求 (MR) 清单 — 共 N 个

| # | MR IID | 标题 | 创建时间 | 状态 | 评审人 | 审批时间 |
|---|--------|------|----------|------|--------|----------|
| 1 | !xxx   | ...  | ...      | ...  | ...    | ...      |

## 二、代码推送统计

### 按任务/分支分组统计(不逐条列举)

| 任务/分支 | 推送次数 | Commit总数 | 主要内容 |
|-----------|----------|------------|----------|
| task-xxxx | N        | N          | 简述     |

## 三、代码审查

### AI 代码审查结果
(列出关键审查意见和发现的风险)

### 人工审批记录
(列出审批人和审批时间)

## 四、工作内容总结

### 按任务归类的工作主题

| 任务号 | 主题 | MR数 | 核心工作内容 |
|--------|------|------|--------------|

### 提交内容语义分析

根据所有 commit 标题和 MR 标题,对用户的工作内容进行主题归类和语义分析:
- 主要技术方向(如:退款逻辑、导出功能、告警系统...)
- 工作类型分布(新功能 vs Bug修复 vs 优化重构)
- 涉及的模块/技术栈
- 关键技术决策和实现思路

报告要点

  1. Push Events 做统计汇总,不逐条列举——按分支/任务分组,统计推送次数和 commit 数,简述主要内容
  2. 最后必须有一段「提交内容语义分析总结」——基于所有 commit title 和 MR title,分析用户做了什么、技术方向是什么、工作类型分布
  3. 报告完成后调用 present_files 展示给用户

重要注意事项

数据安全

  • 所有操作只读:只用 SELECT 查询和 git log 命令,绝不执行 INSERT/UPDATE/DELETE 或任何写操作
  • 每次开始前明确告知用户"所有操作不会修改服务器上的任何文件或数据"

GitLab 版本差异

  • 不同 GitLab 版本的表结构可能有差异(如 merge_requests 表的 state vs state_id 列)
  • 遇到列不存在错误时,先查 information_schema.columns 确认列名
  • notes 表的正文列名固定为 note(不是 body

编码问题

  • psql 输出可能包含中文,使用 decode('utf-8', errors='replace') 处理
  • base64 编码方式处理多行 SQL,避免 shell 引号转义问题

性能

  • eventsnotes 表可能很大,查询时务必带 author_id 和时间范围条件
  • 避免全表扫描

配置文件

服务器连接配置存放在 references/server-config.json,包含 IP、端口、用户名、密码等。

数据库结构参考

详细的 GitLab PostgreSQL 数据库表结构和查询方法见 references/database-guide.md

版本

版本日期作者变更
1.0.02026-07-23初始版本,支持用户工作统计分析报告生成
1.1.02026-07-24安全修复:移除 sudo 链式执行、users 表隐私字段标注、git 命令移除提权

Related skills

Generate structured weekly work reports from Git commit history and file-change statistics. Use when the user asks for a weekly report, work summary, progress review, or sprint recap based on repository activity, or when they need a Markdown report of what changed in a project over a time range.

面向个人开发者的Git仓库协作模式分析工具,只读、零依赖、隐私优先,输出仓库级聚合报告。Use when 需要数据分析、报表生成、统计洞察、数据可视化时使用。不适用于实时流数据处理。适用于独立开发者、企业团队和自动化工作流场景。支持中文交互,无需复杂配置即开即用。输出结果可直接使用,减少二次加工成本。

1 installs

禅道(Zentao)用户工作内容分析工具。通过数据库只读查询分析指定用户在指定时间段内的需求、任务、Bug、工时日志,生成 Markdown 格式的工作报告。仅支持 SQL SELECT 查询,不修改任何数据。

Generate evidence-based project weekly reports from a local code repository. Use when the user asks for a project weekly report, weekly update, status summar...

1 installs

GitLab (gitlab.com). Use this skill for ANY GitLab request — reading, creating, updating, and deleting data. Whenever a task involves GitLab, use this skill instead of calling the API directly.

7 installs