釘釘機器人自動關聯 GitHub 發送 approval prs

摘要:用技術來解決 PM 枯燥的 approval pr 工做,本文將闡述如何自動化獲取 GitHub Organization 下各個 repo 待 merge 的 pull requests 並通知相關人員,告別每日的手動操做。html

釘釘機器人

在平常工做中,你是否遇到如下場景:python

  • Github 存在多個 repo,平常工做中須要一個個地手動篩選大量待 merge 的 pull requests
  • 要找出多個 repo 中 ready to review 的 pull requests,要手動篩選,而後一遍又一遍地粘貼複製提交 dev 進行 review #倍感無聊
  • 想自動推送 GitHub 待 merge 的 prs,GitHub Webhooks 卻沒有該 Event
  • ……

用技術來解決 PM 枯燥的 approval pr 工做,本文將闡述如何自動化獲取 GitHub Organization 下各個 repo 待 merge 的 pull requests 並通知相關人員,告別每日的手動操做。此文主要提供瞭解決自動發送 approval prs 的思路,並以釘釘羣和 Slack 爲例,給出了其 Python 的實現方式,若是你使用其餘通信工具,實現原理是相通的。git

配置消息接收

配置釘釘羣機器人

  1. 打開機器人管理頁面。以 PC 端爲例,打開 PC 端釘釘,點擊「羣設置」 => 「智能羣助手」 => 「添加機器人」。

dignding-chat-bot

  1. 點擊「添加機器人」,選擇「自定義」

釘釘機器人

本例的「安全設置」使用自定義關鍵詞的方式,以後給機器人所發送的消息中必須包含此處設置的關鍵詞。github

  1. 點擊「完成」,獲取 Webhook

詳細的釘釘 bot 配置文檔可參見官方文檔:https://ding-doc.dingtalk.com/doc#/serverapi2/qf2nxq/26eaddd5web

配置 Slack bot

  • 建立一個 app(連接:https://api.slack.com/apps),設置 App Name,選擇目標 Slack Workspace
  • 在左側欄中選擇 「Basic Information」 => 「Add features and functionality」 選在 「Bots」

slack-bot

  • 在左側欄中選擇 「OAuth & Permissions」,在 「Scopes」 中點擊 「Add an OAuth Scope」,添加 chat:write.public 
  • 點擊 「Install App to Workspace」
  • 獲取 OAuth Access Token

詳細的 Slack bot 配置步驟參見官方英文文檔:https://slack.com/intl/en-cn/help/articles/115005265703-Create-a-bot-for-your-workspace#add-a-bot-userc#

配置 Github 獲取 Personal Access Tokens

生成 Token,賦予相應權限。在此例中,讀取了 Organization 下全部 Public 和 Private Repos,須要勾選 repo。api

generate-github-tokens

詳細 GitHub Token 配置步驟參見官方文檔:https://help.github.com/en/github/authenticating-to-github/creating-a-personal-access-token-for-the-command-line安全

代碼說明

獲取 Github 待 merge pr

PyGithub 提供了訪問 Github V3 API 的功能,可讓你用代碼去實現 GitHub 上的操做,可經過 pip install pygithub 進行安裝。微信

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,token or username
        :param password: string
        :param timeout: integer
        :param retry: int or urllib3.util.retry.Retry object
        """
        #實例化對 Github API v3 的訪問
        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:
                #生成查詢的 filter,指定org/repo 下已經approved 的pr
            filter = self.FILTER_TEMPLATE.format(org=self._org,
                                                 repo=self._repo)
        #查詢
        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

函數說明:app

  • __init__ 支持使用 username/ password 或者 token 去實例化對 GitHub API V3的訪問(英語是 instantiate to access the Github API v3)。
  • 在 Github 中,pull requests 也是 issues,getIssues() 函數容許用戶可以使用默認條件(repo:{org}/{repo} is:pr is:open review:approved)查找指定 org/repo 下狀態是 Approved 的 pull requests,也就是待 merge 的 prs。其中:
Qualifier 說明
repo:org_/_repo 查找指定組織 repo 下的projects
is:pr 查找 pull requests
is:open 查找 open 的 issues
review:approved 查找 review 狀態是已經 approved,review status 可能取值 _none_、_required_、_approved_、_changes requested_

用戶也可指定 Github issues 的篩選條件,使用示例:

filter = "repo:myOrg/myRepo is:pr is:open review:approved"
GithubPrList(self.org, 
                            self.repo, 
              self.token).getIssues(filter)

更多篩選條件,請參見官方文檔:https://help.github.com/en/github/searching-for-information-on-github/searching-issues-and-pull-requests

發送消息

發送釘釘消息

DingtalkChatbot 對釘釘消息類型進行了封裝。本文使用此工具發送待 merge 的 pr 到釘釘羣,可經過 pip install DingtalkChatbot 安裝 DingtalkChatbot。

from dingtalkchatbot.chatbot import DingtalkChatbot

webhook = "https://oapi.dingtalk.com/robot/send?access_token=xxxxxxxxxx"
atPerson = ["123xxx456","123xxx678"]

xiaoding = DingtalkChatbot(webhook)
xiaoding.sendMsg({自定義關鍵詞} + "上文中的 pr list", atPerson)

將消息發送到釘釘羣,此處須要用到上文中的釘釘羣機器人的 Webhook 和自定義的關鍵詞。

發送 slack 消息

Python slackclient 是 Slack 開發的官方 API 庫,可以從 Slack 頻道中獲取信息,也能將信息發送到Slack頻道中,支持 Python 3.6 及以上版本。可經過 pip3 install slackclient 進行安裝。

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']}")

用上文配置的 token 替換此處的 {your_token},替換 {channel_name},將 pr_list 發送給目標 channel。

至此,大功告成!來看看效果

dingding-chat-bot-demo

本文中若有任何錯誤或疏漏,歡迎去 GitHub:https://github.com/vesoft-inc/nebula issue 區向咱們提 issue 或者前往官方論壇:https://discuss.nebula-graph.com.cn/建議反饋 分類下提建議 👏;加入 Nebula Graph 交流羣,請聯繫 Nebula Graph 官方小助手微信號:NebulaGraphbot

做者有話說:Hi,我是 Jude,圖數據 Nebula Graph 的 PM,歡迎你們提需求,雖然不必定都會實現,可是咱們會認真評估^ ^
相關文章
相關標籤/搜索