我从存储库创建脚本中学到的 8 件事

2025-06-07

我从存储库创建脚本中学到的 8 件事

小时候,我总是不愿意做家务。我只是觉得每天重复做同样的事情很无聊。随着我长大,这种心态有所改变(感谢上帝),并且在我的职业生涯中,以下这句话滑稽地取代了这种心态:

如果耗时超过 30 秒,则自动执行。

最近,我接到一个任务,要为一个由 Google Developers 支持的DSC-VIT 项目维护的组织创建大约 18 个代码库。所有这些代码库都需要为我们计划在 2020 年前两个季度开展的项目创建。我决定为它编写一个 Shell 脚本,以下是我在这个过程中学到的一些经验。

指数

在这里查找代码:

GitHub 徽标 L04DB4L4NC3R / gitcr

一个非常简单的脚本来批量创建/删除仓库

GitCR

用于批量创建和删除 GitHub 存储库的极其简单的脚本


查看与该项目相关的博客:我从存储库创建脚本中学到的 7 件事

功能

  • 从模板批量创建存储库
  • 恢复创建

运行说明

先决条件

设置

您需要准备两样东西才能开始:

  1. .env使用以下变量调用的文件。请参阅示例

  2. 第二件需要的东西是一个repos.txt包含你想要创建的仓库名称的文件。由于GitHub API 的速率限制,仓库的数量可以是 1 到 5000 之间的任意值。例如:

repo-1
repo-2
repo-3
...
repo-5000

在此处查看示例

执行

要在任何平台上运行脚本,请替换{PATH}...

导入函数

我希望我的代码立即实现模块化。这意味着我需要将代码拆分成更小的文件,每个文件包含更小的函数,然后创建一个入口点(CLI)来执行它们。我create批量创建了代码库,deleterevert批量创建了代码库。我还添加了一个功能,如果有人点击,它会显示一个简洁的小手册help

├── functions
│   ├── config.sh
│   ├── create.sh
│   ├── manual.sh
│   └── revert.sh
├── gitcr
├── .env
├── README.md
└── repos.txt
Enter fullscreen mode Exit fullscreen mode

我必须进行两种导入:

  • 导入环境变量
  • 导入函数

两者都可以通过简单的语法实现:

# in gitcr

. ./functions/config.sh
. ./functions/create.sh
. ./functions/manual.sh
. ./functions/revert.sh
Enter fullscreen mode Exit fullscreen mode

包含文件中的所有函数和导出变量都可以直接在主文件中使用。注意,我使用了 a.来导入上述内容,因为它可以被shShell 识别。你也可以使用source关键字将它们包含在Bash中,但sh无法识别

Echo 无法处理 JSON

我想将每次迭代的输出写入控制台或JSON文件,具体操作由用户指定。我首先想到的是使用echo命令并将其通过管道输出到文件或控制台。echo在这方面表现很差,因为它本身就不是为 JSON 格式化而构建的。因此,我使用了jq相同的方法。结果如下:

jq 演示

jq处理垃圾格式,并从中解析出完整格式化的 JSON。然后可以将其随意传输到文件中。

回声+jq

Shell 中的数组

为了在每次迭代中存储 JSON 输出,我使用了一个数组。shell 中的数组可以通过以下方式声明和使用:

result = () # an empty array

result=("abcd") # an array with 0-th index = "abcd"

echo ${result[0]} # printing out the index

result[1] = "defg" # assigning value to an index

echo ${result[@]} # the '@' can be used for returning the whole array

result[$iterator] = 2 # variables can be used as indices.
Enter fullscreen mode Exit fullscreen mode

请注意,数组的内存不能在 shell 中预先分配。

检查 curl 请求是否成功

curl命令有一个-i标志,可以打印出请求的详细信息,例如返回的状态码和消息。这些信息可以从请求中提取出来,并用于检查请求是否成功。

以下代码返回有关 curl 请求的第一行信息。

$ res=`curl -i -s -XDELETE https://api.github.com/repos/$owner_name/$line -H "Authorization: token $token" | head -1 `

$ echo $res
HTTP/1.1 401 Unauthorized
Enter fullscreen mode Exit fullscreen mode

res变量可以分解为以下方式获取响应的 HTTP 状态代码及其消息:

# To get the status code
$ code=`echo $res | cut -d" " -f2`

$ echo $code
401

# To get the status code response
$ status_of_res=`echo $res | cut -d" " -f3-5`

$ echo $status_of_res
Unauthorized
Enter fullscreen mode Exit fullscreen mode

卷曲成功

现在这里发生了什么?

请注意,该命令会返回任何输入的第一行文本。我们使用该命令获取第一行文本,并以空格作为分隔符head -1进行拆分。cut -d" " -f2

-f2标志表示我们需要分割字符串中的第二个标记。请注意,此编号从 1 开始,而不是从 0 开始。f3-5表示我们需要 3 到 5 之间的标记,因为 HTTP 状态代码消息的长度可能超过一个单词,并且句子在此之后没有其他单词。

现在我们可以使用获取到的状态码来检查请求是否成功。GitHub API在请求成功后会返回状态码 204DELETE,因此简单的检查应该如下所示:

if [[ $code -eq 204 ]]
then
    echo "Request Succeeded"
else 
    echo "Request Failed"
fi
Enter fullscreen mode Exit fullscreen mode

GitHub API 速率限制

GitHub API v3 的速率限制为5000 requests每位经过身份验证的用户每小时约 1 次,未经身份验证的用户每小时最多 60 次请求。每当向 API 发送请求时,它都会以响应标头的形式返回用户的总速率限制和剩余速率:

X-RateLimit-Limit: 5000
X-RateLimit-Remaining: 4998
Enter fullscreen mode Exit fullscreen mode

因此,如果您正在考虑使用 GitHub API 的批量交易应用程序,请在此处阅读有关速率限制的更多信息。

对我来说,在脚本中添加验证很容易:

  • 读取用户想要创建的存储库数量
  • 如果数量大于 5000,则失败

可以通过以下方式轻松编程:

# Read number of words in repos.txt
repo_count=`wc -w < repos.txt`
if [ $repo_count -gt $GITHUB_MAX_REQUESTS ]
then
    echo "You are only allowed 5000 repos"
    exit 1
fi
Enter fullscreen mode Exit fullscreen mode

更实用的方法是X-RateLimit-Remaining通过 ping GitHub API 来检查标头,然后决定用户可以创建多少个存储库,这也可以通过文本处理 curl 响应标头轻松完成。

remaining=`curl -i -s -XDELETE https://api.github.com/repos/L04DB4L4NC3R/BOGUS_REPO -H "Authorization: token $token" | grep X-RateLimit-Remaining | head -1 | cut -d":" -f2`
Enter fullscreen mode Exit fullscreen mode

这里,grep搜索X-RateLimit-Remaining标头,head -1仅取第一句话,并cut -d":" -f2使用冒号分隔符从标头键值对中提取数字,然后将其存储在名为的变量中remaining

壳中的开关盒

shell 中的 Switch-case 语句具有非常独特的语法:

cli(){
    case $1 in 
        create)
            create $@
            ;;
        revert)
            revert $@
            ;;

        *)
        helpFunc
        ;;
    esac
}
Enter fullscreen mode Exit fullscreen mode

请注意,终止词esac实际上与 相反case。此语法的设计旨在简化 CLI 应用程序的编程。与其他编程语言相比,)词素用作 case 语句,而case关键字用作switch语句。在用户输入 CLI 无法处理的内容的情况下,通配符*可用于匹配大小写。default

是函数。在 Shell 中,调用函数时无需括号。参数可以通过在函数调用后以空格分隔的格式写入来传递给函数。有趣的是,用来将所有参数(我们在执行 CLI 时获取的create传递给被调用的函数。reverthelpFunc$@

./gitcr create --out=json
# $@ in the gitcr function = "./gitcr" "create" "--out=json"
# When passed to the create function, it retains all of the 
# original parameters
Enter fullscreen mode Exit fullscreen mode

跨平台执行

我在编写此脚本时面临的挑战之一是使其
跨平台。Docker 帮了我大忙!您可以使用bash仅占用15 MB空间的容器。

码头工人

以下步骤可用于跨平台 CLI 作业:

  • 使用bash 容器
  • 复制所有非用户定义的文件
  • 构建镜像并推送到DockerHub
  • 在运行时,挂载具有用户定义文件的卷
  • 执行完成后删除容器

Dockerfile 如下所示:

FROM bash

RUN apk update && apk add curl && apk add jq

RUN mkdir -p /usr/app/cli

WORKDIR /usr/app/cli

COPY . . 

RUN chmod +x gitcr
Enter fullscreen mode Exit fullscreen mode

运行时可以执行以下命令:

docker run --rm --mount type=bind,source="{PATH}",target=/usr/app/cli/ angadsharma1016/gitcr -c "bash /usr/app/cli/gitcr create"
Enter fullscreen mode Exit fullscreen mode

这里发生了什么?

此命令基于特定镜像运行一个容器,该镜像包含所有代码。在运行时,它会将用户定义的文件(例如.env和 )repos.txt作为​​卷挂载到容器内,然后运行 ​​CLI。您的系统无需安装 bash 和其他工具。

非官方的 bash 严格模式

始终使用以下几行来启动你的 bash 脚本:

set -euo pipefail
IFS=$'\n\t'
Enter fullscreen mode Exit fullscreen mode

它意味着以下事情:

  • set -e:如果任何命令抛出返回代码 1,则退出脚本
  • set u:引用任何未声明的变量都将导致错误
  • set -o pipefail:管道中的命令不会默默失败
  • IFS内部字段分隔符控制 bash 对单词的调用

如果遵循非官方的 Bash 严格模式,可以节省数小时的调试时间。点击此处了解更多信息。

结论

一晚上我都在敲打我的zsh,假装自己知道自己在做什么,这让我学到了很多东西,比如如何编写实用的脚本,自动完成很多现在必须做或近期必须做的工作。最好能从手头的任务中抽出一些时间,真正思考一个更好的解决方案,以便将来能够持续地完成这些任务。

只要是为了个人学习(或者推出比市场上同类产品更好的产品),不必介意编写代码或使用别人开发过的工具。保持求知若渴,保持愚昧!

文章来源:https://dev.to/l04db4l4nc3r/7-things-i-learnt-from-a-script-for-repository-creation-4cbk
PREV
我是如何成为一名企业家的
NEXT
2022 年招聘远程工作者