基于Serverless架构的Git代码统计

{"type":"doc","content":[{"type":"heading","attrs":{"align":null,"level":2},"content":[{"type":"text","text":"前言"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"自己毕业也有一年多了,很想统计一下过去一年自己贡献了多少的代码。想了一下,可能要用"},{"type":"codeinline","content":[{"type":"text","text":"git log"}]},{"type":"text","text":",简单的做了一下,感觉不是很爽,正直自己想通过Serverless做一个工具合集,就想能不能通过Serverless做一个Git的代码统计功能?"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"heading","attrs":{"align":null,"level":2},"content":[{"type":"text","text":"代码实现"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"其实整个逻辑是比较简单的,只需要将"},{"type":"codeinline","content":[{"type":"text","text":"git"}]},{"type":"text","text":"整合到云函数中,再加一个API网关作为触发器,就可以轻松实现。整体代码为:"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"codeblock","attrs":{"lang":"python"},"content":[{"type":"text","text":"import random\nimport subprocess\nimport os\nimport json\nimport uuid\nimport tarfile\n\nrandomStr = lambda num: \"\".join(random.sample('zyxwvutsrqponmlkjihgfedcba',num))\n\ndef return_msg(error, msg):\n return_data = {\n \"uuid\": str(uuid.uuid1()),\n \"error\": error,\n \"message\": msg\n }\n print(return_data)\n return return_data\n\n\ndef installGit():\n targetDir = \"/tmp/git\"\n dir_path = os.path.dirname(os.path.realpath(__file__))\n tar = tarfile.open(os.path.join(dir_path, 'git-2.14.0.tar'))\n tar.extractall(targetDir)\n git_path = os.path.join(targetDir, 'git')\n bin_path = os.path.join(git_path, 'bin')\n\n template_dir = os.path.join(\n git_path,\n 'share',\n 'git-core',\n 'templates'\n )\n\n exec_path = os.path.join(\n git_path,\n 'libexec',\n 'git-core'\n )\n os.environ['PATH'] = bin_path + ':' + os.environ['PATH']\n os.environ['GIT_TEMPLATE_DIR'] = template_dir\n os.environ['GIT_EXEC_PATH'] = exec_path\n\n\ninstallGit()\n\ndef doPopen(gitStr, path):\n child = subprocess.Popen(\"cd %s && %s\" % (path, gitStr), shell=True, stdout=subprocess.PIPE, stderr=subprocess.PIPE)\n return child.stdout.read().decode(\"utf-8\")\n\n\ndef main_handler(event, context):\n try:\n path = \"/tmp/%s\" % (randomStr(5))\n print(\"git clone %s %s\" % (json.loads(event[\"body\"])[\"url\"], path))\n child = subprocess.Popen(\"git clone %s %s\" % (json.loads(event[\"body\"])[\"url\"], path), shell=True, stdout=subprocess.PIPE, stderr=subprocess.PIPE)\n print(child.stdout.read().decode(\"utf-8\"))\n users = {}\n for eveCommit in doPopen(\"git log --format='%aN'\", path).split(\"\\n\"):\n if eveCommit:\n if eveCommit not in users:\n users[eveCommit] = {\"commits\": 1,\n \"added_lines\": 0,\n \"removed_lines\": 0,\n \"total_lines\": 0}\n for eveItem in doPopen('git log --author=\"%s\" --pretty=tformat: --numstat'%eveCommit, path).split(\"\\n\"):\n if eveItem:\n eveItemList = eveItem.split(\"\\t\")\n users[eveCommit][\"added_lines\"] = users[eveCommit][\"added_lines\"] + int(eveItemList[0])\n users[eveCommit][\"removed_lines\"] = users[eveCommit][\"removed_lines\"] + int(eveItemList[1])\n users[eveCommit][\"total_lines\"] = users[eveCommit][\"added_lines\"] - users[eveCommit][\"removed_lines\"]\n\n else:\n users[eveCommit]['commits'] = users[eveCommit]['commits'] + 1\n return return_msg(False, users)\n except Exception as e:\n return return_msg(True, e)"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"在这段代码中,主要就是将Git的压缩包,解压到"},{"type":"codeinline","content":[{"type":"text","text":"/tmp/"}]},{"type":"text","text":"目录,然后将其装载到环境变量中,确保git指令可用。"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"接下来通过"},{"type":"codeinline","content":[{"type":"text","text":"git clone"}]},{"type":"text","text":"指令来进行用户提供的仓库的clone,将其同样存放在"},{"type":"codeinline","content":[{"type":"text","text":"/tmp/"}]},{"type":"text","text":"目录下。"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"然后通过"},{"type":"codeinline","content":[{"type":"text","text":"git log --format='%aN'"}]},{"type":"text","text":"获得该仓库所有提交过过的人的列表,并且可以统计出每个人提交的次数。"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"最后通过"},{"type":"codeinline","content":[{"type":"text","text":"git log --author=\"user\" --pretty=tformat: --numstat"}]},{"type":"text","text":"来统计user的代码行数,最后进行组装并且返回。"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"Serverless的Yaml文件为:"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"codeblock","attrs":{"lang":"yaml"},"content":[{"type":"text","text":"GitStatistics:\n component: \"@serverless/tencent-scf\"\n inputs:\n name: GitStatistics\n codeUri: ./\n exclude:\n - .gitignore\n - .git/**\n - .serverless\n - .env\n handler: index.main_handler\n runtime: Python3.6\n region: ap-beijing\n description: git提交次数统计\n namespace: serverless_tools\n memorySize: 64\n timeout: 1800\n events:\n - apigw:\n name: serverless\n parameters:\n serviceId: service-8d3fi753\n environment: release\n endpoints:\n - path: /git/statistics\n serviceTimeout: 1800\n description: git提交次数统计\n method: POST\n enableCORS: true"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"代码的接口信息:"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"请求地址: http://service-8d3fi753-1256773370.bj.apigw.tencentcs.com/release/git/statistics "}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"请求类型:POST "}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"入参类型:JSON "}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"入参参数:url: git地址,例如:{\"url\": \"https://github.com/serverless-components/tencent-scf.git\"} "}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"出参列表:"}]},{"type":"codeblock","attrs":{"lang":"json"},"content":[{"type":"text","text":"{\n \"uuid\": \"6ff62096-819d-11ea-a6a2-0242cb007105\",\n \"error\": false,\n \"message\": {\n \"yugasun\": {\n \"commits\": 23,\n \"added_lines\": 435,\n \"removed_lines\": 137,\n \"total_lines\": 298\n }\n }\n}"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":" "}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"完整之后,我们可以通过POSTMAN测试一下:"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"image","attrs":{"src":"https://static001.geekbang.org/infoq/3f/3fec67504d29a7a97e65cde24551918c.png","alt":null,"title":null,"style":null,"href":null,"fromPaste":true,"pastePass":true}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"heading","attrs":{"align":null,"level":2},"content":[{"type":"text","text":"总结"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"Serverless架构有很多有趣的应用,通过将Git集成到函数计算中,不仅仅可以更加简单快速,方便的集成CICD流程,也可以额实现代码行数统计,还可以做很多有趣的事情,希望通过我的抛砖引玉,可以让大家有更多的想法,创新性的提出更多的应用。"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}}]}
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章