-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathstamp-version.js
More file actions
130 lines (116 loc) · 4.34 KB
/
Copy pathstamp-version.js
File metadata and controls
130 lines (116 loc) · 4.34 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
#!/usr/bin/env node
// Stamps latest app metadata from GitHub into index.html at build time.
// This keeps visible version/stars stable even when client-side GitHub API
// requests are blocked, rate-limited, or delayed.
// Usage: node stamp-version.js
const fs = require('fs');
const path = require('path');
const https = require('https');
const REPO = 'elkimek/get-based';
const INDEX = path.join(__dirname, 'index.html');
function fetchGitHubJson(apiPath) {
const token = process.env.GITHUB_TOKEN || process.env.GH_TOKEN;
const headers = {
'User-Agent': 'getbased-site-build',
'Accept': 'application/vnd.github+json',
};
if (token) headers.Authorization = `Bearer ${token}`;
return new Promise((resolve, reject) => {
const req = https.request({
hostname: 'api.github.com',
path: apiPath,
headers,
}, (res) => {
let body = '';
res.on('data', (c) => body += c);
res.on('end', () => {
if (res.statusCode !== 200) return reject(new Error(`GH API ${res.statusCode}: ${body.slice(0, 200)}`));
try { resolve(JSON.parse(body)); } catch (e) { reject(e); }
});
});
req.on('error', reject);
req.setTimeout(10000, () => req.destroy(new Error('GH API timeout')));
req.end();
});
}
function fetchLatestReleaseTag() {
// /releases/latest respects the repo's "Latest" flag — sorts by semver are
// unreliable on this repo (version-line reset) and /tags isn't sorted at all.
return fetchGitHubJson(`/repos/${REPO}/releases/latest`).then((release) => {
if (!release || !release.tag_name) throw new Error('No tag_name in latest release');
return String(release.tag_name);
});
}
function fetchStarCount() {
return fetchGitHubJson(`/repos/${REPO}`).then((repo) => {
const stars = Number(repo && repo.stargazers_count);
if (!Number.isFinite(stars) || stars <= 0) throw new Error('No stargazers_count in repo response');
return stars;
});
}
function formatStars(stars) {
return stars >= 1000 ? `${(stars / 1000).toFixed(1).replace(/\.0$/, '')}k` : String(stars);
}
function replaceOrWarn(html, re, replacement, label) {
if (!re.test(html)) {
console.error(`stamp-version: ${label} not found in index.html — skipping`);
return html;
}
return html.replace(re, replacement);
}
(async () => {
const [releaseResult, starsResult] = await Promise.allSettled([
fetchLatestReleaseTag(),
fetchStarCount(),
]);
if (releaseResult.status === 'rejected' && starsResult.status === 'rejected') {
console.error(`stamp-version: ${releaseResult.reason.message}; ${starsResult.reason.message} — keeping current values`);
return;
}
try {
const html = fs.readFileSync(INDEX, 'utf8');
let next = html;
const stamped = [];
if (releaseResult.status === 'fulfilled') {
const tag = releaseResult.value;
const version = tag.replace(/^v/, '');
next = replaceOrWarn(next, /"softwareVersion":\s*"[^"]*"/, `"softwareVersion": "${version}"`, 'softwareVersion field');
next = replaceOrWarn(
next,
/(<span class="hero-badge-meta" id="hero-version">).*?(<\/span>)/,
`$1· ${tag}$2`,
'hero version badge'
);
stamped.push(`version=${tag}`);
} else {
console.error(`stamp-version: ${releaseResult.reason.message} — keeping current version`);
}
if (starsResult.status === 'fulfilled') {
const formattedStars = formatStars(starsResult.value);
next = replaceOrWarn(
next,
/(<span class="hero-badge-meta" id="hero-stars">).*?(<\/span>)/,
`$1· ★ ${formattedStars} stars$2`,
'hero stars badge'
);
next = replaceOrWarn(
next,
/(<span class="github-stars-pill" data-github-stars-pill>).*?(<\/span>)/g,
`$1★ ${formattedStars}$2`,
'GitHub stars pills'
);
stamped.push(`stars=${formattedStars}`);
} else {
console.error(`stamp-version: ${starsResult.reason.message} — keeping current stars`);
}
if (next === html) {
console.log(`stamp-version: already current (${stamped.join(', ')})`);
return;
}
fs.writeFileSync(INDEX, next);
console.log(`stamp-version: stamped ${stamped.join(', ')}`);
} catch (err) {
// Non-fatal: don't fail the deploy if GH is flaky
console.error(`stamp-version: ${err.message} — keeping current value`);
}
})();