我可以通过 GitHub API 添加新的分支保护规则吗?

Mik*_*ard 10 github-api

我知道您可以通过 API 更新现有的分支保护规则,但我在 v3 API 文档 WRT 创建新规则时找不到任何参考。例如,如果我想向与前缀为“dev_”的新分支匹配的存储库添加一条规则,我必须使用“将规则应用于”字段通过 GUI 添加它,然后我可以使用 API 来更新那些规则设置。理想情况下,我希望有一个钩子,如果将新分支引入到存储库,但与现有规则不匹配,它可以自动执行此操作。我应该能够通过 API 创建该规则。有没有办法做到这一点?

Soc*_*j07 7

对于那些现在发现这一点的人来说,仅供参考 - 有一个 API,因此如果您不想,则不必使用 GraphQL。

https://docs.github.com/en/enterprise-cloud@latest/rest/branches/branch-protection#update-branch-protection

curl \
  -X PUT \
  -H "Accept: application/vnd.github+json" \
  -H "Authorization: token <TOKEN>" \
  https://api.github.com/repos/OWNER/REPO/branches/BRANCH/protection \
  -d '{"required_status_checks":{"strict":true,"contexts":["continuous-integration/travis-ci"]},"enforce_admins":true,"required_pull_request_reviews":{"dismissal_restrictions":{"users":["octocat"],"teams":["justice-league"]},"dismiss_stale_reviews":true,"require_code_owner_reviews":true,"required_approving_review_count":2,"bypass_pull_request_allowances":{"users":["octocat"],"teams":["justice-league"]}},"restrictions":{"users":["octocat"],"teams":["justice-league"],"apps":["super-ci"]},"required_linear_history":true,"allow_force_pushes":true,"allow_deletions":true,"block_creations":true,"required_conversation_resolution":true}'
Run Code Online (Sandbox Code Playgroud)

编辑:尽管 API 说这是针对 的update,但它也确实创建了新的分支保护规则。

  • @lukekarrys 我猜这就是他们的标题(“更新”),但我可以确认这确实创建了新的分支保护规则。 (4认同)
  • 该API仅用于更新现有分支保护规则的详细信息。这并没有回答如何“创建”分支保护规则的原始问题。 (2认同)

Sim*_*ane 6

GitHub 似乎决定仅通过 GraphQL API 添加新功能,而不是通过 REST API。因此,虽然这对于 REST API 来说是不可能的,但您可以使用 GraphQLcreateBranchProtectionRule突变来做到这一点。

如果它对任何人有帮助,我使用GitHub 的ghCLI编写了一个脚本来执行此操作:

#!/bin/bash
set -ue
err() { echo 1>&2 "$*"; }
die() { err "ERROR: $*"; exit 1; }
mustBool() {
        [[ "${1#*=}" = "true" || "${1#*=}" = "false" ]] ||
                die "bad boolean property value: $1"
}
mustInt() {
        [[ "${1#*=}" =~ [0-9]+ ]] ||
                die "bad integer property value: $1"
}

[ $# -ge 4 ] || {
        err "usage: $0 HOSTNAME ORG REPO PATTERN [PROPERTIES...]"
        err "   where PROPERTIES can be:"
        err "           dismissesStaleReviews=true|false"
        err "           requiresApprovingReviewCount=INTEGER"
        err "           requiresApprovingReviews=true|false"
        err "           requiresCodeOwnerReviews=true|false"
        err "           restrictPushes=true|false"
        exit 1
}
hostname="$1"
org="$2"
repo="$3"
pattern="$4"
shift 4

repoNodeId="$(gh api --hostname "$hostname" "repos/$org/$repo" --jq .node_id)"
[[ -n "$repoNodeId" ]] || die "could not determine repo nodeId"

graphql="
mutation createBranchProtectionRule {
        createBranchProtectionRule(input: {
                repositoryId: \"$repoNodeId\"
                pattern: \"$pattern\""

seen=()
requiredStatusCheckContexts=()
for property in "$@"; do
        for eSeen in "${seen[@]:-}"; do
                [[ "${eSeen%%=*}" = "${property%%=*}" ]] &&
                # Allow duplication of multivalued properties
                [[ "${eSeen%%=*}" != "requiredStatusCheckContexts" ]] &&
                die "Duplicate property: $property"
        done
        seen+=("${property}")

        case "$property" in
        requiredStatusCheckContexts=*)
                requiredStatusCheckContexts+=("${property#*=}")
                ;;
        \
                allowsDeletions=* | \
                allowsForcePushes=* | \
                dismissesStaleReviews=* | \
                isAdminEnforced=* | \
                requiresApprovingReviews=* | \
                requiresCodeOwnerReviews=* | \
                requiresCommitSignatures=* | \
                requiresLinearHistory=* | \
                requiresStatusChecks=* | \
                requiresStrictStatusChecks=* | \
                restrictPushes=* | \
                restrictsPushes=* | \
                restrictsReviewDismissals=* \
        )
                mustBool "$property"
                graphql="$graphql
                ${property%%=*}: ${property#*=}"
                ;;
        requiredApprovingReviewCount=*)
                mustInt "$property"
                graphql="$graphql
                ${property%%=*}: ${property#*=}"
                ;;
        *)
                die "unknown property: $property"
        esac
done

if [ -n "${requiredStatusCheckContexts[*]:-}" ]; then
        graphql="$graphql
                requiredStatusCheckContexts: [
"
        i=0
        for context in "${requiredStatusCheckContexts[@]}"; do
                [ $i -ne 0 ] && graphql="$graphql,
"
                i=$((1+$i))
                graphql="$graphql"$'\t\t\t'"\"$context\""
        done
        graphql="$graphql
                ]
"
fi

graphql="$graphql
        }) {
                branchProtectionRule {
                        allowsDeletions
                        allowsForcePushes
                        creator { login }
                        databaseId
                        dismissesStaleReviews
                        isAdminEnforced
                        pattern
                        repository { nameWithOwner }
                        requiredApprovingReviewCount
                        requiresApprovingReviews
                        requiredStatusCheckContexts
                        requiresCodeOwnerReviews
                        requiresCommitSignatures
                        requiresLinearHistory
                        requiresStatusChecks
                        requiresStrictStatusChecks
                        restrictsPushes
                        restrictsReviewDismissals
                }
                clientMutationId
        }
}"

gh api --hostname "$hostname" graphql -F "query=$graphql" ||
        die "GraphQL update failed: $graphql"
echo ""
echo "SUCCESS: Branch protection rule successfully created"
Run Code Online (Sandbox Code Playgroud)

这是调用它的示例:

./createBranchProtectionRule.sh github.example.com skissane my-repo v* requiresApprovingReviews=true requiresCodeOwnerReviews=true requiredApprovingReviewCount=1 requiresStatusChecks=true requiresStrictStatusChecks=false requiredStatusCheckContexts=continuous-integration/jenkins/pr-merge requiresLinearHistory=true
Run Code Online (Sandbox Code Playgroud)

产生以下输出:

{
  "data": {
    "createBranchProtectionRule": {
      "branchProtectionRule": {
        "allowsDeletions": false,
        "allowsForcePushes": false,
        "creator": {
          "login": "skissane"
        },
        "databaseId": 1729,
        "dismissesStaleReviews": false,
        "isAdminEnforced": false,
        "pattern": "v*",
        "repository": {
          "nameWithOwner": "skissane/my-repo"
        }
        "requiredApprovingReviewCount": 1,
        "requiresApprovingReviews": true,
        "requiredStatusCheckContexts": [
          "continuous-integration/jenkins/pr-merge"
        ],
        "requiresCodeOwnerReviews": true,
        "requiresCommitSignatures": false,
        "requiresLinearHistory": true,
        "requiresStatusChecks": true,
        "requiresStrictStatusChecks": false,
        "restrictsPushes": false,
        "restrictsReviewDismissals": false
      },
      "clientMutationId": null
    }
  }
}

SUCCESS: Branch protection rule successfully created
Run Code Online (Sandbox Code Playgroud)


Fil*_*lov 2

这为我的 GitHub Enterprise 做到了。

curl --location --request PUT 'https://github.company.com/api/v3/repos/ORG/REPO-NAME/branches/BRANCH-NAME/protection' \
--header 'Accept: application/vnd.github.v3+json' \
--header 'Accept: application/vnd.github.luke-cage-preview+json' \
--header 'Authorization: Basic .................... \
--header 'Content-Type: text/plain' \
--data-raw '{
    "required_status_checks": {
        "strict": false,
        "contexts": ["continuous-integration/jenkins/BRANCH-NAME"]
    },
    "enforce_admins": true,
    "required_pull_request_reviews": {
        "dismissal_restrictions": {},
        "dismiss_stale_reviews": true,
        "require_code_owner_reviews": true,
        "required_approving_review_count": 1
    },
    "restrictions": {
        "users": ["users"],
        "teams": ["teams"],
        "apps": ["apps"]
    }
}
'
Run Code Online (Sandbox Code Playgroud)

  • 这不是问题所问的。问题是如何通过 API 创建*基于名称模式*的分支保护规则,而不仅仅是针对单个命名分支的规则。 (2认同)