🚀

用Python自动生成团队周报,告别复制粘贴

从Git提交记录和日历中自动提取信息,一键生成结构化团队周报。

👁️ - 次阅读

项目背景

每周五下午,团队负责人最头疼的事就是催周报。有人拖到周日晚上才交,有人写三行字糊弄过去。手动汇总更是折磨——打开每个人的文件,复制粘贴,调整格式,改一天就过去了。

有没有办法让周报自动生成?

这个项目的目标是用Python脚本,从Git提交记录和日历中自动提取本周工作信息,生成一份结构清晰、可直接发送的HTML周报。

技术选型

  • Python 3.10+:主力语言
  • GitPython:读取Git仓库提交历史
  • Jinja2:HTML模板渲染
  • smtplib + email:邮件发送(可选)
  • Cron / GitHub Actions:定时触发

不需要数据库,不需要前端框架。纯Python脚本,跑在任意服务器上即可。

实现步骤

第一步:安装依赖

pip install gitpython jinja2

第二步:创建HTML模板

在项目目录新建 report.html:

<!DOCTYPE html>
<html lang="zh-CN">
<head>
<meta charset="UTF-8">
<style>
  body { font-family: -apple-system, sans-serif; max-width: 800px; margin: 40px auto; padding: 0 20px; color: #333; }
  h1 { color: #2c3e50; border-bottom: 2px solid #3498db; padding-bottom: 10px; }
  .member { background: #f8f9fa; border-left: 4px solid #3498db; padding: 15px; margin: 15px 0; }
  .member h3 { margin-top: 0; color: #2c3e50; }
  .commit { padding: 5px 0; border-bottom: 1px solid #eee; }
  .time { color: #888; font-size: 0.85em; }
  .tag { display: inline-block; background: #e8f4fd; color: #2980b9; padding: 2px 8px; border-radius: 3px; font-size: 0.8em; margin-right: 5px; }
</style>
</head>
<body>
<h1>📊 团队周报 — {{ week_label }}</h1>
<p>生成时间:{{ generated_at }}</p>
{% for member in members %}
<div class="member">
  <h3>{{ member.name }}</h3>
  <p><strong>本周完成:</strong></p>
  {% for commit in member.commits %}
  <div class="commit">
    {% for tag in commit.tags %}<span class="tag">{{ tag }}</span>{% endfor %}
    {{ commit.message }}
    <span class="time">{{ commit.date }}</span>
  </div>
  {% endfor %}
  {% if member.summary %}
  <p><strong>总结:</strong>{{ member.summary }}</p>
  {% endif %}
</div>
{% endfor %}
</body>
</html>

第三步:编写核心脚本

创建 generate_report.py:

import git
import os
from datetime import datetime, timedelta
from jinja2 import Environment, FileSystemLoader
import smtplib
from email.mime.text import MIMEText

def get_week_range():
    """获取本周一到周日的日期范围"""
    today = datetime.now()
    monday = today - timedelta(days=today.weekday())
    sunday = monday + timedelta(days=6)
    return monday, sunday, f"{monday.strftime('%m/%d')}-{sunday.strftime('%m/%d')}"

def parse_commit_tags(message):
    """从提交信息中提取标签"""
    tags = []
    if "[feat]" in message or "[feature]" in message:
        tags.append("功能")
    elif "[fix]" in message:
        tags.append("修复")
    elif "[docs]" in message:
        tags.append("文档")
    elif "[refactor]" in message:
        tags.append("重构")
    elif "[perf]" in message:
        tags.append("性能")
    else:
        tags.append("其他")
    return tags

def collect_member_commits(repo_path, member_name, week_start, week_end):
    """收集某成员在指定时间范围内的提交"""
    repo = git.Repo(repo_path)
    commits = []
    for commit in repo.iter_commits(
        author=member_name,
        since=week_start,
        until=week_end,
        max_count=50
    ):
        msg = str(commit.message).strip()
        date_str = commit.committed_datetime.strftime("%Y-%m-%d %H:%M")
        commits.append({
            "message": msg,
            "date": date_str,
            "tags": parse_commit_tags(msg)
        })
    # 按时间倒序排列
    commits.sort(key=lambda x: x["date"], reverse=True)
    return commits[:20]  # 每人最多显示20条

def generate_report(members_data, week_label):
    """使用模板生成HTML周报"""
    env = Environment(loader=FileSystemLoader("."))
    template = env.get_template("report.html")
    now = datetime.now().strftime("%Y-%m-%d %H:%M")
    return template.render(
        members=members_data,
        week_label=week_label,
        generated_at=now
    )

def send_email(html_content, subject, to_addrs):
    """发送邮件(可选功能)"""
    msg = MIMEText(html_content, "html", "utf-8")
    msg["Subject"] = subject
    msg["From"] = "report@navbox.com.cn"
    msg["To"] = ", ".join(to_addrs)
    
    with smtplib.SMTP("smtp.example.com", 587) as server:
        server.starttls()
        server.login("user", "password")
        server.send_message(msg)

# ==================== 配置区域 ====================
REPO_PATH = "/home/ubuntu/my-project"  # Git仓库路径

MEMBERS = [
    {"name": "张三", "summary": "本周完成了用户权限模块的重构,修复了3个线上bug"},
    {"name": "李四", "summary": "完成了支付接口的联调,写了完整的API文档"},
    {"name": "王五", "summary": "优化了首页加载速度,性能提升约40%"},
]

# ==================================================

if __name__ == "__main__":
    week_start, week_end, week_label = get_week_range()
    print(f"📅 报告周期: {week_label}")
    
    members_data = []
    for member in MEMBERS:
        commits = collect_member_commits(REPO_PATH, member["name"], week_start, week_end)
        members_data.append({
            "name": member["name"],
            "commits": commits,
            "summary": member.get("summary", "")
        })
        print(f"  ✅ {member['name']}: {len(commits)} 条提交记录")
    
    html = generate_report(members_data, week_label)
    
    with open("weekly_report.html", "w", encoding="utf-8") as f:
        f.write(html)
    print("✅ 周报已生成: weekly_report.html")
    
    # 取消注释以启用邮件发送
    # send_email(html, f"团队周报 {week_label}", ["manager@example.com"])
    # print("📧 邮件已发送")

第四步:配置定时任务

用Cron实现每周六凌晨自动运行:

crontab -e

添加以下行:

0 9 * * 6 cd ~/my-project && python generate_report.py

这样每周六早上9点自动生成并保存为 weekly_report.html,你可以直接打开查看或配置邮件自动发送。

如果用GitHub Actions,可以在 .github/workflows/weekly-report.yml 中配置:

name: Weekly Report
on:
  schedule:
    - cron: '0 1 * * 6'  # 周六 UTC 01:00 = 北京 09:00
  workflow_dispatch:       # 也支持手动触发

jobs:
  report:
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v4
      - uses: actions/setup-python@v5
        with:
          python-version: '3.12'
      - run: pip install gitpython jinja2
      - run: python generate_report.py
      - name: Upload report
        uses: actions/upload-artifact@v4
        with:
          name: weekly-report
          path: weekly_report.html

运行效果

脚本执行后会在项目根目录生成 weekly_report.html,效果如下:

  • 顶部显示报告周期和生成时间
  • 每位成员一个独立卡片,左侧蓝色边框
  • 每条提交记录带彩色标签(功能/修复/文档/重构/性能)
  • 支持手动填写的本周总结段落
  • 样式简洁,直接在浏览器打开即可查看

如果需要群发,取消邮件发送部分的注释,填入SMTP配置即可。

优化方向

  1. 对接飞书/钉钉机器人:把生成步骤改成直接推送到群组消息,省去手动打开文件的环节。用 requests 库调 webhook 就行。

  2. 多仓库聚合:团队通常有多个Git仓库,修改脚本遍历多个 repo_path,按仓库分组展示。

  3. PR/MR 数据:如果代码托管在GitHub/Gitee,可以通过API拉取本周合并的PR列表,比提交记录更有业务含义。

  4. 数据看板:把周报数据存入SQLite,用Flask做一个简单的查询页面,可以按人/按仓库/按时间筛选统计。

  5. AI润色:接入本地Ollama,让模型根据提交记录自动生成更自然的总结文字,减少人工填写 summary 的负担。


完整代码已开源在 GitHub。 Fork 后修改配置区的仓库路径和成员列表就能直接用。

这篇文章对你有帮助吗?