第88节 Github Webhook


❤️💕💕记录sealosopen in new window开源项目的学习过程。k8s,docker和云原生的学习open in new window。Myblog:http://nsddd.topopen in new window


[TOC]

什么是 GitHub webhook

Webhook 提供了一种在 GitHub 上发生某些事件时将通知传递到外部 Web 服务器的方法。

每当 GitHub 上发生特定事件时,都可以触发 Webhook。例如,您可以将 Webhook 配置为在以下情况下触发:

  • 将代码推送到存储库
  • 拉取请求已打开
  • 构建了 GitHub 页面网站
  • 将新成员添加到团队

您可以将 Webhook 添加到组织、仓库或 GitHub 应用程序。

添加网络钩子时,您可以选择要订阅的事件。若要限制对服务器的 HTTP 请求数,应仅订阅计划处理的特定事件。默认情况下,安装在组织或仓库上的 Webhook 仅订阅推送事件。默认情况下,GitHub 应用程序上的网络钩子不会订阅任何事件。您可以随时更改订阅 Webhook 的事件。有关 Webhook 事件的完整列表,请参阅“Webhook 事件和有效负载”。

curl -v -X POST https://api.github.com/repos/<owner>/<repo>/hooks \
  -H "Accept: application/vnd.github.v3+json" \
  -H "Authorization: token <your-token>" \
  -d '{
    "name": "web",
    "active": true,
    "events": ["push", "pull_request"],
    "config": {
      "url": "http://example.com/webhook",
      "content_type": "json"
    }
  }'

关于存储库的 webhook

存储库 Webhook 允许您在存储库中发生某些事件时接收 HTTP 有效负载。您可以使用 REST API 来管理存储库、组织和应用程序 Webhook。您可以列出 Webhook 的 Webhook 投放,也可以获取并重新投放 webhook 的单个投放,这些投放可以集成到外部应用或服务中。您还可以使用 REST API 更改 Webhook 的配置。例如,您可以修改有效负载 URL、内容类型、SSL 验证和密钥。

PubSubHubbub

GitHub 还可以充当所有存储库的 PubSubHubbubopen in new window 中心。PSHBopen in new window 是一个简单的发布/订阅协议,允许服务器注册以在主题更新时接收更新。更新随 HTTP POST 请求一起发送到回调 URL。GitHub 存储库推送的主题 URL 采用以下格式:

https://github.com/{owner}/{repo}/events/{event}

Response format 相应格式

默认格式是现有接收后挂钩应期望的格式:作为 POST 中的参数发送的 JSON 正文。还可以指定接收带有标头或扩展的原始 JSON 正文。

Accept: application/json
https://github.com/{owner}/{repo}/events/push.json

callback URLs

回调 URL 可以使用 HTTP 协议。

# Send updates to a PostBin bin
https://www.toptal.com/developers/postbin/123

creating webhooks

创建网络钩子的过程分为两步。您首先需要设置 Webhook 应该侦听哪些事件。之后,您将设置服务器以接收和管理有效负载。

您可以使用 REST API 来管理存储库、组织和应用程序 Webhook。您可以列出 Webhook 的 Webhook 投放,也可以获取并重新投放 webhook 的单个投放,这些投放可以集成到外部应用或服务中。您还可以使用 REST API 更改 Webhook 的配置。例如,您可以修改有效负载 URL、内容类型、SSL 验证和密钥。有关详细信息。

将本地主机暴露给互联网

出于本教程的目的,我们将使用本地服务器从 GitHub 接收 Webhook 事件。

首先,我们需要将我们的本地开发环境公开给互联网,以便 GitHub 可以交付事件。我们将用来 ngrokopen in new window 此操作。

免费提供,适用于所有主要操作系统。有关详细信息,请参阅下载页面。

安装 后,您可以通过在命令行上运行来公开本地主机。 是我们的服务器将侦听消息的端口号。您应该看到如下所示的行:

https://d0bc-113-99-98-99.ngrok-free.app -> http://localhost:80

记下网址。我们将使用它来设置我们的网络钩子。

添加 webhook

只有具有组织所有者权限或仓库管理员权限的成员才能管理组织的 Webhook。更多信息请参阅“组织中的角色”。

要设置 Webhook,请转到仓库或组织的设置页面。从那里,单击网络钩子,然后单击添加网络钩子。

或者,您可以选择通过 Webhooks API 构建和管理 Webhook。

Webhook 需要一些配置选项才能使用它们。我们将在下面介绍这些设置中的每一个。

负载网址

负载 URL 是将接收 Webhook 请求的服务器的 URL POST

由于我们正在本地开发教程,因此我们将其设置为*.ngrok.ioURL,后跟/payload. 例如,http://7e9ea9dc.ngrok.io/payload.

内容类型

Webhook 可以使用不同的内容类型进行传递:

  • 内容application/json类型将直接传递 JSON 有效负载作为请求正文POST
  • 内容application/x-www-form-urlencoded类型将发送 JSON 有效负载作为名为 的表单参数payload

选择最适合您需求的一款。对于本教程,默认内容类型application/json就可以了。

内容类型

Webhook 可以使用不同的内容类型进行传递:

  • 内容application/json类型将直接传递 JSON 有效负载作为请求正文POST
  • 内容application/x-www-form-urlencoded类型将发送 JSON 有效负载作为名为 的表单参数payload

选择最适合您需求的一款。对于本教程,默认内容类型application/json就可以了。

秘密

设置 Webhook 密钥可让您确保POST发送到负载 URL 的请求来自 GitHub。设置机密后,您将收到Webhook 请求中的X-Hub-Signature和标头。有关如何使用带有签名标头的密钥来保护您的 Webhook 负载的更多信息,请参阅“保护您的 Webhook 的安全open in new window”。X-Hub-Signature-256``POST

ssh

如果您的“有效负载 URL”是安全站点 (HTTPS),您将可以选择配置 SSL 验证设置。如果您的“有效负载 URL”不安全 (HTTP),GitHub 将不会显示此选项。默认情况下,GitHub 在传送 Webhook 负载时验证您网站的 SSL 证书。SSL 验证有助于确保挂钩有效负载安全地传递到您的 URL 端点。您可以选择禁用 SSL,但我们建议保持选中**“启用 SSL 验证”**。

默认情况下,Webhook 传送处于“活动”状态。您可以通过取消选择“活动”来选择禁用 Webhook 有效负载的传送。

活动

事件是 Webhooks 的核心。每当对存储库执行特定操作时,这些 Webhook 就会触发,您的服务器的有效负载 URL 会拦截该存储库并对其进行操作。

Webhook 事件及其执行时间的完整列表可以在webhooks APIopen in new window参考中找到。

由于我们的 webhook 正在处理存储库中的问题,因此我们将单击Let me select individual events,然后单击Issues。确保选择**“活动”**以接收触发的 Webhook 的问题事件。您还可以使用默认选项选择所有事件。

完成后,点击添加 webhook

现在您已经创建了 Webhook,是时候设置我们的本地服务器来测试 Webhook 了。请前往配置您的服务器open in new window以了解如何执行此操作。

保护 webhook

一旦您的服务器配置为接收有效负载,它将侦听发送到您配置的端点的任何有效负载。出于安全原因,您可能希望将请求限制为来自 GitHub 的请求。有几种方法可以解决此问题(例如,您可以选择允许来自 GitHub IP 地址的请求),但更简单的方法是设置秘密令牌并验证信息。

Github CRL

我希望通过 github cli 来解决一个问题:

我希望希望获取到后面的那个数字,这个数字得到的一个值就是 issue 的编号

ISSUEID=$(gh pr view 642 --repo OpenIMSDK/Open-IM-Server | grep -oP 'Fixes #\K\d+')

拿到 Issue 编号后,我还需要 通过 issue 编号 获取到 对应的 issue 信息:

ISSUE=$(gh issue view $ISSUEID --repo OpenIMSDK/Open-IM-Server --json labels,assignees,milestone,title)
  • 获取到 labels 并且设置 PR 的 labels 和 issue 相同
  • 获取到 Assignees 并且设置 PR 的 Assignees 和 issue 相同
  • 获取到 Milestone 并且设置 PR 的 Milestone 和 issue 相同
  • 获取到 PR 的标题,并且设置为 TABLE
LABELS=$(echo $ISSUE | jq -r '.labels[] | select(.name) | .name')
# LABELS=$(echo $ISSUE | jq -r '.labels[] | select(.name) | .name' | jq -R -r -s -c 'split("\n")[:-1] | join(",")')
ASSIGNEES=$(echo $ISSUE | jq -r '.assignees[] | select(.login) | .login' | jq -R -s -c 'split("\n")[:-1] | join(",")')
MILESTONE=$(echo $ISSUE | jq -r '.milestone | select(.title) | .title')
TITLE=$(echo $ISSUE | jq -r '.title')

JQ:

root@PS2023EVRHNCXG:~/workspaces/openim/Open-IM-Server# echo $ISSUE | jq
{
  "assignees": [
    {
      "id": "MDQ6VXNlcjg2MTQwOTAz",
      "login": "cubxxw",
      "name": "Xinwei Xiong"
    }
  ],
  "labels": [
    {
      "id": "MDU6TGFiZWwzMDMyNTUxMTc1",
      "name": "enhancement",
      "description": "New feature or request",
      "color": "a2eeef"
    },
    {
      "id": "MDU6TGFiZWwzMDMyNTUxMTc3",
      "name": "good first issue",
      "description": "Denotes an issue ready for a new contributor, according to the \"help wanted\" guidelines.",
      "color": "7057ff"
    },
    {
      "id": "LA_kwDOFhyqls8AAAABRELYbA",
      "name": "kind/feature",
      "description": "Categorizes issue or PR as related to a new feature.",
      "color": "c7def8"
    }
  ],
  "milestone": {
    "number": 1,
    "title": "v3.1",
    "description": "https://github.com/OpenIMSDK/Open-IM-Server/tree/release-v3.1",
    "dueOn": null
  },
  "title": "OpenIM AI Feature Issue - Web-based Issue Generation and Analysis"
}

提一个 PR :

gh pr edit 642 --repo OpenIMSDK/Open-IM-Server --add-label "$LABELS" --add-assignee "$ASSIGNEES" --milestone "$MILESTONE"

更多:

root@PS2023EVRHNCXG:~/workspaces/openim/Open-IM-Server# echo $ISSUE | jq -r '.labels[] | select(.name) | .name'
enhancement
good first issue
kind/feature

受让:

  push:
    branches:
      - main
      
name: Assign issue to comment author
on:
  issue_comment:
    types: [created]
jobs:
  assign-issue:
    if: |
      contains(github.event.comment.body, '/assign') || contains(github.event.comment.body, '/accept') &&
      !contains(github.event.comment.user.login, 'openimbot') &&
      !contains(github.event.comment.user.login, 'kubbot')
    runs-on: ubuntu-latest
    permissions:
      issues: write
    steps:
      - name: Checkout code
        uses: actions/checkout@v3

      - name: Assign the issue
        run: |
          export LETASE_MILESTONES=$(curl 'https://api.github.com/repos/$OWNER/$PEPO/milestones' | jq -r 'last(.[]).title')
          gh issue edit ${{ github.event.issue.number }} --add-assignee "${{ github.event.comment.user.login }}"
          gh issue edit ${{ github.event.issue.number }} --add-label "triage/accepted"
          gh issue edit ${{ github.event.issue.number }} --milestone "$LETASE_MILESTONES"
          gh issue comment $ISSUE --body "@${{ github.event.comment.user.login }} Glad to see you accepted this issue🤲, this issue has been assigned to you. I set the milestones for this issue to [$LETASE_MILESTONES](https://github.com/$OWNER/$PEPO/milestones), We are looking forward to your PR!"
        env:
          GH_TOKEN: ${{ secrets.REDBOT_GITHUB_TOKEN }}
          ISSUE: ${{ github.event.issue.html_url }}
          OWNER: ${{ github.repository_owner }}
          REPO: ${{ github.event.repository.name }}

END 链接