Source snapshot: 97d7f0fae96dc04b7ddad56fc1db6a108ed662cc [SEC-CLEAN] · pre-push-clean v1.0 · 109处敏感信息已自动转乱码
237 lines
6.8 KiB
Markdown
237 lines
6.8 KiB
Markdown
---
|
||
belongs_to:
|
||
- "[[INDEX · 铸渊·协作指令|GitHub ↔ Notion 桥接协议]]"
|
||
---
|
||
# 🔧 铸渊指令|rclone OAuth2 Token JSON 拼接修复 · 同步到 Google Drive 报错修复(ZY-RCLONE-FIX-2026-0324-001)
|
||
|
||
---
|
||
|
||
<aside>
|
||
🚨
|
||
|
||
**指令编号:ZY-RCLONE-FIX-2026-0324-001**
|
||
|
||
**签发人:** 霜砚(ICE-NTN-SY001)· 代 TCS-0002∞ 冰朔 签发
|
||
|
||
**签发时间:** 2026-03-24T19:25+08:00
|
||
|
||
**优先级:** 🔴 P0 · 存储链路阻断 · 线上报错修复
|
||
|
||
**关联仓库:** [https://github.com/qinfendebingshuo/guanghulab](https://github.com/qinfendebingshuo/guanghulab)
|
||
|
||
**前置指令:** ZY-OAUTH2-REBUILD-2026-0324-001(OAuth2 代理人重构)
|
||
|
||
**版权锚点:** 国作登字-2026-A-00037559 · TCS-0002∞ 冰朔
|
||
|
||
</aside>
|
||
|
||
---
|
||
|
||
## 🎯 问题描述
|
||
|
||
### 现象
|
||
|
||
「同步到驱动器」Workflow 执行失败,错误发生在「同步到 Google 云端硬盘」步骤:
|
||
|
||
```
|
||
Failed to create file system for "gdrive:": drive: failed when making
|
||
oauth client: failed to create oauth client: unexpected end of JSON input
|
||
```
|
||
|
||
### 分析
|
||
|
||
<aside>
|
||
❌
|
||
|
||
**根因:rclone 配置中的 OAuth token JSON 字符串拼接有 bug。**
|
||
|
||
`unexpected end of JSON input` 说明 rclone 读取到的 token JSON **不完整/被截断**。
|
||
|
||
这不是 OAuth2 凭据本身的问题(凭据已验证有效),而是铸渊在 Workflow 中将凭据写入 rclone 配置时,JSON 字符串拼接方式有缺陷。
|
||
|
||
</aside>
|
||
|
||
### 可能的具体原因
|
||
|
||
1. **Shell 变量中的特殊字符被转义/吞掉** — Refresh Token 中包含 `//`,在某些 shell 拼接方式下会被处理
|
||
2. **JSON 引号嵌套错误** — rclone 的 token 字段需要一个完整的 JSON 对象字符串,嵌套引号在 YAML → shell → JSON 三层传递中容易出错
|
||
3. **YAML 多行字符串截断** — 如果使用了 `|` 或 `>` 格式的 YAML 字符串,可能导致 JSON 被截断
|
||
4. **环境变量注入时换行符/空格** — `$ secrets.GDRIVE_REFRESH_TOKEN` 前后可能带入了不可见字符
|
||
|
||
---
|
||
|
||
## 📋 铸渊执行任务
|
||
|
||
### Phase 1 · 定位问题代码
|
||
|
||
1. 找到「同步到驱动器」Workflow 文件(大概率是 `sync-griddb-to-drive.yml` 或类似名称)
|
||
2. 找到「配置 rclone (OAuth2)」步骤的代码
|
||
3. 检查 rclone 配置文件的生成方式,特别是 `token` 字段的 JSON 拼接
|
||
|
||
### Phase 2 · 修复 rclone 配置
|
||
|
||
**正确的 rclone OAuth2 配置方式:**
|
||
|
||
rclone 需要的配置格式如下(`~/.config/rclone/rclone.conf`):
|
||
|
||
```
|
||
[gdrive]
|
||
type = drive
|
||
client_id = 从环境变量读取
|
||
client_secret = 从环境变量读取
|
||
scope = drive
|
||
token = {"access_token":"","token_type":"Bearer","refresh_token":"从环境变量读取","expiry":"2000-01-01T00:00:00Z"}
|
||
root_folder_id = 光湖格点库文件夹ID
|
||
```
|
||
|
||
**关键修复点:`token` 字段的 JSON 必须是完整的、单行的、正确转义的。**
|
||
|
||
#### 推荐方案:用 `jq` 或 `node` 生成 token JSON,避免手动拼接
|
||
|
||
```yaml
|
||
- name: 🔑 配置 rclone(OAuth2)
|
||
env:
|
||
GDRIVE_CLIENT_ID: $ secrets.GDRIVE_CLIENT_ID
|
||
GDRIVE_CLIENT_SECRET: $ secrets.GDRIVE_CLIENT_SECRET
|
||
GDRIVE_REFRESH_TOKEN: $ secrets.GDRIVE_REFRESH_TOKEN
|
||
run: |
|
||
mkdir -p ~/.config/rclone
|
||
|
||
# 用 node 生成正确的 token JSON,避免 shell 转义问题
|
||
TOKEN_JSON=$(node -e "
|
||
const token = {
|
||
access_token: '',
|
||
token_type: 'Bearer',
|
||
refresh_token: process.env.GDRIVE_REFRESH_TOKEN,
|
||
expiry: '2000-01-01T00:00:00Z'
|
||
};
|
||
process.stdout.write(JSON.stringify(token));
|
||
")
|
||
|
||
cat > ~/.config/rclone/rclone.conf << RCLONE_EOF
|
||
[gdrive]
|
||
type = drive
|
||
client_id = ${GDRIVE_CLIENT_ID}
|
||
client_secret = ${GDRIVE_CLIENT_SECRET}
|
||
scope = drive
|
||
token = ${TOKEN_JSON}
|
||
RCLONE_EOF
|
||
|
||
echo "✅ rclone 配置完成"
|
||
```
|
||
|
||
<aside>
|
||
⚠️
|
||
|
||
**为什么用 `node` 而不是 shell 拼接?**
|
||
|
||
- `JSON.stringify()` 能正确处理所有特殊字符(`//`、`=`、`+` 等)
|
||
- 不会有引号嵌套问题
|
||
- 保证输出是完整的单行 JSON
|
||
- 仓库已有 Node.js 环境,无需额外安装
|
||
|
||
如果仓库环境没有 node,也可以用 `jq`:
|
||
|
||
```bash
|
||
TOKEN_JSON=$(jq -n --arg rt "$GDRIVE_REFRESH_TOKEN" \
|
||
'{access_token:"",token_type:"Bearer",refresh_token:$rt,expiry:"2000-01-01T00:00:00Z"}')
|
||
```
|
||
|
||
</aside>
|
||
|
||
### Phase 3 · 本地验证
|
||
|
||
修复后,在提交前验证:
|
||
|
||
1. **检查生成的 rclone.conf** — 确认 token 字段是完整的 JSON
|
||
2. **运行 `rclone lsf gdrive:`** — 确认能正常列出 Drive 文件
|
||
3. **运行 `rclone copy . gdrive:test/ --dry-run`** — 确认同步命令无报错
|
||
|
||
### Phase 4 · 🦅 天眼全局扫描(必须执行)
|
||
|
||
<aside>
|
||
🦅
|
||
|
||
**修复完成后,必须运行天眼系统进行全局扫描!**
|
||
|
||
天眼扫描通过后才能提交。
|
||
|
||
</aside>
|
||
|
||
**扫描清单:**
|
||
|
||
1. **rclone 配置扫描**
|
||
- ✅ token 字段是完整的 JSON 对象(包含 `access_token`、`token_type`、`refresh_token`、`expiry` 四个字段)
|
||
- ✅ token JSON 能被 `JSON.parse()` 正确解析
|
||
- ✅ `refresh_token` 值与环境变量一致,没有被截断或转义
|
||
- ❌ 没有硬编码任何凭据
|
||
2. **Workflow 扫描**
|
||
- ✅ 所有使用 rclone 的 Workflow 都采用了修复后的配置方式
|
||
- ✅ 没有使用 shell 手动拼接 JSON 字符串的地方
|
||
- ✅ `[skip ci]` 防循环标记存在
|
||
3. **Drive 连接扫描**
|
||
- ✅ `rclone lsf gdrive:` 能正常执行
|
||
- ✅ 文件上传测试通过
|
||
- ✅ 文件列表读取测试通过
|
||
4. **安全扫描**
|
||
- ❌ 日志中不会打印 token / secret 内容
|
||
- ❌ rclone.conf 在 Workflow 结束后被清理(清理凭证步骤仍然正常工作)
|
||
|
||
### Phase 5 · 提交
|
||
|
||
<aside>
|
||
🚫
|
||
|
||
**Phase 4 天眼扫描未通过前,禁止提交。**
|
||
|
||
</aside>
|
||
|
||
天眼扫描全部通过后:
|
||
|
||
```bash
|
||
git add -A
|
||
git commit -m "fix: rclone OAuth2 token JSON 拼接修复 · 改用 node/jq 生成 · ZY-RCLONE-FIX-2026-0324-001 [skip ci]"
|
||
git push
|
||
```
|
||
|
||
### Phase 6 · 验证 Workflow
|
||
|
||
提交后手动触发一次「同步到驱动器」Workflow,确认:
|
||
|
||
- ✅ 「配置 rclone (OAuth2)」步骤通过
|
||
- ✅ 「同步到 Google 云端硬盘」步骤通过
|
||
- ✅ 文件成功同步到 Drive
|
||
|
||
---
|
||
|
||
## 📝 执行回执区
|
||
|
||
| **Phase** | **状态** | **完成时间** | **备注 / Commit SHA** |
|
||
| --- | --- | --- | --- |
|
||
| Phase 1 · 定位问题代码 | ⏳ 待执行 | — | — |
|
||
| Phase 2 · 修复 rclone 配置 | ⏳ 待执行 | — | — |
|
||
| Phase 3 · 本地验证 | ⏳ 待执行 | — | — |
|
||
| Phase 4 · 天眼全局扫描 | ⏳ 待执行 | — | — |
|
||
| Phase 5 · 提交 | ⏳ 待执行 | — | — |
|
||
| Phase 6 · 验证 Workflow | ⏳ 待执行 | — | — |
|
||
|
||
---
|
||
|
||
## 👤 人类手动操作区
|
||
|
||
<aside>
|
||
👤
|
||
|
||
**本指令所有任务均可由铸渊独立完成,当前无需人类操作。**
|
||
|
||
</aside>
|
||
|
||
---
|
||
|
||
## ⚖️ 签发声明
|
||
|
||
🖋️ 霜砚 · PER-SY001
|
||
|
||
🧊 代 TCS-0002∞ 冰朔 签发
|
||
|
||
📅 2026-03-24T19:25+08:00 |