Add Gitea integration; fix .env never being loaded outside Docker
Second live integration: repo list with last CI run status, and re-running
failed jobs on a workflow run — matching the "dashboard + basic actions"
depth from the plan. Adapter built directly against the real Gitea 1.27
swagger spec (fetched from the user's own instance) rather than guessing at
the API shape: GET /user/repos for the repo list, GET
/repos/{owner}/{repo}/actions/runs?limit=1 for the latest run per repo (only
for repos with Actions enabled), and POST .../rerun-failed-jobs for retrying
just the failed jobs in a run. Follows the same config-in-UI +
encrypted-credential pattern as Tailscale and DNS providers.
Since Gitea collects its own base URL as a config field (unlike Tailscale,
which always talks to a fixed api.tailscale.com), generalized the
"integrations.baseUrl" bookkeeping into resolveBaseUrl() instead of the
one-fixed-URL-per-type map used previously.
Also fixed a real gap found while setting this up: server/src/env.ts reads
process.env directly, but nothing in the app ever loaded .env into
process.env for plain `node dist/index.js` / `tsx src/index.ts` runs — only
Docker's `env_file` config populated it, by injecting vars before Node even
starts. Every local (non-Docker) run silently had every setting at its
insecure default. Added server/src/loadEnv.ts (dotenv, pointed at the
repo-root .env) as the first import in both server/src/index.ts and
server/src/db/migrate.ts's standalone entrypoint.
Verified against the user's real, reachable services — not mocks:
- Authentik (auth.labsconnect.se): full OIDC login completed by the user
through the real UI; confirmed their account landed as admin (first user).
- Gitea (gitea.labsconnect.se): the compiled adapter run directly against a
real API token correctly listed all 11 real repos; a full HTTP-layer test
against the live server (8 checks) additionally covered a real
test-connection ping, credential non-leakage in list responses, and role
gating (403) on the rerun-failed-jobs action even with a valid token
behind it. None of the real repos have any workflow run history yet, so
the success/failure status badge and the rerun action itself are
implemented per the swagger spec but not yet exercised against a real run
— worth checking once one of those repos has actual CI activity.
Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
This commit is contained in:
1 parent
069225c656
commit
79710aa7a5
12 files changed
+479
-6
No files matched your search
@@ -1,11 +1,25 @@
|
||||
import type { IntegrationType } from "../db/schema.js";
|
||||
import type { IntegrationConfig } from "./types.js";
|
||||
import { createTailscaleAdapter, type TailscaleAdapter } from "./tailscale/adapter.js";
|
||||
import { createTailscaleAdapter } from "./tailscale/adapter.js";
|
||||
import { createGiteaAdapter } from "./gitea/adapter.js";
|
||||
|
||||
export function createIntegrationAdapter(type: IntegrationType, config: IntegrationConfig): TailscaleAdapter {
|
||||
export interface PingableAdapter {
|
||||
ping(): Promise<{ ok: boolean; latencyMs?: number; error?: string }>;
|
||||
}
|
||||
|
||||
/**
|
||||
* Generic dispatch used only where a ping() is all that's needed (the "test
|
||||
* connection" endpoint). Type-specific routes construct their own concrete
|
||||
* adapter directly (see requireTailscaleAdapter / requireGiteaAdapter in
|
||||
* routes/integrations.ts) so a not-yet-implemented type can never throw here
|
||||
* for an existing row of some OTHER type.
|
||||
*/
|
||||
export function createIntegrationAdapter(type: IntegrationType, config: IntegrationConfig): PingableAdapter {
|
||||
switch (type) {
|
||||
case "tailscale":
|
||||
return createTailscaleAdapter(config as any);
|
||||
case "gitea":
|
||||
return createGiteaAdapter(config as any);
|
||||
default:
|
||||
throw new Error(`Integration type "${type}" is not implemented yet`);
|
||||
}
|
||||
|
||||
Reference in new issue
Block a user