feat(config): switch to routes-only config, drop default channel

Remove hardcoded DEFAULT_ROUTES and Config.discord.defaultChannelId so
forwarding is driven entirely by user-defined routes (empty KV = no
forwarding). Add ADMIN_USER_IDS, DISCORD_GATEWAY_ENABLED and ASSETS to Env.
This commit is contained in:
RhenCloud 2026-08-02 06:49:56 +08:00
parent ccab01d23a
commit 4d5c90773d
No known key found for this signature in database
GPG key ID: A574A617378C4E0B
2 changed files with 32 additions and 69 deletions

View file

@ -1,78 +1,37 @@
import type { Env, Config, Route } from "./types"; import type { Env, Config, Route } from "./types";
import { log } from "./log"; import { log } from "./log";
const DEFAULT_ROUTES: Route[] = [ const CONFIG_CACHE_TTL = 60_000;
{ const ROUTES_KEY = "config:routes";
id: "all-push", let configCache: { config: Config; expiresAt: number } | null = null;
name: "All Push Events",
enabled: true, export async function loadRoutes(kv: KVNamespace): Promise<Route[]> {
filters: [{ type: "event", match: "push" }], try {
target: { channelId: "" }, const stored = await kv.get<Route[]>(ROUTES_KEY, "json");
}, if (stored) return stored;
{ } catch (err) {
id: "pull-requests", log.warn({ err }, "Failed to load routes from KV");
name: "Pull Requests", }
enabled: true, return [];
filters: [{ type: "event", match: "pull_request" }], }
target: { channelId: "" },
}, export async function saveRoutes(kv: KVNamespace, routes: Route[]): Promise<void> {
{ await kv.put(ROUTES_KEY, JSON.stringify(routes));
id: "issues", configCache = null;
name: "Issues", }
enabled: true,
filters: [{ type: "event", match: "issues" }], export function invalidateConfigCache(): void {
target: { channelId: "" }, configCache = null;
}, }
{
id: "issue-comments",
name: "Issue Comments",
enabled: true,
filters: [{ type: "event", match: "issue_comment" }],
target: { channelId: "" },
},
{
id: "workflow-runs",
name: "Workflow Runs",
enabled: true,
filters: [{ type: "event", match: "workflow_run" }],
target: { channelId: "" },
},
{
id: "releases",
name: "Releases",
enabled: true,
filters: [{ type: "event", match: "release" }],
target: { channelId: "" },
},
{
id: "branch-activity",
name: "Branch Create/Delete",
enabled: true,
filters: [{ type: "event", match: ["create", "delete"] }],
target: { channelId: "" },
},
];
export async function loadConfig(env: Env): Promise<Config> { export async function loadConfig(env: Env): Promise<Config> {
let routes = DEFAULT_ROUTES; if (configCache && Date.now() < configCache.expiresAt) {
return configCache.config;
try {
const stored = await env.KV.get("config:routes", "json");
if (stored) {
routes = stored as Route[];
}
} catch (err) {
log.warn({ err }, "Failed to load routes from KV, using defaults");
} }
const defaultChannelId = env.DISCORD_CHANNEL_ID ?? ""; const routes = await loadRoutes(env.KV);
routes = routes.map((r) => ({ const config: Config = {
...r,
target: { ...r.target, channelId: r.target.channelId || defaultChannelId },
}));
return {
baseUrl: env.BASE_URL ?? "https://webhooker.example.workers.dev", baseUrl: env.BASE_URL ?? "https://webhooker.example.workers.dev",
github: { github: {
webhookSecret: env.GITHUB_WEBHOOK_SECRET, webhookSecret: env.GITHUB_WEBHOOK_SECRET,
@ -83,8 +42,10 @@ export async function loadConfig(env: Env): Promise<Config> {
}, },
discord: { discord: {
token: env.DISCORD_TOKEN ?? "", token: env.DISCORD_TOKEN ?? "",
defaultChannelId,
}, },
routes, routes,
}; };
configCache = { config, expiresAt: Date.now() + CONFIG_CACHE_TTL };
return config;
} }

View file

@ -7,6 +7,9 @@ export interface Env {
DISCORD_TOKEN?: string; DISCORD_TOKEN?: string;
DISCORD_CHANNEL_ID?: string; DISCORD_CHANNEL_ID?: string;
BASE_URL?: string; BASE_URL?: string;
ADMIN_USER_IDS?: string;
DISCORD_GATEWAY_ENABLED?: string;
ASSETS?: Fetcher;
KV: KVNamespace; KV: KVNamespace;
DISCORD_GATEWAY: DurableObjectNamespace; DISCORD_GATEWAY: DurableObjectNamespace;
} }
@ -22,7 +25,6 @@ export interface Config {
}; };
discord: { discord: {
token: string; token: string;
defaultChannelId: string;
}; };
routes: Route[]; routes: Route[];
} }