你还在手动操作Github吗?建议使用命令进行操作~~仓库管理篇~~

首先

你好,我是 @uchidash456!!最近我的生活方式发生了很多混乱,我正在忙着应对这些变化。

这次我们要谈的是“存储库混乱即心灵混乱”的问题,我将写一下关于将存储库管理命令化,以便能够统一管理一个存储库的经历。

背景- background

最近,AWS和GCP的代码管理已经变得司空见惯。在我的工作中,几乎所有的设置都是通过Terraform进行描述的。
与此同时,我们很少见到为了代码管理而维护的Github仓库。一旦设置好仓库,很少有需要频繁更改的情况,所以可能没有必要将其代码化。

根据我的经验,在每次新建存储库时都要进行相同的设置是很麻烦的,而且由于频率较低,我有时候会忘记平常的设置。特别是对于企业来说,往往有成百上千个存储库,管理变得模糊,容易出现不太好的存储库。后来可能会举行一次大清理…

我试着列举了微妙存储库的特点。

    • 管理人不在(レポジトリのステータスが不明。削除したいときに確認が手間。)

 

    • オプション設定が荒い(ブランチが保護されていない、デフォルトブランチに直 push できるなど)

 

    統一感の欠如(命名規則や Description の有無など)

代码管理的好处在于可以解决上述问题。相反地,代码管理的缺点可以列举如下。

    • コード化が手間

 

    Gihtub API 仕様が変更されてしまった場合に対応が必要

礼物 ?

我创建了一个名为 github_manager 的管理库,并将以下一系列库设置命令化。

    1. 创建存储库

如果存储库不存在,则会创建一个新的存储库。

更新存储库

更新默认分支名称、主题和描述等设置。

创建分支保护设置

创建分支保护规则。

更新分支保护设置

更新必须进行 PR、必须进行批准等设置。

t-rec.gif

電腦環境

# sw_vers
ProductName: macOS
ProductVersion: 12.6
BuildVersion: 21G115

# gh --version
gh version 2.23.0 (2023-02-07)

代码介绍

首先,我将介绍一部分实际的源代码。
首先,让我们提取创建和更新存储库的部分。

#!/bin/sh

set -u

readonly DEV_NULL=/dev/null

readonly OWNER_NAME=shoot16625
readonly REPO_NAME=github_manager
readonly LICENSE=MIT
readonly DEFAULT_BRANCH=main
readonly DESCRIPTION="Github を管理するレポジトリ"
readonly TOPICS="github,cli,gh"

# create repo
err_msg=$(gh repo view $OWNER_NAME/$REPO_NAME 2>&1 >/dev/null)
if [ -n "$err_msg" ]; then # if repo does not exist
 gh repo create $REPO_NAME --add-readme --public --license $LICENSE
fi

# update repo
gh repo edit $OWNER_NAME/$REPO_NAME --add-topic $TOPICS --default-branch $DEFAULT_BRANCH --delete-branch-on-merge --description "$DESCRIPTION"

在使用gh repo进行简化操作的同时,对于不支持的命令会使用gh api进行查询指定。(参考:GitHub CLI手册,《开始愉快的GitHub生活:GitHub CLI》)
如果仓库已经存在,那么在执行gh repo create时将会出现错误(HTTP 422: Repository creation failed. (https://api.github.com/user/repos) name already exists on this account),因此我们先进行存在性检查。但是,如果在shell脚本中未设置set -e,则即使出现错误也会继续执行,因此可能不需要进行错误处理。※如果万一未来gh repo create的规范发生变化,要求强制初始化仓库的话,代码可能会失效。

image.png
# create a branch protection rule
repositoryId=$(gh api graphql -f query='
{
 repository(owner:"'$OWNER_NAME'", name:"'$REPO_NAME'"){id}
}
' -q .data.repository.id)

gh api graphql -f query='
mutation($repositoryId:ID!,$branch:String!) {
 createBranchProtectionRule(input: {
  repositoryId: $repositoryId
  pattern: $branch
 }) { clientMutationId }
}
' -f repositoryId="$repositoryId" -f branch="$DEFAULT_BRANCH" >$DEV_NULL

# update a branch protection rule
branchProtectionRuleId=$(gh api graphql -f query='
{
 repository(owner:"'$OWNER_NAME'", name:"'$REPO_NAME'"){
  branchProtectionRules(first:100){
   nodes{
    id,
    pattern
   }
  }
 }
}
' -q ' .data.repository.branchProtectionRules.nodes.[] | select(.pattern=="'$DEFAULT_BRANCH'") | .id ')

gh api graphql -f query='
mutation($branchProtectionRuleId:ID!) {
 updateBranchProtectionRule(input: {
  branchProtectionRuleId: $branchProtectionRuleId
  requiresApprovingReviews: true
  requiredApprovingReviewCount: 1
  requiresCodeOwnerReviews: true
  isAdminEnforced: false
 }) { clientMutationId }
}
' -f branchProtectionRuleId="$branchProtectionRuleId" >$DEV_NULL

我们在这里使用 gh api graphql(同时也学习了 GraphQL。参考:ここさえ抑えれば GitHub API v4 がわかる!GraphQL 入門)来进行操作。关于查询的内容,我们参考了文档(参考:branchProtectionRules, updateBranchProtectionRule),并经过试错,成功使其运作起来了。

为了不显示gh api的输出结果,使用`$DEV_NULL`。否则,终端会进入操作模式,导致处理停止。

image.png
# レポジトリ操作
make exec_query REPO_NAME=repository_name

# 全てのレポジトリ操作
make exec_all_queries

未来,进一步发展并将脚本执行自动化在 Github Actions 中能够很方便呢。顺便说一下,Github Actions 的权限设置也可以在这里进行代码化。※不支持 GraphQL。

结束

当实际使用后,体验比我想象中好,“每次都不需要重新设置”和“可以防止遗忘描述”这样的好处让人高兴地声称。如果存储库数量增加,体验会更好吧?如果您感兴趣,请务必试试看!

附言:学习GraphQL真是太好了!

广告
将在 10 秒后关闭
bannerAds