gitlab-badge-proxy 0.1.2 → 0.1.4
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +12 -0
- package/dist/src/app.d.ts.map +1 -1
- package/dist/src/app.js +130 -52
- package/dist/src/gitlab.d.ts.map +1 -1
- package/dist/src/gitlab.js +9 -0
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -76,6 +76,18 @@ explicitly whitelisted. The ref segment is free-form (any branch of a whiteliste
|
|
|
76
76
|
the fixed `GITLAB_REF` used by the flat `/pipeline.svg` / `/coverage.svg` routes above. The coverage
|
|
77
77
|
route also accepts `?job=<job-name>`, same as the flat route.
|
|
78
78
|
|
|
79
|
+
## Project-scoped badges beyond pipeline/coverage/release
|
|
80
|
+
|
|
81
|
+
The rest of the [Routes](#routes) above — stars, forks, contributors, issues, merge requests, last
|
|
82
|
+
commit, license, tag, languages, language count, labels, go.mod version — aren't part of GitLab's own
|
|
83
|
+
badge system, so there's no GitLab-native URL shape to mirror for them. This proxy has its own:
|
|
84
|
+
`GET /<group/project>/badges/<name>.svg`, e.g. `https://badges.yourdomain.tld/ardenslab/pm2-dash/badges/stars.svg`
|
|
85
|
+
or `.../badges/issues.svg?state=opened&labels=bug`. `<name>` is one of `stars`, `forks`,
|
|
86
|
+
`contributors`, `issues`, `merge-requests`, `last-commit`, `license`, `tag`, `languages`,
|
|
87
|
+
`languages-count`, `labels`, `go-mod` — same query params as the matching flat route (`labels.svg`
|
|
88
|
+
still needs `?name=`). Gated by the same `GITLAB_PROJECTS` whitelist as the GitLab-shaped routes
|
|
89
|
+
above; an unlisted project 404s the same way.
|
|
90
|
+
|
|
79
91
|
## Badge preview page
|
|
80
92
|
|
|
81
93
|
`GET /debug/<group/project>?ref=<branch>` renders an HTML page with every badge this proxy can
|
package/dist/src/app.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"app.d.ts","sourceRoot":"","sources":["../../src/app.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,IAAI,EAAgB,MAAM,MAAM,CAAC;AAE1C,OAAO,EAAc,KAAK,MAAM,EAAE,MAAM,aAAa,CAAC;AACtD,OAAO,EAAE,UAAU,EAAE,KAAK,MAAM,EAAE,MAAM,aAAa,CAAC;AAoBtD,OAAO,EACL,eAAe,EAkBhB,MAAM,YAAY,CAAC;
|
|
1
|
+
{"version":3,"file":"app.d.ts","sourceRoot":"","sources":["../../src/app.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,IAAI,EAAgB,MAAM,MAAM,CAAC;AAE1C,OAAO,EAAc,KAAK,MAAM,EAAE,MAAM,aAAa,CAAC;AACtD,OAAO,EAAE,UAAU,EAAE,KAAK,MAAM,EAAE,MAAM,aAAa,CAAC;AAoBtD,OAAO,EACL,eAAe,EAkBhB,MAAM,YAAY,CAAC;AAkcpB,wBAAgB,SAAS,CAAC,SAAS,GAAE,MAAM,MAAmB,GAAG,IAAI,CAoOpE;AAED,OAAO,EAAE,eAAe,EAAE,CAAC;AAC3B,eAAO,MAAM,GAAG,4EAAc,CAAC"}
|
package/dist/src/app.js
CHANGED
|
@@ -12,6 +12,27 @@ const UNKNOWN = { label: "gitlab", message: "unknown", color: "lightgrey" };
|
|
|
12
12
|
const BADGE_PATH_PATTERN = /^(.+)\/badges\/([^/]+)\/(pipeline|coverage)\.svg$/;
|
|
13
13
|
/** Matches GitLab's latest-release badge shape: `<project path>/-/badges/release.svg` (no ref). */
|
|
14
14
|
const RELEASE_PATH_PATTERN = /^(.+)\/-\/badges\/release\.svg$/;
|
|
15
|
+
/**
|
|
16
|
+
* This proxy's own badge shape (not one GitLab itself has): `<project path>/badges/<name>.svg`,
|
|
17
|
+
* for everything besides pipeline/coverage/release that isn't tied to a ref. Lets any whitelisted
|
|
18
|
+
* project use these the same way it already can use the GitLab-native ones above, instead of only
|
|
19
|
+
* the single fixed GITLAB_PROJECT getting them (via the flat /<name>.svg routes).
|
|
20
|
+
*/
|
|
21
|
+
const SIMPLE_BADGE_NAMES = [
|
|
22
|
+
"stars",
|
|
23
|
+
"forks",
|
|
24
|
+
"contributors",
|
|
25
|
+
"issues",
|
|
26
|
+
"merge-requests",
|
|
27
|
+
"last-commit",
|
|
28
|
+
"license",
|
|
29
|
+
"tag",
|
|
30
|
+
"languages",
|
|
31
|
+
"languages-count",
|
|
32
|
+
"labels",
|
|
33
|
+
"go-mod",
|
|
34
|
+
];
|
|
35
|
+
const SIMPLE_BADGE_PATH_PATTERN = new RegExp(`^(.+)\\/badges\\/(${SIMPLE_BADGE_NAMES.join("|")})\\.svg$`);
|
|
15
36
|
/**
|
|
16
37
|
* Known-safe `/api/v4/projects/:id/<subpath>` suffixes: just enough of the real GitLab REST API
|
|
17
38
|
* for shields.io-style "point gitlab_url at a different host" badges (release/tag/pipeline/
|
|
@@ -98,6 +119,8 @@ async function proxyGitlabApi(config, projectPath, subpath, search) {
|
|
|
98
119
|
const upstream = `${config.gitlabUrl}/api/v4/projects/${encodeURIComponent(projectPath)}${subpath ? `/${subpath}` : ""}${search}`;
|
|
99
120
|
try {
|
|
100
121
|
const response = await fetch(upstream, { headers: { "PRIVATE-TOKEN": config.gitlabToken } });
|
|
122
|
+
// Server-side only (stdout), never echoed back to the client.
|
|
123
|
+
console.log(`gitlab-badge-proxy: GET ${upstream} -> ${response.status}`);
|
|
101
124
|
const text = await response.text();
|
|
102
125
|
const maxAge = response.ok ? config.cacheMaxAgeSeconds : 30;
|
|
103
126
|
let body = text;
|
|
@@ -164,6 +187,18 @@ function renderDebugPage(project, ref, origin) {
|
|
|
164
187
|
{ label: "pipeline", src: `/${project}/badges/${ref}/pipeline.svg` },
|
|
165
188
|
{ label: "coverage", src: `/${project}/badges/${ref}/coverage.svg` },
|
|
166
189
|
{ label: "release", src: `/${project}/-/badges/release.svg` },
|
|
190
|
+
{ label: "stars", src: `/${project}/badges/stars.svg` },
|
|
191
|
+
{ label: "forks", src: `/${project}/badges/forks.svg` },
|
|
192
|
+
{ label: "contributors", src: `/${project}/badges/contributors.svg` },
|
|
193
|
+
{ label: "issues", src: `/${project}/badges/issues.svg` },
|
|
194
|
+
{ label: "merge requests", src: `/${project}/badges/merge-requests.svg` },
|
|
195
|
+
{ label: "last commit", src: `/${project}/badges/last-commit.svg` },
|
|
196
|
+
{ label: "license", src: `/${project}/badges/license.svg` },
|
|
197
|
+
{ label: "tag", src: `/${project}/badges/tag.svg` },
|
|
198
|
+
{ label: "top language", src: `/${project}/badges/languages.svg` },
|
|
199
|
+
{ label: "language count", src: `/${project}/badges/languages-count.svg` },
|
|
200
|
+
{ label: "label color (bug)", src: `/${project}/badges/labels.svg?name=bug` },
|
|
201
|
+
{ label: "go.mod version", src: `/${project}/badges/go-mod.svg` },
|
|
167
202
|
];
|
|
168
203
|
const nativeDefaultBadges = [
|
|
169
204
|
{ label: "pipeline", src: "/pipeline.svg" },
|
|
@@ -284,6 +319,54 @@ async function resolveReleaseSpec(config, projectPath) {
|
|
|
284
319
|
return releaseToBadge(release);
|
|
285
320
|
});
|
|
286
321
|
}
|
|
322
|
+
/** Computes one of SIMPLE_BADGE_NAMES's badges for `projectPath` - shared by the flat `/<name>.svg`
|
|
323
|
+
* routes (always `config.project`) and the project-scoped `/:project/badges/<name>.svg` routes
|
|
324
|
+
* (any whitelisted project), so the two stay identical instead of duplicating this per route. */
|
|
325
|
+
async function computeSimpleBadge(config, projectPath, name, c) {
|
|
326
|
+
switch (name) {
|
|
327
|
+
case "stars":
|
|
328
|
+
return starsToBadge(await getStarsCount(config, projectPath));
|
|
329
|
+
case "forks":
|
|
330
|
+
return forksToBadge(await getForksCount(config, projectPath));
|
|
331
|
+
case "contributors":
|
|
332
|
+
return contributorsToBadge(await getContributorsCount(config, projectPath));
|
|
333
|
+
case "issues": {
|
|
334
|
+
const state = c.req.query("state") ?? "all";
|
|
335
|
+
const labels = c.req.query("labels");
|
|
336
|
+
return issuesToBadge(await getIssuesCount(config, projectPath, state, labels), state, labels);
|
|
337
|
+
}
|
|
338
|
+
case "merge-requests": {
|
|
339
|
+
const state = c.req.query("state") ?? "opened";
|
|
340
|
+
const labels = c.req.query("labels");
|
|
341
|
+
return mergeRequestsToBadge(await getMergeRequestsCount(config, projectPath, state, labels), state, labels);
|
|
342
|
+
}
|
|
343
|
+
case "last-commit": {
|
|
344
|
+
const ref = c.req.query("ref") ?? config.ref;
|
|
345
|
+
const path = c.req.query("path");
|
|
346
|
+
return lastCommitToBadge(await getLastCommitDate(config, projectPath, ref, path));
|
|
347
|
+
}
|
|
348
|
+
case "license":
|
|
349
|
+
return licenseToBadge(await getLicenseName(config, projectPath));
|
|
350
|
+
case "tag":
|
|
351
|
+
return tagToBadge(await getLatestTag(config, projectPath));
|
|
352
|
+
case "languages":
|
|
353
|
+
return topLanguageToBadge(await getLanguages(config, projectPath));
|
|
354
|
+
case "languages-count":
|
|
355
|
+
return languagesCountToBadge(await getLanguages(config, projectPath));
|
|
356
|
+
case "labels": {
|
|
357
|
+
const labelName = c.req.query("name");
|
|
358
|
+
if (!labelName) {
|
|
359
|
+
throw new Error("missing required ?name= query param");
|
|
360
|
+
}
|
|
361
|
+
return labelToBadge(labelName, await getLabelColor(config, projectPath, labelName));
|
|
362
|
+
}
|
|
363
|
+
case "go-mod": {
|
|
364
|
+
const ref = c.req.query("ref") ?? config.ref;
|
|
365
|
+
const filename = c.req.query("filename") ?? "go.mod";
|
|
366
|
+
return goModVersionToBadge(await getGoModVersion(config, projectPath, ref, filename));
|
|
367
|
+
}
|
|
368
|
+
}
|
|
369
|
+
}
|
|
287
370
|
/** Registers a flat `/<path>.svg` route fixed to the configured default project (and ref, where relevant). */
|
|
288
371
|
function registerBadgeRoute(app, getConfig, path, fallback, context, compute) {
|
|
289
372
|
app.get(path, async (c) => {
|
|
@@ -351,40 +434,18 @@ export function createApp(getConfig = loadConfig) {
|
|
|
351
434
|
const { spec, maxAge } = await resolveReleaseSpec(config, config.project);
|
|
352
435
|
return svgResponse(await fetchBadgeSvg(spec), maxAge);
|
|
353
436
|
});
|
|
354
|
-
registerBadgeRoute(app, getConfig, "/stars.svg", UNKNOWN, "stars",
|
|
355
|
-
registerBadgeRoute(app, getConfig, "/forks.svg", UNKNOWN, "forks",
|
|
356
|
-
registerBadgeRoute(app, getConfig, "/contributors.svg", UNKNOWN, "contributors",
|
|
357
|
-
registerBadgeRoute(app, getConfig, "/issues.svg", UNKNOWN, "issues",
|
|
358
|
-
|
|
359
|
-
|
|
360
|
-
|
|
361
|
-
|
|
362
|
-
registerBadgeRoute(app, getConfig, "/
|
|
363
|
-
|
|
364
|
-
|
|
365
|
-
|
|
366
|
-
});
|
|
367
|
-
registerBadgeRoute(app, getConfig, "/last-commit.svg", UNKNOWN, "last commit", async (config, c) => {
|
|
368
|
-
const ref = c.req.query("ref") ?? config.ref;
|
|
369
|
-
const path = c.req.query("path");
|
|
370
|
-
return lastCommitToBadge(await getLastCommitDate(config, config.project, ref, path));
|
|
371
|
-
});
|
|
372
|
-
registerBadgeRoute(app, getConfig, "/license.svg", UNKNOWN, "license", async (config) => licenseToBadge(await getLicenseName(config, config.project)));
|
|
373
|
-
registerBadgeRoute(app, getConfig, "/tag.svg", UNKNOWN, "tag", async (config) => tagToBadge(await getLatestTag(config, config.project)));
|
|
374
|
-
registerBadgeRoute(app, getConfig, "/languages.svg", UNKNOWN, "top language", async (config) => topLanguageToBadge(await getLanguages(config, config.project)));
|
|
375
|
-
registerBadgeRoute(app, getConfig, "/languages-count.svg", UNKNOWN, "language count", async (config) => languagesCountToBadge(await getLanguages(config, config.project)));
|
|
376
|
-
registerBadgeRoute(app, getConfig, "/labels.svg", UNKNOWN, "label", async (config, c) => {
|
|
377
|
-
const name = c.req.query("name");
|
|
378
|
-
if (!name) {
|
|
379
|
-
throw new Error("missing required ?name= query param");
|
|
380
|
-
}
|
|
381
|
-
return labelToBadge(name, await getLabelColor(config, config.project, name));
|
|
382
|
-
});
|
|
383
|
-
registerBadgeRoute(app, getConfig, "/go-mod.svg", UNKNOWN, "go.mod version", async (config, c) => {
|
|
384
|
-
const ref = c.req.query("ref") ?? config.ref;
|
|
385
|
-
const filename = c.req.query("filename") ?? "go.mod";
|
|
386
|
-
return goModVersionToBadge(await getGoModVersion(config, config.project, ref, filename));
|
|
387
|
-
});
|
|
437
|
+
registerBadgeRoute(app, getConfig, "/stars.svg", UNKNOWN, "stars", (config, c) => computeSimpleBadge(config, config.project, "stars", c));
|
|
438
|
+
registerBadgeRoute(app, getConfig, "/forks.svg", UNKNOWN, "forks", (config, c) => computeSimpleBadge(config, config.project, "forks", c));
|
|
439
|
+
registerBadgeRoute(app, getConfig, "/contributors.svg", UNKNOWN, "contributors", (config, c) => computeSimpleBadge(config, config.project, "contributors", c));
|
|
440
|
+
registerBadgeRoute(app, getConfig, "/issues.svg", UNKNOWN, "issues", (config, c) => computeSimpleBadge(config, config.project, "issues", c));
|
|
441
|
+
registerBadgeRoute(app, getConfig, "/merge-requests.svg", UNKNOWN, "merge requests", (config, c) => computeSimpleBadge(config, config.project, "merge-requests", c));
|
|
442
|
+
registerBadgeRoute(app, getConfig, "/last-commit.svg", UNKNOWN, "last commit", (config, c) => computeSimpleBadge(config, config.project, "last-commit", c));
|
|
443
|
+
registerBadgeRoute(app, getConfig, "/license.svg", UNKNOWN, "license", (config, c) => computeSimpleBadge(config, config.project, "license", c));
|
|
444
|
+
registerBadgeRoute(app, getConfig, "/tag.svg", UNKNOWN, "tag", (config, c) => computeSimpleBadge(config, config.project, "tag", c));
|
|
445
|
+
registerBadgeRoute(app, getConfig, "/languages.svg", UNKNOWN, "top language", (config, c) => computeSimpleBadge(config, config.project, "languages", c));
|
|
446
|
+
registerBadgeRoute(app, getConfig, "/languages-count.svg", UNKNOWN, "language count", (config, c) => computeSimpleBadge(config, config.project, "languages-count", c));
|
|
447
|
+
registerBadgeRoute(app, getConfig, "/labels.svg", UNKNOWN, "label", (config, c) => computeSimpleBadge(config, config.project, "labels", c));
|
|
448
|
+
registerBadgeRoute(app, getConfig, "/go-mod.svg", UNKNOWN, "go.mod version", (config, c) => computeSimpleBadge(config, config.project, "go-mod", c));
|
|
388
449
|
// Visual test page: every native and shields.io badge shape this proxy can produce, for one
|
|
389
450
|
// project/ref given in the URL. /debug alone falls back to the fixed default project.
|
|
390
451
|
app.get("/debug", (c) => {
|
|
@@ -457,26 +518,43 @@ export function createApp(getConfig = loadConfig) {
|
|
|
457
518
|
return svgResponse(await fetchBadgeSvg(spec), maxAge);
|
|
458
519
|
}
|
|
459
520
|
const match = BADGE_PATH_PATTERN.exec(rest);
|
|
460
|
-
if (
|
|
461
|
-
|
|
462
|
-
|
|
463
|
-
|
|
464
|
-
|
|
465
|
-
|
|
466
|
-
|
|
467
|
-
|
|
468
|
-
|
|
469
|
-
|
|
470
|
-
|
|
471
|
-
|
|
521
|
+
if (match) {
|
|
522
|
+
const [, projectPath, ref, kind] = match;
|
|
523
|
+
let config;
|
|
524
|
+
try {
|
|
525
|
+
config = getConfig();
|
|
526
|
+
}
|
|
527
|
+
catch (error) {
|
|
528
|
+
console.error("gitlab-badge-proxy: failed to load config", error);
|
|
529
|
+
const fallback = kind === "pipeline" ? UNKNOWN_PIPELINE : UNKNOWN_COVERAGE;
|
|
530
|
+
return svgResponse(await fetchBadgeSvg(fallback), 30);
|
|
531
|
+
}
|
|
532
|
+
if (!config.allowedProjects.includes(projectPath)) {
|
|
533
|
+
return c.notFound();
|
|
534
|
+
}
|
|
535
|
+
const { spec, maxAge } = kind === "pipeline"
|
|
536
|
+
? await resolvePipelineSpec(config, projectPath, ref)
|
|
537
|
+
: await resolveCoverageSpec(config, projectPath, ref, c.req.query("job"));
|
|
538
|
+
return svgResponse(await fetchBadgeSvg(spec), maxAge);
|
|
472
539
|
}
|
|
473
|
-
|
|
474
|
-
|
|
540
|
+
const simpleMatch = SIMPLE_BADGE_PATH_PATTERN.exec(rest);
|
|
541
|
+
if (simpleMatch) {
|
|
542
|
+
const [, projectPath, name] = simpleMatch;
|
|
543
|
+
let config;
|
|
544
|
+
try {
|
|
545
|
+
config = getConfig();
|
|
546
|
+
}
|
|
547
|
+
catch (error) {
|
|
548
|
+
console.error("gitlab-badge-proxy: failed to load config", error);
|
|
549
|
+
return svgResponse(await fetchBadgeSvg(UNKNOWN), 30);
|
|
550
|
+
}
|
|
551
|
+
if (!config.allowedProjects.includes(projectPath)) {
|
|
552
|
+
return c.notFound();
|
|
553
|
+
}
|
|
554
|
+
const { spec, maxAge } = await resolveSpec(config, UNKNOWN, name, () => computeSimpleBadge(config, projectPath, name, c));
|
|
555
|
+
return svgResponse(await fetchBadgeSvg(spec), maxAge);
|
|
475
556
|
}
|
|
476
|
-
|
|
477
|
-
? await resolvePipelineSpec(config, projectPath, ref)
|
|
478
|
-
: await resolveCoverageSpec(config, projectPath, ref, c.req.query("job"));
|
|
479
|
-
return svgResponse(await fetchBadgeSvg(spec), maxAge);
|
|
557
|
+
return c.notFound();
|
|
480
558
|
});
|
|
481
559
|
return app;
|
|
482
560
|
}
|
package/dist/src/gitlab.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"gitlab.d.ts","sourceRoot":"","sources":["../../src/gitlab.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,MAAM,EAAE,MAAM,aAAa,CAAC;AAE1C,MAAM,WAAW,eAAe;IAC9B,EAAE,EAAE,MAAM,CAAC;IACX,MAAM,EAAE,MAAM,CAAC;CAChB;AAED,MAAM,WAAW,cAAc;IAC7B,IAAI,EAAE,MAAM,CAAC;IACb,OAAO,EAAE,MAAM,CAAC;CACjB;
|
|
1
|
+
{"version":3,"file":"gitlab.d.ts","sourceRoot":"","sources":["../../src/gitlab.ts"],"names":[],"mappings":"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"}
|
package/dist/src/gitlab.js
CHANGED
|
@@ -4,7 +4,16 @@ async function gitlabRequest(config, projectPath, path) {
|
|
|
4
4
|
const response = await fetch(url, {
|
|
5
5
|
headers: { "PRIVATE-TOKEN": config.gitlabToken },
|
|
6
6
|
});
|
|
7
|
+
// Server-side only (stdout), never echoed back to the client - shows the exact upstream call this
|
|
8
|
+
// request triggered, for anyone watching the proxy's own logs to debug a GitLab-side issue.
|
|
9
|
+
console.log(`gitlab-badge-proxy: GET ${url} -> ${response.status}`);
|
|
7
10
|
if (!response.ok) {
|
|
11
|
+
// GitLab's own error body (e.g. `{"message":"401 Unauthorized"}`) plus the token's length (never
|
|
12
|
+
// its value) are usually enough to tell "GITLAB_TOKEN isn't set" (length 0) apart from "it's set
|
|
13
|
+
// but wrong/expired/missing scope" (non-zero length, still 401/403) from the logs alone.
|
|
14
|
+
const body = await response.text().catch(() => "<unreadable response body>");
|
|
15
|
+
console.error(`gitlab-badge-proxy: GitLab API error ${response.status} for ${url} ` +
|
|
16
|
+
`(GITLAB_TOKEN length: ${config.gitlabToken.length}): ${body.slice(0, 300)}`);
|
|
8
17
|
throw new Error(`GitLab API responded with ${response.status}`);
|
|
9
18
|
}
|
|
10
19
|
return response;
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "gitlab-badge-proxy",
|
|
3
|
-
"version": "0.1.
|
|
3
|
+
"version": "0.1.4",
|
|
4
4
|
"description": "Server-side proxy that turns private GitLab pipeline/coverage status into public SVG badges, without ever exposing the GitLab instance's URL to clients.",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"license": "MIT",
|