Featured image of post Resolving Vercel's Inability to Build with Private Submodule Repositories

Resolving Vercel's Inability to Build with Private Submodule Repositories

For daily free static blog hosting, services like Vercel, Cloudflare Pages, Netlify, and OneEdge are commonly used. However, in China, Vercel and Netlify generally offer the fastest speeds. Recently, Netlify adjusted its free tier, providing only 300 credits to free users by default, with each build consuming 20 credits. If you update your blog frequently, the credits can run out quickly. Overall, Vercel remains the best option.

Problem Description

Recently, while switching the Hugo theme for this blog, I encountered build issues on Vercel due to the use of private repository submodules. Specifically, the submodules failed to pull during the build process, resulting in the error: Warning: Failed to fetch one or more git submodules. This caused the built website to have only the framework without any article content.

Build Error

Initially, I suspected a permission issue, but after investigation, I found that the GitHub App authorization I enabled on Vercel had sufficient permissions to pull private repository submodules. Additionally, when testing the build on Cloudflare Pages, this issue did not occur.

Upon researching the Vercel community, I discovered that this is a long-standing problem. Vercel’s Git integration mechanism is relatively simple, and the deployment process cannot automatically inherit the main repository’s authentication permissions for submodules, leading to pull failures. Cloudflare, with its more comprehensive functionality, does not have this issue.

To resolve this, I tried various methods, including changing the submodule links from Git to HTTPS and specifying submodule pulls in vercel.json, but none succeeded.

Finally, I found a GitHub project, beeinger/vercel-private-submodule, which contains only one script file, vercel-submodule-workaround.sh, that indirectly achieves the goal.

Solution

Using this script is straightforward.

  1. Create the Script File

Create the script file vercel-submodule-workaround.sh in the project root directory, or download the file from the aforementioned project to your local project root. Modify the submodule link and path in lines 1 and 2. For example, my project is hugo-content, and Hugo uses this path as well.

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
SUBMODULE_GITHUB=github.com/user/hugo-content
SUBMODULE_PATH=hugo-content
if [ "$GITHUB_ACCESS_TOKEN" == "" ]; then
  echo "Error: GITHUB_ACCESS_TOKEN is empty"
  exit 1
fi
set -e
output=`git submodule status --recursive`
no_prefix=${output#*-} 
COMMIT=${no_prefix% *} 
rm -rf tmp || true 
mkdir tmp 
cd tmp 
git init 
git remote add origin https://$GITHUB_ACCESS_TOKEN@$SUBMODULE_GITHUB 
git fetch --depth=1 origin $COMMIT 
git checkout $COMMIT 
cd .. 
rm -rf tmp/.git 
mv tmp/* $SUBMODULE_PATH/ 
rm -rf tmp 
  1. Create a PAT

Create a Personal Access Token (PAT) in GitHub under Settings > Developer settings > Personal access tokens > Fine-grained tokens (or Classic tokens), granting access to the private submodule repository. Then, add this PAT to Vercel’s project Settings > Environment Variables with the name GITHUB_ACCESS_TOKEN.

Vercel PAT Setup

  1. Set the Install Command

In the Vercel Dashboard > Project > Settings > General > Build & Development Settings, set the install command, ensuring to add chmod +x at the beginning.

1
chmod +x vercel-submodule-workaround.sh && ./vercel-submodule-workaround.sh hugo-content

Deployment Settings

In summary, this experience highlighted that behind the convenience of cloud services, there are often limitations in specific scenarios. While Vercel is fast, its lack of submodule support caused me repeated frustration. Finding this workaround script on GitHub felt like stumbling upon a hidden path after being lost—a true “light at the end of the tunnel.” At one point, I considered abandoning the private repository approach and switching to a public one, but thankfully, the issue was resolved successfully.

Built with Hugo, Powered by Github.
Total Posts: 385, Total Words: 565004.