Add an env-var-gated, off-by-default Sentry SDK integration so MCP runtime errors, fail-closed workflow blockers, lease/terminal-lock/stale-runtime collisions, and recurring watchdog check-ins are visible in a self-hosted Sentry at https://sentry.prgs.cc/. Gitea stays the source of truth; Sentry is observe-only. New module `sentry_observability.py` mirrors the `gitea_audit` conventions (env-gated, best-effort, redacting): - Config from MCP_SENTRY_ENABLED / SENTRY_DSN / SENTRY_ENVIRONMENT / SENTRY_RELEASE / MCP_SENTRY_TRACES_SAMPLE_RATE / MCP_SENTRY_ENABLE_LOGS. Active only when enabled AND a DSN is present; otherwise a hard no-op. - Fail OPEN for observability (never blocks a tool success path) and fail CLOSED for redaction (drop a field rather than risk leaking it). - `scrub_event` before_send/before_send_log hook + allowlisted tags: no tokens/passwords/keychain ids/DSNs/cookies, no raw session-state or full prompt bodies (session_id -> 12-char hash), no full filesystem paths (worktree path -> coarse category). Reuses incident_bridge + gitea_audit scrubbers. - capture_exception, capture_workflow_blocker (with canonical next action), and monitor_checkin with six stable cron slugs (stale lease scan, terminal lock scan, allocator health, namespace health, dashboard freshness, reconciler cleanup). - `sentry_sdk` is a lazily-imported optional dependency; the module imports and no-ops cleanly when the package is absent. Wiring in gitea_mcp_server.py (additive, guarded, best-effort): - init_sentry() in __main__ before mcp.run. - capture_exception in the `_audited` failure path; capture_workflow_blocker in `_audit_pr_result` BLOCKED/FAILED path. - allocator + namespace-health watchdog check-ins at their MCP tool sites (domain modules left pure). Also: pin `sentry-sdk==2.20.0` (optional), document the six env vars in `.env.example`, and add `docs/observability/sentry-integration.md` covering project creation in https://sentry.prgs.cc/, DSN handling, local/dev/prod config, redaction guarantees, and coexistence with the #612 incident bridge. Tests: tests/test_sentry_observability.py (36 cases) cover disabled / enabled / missing-DSN / missing-SDK, redaction, exception capture, workflow-blocker capture, and cron check-in behaviour. Full suite: 2632 passed, 6 skipped. Co-Authored-By: Claude Opus 4.8 (1M context) <[email protected]>
79 lines
3.9 KiB
Bash
79 lines
3.9 KiB
Bash
# Gitea MCP runtime profile — EXAMPLE / PLACEHOLDERS ONLY.
|
||
#
|
||
# Copy to a real, gitignored env file (e.g. .env.reviewer) per runtime profile.
|
||
# The same MCP server code is launched as separate MCP entries, each pointed at
|
||
# a different env file so each process authenticates as ONE token and carries
|
||
# ONE profile name. Do NOT put real tokens in this file.
|
||
#
|
||
# The token is read only by the auth layer; it is never returned, logged, or
|
||
# committed. Profile name and allowed operations are non-secret metadata.
|
||
|
||
# Base URL of the Gitea instance (informational).
|
||
GITEA_BASE_URL=https://gitea.example.invalid
|
||
|
||
# The API token for THIS runtime profile. Placeholder only — replace in a real,
|
||
# gitignored env file. Never commit a real token.
|
||
GITEA_TOKEN=replace-with-token
|
||
|
||
# Human label for the running profile (non-secret metadata).
|
||
# Examples: gitea-author, gitea-reviewer, gitea-merger, gitea-issue-manager.
|
||
GITEA_PROFILE_NAME=gitea-reviewer
|
||
|
||
# Optional, comma-separated operation categories this profile is intended for
|
||
# (descriptive only in this issue; enforcement is a later roadmap item).
|
||
GITEA_ALLOWED_OPERATIONS=read,review,approve
|
||
|
||
# Optional, comma-separated operation categories this profile must NOT perform
|
||
# (descriptive metadata; surfaced by gitea_get_profile).
|
||
GITEA_FORBIDDEN_OPERATIONS=merge,branch.push
|
||
|
||
# Optional short label attached to this runtime for audit purposes.
|
||
GITEA_AUDIT_LABEL=reviewer-runtime
|
||
|
||
# Optional path to an audit log file (#18). When set, each mutating action
|
||
# appends one redacted JSON record (profile + authenticated user + outcome).
|
||
# Leave unset to disable auditing entirely (no records, no extra API calls).
|
||
GITEA_AUDIT_LOG=/path/to/gitea-mcp-audit.log
|
||
|
||
# Optional NAME of the token's source (e.g. an env var name). This is a name
|
||
# only — never the token value. Surfaced by gitea_get_profile.
|
||
GITEA_TOKEN_SOURCE=GITEA_TOKEN
|
||
|
||
# ── Optional self-hosted Sentry observability (#606) ────────────────────────
|
||
# Emits runtime errors, fail-closed workflow blockers, lease/terminal-lock/
|
||
# stale-runtime collisions, and watchdog cron check-ins to a SELF-HOSTED Sentry
|
||
# (https://sentry.prgs.cc/) — never Sentry Cloud. Gitea stays the source of
|
||
# truth; Sentry is observe-only. OFF by default: with MCP_SENTRY_ENABLED unset
|
||
# or SENTRY_DSN empty, nothing is initialised and no events are sent.
|
||
#
|
||
# Master gate. Truthy = 1/true/yes/on. Both this AND SENTRY_DSN are required.
|
||
MCP_SENTRY_ENABLED=0
|
||
# DSN for the self-hosted project (create a `gitea-tools-mcp` project in
|
||
# https://sentry.prgs.cc/ and copy its DSN). Never commit a real DSN.
|
||
SENTRY_DSN=
|
||
# Deployment environment tag (local/dev/prod). Defaults to "development".
|
||
SENTRY_ENVIRONMENT=development
|
||
# Optional release identifier (e.g. a git SHA or version string).
|
||
SENTRY_RELEASE=
|
||
# Performance-trace sample rate, 0.0–1.0 (clamped). Default 0.0 (traces off).
|
||
MCP_SENTRY_TRACES_SAMPLE_RATE=0.0
|
||
# Set to 1 to forward Python logs to Sentry as structured logs. Default off.
|
||
MCP_SENTRY_ENABLE_LOGS=0
|
||
|
||
# Optional canonical runtime-profile config (#19). Instead of the fields above,
|
||
# point every LLM launcher at ONE JSON file of named profiles and select one.
|
||
# Secrets are referenced (keychain id / env var name), never inlined. See
|
||
# gitea-mcp.example.json. Explicit env vars above still override the selected
|
||
# profile's values. Leave unset for pure env-based configuration.
|
||
GITEA_MCP_CONFIG=/Users/jasonwalker/.config/gitea-tools/profiles.json
|
||
GITEA_MCP_PROFILE=prgs
|
||
|
||
# Namespace-scoped active task workspaces (#510). Each MCP namespace uses only
|
||
# its own role env var; foreign bindings (e.g. GITEA_AUTHOR_WORKTREE in a
|
||
# merger process) are ignored.
|
||
# GITEA_AUTHOR_WORKTREE=/path/to/repo/branches/issue-123-work
|
||
# GITEA_REVIEWER_WORKTREE=/path/to/repo/branches/review-pr456
|
||
# GITEA_MERGER_WORKTREE=/path/to/repo/branches/merge-pr456
|
||
# GITEA_RECONCILER_WORKTREE=/path/to/repo/branches/reconcile-pr456
|
||
# GITEA_ACTIVE_WORKTREE=/path/to/repo/branches/session-override
|