解决Vercel不支持私有submodule仓库构建问题
日常免费静态博客托管,主要有 Vercel Cloudflare-Pages Netlify OneEdge 等服务,但在国内而言,总体上 Vercel 和 Netlify 速度算是最快的,但 Netlify 近年调整了免费额度,默认只给免费用户 300 个积分,而一次构建就需要 20 积分,如果博客更新频繁,很快就用尽额度。所以综合来看,还是 Vercel 最好。
n
问题描述
n
不过,最近本博客在更换 Hugo 主题过程中,由于启用了私有仓库 Submodule 功能,导致 Vercel 那边构建一直存在问题。具体来说就是无法拉取子模块。在构建过程中报错 Warning: Failed to fetch one or more git submodules 。导致构建出来的网站,实际只有框架,而无文章内容。
n
n nn nn
nnn
n
一开始我以为是权限问题,但排查后发现,我在 Vercel 上启用的 Github APP 授权足够拉取私有仓库子模块。同时,我在 Cloudflare Pages 上测试构建时,也并未发现有这个故障。
n
后来在 Vercel 社区查询才发现,这个问题由来已久,是因为 Vercel 的 Git 集成机制较为简单,部署流程无法自动继承主仓库的认证权限到子模块,导致拉取失败。而 Cloudflare 那边功能更全面,也就不存在这个问题。
n
为了解决这个问题,我尝试了多种方法,包括将 Submodule 中链接由 Git 改为 https 模式,以及在 vercel.json 中指定拉取子模块等方式,但都无法实现成功拉取。
n
最后,我找到一个 Github 项目 beeinger/vercel-private-submodule 。这个项目只有一个 vercel-submodule-workaround.sh 脚本文件,可以通过间接方式实现目的。
n
解决办法
n
这个脚本使用起来也比较简单。
n
- n
- 创建脚本文件
n
n
在项目根目录下创建脚本文件vercel-submodule-workaround.sh,或将上述项目文件下载到本地项目根目录。n修改第1、2行的 Submodule 链接和路径。比如我的项目是 hugo-content 同时在 hugo 中也使用这个路径。
nnnnnn
1SUBMODULE_GITHUB=github.com/user/hugo-contentn 2SUBMODULE_PATH=hugo-contentn 3if [ "$GITHUB_ACCESS_TOKEN" == "" ]; thenn 4 echo "Error: GITHUB_ACCESS_TOKEN is empty"n 5 exit 1n 6fin 7set -en 8output=`git submodule status --recursive`n 9no_prefix=${output#*-} n10COMMIT=${no_prefix% *} n11rm -rf tmp || true n12mkdir tmp n13cd tmp n14git init n15git remote add origin https://$GITHUB_ACCESS_TOKEN@$SUBMODULE_GITHUB n16git fetch --depth=1 origin $COMMIT n17git checkout $COMMIT n18cd .. n19rm -rf tmp/.git n20mv tmp/* $SUBMODULE_PATH/ n21rm -rf tmp
- n
- 创建 PAT
n
n
在 GitHub > Settings > Developer settings > Personal access tokens > Fine-grained tokens(或 Classic tokens)创建一个 PAT,授权对子模块私有仓库的访问权限。同时在 Vercel 项目的 Settings > Environment Variables 中填入该 PAT,名称为 GITHUB_ACCESS_TOKEN。
n
n nn nn
nnn
n
- n
- 设置安装命令
n
n
在 Vercel Dashboard > 项目 > Settings > General > Build & Development Settings 中设置安装命令,注意在前边添加 chmod +x。
nnnnnn
1chmod +x vercel-submodule-workaround.sh && ./vercel-submodule-workaround.sh hugo-contnet
n nn nn
nnn
n
总的来说,经过这次折腾,也算是体会到云服务的便捷背后往往藏着特定场景的局限性。Vercel 虽快但子模块支持的短板让我之前多次“捉急”。而在 Github 找到这种使用脚本迂回解决方案后,也算是山重水复疑无路,柳暗花明又一村了。过程中,我都一度想放弃私有仓库的搞法,转为公开仓库。好在最终成功解决问题。