基於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}}]}
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章