range42/gh-repo-organizer
GitHub: range42/gh-repo-organizer
一款用于批量克隆 GitHub 组织仓库并执行标准合规性与安全扫描审计的 Bash 自动化工具。
Stars: 2 | Forks: 0
# GitHub 组织仓库克隆工具
**GitHub 组织仓库克隆工具 - 自动克隆并审计 GitHub 组织的所有仓库,并进行全面的标准合规性检查。**
一个强大的 bash 脚本,用于克隆和审计 GitHub 组织的所有仓库。自动将仓库分类到公共和私有目录中,并对仓库的标准合规性进行全面的完整性检查。
## 功能特性
- **批量克隆仓库**:从任何 GitHub 组织克隆所有可访问的仓库
- **智能分类**:自动将公共和私有仓库分离到专门的目录中
- **自动更新**:使用 `git pull` 自动更新现有仓库
- **感知身份验证**:无论是否通过 GitHub 身份验证均可工作(未认证时仅限公共仓库)
- **全面的完整性检查**:逐行输出审计仓库的标准文件和最佳实践
- **仓库过滤**:对特定仓库运行完整性检查以便进行集中分析
- **灵活的配置**:基于环境变量的配置,易于自定义
- **健壮的错误处理**:通过 HTTPS 回退优雅地处理克隆失败的情况
- **彩色输出**:清晰、彩色的终端输出以提供更好的可视性
## 快速开始
1. **安装前置条件**:
# 安装 GitHub CLI
brew install gh # macOS
# 或者
sudo apt install gh # Ubuntu/Debian
# 安装 jq 用于 JSON 解析
brew install jq # macOS
# 或者
sudo apt install jq # Ubuntu/Debian
2. **配置脚本**:
# 创建配置文件
cp config.env.example config.env
# 编辑你的组织名称
vim config.env
3. **运行脚本**:
# 克隆所有仓库
./gh_repo_cloner.sh
# 对所有仓库执行完整性检查
./gh_repo_cloner.sh --sanity-check
# 检查特定仓库
./gh_repo_cloner.sh --sanity-check my-repo-name
## 前置条件
- **GitHub CLI (`gh`)** - 用于列出仓库和进行身份验证
- **Git** - 用于克隆仓库
- **jq** - 用于解析 JSON
- **Bash 4.0+** - 用于执行脚本
## 配置
创建一个包含以下变量的 `config.env` 文件:
```
# 必填:组织名称
ORG="your-organization-name"
# 可选:目录路径(显示默认值)
PUB_DIR="./pub"
PRIV_DIR="./priv"
# 可选:输出颜色(显示默认值)
RED='\033[0;31m'
GREEN='\033[0;32m'
YELLOW='\033[1;33m'
BLUE='\033[0;34m'
NC='\033[0m' # No Color
```
### 配置选项
| 变量 | 描述 | 默认值 | 是否必填 |
|----------|-------------|---------|----------|
| `ORG` | GitHub 组织名称 | - | 是 |
| `PUB_DIR` | 公共仓库目录 | `./pub` | 否 |
| `PRIV_DIR` | 私有仓库目录 | `./priv` | 否 |
| `RED`, `GREEN` 等 | 终端颜色 | ANSI 代码 | 否 |
## 用法
### 基本命令
```
# 显示帮助
./gh_repo_cloner.sh --help
# Clone 所有 repositories
./gh_repo_cloner.sh
# 对所有 repositories 执行 sanity checks
./gh_repo_cloner.sh --sanity-check
# 对特定 repository 执行 sanity check
./gh_repo_cloner.sh --sanity-check my-repository-name
# 替代语法(简写形式)
./gh_repo_cloner.sh -s my-repository-name
```
### 命令行选项
| 选项 | 描述 |
|--------|-------------|
| `-s, --sanity-check [REPO]` | 对仓库执行完整性检查以确认常见文件。可选择指定要检查的特定仓库名称 |
| `-h, --help` | 显示帮助信息并退出 |
### 使用示例
```
# 从该组织 Clone 所有 repositories
./gh_repo_cloner.sh
# 对所有 repositories 运行全面的 sanity checks
./gh_repo_cloner.sh --sanity-check
# 仅检查 "range42-inventory" repository
./gh_repo_cloner.sh --sanity-check range42-inventory
# 仅检查 "my-backend-api" repository(简写形式)
./gh_repo_cloner.sh -s my-backend-api
```
## 仓库过滤
该脚本支持将完整性检查过滤到特定仓库,这对于以下情况非常有用:
- **集中分析**:检查单个仓库,不受其他仓库的干扰
- **快速验证**:验证特定仓库上的修复
- **新人入职**:向新开发人员展示特定项目的标准
- **CI 集成**:在自动化工作流程中验证特定仓库
### 过滤行为
- **自动发现**:脚本会在 `./pub` 和 `./priv` 目录中搜索指定的仓库
- **错误处理**:如果未找到该仓库,它会列出所有可用的仓库
- **精简输出**:仅显示指定仓库的结果,并提供简化的摘要
### 过滤示例
```
# 检查 "awesome-project" repository
./gh_repo_cloner.sh -s awesome-project
# 输出仅显示该 repository 的结果:
# [INFO] Checking repository: awesome-project
# [INFO] awesome-project:
# ✓ LICENSE
# ✗ CHANGELOG
# ...
# [INFO] Repository checked: awesome-project
# [SUCCESS] Repository has all required files!
```
## 完整性检查
该脚本可以审计仓库是否符合通用标准和最佳实践:
### 检查的文件
| 类别 | 文件/目录 |
|----------|-------------------|
| **许可证** | `LICENSE`, `LICENSE.txt`, `LICENSE.md`, `COPYING`, `COPYRIGHT`(包含内容验证) |
| **文档** | `README.md`, `README.txt`, `README` |
| **更新日志** | `CHANGELOG.md`, `HISTORY.md`, `RELEASES.md` |
| **贡献指南** | `CONTRIBUTING.md`, `CONTRIBUTING.txt` |
| **安全** | `SECURITY.md`, `SECURITY.txt` |
| **行为准则** | `CODE_OF_CONDUCT.md` |
| **Git 配置** | `.gitignore` |
| **编辑器配置** | `.editorconfig` |
| **文档目录** | `docs/`, `documentation/` |
| **GitHub 模板** | `.github/ISSUE_TEMPLATE/`, `.github/PULL_REQUEST_TEMPLATE.md` |
### CI/CD 检测
该脚本会自动检测各种 CI/CD 配置:
- **GitHub Actions** - `.github/workflows/`
- **GitLab CI** - `.gitlab-ci.yml`
- **Travis CI** - `.travis.yml`
- **Jenkins** - `Jenkinsfile`
- **CircleCI** - `.circleci/`
- **Azure Pipelines** - `azure-pipelines.yml`
- **Buildkite** - `.buildkite/`
- **Bitbucket Pipelines** - `bitbucket-pipelines.yml`
### LICENSE 内容验证
该脚本不仅检查是否存在 LICENSE 文件,还会验证许可证是否已正确填写。它会检测指示许可证不完整的常见模板占位符:
**检测到的模板占位符:**
- ``, `[year]`, `YYYY` - 年份占位符
- ``, ``, `` - 作者占位符
- ``, `` - 版权占位符
- `COPYRIGHT_HOLDER`, `AUTHOR_NAME`, `YOUR_NAME`, `YOUR NAME` - 常见的模板变量
**检测到的 LICENSE 文件变体:**
- 标准名称:`LICENSE`, `LICENSE.txt`, `LICENSE.md`, `LICENSE.rst`
- 大小写变体:`license`, `License`
- 替代名称:`COPYING`, `COPYRIGHT`(在某些项目中很常见)
- 所有检查均带有适当的文件类型验证(而非目录或符号链接)
**LICENSE 状态指示符:**
- **✓ LICENSE** - 文件存在且已正确填写
- **⚠ LICENSE(包含模板占位符)** - 文件存在但需要自定义
- **✗ LICENSE** - 完全缺少文件
## 安全扫描
当你运行 `make prep_ai` 时,流水线会针对 `pub/` 和 `priv/` 仓库执行 `./helpers/3_static_scan.sh`,并自动执行基于文件的安全扫描检测。
### 扫描器检测规则
| 触发条件 | 扫描器 | 输出文件 |
|---------|---------|-------------|
| 存在 `requirements.txt` | `pip-audit -r requirements.txt --format json` | `analysis/files//pip_audit.json` |
| 存在 `requirements.txt` | `safety check --file=requirements.txt --json` | `analysis/files//safety.json` |
| 存在 `package.json` **且**存在 `package-lock.json`、`yarn.lock` 或 `pnpm-lock.yaml` 之一 | `npm audit --json` | `analysis/files//npm_audit.json` |
| 仓库中存在任何 `*.py` 文件 | `bandit -r -f json` | `analysis/files//bandit_report.json` |
### 行为与输出
- 扫描结果将作为 JSON 文件写入 `analysis/files//` 下。
- 在当前实现中,扫描是非阻塞的(`|| true`):扫描器失败不会中断整个 `prep_ai` 流水线。
- 如果仓库有 `package.json` 但没有锁文件(lock file),该工具会向 `npm_audit.json` 写入错误 JSON 负载,并向 stderr 打印警告。
### 配置 / 退出机制
- 目前没有专用的扫描级别 CLI 标志或 `config.env` 开关来启用/禁用各个扫描器。
- 要跳过这些扫描,请运行 `make prep_ai` 以外的工作流,或修改 `helpers/3_static_scan.sh` 以实现自定义行为。
## 示例输出
### 仓库克隆
```
[INFO] GitHub Organization Repository Cloner
[INFO] ======================================
[SUCCESS] Authenticated with GitHub
[INFO] Authenticated as: username
[INFO] Organization: awesome-org
[INFO] Found 25 repositories
[INFO] Repository awesome-project already exists, updating...
[SUCCESS] ✓ Updated awesome-project in ./pub/
[SUCCESS] ✓ Cloned new-secret-sauce to ./priv/
[ERROR] ✗ Failed to update modified-repo (may have local changes or connection issues)
[SUCCESS] Cloning completed!
[INFO] Summary:
[INFO] Public repositories cloned: 12
[INFO] Private repositories cloned: 8
[WARNING] Failed to clone: 5
```
### 完整性检查结果(所有仓库)
```
[INFO] Checking public repositories in ./pub:
awesome-project:
✓ LICENSE
✓ CHANGELOG
✓ CONTRIBUTING
✓ README
✓ GITIGNORE
✓ SECURITY
✓ CODE_OF_CONDUCT
✓ EDITORCONFIG
✓ DOCS
✓ ISSUE_TEMPLATES
✓ PR_TEMPLATE
✓ CI/CD
legacy-tool:
⚠ LICENSE (contains template placeholders)
✗ CHANGELOG
✗ CONTRIBUTING
✓ README
✓ GITIGNORE
✗ SECURITY
✗ CODE_OF_CONDUCT
✗ EDITORCONFIG
✗ DOCS
✗ ISSUE_TEMPLATES
✗ PR_TEMPLATE
✓ CI/CD
[INFO] Sanity Check Summary:
[INFO] =====================
[INFO] Total repositories checked: 25
[SUCCESS] Repositories with all files: 8
[WARNING] Repositories missing files: 17
[INFO] Legend:
[INFO] ✓ = File/directory present and complete
[INFO] ✗ = File/directory missing
[INFO] ⚠ = LICENSE present but contains template placeholders
```
### 完整性检查结果(单个仓库)
```
[INFO] Running sanity check on repository: range42-inventory
[INFO] Checking repository: range42-inventory
[INFO] range42-inventory:
⚠ LICENSE (contains template placeholders)
✗ CHANGELOG
✗ CONTRIBUTING
✓ README
✓ GITIGNORE
✗ SECURITY
✗ CODE_OF_CONDUCT
✗ EDITORCONFIG
✗ DOCS
✗ ISSUE_TEMPLATES
✗ PR_TEMPLATE
✗ CI/CD
[INFO] Sanity Check Summary:
[INFO] =====================
[INFO] Repository checked: range42-inventory
[WARNING] Repository is missing some files.
[INFO] Legend:
[INFO] ✓ = File/directory present and complete
[INFO] ✗ = File/directory missing
[INFO] ⚠ = LICENSE present but contains template placeholders
```
## 身份验证
### GitHub CLI 身份验证
```
# 使用 GitHub CLI 登录
gh auth login
# 检查身份验证状态
gh auth status
```
### 不同身份验证状态下的行为
| 身份验证 | 公共仓库 | 私有仓库 | 频率限制 |
|----------------|--------------|---------------|-------------|
| 已认证 | 完全访问权限 | 基于权限的访问 | 5,000次/小时 |
| 未认证 | 只读访问 | 无访问权限 | 60次/小时 |
## 错误处理
该脚本包含健壮的错误处理机制:
- **SSH 到 HTTPS 回退**:自动使用 HTTPS 重试失败的 SSH 克隆
- **现有仓库更新**:自动为现有仓库拉取(pull)最新更改
- **权限验证**:针对访问问题提供清晰的错误消息
- **速率限制感知**:针对未认证用户发出 API 速率限制警告
- **未找到仓库**:在过滤时,提供带有可用仓库列表的有用错误消息
## 目录结构
运行脚本后,你的目录结构将如下所示:
```
project-root/
├── gh_repo_cloner.sh
├── config.env
├── pub/
│ ├── public-repo-1/
│ ├── public-repo-2/
│ └── ...
└── priv/
├── private-repo-1/
├── private-repo-2/
└── ...
```
## 开发
### 运行测试
```
# 测试 configuration 加载
./gh_repo_cloner.sh --help
# 测试身份验证检查
gh auth status
# Dry run sanity checks
./gh_repo_cloner.sh --sanity-check
# 测试 repository 过滤
./gh_repo_cloner.sh --sanity-check non-existent-repo # Should show available repos
```
## 最佳实践
### 对于组织
- **定期审计**:每月运行一次完整性检查以确保仓库标准
- **标准化模板**:使用该脚本识别缺少 issue/PR 模板的仓库
- **安全合规**:确保所有仓库都有 `SECURITY.md` 文件
- **文档**:验证所有项目都有合适的 `README.md` 和 `docs/` 目录
- **针对性审查**:在代码审查期间使用仓库过滤来验证特定项目
### 对于仓库管理
- **批量更新**:使用该脚本识别需要标准化的仓库
- **定期同步**:定期运行脚本以保持本地副本最新
- **干净的工作目录**:在运行更新之前,确保本地仓库没有未提交的更改
- **新人入职**:将完整性检查结果包含在新开发人员入职培训中
- **合规性**:跟踪全组织对仓库标准的遵守情况
- **针对性修复**:使用过滤来验证特定仓库上的修复
## 局限性
- **大型组织**:对于拥有 1000+ 仓库的组织,建议分批运行
- **私有仓库访问**:需要适当的 GitHub 权限
- **存储空间**:克隆大量仓库需要大量的磁盘空间
- **网络使用**:初始克隆会消耗大量带宽
## 故障排除
### 常见问题
**"找不到组织" (Organization not found)**
- 验证 `config.env` 中的组织名称
- 检查该组织是否存在且可访问
**"找不到仓库" (No repositories found)**
- 组织可能只有私有仓库(使用 `gh auth login` 进行身份验证)
- 组织名称可能不正确
**"找不到仓库 'repo-name'"**(过滤时)
- 检查仓库名称的拼写
- 确保首先克隆了仓库(运行时不加 `-s` 标志)
- 仓库可能是不同的大小写(名称区分大小写)
- 使用错误输出查看可用的仓库
**"权限拒绝" (Permission denied)**
- SSH 密钥未正确配置
- 使用 `gh auth login` 进行身份验证
- 检查仓库访问权限
**"超出速率限制" (Rate limit exceeded)**
- 使用 GitHub CLI 认证:`gh auth login`
- 等待速率限制重置(显示在错误消息中)
**"更新仓库失败" (Failed to update repository)**
- 仓库可能有未提交的本地更改
- 检查合并冲突:`cd repo_directory && git status`
- 如果安全,重置本地更改:`git reset --hard origin/main`
- 可能表明存在网络连接问题
**"LICENSE 显示警告 (⚠) 符号"**
- LICENSE 文件包含模板占位符,如 `` 或 ``
- 编辑 LICENSE 文件,将占位符替换为实际值
- 常见占位符:`` → 实际年份,`` → 你的姓名/组织名称
**"LICENSE 显示丢失 (✗) 但文件存在"**
- LICENSE 文件可能具有意外的名称或扩展名
- 支持的名称:`LICENSE`, `LICENSE.txt`, `LICENSE.md`, `license`, `License`, `COPYING`, `COPYRIGHT`
- 检查文件权限(必须可读)
- 验证文件不是目录或符号链接
## 许可证
本项目基于 MIT 许可证授权 - 详情请参阅 [LICENSE](LICENSE) 文件。
## 支持
- **问题**:通过 [GitHub Issues](../../issues) 报告错误并请求功能- **讨论**:在 [GitHub Discussions](../../discussions) 中加入对话
- **文档**:查看此 README 和内联脚本注释
**用心制作,旨在为您提供更好的仓库管理体验**
标签:Bash, SOC Prime, 应用安全, 开发工具, 数字取证, 网络安全研究, 自动化脚本