Skip to content

Commit 899b320

Browse files
fix (deploy): extract templates without jq for Vercel builds
Replace the bash+jq template download step with a Node script so yarn install and production builds succeed on Vercel, and resolve template file paths relative to the project root.
1 parent fb719e4 commit 899b320

4 files changed

Lines changed: 129 additions & 96 deletions

File tree

extract-shopify.sh

Lines changed: 1 addition & 57 deletions
Original file line numberDiff line numberDiff line change
@@ -1,60 +1,4 @@
11
#!/bin/bash
22
set -euo pipefail
33

4-
GITHUB_TOKEN="${GITHUB_TOKEN:-}"
5-
6-
if ! command -v jq >/dev/null 2>&1; then
7-
echo "jq is required to extract templates."
8-
echo "Install jq and retry (macOS: brew install jq)."
9-
exit 1
10-
fi
11-
12-
ROOT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
13-
TEMPLATES_DIR="$ROOT_DIR/templates"
14-
15-
rm -rf "$TEMPLATES_DIR"
16-
mkdir -p "$TEMPLATES_DIR"
17-
18-
jq -c '.[]' "$ROOT_DIR/template-sources.json" | while read -r i; do
19-
version=$(echo "${i}" | jq -r '.version')
20-
commit=$(echo "${i}" | jq -r '.commit')
21-
branch=$(echo "${i}" | jq -r '.branch')
22-
organization=$(echo "${i}" | jq -r '.organization')
23-
repository=$(echo "${i}" | jq -r '.repository')
24-
repositoryType=$(echo "${i}" | jq -r '.repositoryType')
25-
26-
if [ -n "$version" ] && [ "$version" != "null" ]; then
27-
url="https://codeload.github.com/$organization/$repository/legacy.zip/refs/tags/$version"
28-
fileName="$repository@$version"
29-
elif [ -n "$commit" ] && [ "$commit" != "null" ]; then
30-
url="https://codeload.github.com/$organization/$repository/legacy.zip/$commit"
31-
fileName="$repository@$commit"
32-
elif [ -n "$branch" ] && [ "$branch" != "null" ]; then
33-
url="https://codeload.github.com/$organization/$repository/legacy.zip/refs/heads/$branch"
34-
fileName="$repository@$branch"
35-
else
36-
url="https://api.github.com/repos/$organization/$repository/zipball/"
37-
fileName="$repository"
38-
fi
39-
40-
if [ "$repositoryType" = "private" ] && [ -z "$GITHUB_TOKEN" ]; then
41-
echo "Skipping private repository $organization/$repository (missing GITHUB_TOKEN)"
42-
continue
43-
fi
44-
45-
targetDir="$TEMPLATES_DIR/$fileName"
46-
mkdir -p "$targetDir"
47-
cd "$targetDir"
48-
49-
if [ "$repositoryType" = "private" ]; then
50-
curl -sS \
51-
-H "Accept: application/vnd.github+json" \
52-
-H "Authorization: token $GITHUB_TOKEN" \
53-
"$url" > file.zip
54-
else
55-
curl -sS "$url" > file.zip
56-
fi
57-
58-
unzip -oq file.zip
59-
rm -f file.zip
60-
done
4+
exec node "$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)/scripts/extract-templates.js"

package.json

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -13,7 +13,7 @@
1313
"scripts": {
1414
"dev": "node ./scripts/generate-movies-sample.js && NODE_ENV=development webpack-dev-server --mode development . --history-api-fallback --hot --progress --port 3333 --no-client-overlay",
1515
"lint": "eslint --cache .",
16-
"build": "node ./scripts/generate-movies-sample.js && NODE_ENV=production node ./scripts/create-env.js && node --max_old_space_size=8192 ./node_modules/webpack/bin/webpack.js --mode production --progress",
16+
"build": "node ./scripts/extract-templates.js && node preinstall-server.js && node ./scripts/generate-movies-sample.js && NODE_ENV=production node ./scripts/create-env.js && node --max_old_space_size=8192 ./node_modules/webpack/bin/webpack.js --mode production --progress",
1717
"glow": "glow --watch",
1818
"format": "prettier --write --use-tabs 'src/!(batteries*)**/**/*.js'",
1919
"analyze": "source-map-explorer 'dist/*.js'",
@@ -22,7 +22,7 @@
2222
"cypress:open": " cypress open",
2323
"cypress:chrome": "cypress run --headless chrome",
2424
"cypress:install": "npx cypress@5.6.0 install",
25-
"setup:templates": "./extract-shopify.sh && node preinstall-server.js",
25+
"setup:templates": "node ./scripts/extract-templates.js && node preinstall-server.js",
2626
"postinstall": "node ./scripts/build-playground.js && node ./scripts/patch-importer.js"
2727
},
2828
"husky": {

preinstall-server.js

Lines changed: 17 additions & 37 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,13 @@ const https = require('https');
22
const fs = require('fs');
33
const path = require('path');
44
const templatesConstants = require('./template-sources.json');
5+
const ROOT_DIR = path.resolve(__dirname);
6+
7+
function readProjectFile(filePath, encoding) {
8+
return fs.readFileSync(path.join(ROOT_DIR, path.relative(ROOT_DIR, filePath)), {
9+
encoding,
10+
});
11+
}
512

613
var walk = function (dir, done) {
714
let results = [];
@@ -71,49 +78,22 @@ async function generateTemplatesOutput() {
7178

7279
if (err) throw err;
7380

74-
results.forEach((path) => {
81+
results.forEach((filePath) => {
7582
// Read file contents and store in files.js
76-
const fileName = path.split(`${file}`)[1];
77-
if (fileName.includes('.ico') || fileName.includes('.png')) {
78-
const data = fs.readFileSync(
79-
`./${
80-
path.split('arc-dashboard/')[1] ||
81-
path.split('repo/')[1] ||
82-
path.split('vercel/path0/')[1]
83-
}`,
84-
{
85-
encoding: 'base64',
86-
},
87-
);
88-
filesObj[fileName] = data; //content for files.js
83+
const relativeFileName = filePath.split(`${file}`)[1];
84+
if (relativeFileName.includes('.ico') || relativeFileName.includes('.png')) {
85+
const fileData = readProjectFile(filePath, 'base64');
86+
filesObj[relativeFileName] = fileData; //content for files.js
8987
} else {
90-
if (!fileName.includes('build')) {
91-
const data = fs.readFileSync(
92-
`./${
93-
path.split('arc-dashboard/')[1] ||
94-
path.split('repo/')[1] ||
95-
path.split('vercel/path0/')[1]
96-
}`,
97-
{
98-
encoding: 'utf8',
99-
},
100-
);
101-
filesObj[fileName] = data; //content for files.js
88+
if (!relativeFileName.includes('build')) {
89+
const fileData = readProjectFile(filePath, 'utf8');
90+
filesObj[relativeFileName] = fileData; //content for files.js
10291
}
10392
}
10493

10594
// Check if manifest file exists in the repo
106-
if (data.manifest_path === path.split(`${file}/`)[1]) {
107-
const templateData = fs.readFileSync(
108-
`./${
109-
path.split('arc-dashboard/')[1] ||
110-
path.split('repo/')[1] ||
111-
path.split('vercel/path0/')[1]
112-
}`,
113-
{
114-
encoding: 'utf8',
115-
},
116-
);
95+
if (data.manifest_path === filePath.split(`${file}/`)[1]) {
96+
const templateData = readProjectFile(filePath, 'utf8');
11797

11898
templateOutputObj = {
11999
...data,

scripts/extract-templates.js

Lines changed: 109 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,109 @@
1+
const https = require('https');
2+
const http = require('http');
3+
const fs = require('fs');
4+
const path = require('path');
5+
const { execSync } = require('child_process');
6+
7+
const ROOT_DIR = path.resolve(__dirname, '..');
8+
const TEMPLATES_DIR = path.join(ROOT_DIR, 'templates');
9+
const GITHUB_TOKEN = process.env.GITHUB_TOKEN || '';
10+
11+
const sources = require(path.join(ROOT_DIR, 'template-sources.json'));
12+
13+
function resolveRef(data) {
14+
const { organization, repository, version, commit, branch } = data;
15+
16+
if (version) {
17+
return {
18+
url: `https://codeload.github.com/${organization}/${repository}/legacy.zip/refs/tags/${version}`,
19+
fileName: `${repository}@${version}`,
20+
};
21+
}
22+
23+
if (commit) {
24+
return {
25+
url: `https://codeload.github.com/${organization}/${repository}/legacy.zip/${commit}`,
26+
fileName: `${repository}@${commit}`,
27+
};
28+
}
29+
30+
if (branch) {
31+
return {
32+
url: `https://codeload.github.com/${organization}/${repository}/legacy.zip/refs/heads/${branch}`,
33+
fileName: `${repository}@${branch}`,
34+
};
35+
}
36+
37+
return {
38+
url: `https://api.github.com/repos/${organization}/${repository}/zipball/`,
39+
fileName: repository,
40+
};
41+
}
42+
43+
function download(url, headers = {}) {
44+
return new Promise((resolve, reject) => {
45+
const client = url.startsWith('https') ? https : http;
46+
47+
client
48+
.get(url, { headers }, (response) => {
49+
if (
50+
response.statusCode >= 300 &&
51+
response.statusCode < 400 &&
52+
response.headers.location
53+
) {
54+
download(response.headers.location, headers).then(resolve, reject);
55+
return;
56+
}
57+
58+
if (response.statusCode !== 200) {
59+
reject(new Error(`Download failed (${response.statusCode}): ${url}`));
60+
return;
61+
}
62+
63+
const chunks = [];
64+
response.on('data', (chunk) => chunks.push(chunk));
65+
response.on('end', () => resolve(Buffer.concat(chunks)));
66+
response.on('error', reject);
67+
})
68+
.on('error', reject);
69+
});
70+
}
71+
72+
async function main() {
73+
fs.rmSync(TEMPLATES_DIR, { recursive: true, force: true });
74+
fs.mkdirSync(TEMPLATES_DIR, { recursive: true });
75+
76+
for (const source of sources) {
77+
const { url, fileName } = resolveRef(source);
78+
79+
if (source.repositoryType === 'private' && !GITHUB_TOKEN) {
80+
console.warn(
81+
`Skipping private repository ${source.organization}/${source.repository} (missing GITHUB_TOKEN)`,
82+
);
83+
continue;
84+
}
85+
86+
const targetDir = path.join(TEMPLATES_DIR, fileName);
87+
fs.mkdirSync(targetDir, { recursive: true });
88+
89+
const headers =
90+
source.repositoryType === 'private'
91+
? {
92+
Accept: 'application/vnd.github+json',
93+
Authorization: `token ${GITHUB_TOKEN}`,
94+
}
95+
: {};
96+
97+
console.log(`Downloading ${source.organization}/${source.repository}...`);
98+
const zipData = await download(url, headers);
99+
const zipPath = path.join(targetDir, 'file.zip');
100+
fs.writeFileSync(zipPath, zipData);
101+
execSync('unzip -oq file.zip', { cwd: targetDir, stdio: 'inherit' });
102+
fs.unlinkSync(zipPath);
103+
}
104+
}
105+
106+
main().catch((error) => {
107+
console.error(error);
108+
process.exit(1);
109+
});

0 commit comments

Comments
 (0)