{"id":126557,"date":"2020-01-18T22:18:55","date_gmt":"2020-01-18T14:18:55","guid":{"rendered":"http:\/\/4563.org\/?p=126557"},"modified":"2020-06-29T05:21:59","modified_gmt":"2020-06-28T21:21:59","slug":"%e9%92%89%e9%92%89%e6%9c%ba%e5%99%a8%e4%ba%ba%e8%87%aa%e5%8a%a8%e5%85%b3%e8%81%94-github-%e5%8f%91%e9%80%81-approval-prs","status":"publish","type":"post","link":"http:\/\/4563.org\/?p=126557","title":{"rendered":"\u9489\u9489\u673a\u5668\u4eba\u81ea\u52a8\u5173\u8054 GitHub \u53d1\u9001 approval prs"},"content":{"rendered":"<div>\n<div>\n<div>\n<h1>                  \u9489\u9489\u673a\u5668\u4eba\u81ea\u52a8\u5173\u8054 GitHub \u53d1\u9001 approval prs               <\/h1>\n<p> <\/p>\n<div>\n<div> <span>\u8cc7\u6df1\u5927\u4f6c : NebulaGraph <\/span>  <span><i><\/i> 7<\/span> <\/div>\n<div> <\/div>\n<\/p><\/div>\n<\/p><\/div>\n<\/p><\/div>\n<div isfirst=\"1\"> <\/p>\n<p>\u6458\u8981\uff1a\u7528\u6280\u672f\u6765\u89e3\u51b3 PM \u67af\u71e5\u7684 approval pr \u5de5\u4f5c\uff0c\u672c\u6587\u5c06\u9610\u8ff0\u5982\u4f55\u81ea\u52a8\u5316\u83b7\u53d6 GitHub Organization \u4e0b\u5404\u4e2a repo \u5f85 merge \u7684 pull requests \u5e76\u901a\u77e5\u76f8\u5173\u4eba\u5458\uff0c\u544a\u522b\u6bcf\u65e5\u7684\u624b\u52a8\u64cd\u4f5c\u3002<\/p>\n<p><img decoding=\"async\" src=\"http:\/\/4563.org\/wp-content\/uploads\/2020\/06\/20200628_5ef909c7c75e0.png\" alt=\"\u9489\u9489\u673a\u5668\u4eba\u81ea\u52a8\u5173\u8054 GitHub \u53d1\u9001 approval prs\" \/><\/p>\n<p>\u5728\u65e5\u5e38\u5de5\u4f5c\u4e2d\uff0c\u4f60\u662f\u5426\u9047\u5230\u4ee5\u4e0b\u573a\u666f\uff1a<\/p>\n<ul>\n<li>Github \u5b58\u5728\u591a\u4e2a repo\uff0c\u65e5\u5e38\u5de5\u4f5c\u4e2d\u9700\u8981\u4e00\u4e2a\u4e2a\u5730\u624b\u52a8\u7b5b\u9009\u5927\u91cf\u5f85 merge \u7684 pull requests<\/li>\n<li>\u8981\u627e\u51fa\u591a\u4e2a repo \u4e2d <code>ready to review<\/code>\u00a0\u7684 pull requests\uff0c\u8981\u624b\u52a8\u7b5b\u9009\uff0c\u7136\u540e\u4e00\u904d\u53c8\u4e00\u904d\u5730\u7c98\u8d34\u590d\u5236\u63d0\u4ea4 dev \u8fdb\u884c review #\u500d\u611f\u65e0\u804a<\/li>\n<li>\u60f3\u81ea\u52a8\u63a8\u9001 GitHub \u5f85 merge \u7684 prs\uff0cGitHub Webhooks \u5374\u6ca1\u6709\u8be5 Event<\/li>\n<li>\u2026\u2026<\/li>\n<\/ul>\n<p>\u7528\u6280\u672f\u6765\u89e3\u51b3 PM \u67af\u71e5\u7684 approval pr \u5de5\u4f5c\uff0c\u672c\u6587\u5c06\u9610\u8ff0\u5982\u4f55\u81ea\u52a8\u5316\u83b7\u53d6 GitHub Organization \u4e0b\u5404\u4e2a repo \u5f85 merge \u7684 pull requests \u5e76\u901a\u77e5\u76f8\u5173\u4eba\u5458\uff0c\u544a\u522b\u6bcf\u65e5\u7684\u624b\u52a8\u64cd\u4f5c\u3002\u6b64\u6587\u4e3b\u8981\u63d0\u4f9b\u4e86\u89e3\u51b3\u81ea\u52a8\u53d1\u9001 approval prs \u7684\u601d\u8def\uff0c\u5e76\u4ee5\u9489\u9489\u7fa4\u548c Slack \u4e3a\u4f8b\uff0c\u7ed9\u51fa\u4e86\u5176 Python \u7684\u5b9e\u73b0\u65b9\u5f0f\uff0c\u5982\u679c\u4f60\u4f7f\u7528\u5176\u4ed6\u901a\u8baf\u5de5\u5177\uff0c\u5b9e\u73b0\u539f\u7406\u662f\u76f8\u901a\u7684\u3002<\/p>\n<h2>\u914d\u7f6e\u6d88\u606f\u63a5\u6536<\/h2>\n<h3>\u914d\u7f6e\u9489\u9489\u7fa4\u673a\u5668\u4eba<\/h3>\n<ol>\n<li>\u6253\u5f00\u673a\u5668\u4eba\u7ba1\u7406\u9875\u9762\u3002\u4ee5 PC \u7aef\u4e3a\u4f8b\uff0c\u6253\u5f00 PC \u7aef\u9489\u9489\uff0c\u70b9\u51fb\u201c\u7fa4\u8bbe\u7f6e\u201d =&gt; \u201c\u667a\u80fd\u7fa4\u52a9\u624b\u201d =&gt; \u201c\u6dfb\u52a0\u673a\u5668\u4eba\u201d\u3002<\/li>\n<\/ol>\n<p><img decoding=\"async\" src=\"http:\/\/4563.org\/wp-content\/uploads\/2020\/06\/20200628_5ef909cdb1cb6.png\" alt=\"\u9489\u9489\u673a\u5668\u4eba\u81ea\u52a8\u5173\u8054 GitHub \u53d1\u9001 approval prs\" \/><\/p>\n<ol>\n<li>\u70b9\u51fb\u201c\u6dfb\u52a0\u673a\u5668\u4eba\u201d\uff0c\u9009\u62e9\u201c\u81ea\u5b9a\u4e49\u201d<\/li>\n<\/ol>\n<p><img decoding=\"async\" src=\"http:\/\/4563.org\/wp-content\/uploads\/2020\/06\/\u9489\u9489\u673a\u5668\u4eba.png\" alt=\"\u9489\u9489\u673a\u5668\u4eba\u81ea\u52a8\u5173\u8054 GitHub \u53d1\u9001 approval prs\" \/><\/p>\n<p>\u672c\u4f8b\u7684\u201c\u5b89\u5168\u8bbe\u7f6e\u201d\u4f7f\u7528\u81ea\u5b9a\u4e49\u5173\u952e\u8bcd\u7684\u65b9\u5f0f\uff0c\u4e4b\u540e\u7ed9\u673a\u5668\u4eba\u6240\u53d1\u9001\u7684\u6d88\u606f\u4e2d\u5fc5\u987b\u5305\u542b\u6b64\u5904\u8bbe\u7f6e\u7684\u5173\u952e\u8bcd\u3002<\/p>\n<ol>\n<li>\u70b9\u51fb\u201c\u5b8c\u6210\u201d\uff0c\u83b7\u53d6 Webhook<\/li>\n<\/ol>\n<p>\u8be6\u7ec6\u7684\u9489\u9489 bot \u914d\u7f6e\u6587\u6863\u53ef\u53c2\u89c1\u5b98\u65b9\u6587\u6863\uff1ahttps:\/\/ding-doc.dingtalk.com\/doc#\/serverapi2\/qf2nxq\/26eaddd5<\/p>\n<h3>\u914d\u7f6e Slack bot<\/h3>\n<ul>\n<li>\u521b\u5efa\u4e00\u4e2a app \uff08\u94fe\u63a5\uff1ahttps:\/\/api.slack.com\/apps\uff09\uff0c\u8bbe\u7f6e App Name\uff0c\u9009\u62e9\u76ee\u6807 Slack Workspace<\/li>\n<li>\u5728\u5de6\u4fa7\u680f\u4e2d\u9009\u62e9 \u201cBasic Information\u201d =&gt; \u201cAdd features and functionality\u201d \u9009\u5728 \u201cBots\u201d<\/li>\n<\/ul>\n<p><img decoding=\"async\" src=\"http:\/\/4563.org\/wp-content\/uploads\/2020\/06\/20200628_5ef909e168dfd.png\" alt=\"\u9489\u9489\u673a\u5668\u4eba\u81ea\u52a8\u5173\u8054 GitHub \u53d1\u9001 approval prs\" \/><\/p>\n<ul>\n<li>\u5728\u5de6\u4fa7\u680f\u4e2d\u9009\u62e9 \u201cOAuth &amp; Permissions\u201d\uff0c\u5728 \u201cScopes\u201d \u4e2d\u70b9\u51fb \u201cAdd an OAuth Scope\u201d\uff0c\u6dfb\u52a0 <code>chat:write.public<\/code><\/li>\n<li>\u70b9\u51fb \u201cInstall App to Workspace\u201d<\/li>\n<li>\u83b7\u53d6 OAuth Access Token<\/li>\n<\/ul>\n<p>\u8be6\u7ec6\u7684 Slack bot \u914d\u7f6e\u6b65\u9aa4\u53c2\u89c1\u5b98\u65b9\u82f1\u6587\u6587\u6863\uff1ahttps:\/\/slack.com\/intl\/en-cn\/help\/articles\/115005265703-Create-a-bot-for-your-workspace#add-a-bot-user<\/p>\n<h2>\u914d\u7f6e Github \u83b7\u53d6 Personal Access Tokens<\/h2>\n<p>\u751f\u6210 Token\uff0c\u8d4b\u4e88\u76f8\u5e94\u6743\u9650\u3002\u5728\u6b64\u4f8b\u4e2d\uff0c\u8bfb\u53d6\u4e86 Organization \u4e0b\u6240\u6709 Public \u548c Private Repos\uff0c\u9700\u8981\u52fe\u9009 repo \u3002<\/p>\n<p><img decoding=\"async\" src=\"http:\/\/4563.org\/wp-content\/uploads\/2020\/06\/20200628_5ef909e691078.gif\" alt=\"\u9489\u9489\u673a\u5668\u4eba\u81ea\u52a8\u5173\u8054 GitHub \u53d1\u9001 approval prs\" \/><\/p>\n<p>\u8be6\u7ec6 GitHub Token \u914d\u7f6e\u6b65\u9aa4\u53c2\u89c1\u5b98\u65b9\u6587\u6863\uff1ahttps:\/\/help.github.com\/en\/github\/authenticating-to-github\/creating-a-personal-access-token-for-the-command-line<\/p>\n<h2>\u4ee3\u7801\u8bf4\u660e<\/h2>\n<h3>\u83b7\u53d6 Github \u5f85 merge pr<\/h3>\n<p>PyGithub \u63d0\u4f9b\u4e86\u8bbf\u95ee Github V3 API \u7684\u529f\u80fd\uff0c\u53ef\u4ee5\u8ba9\u4f60\u7528\u4ee3\u7801\u53bb\u5b9e\u73b0 GitHub \u4e0a\u7684\u64cd\u4f5c\uff0c\u53ef\u901a\u8fc7 <code>pip install pygithub<\/code>\u00a0\u8fdb\u884c\u5b89\u88c5\u3002<\/p>\n<pre><code>FILTER_TEMPLATE = \"repo:{org}\/{repo} is:pr is:open review:approved\"  class GithubPrList:      @property     def gh(self):         return self._gh      @property     def org(self):         return self._org      FILTER_TEMPLATE = \"repo:{org}\/{repo} is:pr is:open review:approved\"      def __init__(self,                  org,                  repo,                  login_or_token,                  password=None,                  timeout=DEFAULT_CONNECT_TIMEOUT,                  retry=None,                  ):         \"\"\"         :param org: string         :param repo: string         :param login_or_token: string\uff0ctoken or username         :param password: string         :param timeout: integer         :param retry: int or urllib3.util.retry.Retry object         \"\"\"         #\u5b9e\u4f8b\u5316\u5bf9 Github API v3 \u7684\u8bbf\u95ee         self._gh = Github(login_or_token=login_or_token,                           password=password,                           timeout=timeout,                           retry=retry)         self._org = org         self._repo = repo    def getIssues(self,                       filter=None,                        sort=DEFAULT_PR_SORT,                        order=DEFAULT_ORDER,                        ):         \"\"\"         :param filter: string         :param order: string ('asc', 'desc')         :param sort: string('comments', 'created', 'updated')         :rtype :class:`List` of :class:`PrList2.PrElement`         \"\"\"         if not filter:           #\u751f\u6210\u67e5\u8be2\u7684 filter\uff0c\u6307\u5b9a org\/repo \u4e0b\u5df2\u7ecf approved \u7684 pr             filter = self.FILTER_TEMPLATE.format(org=self._org,                                                  repo=self._repo)         #\u67e5\u8be2         issues = self._gh.search_issues(filter, sort, order)         prList = []          for issue in issues:             prList.append(PrElement(issue.number, issue.title, issue.html_url))          return prList <\/code><\/pre>\n<p>\u51fd\u6570\u8bf4\u660e\uff1a<\/p>\n<ul>\n<li><code>__init__<\/code>\u00a0\u652f\u6301\u4f7f\u7528 username\/ password \u6216\u8005 token \u53bb\u5b9e\u4f8b\u5316\u5bf9 GitHub API V3 \u7684\u8bbf\u95ee\uff08\u82f1\u8bed\u662f instantiate to access the Github API v3 \uff09\u3002<\/li>\n<li>\u5728 Github \u4e2d\uff0cpull requests \u4e5f\u662f issues\uff0c<code>getIssues()<\/code> \u51fd\u6570\u5141\u8bb8\u7528\u6237\u53ef\u4f7f\u7528\u9ed8\u8ba4\u6761\u4ef6\uff08<code>repo:{org}\/{repo} is:pr is:open review:approved<\/code>\uff09\u67e5\u627e\u6307\u5b9a org\/repo \u4e0b\u72b6\u6001\u662f Approved \u7684 pull requests\uff0c\u4e5f\u5c31\u662f\u5f85 merge \u7684 prs \u3002\u5176\u4e2d:<\/li>\n<\/ul>\n<p><img decoding=\"async\" src=\"http:\/\/4563.org\/wp-content\/uploads\/2020\/06\/20200628_5ef909ec8bc9c.png\" alt=\"\u9489\u9489\u673a\u5668\u4eba\u81ea\u52a8\u5173\u8054 GitHub \u53d1\u9001 approval prs\" \/><\/p>\n<p>\u7528\u6237\u4e5f\u53ef\u6307\u5b9a Github issues \u7684\u7b5b\u9009\u6761\u4ef6\uff0c\u4f7f\u7528\u793a\u4f8b\uff1a<\/p>\n<pre><code>filter = \"repo:myOrg\/myRepo is:pr is:open review:approved\" GithubPrList(self.org,         self.repo,                self.token).getIssues(filter) <\/code><\/pre>\n<p>\u66f4\u591a\u7b5b\u9009\u6761\u4ef6\uff0c\u8bf7\u53c2\u89c1\u5b98\u65b9\u6587\u6863\uff1ahttps:\/\/help.github.com\/en\/github\/searching-for-information-on-github\/searching-issues-and-pull-requests<\/p>\n<h3>\u53d1\u9001\u6d88\u606f<\/h3>\n<h4>\u53d1\u9001\u9489\u9489\u6d88\u606f<\/h4>\n<p>DingtalkChatbot \u5bf9\u9489\u9489\u6d88\u606f\u7c7b\u578b\u8fdb\u884c\u4e86\u5c01\u88c5\u3002\u672c\u6587\u4f7f\u7528\u6b64\u5de5\u5177\u53d1\u9001\u5f85 merge \u7684 pr \u5230\u9489\u9489\u7fa4\uff0c\u53ef\u901a\u8fc7 <code>pip install DingtalkChatbot<\/code>\u00a0\u5b89\u88c5 DingtalkChatbot \u3002<\/p>\n<pre><code>from dingtalkchatbot.chatbot import DingtalkChatbot  webhook = \"https:\/\/oapi.dingtalk.com\/robot\/send?access_token=xxxxxxxxxx\" atPerson = [\"123xxx456\",\"123xxx678\"]  xiaoding = DingtalkChatbot(webhook) xiaoding.sendMsg({\u81ea\u5b9a\u4e49\u5173\u952e\u8bcd} + \"\u4e0a\u6587\u4e2d\u7684 pr list\", atPerson) <\/code><\/pre>\n<p>\u5c06\u6d88\u606f\u53d1\u9001\u5230\u9489\u9489\u7fa4\uff0c\u6b64\u5904\u9700\u8981\u7528\u5230\u4e0a\u6587\u4e2d\u7684\u9489\u9489\u7fa4\u673a\u5668\u4eba\u7684 Webhook \u548c\u81ea\u5b9a\u4e49\u7684\u5173\u952e\u8bcd\u3002<\/p>\n<h4>\u53d1\u9001 slack \u6d88\u606f<\/h4>\n<p>Python slackclient \u662f Slack \u5f00\u53d1\u7684\u5b98\u65b9 API \u5e93\uff0c\u80fd\u591f\u4ece Slack \u9891\u9053\u4e2d\u83b7\u53d6\u4fe1\u606f\uff0c\u4e5f\u80fd\u5c06\u4fe1\u606f\u53d1\u9001\u5230 Slack \u9891\u9053\u4e2d\uff0c\u652f\u6301 Python 3.6 \u53ca\u4ee5\u4e0a\u7248\u672c\u3002\u53ef\u901a\u8fc7 <code>pip3 install slackclient<\/code> \u8fdb\u884c\u5b89\u88c5\u3002<\/p>\n<pre><code>from slack import WebClient from slack.errors import SlackApiError  client = WebClient(token={your_token})  try:     response = client.chat_postMessage(         channel='#{channel_name}',         text=\"Hello world!\")     assert response[\"message\"][\"text\"] == {pr_list} except SlackApiError as e:     # You will get a SlackApiError if \"ok\" is False     assert e.response[\"ok\"] is False     assert e.response[\"error\"]  # str like 'invalid_auth', 'channel_not_found'     print(f\"Got an error: {e.response['error']}\") <\/code><\/pre>\n<p>\u7528\u4e0a\u6587\u914d\u7f6e\u7684 token \u66ff\u6362\u6b64\u5904\u7684 {your_token}\uff0c\u66ff\u6362 {channel_name}\uff0c\u5c06 pr_list \u53d1\u9001\u7ed9\u76ee\u6807 channel \u3002<\/p>\n<p>\u81f3\u6b64\uff0c\u5927\u529f\u544a\u6210\uff01\u6765\u770b\u770b\u6548\u679c<\/p>\n<p><img decoding=\"async\" src=\"http:\/\/4563.org\/wp-content\/uploads\/2020\/06\/20200628_5ef909f1b270e.png\" alt=\"\u9489\u9489\u673a\u5668\u4eba\u81ea\u52a8\u5173\u8054 GitHub \u53d1\u9001 approval prs\" \/><\/p>\n<p>\u672c\u6587\u4e2d\u5982\u6709\u4efb\u4f55\u9519\u8bef\u6216\u758f\u6f0f\uff0c\u6b22\u8fce\u53bb GitHub\uff1ahttps:\/\/github.com\/vesoft-inc\/nebula issue \u533a\u5411\u6211\u4eec\u63d0 issue \u6216\u8005\u524d\u5f80\u5b98\u65b9\u8bba\u575b\uff1ahttps:\/\/discuss.nebula-graph.com.cn\/ \u7684 <code>\u5efa\u8bae\u53cd\u9988<\/code> \u5206\u7c7b\u4e0b\u63d0\u5efa\u8bae       <\/div>\n<div> <b>\u5927\u4f6c\u6709\u8a71\u8aaa<\/b> (<span>6<\/span>)        <\/div>\n<div> <\/div>\n<\/p><\/div>\n<\/p><\/div>\n<ul>\n<li data-pid=\"2102664\" data-uid=\"2\">\n<div>\n<div>\n<div> <span>\u8cc7\u6df1\u5927\u4f6c : hantsy <\/span>  <\/div>\n<div> <i title=\"\u5f15\u7528\"><\/i>  <span>          <\/span> <\/div>\n<\/p><\/div>\n<div>                                                             \u5509\uff0cSlack \u4e2d\u7528\u6765\u63a5\u6536\u5404\u79cd\u901a\u77e5\uff0c\u5df2\u7ecf\u7528\u4e86\u597d\u591a\u5e74\u4e86\u3002<\/p>\n<p>\u641e\u534a\u5929\u8fd8\u662f\u5229\u7528 SlackBot\uff0c\u6211\u8fd8\u4ee5\u4e3a\u9489\u81ea\u5df1\u8ddf\u4e0a\u811a\u6b65\u4e86\u3002\u6628\u5929\u770b\u770b\u9489\u9489\u7684\u7537\u88c5\u89c6\u9891\uff0c\u9e21\u76ae\u7599\u7629\u90fd\u8d77\u6765\u4e86\u3002                                                            <\/p><\/div>\n<\/p><\/div>\n<\/li>\n<li data-pid=\"2102665\" data-uid=\"2\">\n<div>\n<div>\n<div> <span>\u8cc7\u6df1\u5927\u4f6c : hantsy <\/span>  <\/div>\n<div> <i title=\"\u5f15\u7528\"><\/i>  <span>          <\/span> <\/div>\n<\/p><\/div>\n<div>                                                             \u4f60\u8fd9\u4e2a\u4f53\u9a8c\u4e0e Slack \u5dee\u5f97\u6709\u70b9\u8fdc\uff0cSlack \u4e2d\u5f88\u591a\u6df1\u5ea6\u96c6\u6210\u7684\u5de5\u5177\uff0c\u53ef\u4ee5\u76f4\u63a5\u5728 Slack \u4e2d\u8fdb\u884c\u64cd\u4f5c\uff0c\u4e0d\u9700\u8981\u518d\u8df3\u5230\u539f\u6709\u7684\u7cfb\u7edf\u754c\u9762\u4e0a\u53bb\u64cd\u4f5c\u3002                                                            <\/div>\n<\/p><\/div>\n<\/li>\n<li data-pid=\"2102666\" data-uid=\"2\">\n<div>\n<div>\n<div> <span>\u4e3b<\/span> <span>\u8cc7\u6df1\u5927\u4f6c : NebulaGraph <\/span>  <\/div>\n<div> <i title=\"\u5f15\u7528\"><\/i>  <span>          <\/span> <\/div>\n<\/p><\/div>\n<div>                                                             @hantsy \u6211\u4eec\u4e3b\u8981\u662f\u4e3a\u4e86\u4f7f\u7528\u540c\u4e00\u4e2a\u5957\u903b\u8f91\u53bb\u9002\u914d Slack \u548c\u9489\u9489\uff0cbtw\uff0c\u9489\u9489\u7684\u201c\u5973\u201d\u88c5\u89c6\u9891\u770b\u4e2a\u622a\u56fe\u5c31\u597d                                                             <\/div>\n<\/p><\/div>\n<\/li>\n<li data-pid=\"2102667\" data-uid=\"2\">\n<div>\n<div>\n<div> <span>\u8cc7\u6df1\u5927\u4f6c : hantsy <\/span>  <\/div>\n<div> <i title=\"\u5f15\u7528\"><\/i>  <span>          <\/span> <\/div>\n<\/p><\/div>\n<div>                                                             \u5f88\u591a\u56fd\u5916\u5df2\u7ecf\u5f88\u591a\u4ea7\u54c1\u5728\u505a GitOps\uff0cChatOps \u7b49\u7406\u5ff5\uff0c\u4e0e \u8f6f\u4ef6\u5de5\u7a0b\uff0c\u8f6f\u4ef6\u4ea4\u4ed8\u8fc7\u7a0b \u7d27\u5bc6\u76f8\u7ed3\u5408\u7684\uff0c\u66f4\u597d\u5b9e\u73b0\u4ea4\u4ed8\u81ea\u52a8\u5316\u3002<\/p>\n<p>Spring \u7684\u4ed6\u59cb\u4eba\uff08\u5df2\u7ecf\u8131\u79bb Spring \u5f88\u4e45\u4e86\uff09 Johnson \u7684\u65b0\u516c\u53f8\u4e5f\u662f\u505a\u4e00\u6b3e\u8f6f\u4ef6\u4ea4\u4ed8\u7684\u4ea7\u54c1\u3002<\/p>\n<p>https:\/\/atomist.com\/ <\/p>\n<p>\u4ee5\u524d\u770b\u8fc7\u4e00\u7bc7\u6587\u7ae0\uff0c\u53ef\u4ee5\u5728 Slack \u76d1\u63a7\u670d\u52a1\u5668\u4e2d APP \u8fd0\u884c\u72b6\u6001\u7b49\uff0c\u4e5f\u53ef\u4ee5\u901a\u8fc7 Slack \u547d\u4ee4\u7c7b\u4f3c \/start \u8fd9\u6837\u7684\u6d88\u606f\uff0c\u53bb\u91cd\u542f\uff0c\u90e8\u7f72\uff0cScale \u5e94\u7528\u3002                                                            <\/p><\/div>\n<\/p><\/div>\n<\/li>\n<li data-pid=\"2102668\" data-uid=\"2\">\n<div>\n<div>\n<div> <span>\u4e3b<\/span> <span>\u8cc7\u6df1\u5927\u4f6c : NebulaGraph <\/span>  <\/div>\n<div> <i title=\"\u5f15\u7528\"><\/i>  <span>          <\/span> <\/div>\n<\/p><\/div>\n<div>                                                             @hantsy Slack \u679c\u7136\u5f3a\u5927\uff0c\u6211\u4eec\u5185\u90e8\u8fd8\u662f\u7528\u7684\u9489\u9489\uff0cSlack \u4e3b\u8981\u662f\u7ed9\u56fd\u9645\u53cb\u4eba\u6765\u53cd\u9988\u4fe1\u606f\u7528\u7684                                                            <\/div>\n<\/p><\/div>\n<\/li>\n<li data-pid=\"2102669\" data-uid=\"2\">\n<div>\n<div>\n<div> <span>\u8cc7\u6df1\u5927\u4f6c : xiaochun41 <\/span>  <\/div>\n<div> <i title=\"\u5f15\u7528\"><\/i>  <span>          <\/span> <\/div>\n<\/p><\/div>\n<div>                                                             ChatOps \u7684\u7406\u5ff5\u8fd8\u662f\u5f88\u597d\u7684\uff0c\u81ea\u5df1\u5e2e\u56e2\u961f\u4e5f\u505a\u8fc7\u4e00\u4e9b\u5c1d\u8bd5\uff0c\u63d0\u6548\u8fd8\u662f\u5f88\u660e\u663e\u7684                                                            <\/div>\n<\/p><\/div>\n<\/li>\n<li>\n","protected":false},"excerpt":{"rendered":"<p>\u9489\u9489\u673a\u5668\u4eba\u81ea\u52a8\u5173\u8054 GitHub &hellip;<\/p>\n","protected":false},"author":1,"featured_media":0,"comment_status":"open","ping_status":"open","sticky":false,"template":"","format":"standard","meta":[],"categories":[],"tags":[],"_links":{"self":[{"href":"http:\/\/4563.org\/index.php?rest_route=\/wp\/v2\/posts\/126557"}],"collection":[{"href":"http:\/\/4563.org\/index.php?rest_route=\/wp\/v2\/posts"}],"about":[{"href":"http:\/\/4563.org\/index.php?rest_route=\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"http:\/\/4563.org\/index.php?rest_route=\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"http:\/\/4563.org\/index.php?rest_route=%2Fwp%2Fv2%2Fcomments&post=126557"}],"version-history":[{"count":1,"href":"http:\/\/4563.org\/index.php?rest_route=\/wp\/v2\/posts\/126557\/revisions"}],"predecessor-version":[{"id":126559,"href":"http:\/\/4563.org\/index.php?rest_route=\/wp\/v2\/posts\/126557\/revisions\/126559"}],"wp:attachment":[{"href":"http:\/\/4563.org\/index.php?rest_route=%2Fwp%2Fv2%2Fmedia&parent=126557"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"http:\/\/4563.org\/index.php?rest_route=%2Fwp%2Fv2%2Fcategories&post=126557"},{"taxonomy":"post_tag","embeddable":true,"href":"http:\/\/4563.org\/index.php?rest_route=%2Fwp%2Fv2%2Ftags&post=126557"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}