feat: fetch gitea repos of given user to generate corresponding traefik middleware config
All checks were successful
Build and Push Docker Image / build (push) Successful in 12s

This commit is contained in:
Pihkaal
2025-12-21 17:12:20 +01:00
parent 5dcd12a8a8
commit 999848d581
4 changed files with 94 additions and 0 deletions

View File

@@ -1 +1,15 @@
PORT="3000" PORT="3000"
# Gitea base url (like https://git.pihkaal.xyz)
GITEA_URL=""
# Gitea main username (for me it's pihkaal)
GITEA_USERNAME=""
# Create an access token here /user/settings/applications
# Required permissions:
# - read:repository
# - read:user
GITEA_TOKEN=""
# Create your own in /user/settings/hooks
GITEA_WEBHOOK_SECRET=""
# File used by traefik to create the middleware
TEMPLATE_FILE="gitea-rewrites.yml.in"
OUTPUT_FILE="gitea-rewrites.yml"

View File

@@ -0,0 +1,7 @@
# example template file
http:
middlewares:
gitea-rewrites:
replacePathRegex:
regex: "^/({{REPOSITORIES}})(.*)$"
replacement: "/{{USERNAME}}/$1$2"

View File

@@ -3,7 +3,12 @@ import { z } from "zod";
const schema = z.object({ const schema = z.object({
PORT: z.coerce.number(), PORT: z.coerce.number(),
GITEA_URL: z.url(),
GITEA_USERNAME: z.string(),
GITEA_TOKEN: z.string(),
GITEA_WEBHOOK_SECRET: z.string(), GITEA_WEBHOOK_SECRET: z.string(),
TEMPLATE_FILE: z.string(),
OUTPUT_FILE: z.string(),
}); });
const result = schema.safeParse(process.env); const result = schema.safeParse(process.env);

68
src/sync.ts Normal file
View File

@@ -0,0 +1,68 @@
import { readFile, writeFile } from "fs/promises";
import { z } from "zod";
import { env } from "./env";
const giteaRepoSchema = z.object({
name: z.string(),
owner: z.object({
login: z.string(),
}),
});
const fetchGiteaRepos = async (): Promise<string[]> => {
try {
const response = await fetch(
`${env.GITEA_URL}/api/v1/users/${env.GITEA_USERNAME}/repos`,
{
headers: {
Authorization: `token ${env.GITEA_TOKEN}`,
},
},
);
if (!response.ok) {
throw new Error(`HTTP ${response.status}: ${response.statusText}`);
}
const json = await response.json();
const repos = z.array(giteaRepoSchema).parse(json);
const userRepos = repos
.filter((repo) => repo.owner.login === env.GITEA_USERNAME)
.map((repo) => repo.name);
return userRepos;
} catch (error) {
console.error(
`ERROR: can't fetch repos from Gitea: ${error instanceof Error ? error.message : error}`,
);
process.exit(1);
}
};
const createOutputFile = async (repos: string[]): Promise<void> => {
try {
const template = await readFile(env.TEMPLATE_FILE, "utf-8");
const reposPattern = repos.join("|");
let output = template.replace("{{REPOSITORIES}}", reposPattern);
output = output.replace("{{USERNAME}}", env.GITEA_USERNAME);
await writeFile(env.OUTPUT_FILE, output);
console.log(`Successfully wrote ${env.OUTPUT_FILE}`);
} catch (error) {
if (error instanceof Error && "code" in error && error.code === "ENOENT") {
console.error(`ERROR: Template file '${env.TEMPLATE_FILE}' not found`);
} else {
console.error(
`ERROR: can't read/write file: ${error instanceof Error ? error.message : error}`,
);
}
process.exit(1);
}
};
export const syncGiteaRewrites = async (): Promise<void> => {
const repos = await fetchGiteaRepos();
await createOutputFile(repos);
};