Skip to main content
Glama
github.routes.ts5.36 kB
import _ from 'lodash'; import Axios from "axios"; import { tryCatch } from "../lib/try-catch"; import { ApiError } from "../lib/api-error"; import { router } from "."; const ghApi = Axios.create({ baseURL: `https://${process.env.GH_DOMAIN}`, }); interface Asset { id: number; contentType: string; size: number; name: string; url: string; } interface Release { id: number; version: string; name: string; description: string; assets: Asset[]; publishedAt: string; } let releaseCachedAt: Date | null = null; let releases: Release[] | null = null; let loadingReleases: boolean = false; const loadReleases = async (): Promise<Release[]> => { const seconds = Math.abs(Date.now() - (releaseCachedAt?.getTime() ?? 0)); if ((seconds > 180 * 1000 || !releases) && !loadingReleases) { loadingReleases = true; try { const data = await tryCatch(async () => { const req = await ghApi.get("/repos/systeminit/si/releases", { headers: { Accept: "application/vnd.github+json", Authorization: `Bearer ${process.env.GH_TOKEN}`, "X-Github-Api-Version": "2022-11-28", }, }); return req.data; }, (err) => { throw new ApiError( 'Conflict', `Fetching relases from github failed: ${err.response.statusText} - ${err.response.data.message}`, ); }); const releasesTemp: Release[] = []; for (const githubRelease of data) { const release: Release = { id: githubRelease.id, version: githubRelease.tag_name, name: githubRelease.name, description: githubRelease.body, publishedAt: githubRelease.published_at, assets: [], }; for (const githubAsset of githubRelease.assets) { const asset: Asset = { id: githubAsset.id, contentType: githubAsset.content_type, size: githubAsset.size, name: githubAsset.name, url: githubAsset.browser_download_url, }; release.assets.push(asset); } releasesTemp.push(release); } releaseCachedAt = new Date(); releases = releasesTemp; } catch (err) { if (releases) { // eslint-disable-next-line no-console console.error(err); return releases; } throw err; } finally { loadingReleases = false; } } return releases ?? []; }; router.get("/github/releases/latest", async (ctx) => { const latest = (await loadReleases())[0]; if (!latest) { throw new ApiError( "Conflict", "Could not find the latest release on Github", ); } ctx.body = latest; }); router.get("/github/releases", async (ctx) => { ctx.body = await loadReleases(); }); interface GithubTag { ref: string; node_id: string; url: string; object: { sha: string; type: string; url: string; }; } interface LatestContainer { namespace: string; repository: string; gitSha: string; digest: string; } let containersCachedAt: Date | null = null; let containers: LatestContainer[] | null = null; let loadingContainers: boolean = false; router.get("/github/containers/latest", async (ctx) => { // ctx.body = []; // TODO: re-enable container updates when we fix the tags const seconds = Math.abs(Date.now() - (containersCachedAt?.getTime() ?? 0)); if ((seconds > 180 * 1000 || !containers) && !loadingContainers) { loadingContainers = true; try { const data: GithubTag[] = await tryCatch(async () => { const req = await ghApi.get("/repos/systeminit/si/git/matching-refs/tags", { headers: { Accept: "application/vnd.github+json", Authorization: `Bearer ${process.env.GH_TOKEN}`, "X-Github-Api-Version": "2022-11-28", }, }); return req.data; }, (err) => { throw new ApiError( err.response.statusText, "GITHUB_LIST_TAGS_FAILURE", err.response.data.message, ); }); const sortedData = _.orderBy(data, (d) => d.ref, 'desc'); const prefixes = ["bin/sdf", "bin/veritech", "bin/pinga", "bin/council", "app/web", "component/otelcol", "component/jaeger", "component/nats", "component/postgres"]; const latestContainers = []; for (const tag of sortedData) { for (const prefix of prefixes) { const split = prefix.split("/"); const start = `refs/tags/${prefix}/image/`; if (tag.ref.startsWith(start)) { const indexOfPrefix = prefixes.indexOf(prefix); prefixes.splice(indexOfPrefix, 1); const digest = tag.ref.replace(start, ""); latestContainers.push({ namespace: "systeminit", repository: split[split.length - 1], gitSha: tag.object.sha, digest, }); break; } } } containersCachedAt = new Date(); containers = latestContainers; } catch (err) { if (containers) { // eslint-disable-next-line no-console console.error(err); ctx.body = containers; return; } throw err; } finally { loadingContainers = false; } } ctx.body = containers ?? []; });

Latest Blog Posts

MCP directory API

We provide all the information about MCP servers via our MCP API.

curl -X GET 'https://glama.ai/api/mcp/v1/servers/systeminit/si'

If you have feedback or need assistance with the MCP directory API, please join our Discord server