Convert wiki-links to title-based format (#89)
## Summary - Add `doc-card-titles` mise task to enumerate all doc cards by title/id and detect duplicates - Remove redundant aliases from zk cards where alias matched the id - Rename `reference/storage/postgresql.md` title to "PostgreSQL Storage" to avoid duplicate with `reference/services/postgresql.md` - Convert all 175 path-based wiki-links `[[reference/path|Title]]` to title-based `[[Title]]` format - Add pre-commit hook to check for duplicate card titles on doc changes ## Deployment and Testing - [x] Pre-commit hooks pass - [x] `mise run doc-card-titles` shows no duplicates - [ ] Verify wiki-links work correctly in Quartz build 🤖 Generated with [Claude Code](https://claude.com/claude-code) Reviewed-on: https://forge.ops.eblu.me/eblume/blumeops/pulls/89
This commit is contained in:
parent
ae64021224
commit
a45a78b478
46 changed files with 336 additions and 189 deletions
|
|
@ -88,3 +88,13 @@ repos:
|
|||
- id: actionlint-system
|
||||
args: ['-config-file', '.github/actionlint.yaml']
|
||||
files: ^\.forgejo/workflows/
|
||||
|
||||
# Documentation - check for duplicate card titles
|
||||
- repo: local
|
||||
hooks:
|
||||
- id: doc-card-titles
|
||||
name: doc-card-titles
|
||||
entry: mise run doc-card-titles
|
||||
language: system
|
||||
files: ^docs/.*\.md$
|
||||
pass_filenames: false
|
||||
|
|
|
|||
1
docs/changelog.d/wiki-link-titles.doc.md
Normal file
1
docs/changelog.d/wiki-link-titles.doc.md
Normal file
|
|
@ -0,0 +1 @@
|
|||
Convert wiki-links to title-based format and add duplicate title detection
|
||||
|
|
@ -8,4 +8,4 @@ Welcome to the BlumeOps documentation.
|
|||
|
||||
## Sections
|
||||
|
||||
- [[reference/index|Reference]] - Technical reference cards for services, infrastructure, and operations
|
||||
- [[Reference]] - Technical reference cards for services, infrastructure, and operations
|
||||
|
|
|
|||
|
|
@ -14,54 +14,54 @@ Individual service reference cards with URLs and configuration details.
|
|||
|
||||
| Service | Description | Location |
|
||||
|---------|-------------|----------|
|
||||
| [[reference/services/alloy|Alloy]] | Observability collector (metrics & logs) | indri + k8s |
|
||||
| [[reference/services/argocd|ArgoCD]] | GitOps continuous delivery | k8s |
|
||||
| [[reference/services/borgmatic|Borgmatic]] | Backup system | indri |
|
||||
| [[reference/services/1password|1Password]] | Secrets management | cloud + k8s |
|
||||
| [[reference/services/forgejo|Forgejo]] | Git forge & CI/CD | indri |
|
||||
| [[reference/services/grafana|Grafana]] | Dashboards & visualization | k8s |
|
||||
| [[reference/services/immich|Immich]] | Photo management | k8s |
|
||||
| [[reference/services/jellyfin|Jellyfin]] | Media server | indri |
|
||||
| [[reference/services/kiwix|Kiwix]] | Offline Wikipedia & ZIM archives | k8s |
|
||||
| [[reference/services/loki|Loki]] | Log aggregation | k8s |
|
||||
| [[reference/services/miniflux|Miniflux]] | RSS feed reader | k8s |
|
||||
| [[reference/services/navidrome|Navidrome]] | Music streaming | k8s |
|
||||
| [[reference/services/postgresql|PostgreSQL]] | Database cluster | k8s |
|
||||
| [[reference/services/prometheus|Prometheus]] | Metrics collection | k8s |
|
||||
| [[reference/services/teslamate|TeslaMate]] | Tesla data logger | k8s |
|
||||
| [[reference/services/transmission|Transmission]] | BitTorrent daemon | k8s |
|
||||
| [[reference/services/zot|Zot]] | Container registry | indri |
|
||||
| [[Grafana Alloy|Alloy]] | Observability collector (metrics & logs) | indri + k8s |
|
||||
| [[ArgoCD]] | GitOps continuous delivery | k8s |
|
||||
| [[Borgmatic]] | Backup system | indri |
|
||||
| [[1Password]] | Secrets management | cloud + k8s |
|
||||
| [[Forgejo]] | Git forge & CI/CD | indri |
|
||||
| [[Grafana]] | Dashboards & visualization | k8s |
|
||||
| [[Immich]] | Photo management | k8s |
|
||||
| [[Jellyfin]] | Media server | indri |
|
||||
| [[Kiwix]] | Offline Wikipedia & ZIM archives | k8s |
|
||||
| [[Loki]] | Log aggregation | k8s |
|
||||
| [[Miniflux]] | RSS feed reader | k8s |
|
||||
| [[Navidrome]] | Music streaming | k8s |
|
||||
| [[PostgreSQL]] | Database cluster | k8s |
|
||||
| [[Prometheus]] | Metrics collection | k8s |
|
||||
| [[TeslaMate]] | Tesla data logger | k8s |
|
||||
| [[Transmission]] | BitTorrent daemon | k8s |
|
||||
| [[Zot]] | Container registry | indri |
|
||||
|
||||
## Infrastructure
|
||||
|
||||
Host inventory and network configuration.
|
||||
|
||||
- [[reference/infrastructure/hosts|Hosts]] - Device inventory
|
||||
- [[reference/infrastructure/indri|Indri]] - Primary server
|
||||
- [[reference/infrastructure/gilbert|Gilbert]] - Development workstation
|
||||
- [[reference/infrastructure/tailscale|Tailscale]] - ACLs, groups, tags
|
||||
- [[reference/infrastructure/routing|Routing]] - DNS domains, port mappings
|
||||
- [[Host Inventory|Hosts]] - Device inventory
|
||||
- [[Indri]] - Primary server
|
||||
- [[Gilbert]] - Development workstation
|
||||
- [[Tailscale]] - ACLs, groups, tags
|
||||
- [[Service Routing|Routing]] - DNS domains, port mappings
|
||||
|
||||
## Kubernetes
|
||||
|
||||
Cluster configuration and application registry.
|
||||
|
||||
- [[reference/kubernetes/cluster|Cluster]] - Minikube specs, storage, networking
|
||||
- [[reference/kubernetes/apps|Apps]] - ArgoCD application registry
|
||||
- [[reference/kubernetes/external-secrets|External Secrets]] - Secrets management
|
||||
- [[Kubernetes Cluster|Cluster]] - Minikube specs, storage, networking
|
||||
- [[ArgoCD Applications|Apps]] - ArgoCD application registry
|
||||
- [[External Secrets]] - Secrets management
|
||||
|
||||
## Storage
|
||||
|
||||
Network storage and backup configuration.
|
||||
|
||||
- [[reference/storage/sifaka|Sifaka]] - Synology NAS configuration
|
||||
- [[reference/storage/postgresql|PostgreSQL]] - Database cluster
|
||||
- [[reference/storage/backups|Backups]] - Backup policy and schedule
|
||||
- [[Sifaka NAS|Sifaka]] - Synology NAS configuration
|
||||
- [[PostgreSQL Storage]] - Database cluster
|
||||
- [[Backup Policy|Backups]] - Backup policy and schedule
|
||||
|
||||
## Operations
|
||||
|
||||
Operational concerns and their components.
|
||||
|
||||
- [[reference/operations/observability|Observability]] - Metrics, logs, dashboards
|
||||
- [[reference/operations/backup|Backup]] - Data protection
|
||||
- [[reference/operations/disaster-recovery|Disaster Recovery]] - Recovery procedures (TBD)
|
||||
- [[Observability]] - Metrics, logs, dashboards
|
||||
- [[Backup]] - Data protection
|
||||
- [[Disaster Recovery]] - Recovery procedures (TBD)
|
||||
|
|
|
|||
|
|
@ -23,5 +23,5 @@ Managed via `Brewfile` and `mise.toml` in the blumeops repo.
|
|||
|
||||
## Related
|
||||
|
||||
- [[reference/infrastructure/indri|Indri]] - Server accessed from gilbert
|
||||
- [[reference/kubernetes/cluster|Cluster]] - Remote k8s access
|
||||
- [[Indri]] - Server accessed from gilbert
|
||||
- [[Kubernetes Cluster|Cluster]] - Remote k8s access
|
||||
|
|
|
|||
|
|
@ -12,14 +12,14 @@ All devices connected via [Tailscale](https://login.tailscale.com/) tailnet `tai
|
|||
|
||||
| Host | Description | Card |
|
||||
|------|-------------|------|
|
||||
| **Indri** | Mac Mini M1, 2020 - Primary server | [[reference/infrastructure/indri|Details]] |
|
||||
| **Gilbert** | MacBook Air M4, 2025 - Workstation | [[reference/infrastructure/gilbert|Details]] |
|
||||
| **[[reference/storage/sifaka|Sifaka]]** | Synology NAS - Storage & backups | [[reference/storage/sifaka|Details]] |
|
||||
| **Indri** | Mac Mini M1, 2020 - Primary server | [[Indri|Details]] |
|
||||
| **Gilbert** | MacBook Air M4, 2025 - Workstation | [[Gilbert|Details]] |
|
||||
| **[[Sifaka NAS|Sifaka]]** | Synology NAS - Storage & backups | [[Sifaka NAS|Details]] |
|
||||
| **Mouse** | MacBook Air M2 - Allison's laptop | - |
|
||||
| **UniFi** | UniFi Express 7 - Home WiFi | - |
|
||||
| **Dwarf** | iPad Air - Employer-provided, off tailnet | - |
|
||||
|
||||
## Related
|
||||
|
||||
- [[reference/infrastructure/tailscale|Tailscale]] - Network configuration
|
||||
- [[reference/infrastructure/routing|Routing]] - Service URLs
|
||||
- [[Tailscale]] - Network configuration
|
||||
- [[Service Routing|Routing]] - Service URLs
|
||||
|
|
|
|||
|
|
@ -22,17 +22,17 @@ Primary BlumeOps server. Mac Mini M1 (2020).
|
|||
## Services Hosted
|
||||
|
||||
**Native (via Ansible):**
|
||||
- [[reference/services/forgejo|Forgejo]] - Git forge
|
||||
- [[reference/services/zot|Zot]] - Container registry
|
||||
- [[reference/services/jellyfin|Jellyfin]] - Media server
|
||||
- [[reference/services/borgmatic|Borgmatic]] - Backup system
|
||||
- [[reference/services/alloy|Alloy]] - Metrics/logs collector
|
||||
- [[Forgejo]] - Git forge
|
||||
- [[Zot]] - Container registry
|
||||
- [[Jellyfin]] - Media server
|
||||
- [[Borgmatic]] - Backup system
|
||||
- [[Grafana Alloy|Alloy]] - Metrics/logs collector
|
||||
- Caddy - Reverse proxy for `*.ops.eblu.me`
|
||||
|
||||
**Kubernetes (via minikube):**
|
||||
- [[reference/kubernetes/apps|All k8s applications]]
|
||||
- [[ArgoCD Applications|All k8s applications]]
|
||||
|
||||
## Related
|
||||
|
||||
- [[reference/infrastructure/routing|Routing]] - Port mappings
|
||||
- [[reference/kubernetes/cluster|Cluster]] - Minikube details
|
||||
- [[Service Routing|Routing]] - Port mappings
|
||||
- [[Kubernetes Cluster|Cluster]] - Minikube details
|
||||
|
|
|
|||
|
|
@ -25,20 +25,20 @@ DNS points to indri's Tailscale IP (100.98.163.89). TLS via Let's Encrypt (ACME
|
|||
| Service | URL | Description |
|
||||
|---------|-----|-------------|
|
||||
| Homepage | https://go.ops.eblu.me | Service dashboard |
|
||||
| [[reference/services/forgejo|Forgejo]] | https://forge.ops.eblu.me | Git hosting (SSH: 2222) |
|
||||
| [[reference/services/zot|Zot]] | https://registry.ops.eblu.me | Container registry |
|
||||
| [[reference/services/grafana|Grafana]] | https://grafana.ops.eblu.me | Dashboards |
|
||||
| [[reference/services/argocd|ArgoCD]] | https://argocd.ops.eblu.me | GitOps CD |
|
||||
| [[reference/services/prometheus|Prometheus]] | https://prometheus.ops.eblu.me | Metrics |
|
||||
| [[reference/services/loki|Loki]] | https://loki.ops.eblu.me | Logs |
|
||||
| [[reference/services/miniflux|Miniflux]] | https://feed.ops.eblu.me | RSS reader |
|
||||
| [[reference/services/kiwix|Kiwix]] | https://kiwix.ops.eblu.me | Offline Wikipedia |
|
||||
| [[reference/services/transmission|Transmission]] | https://torrent.ops.eblu.me | BitTorrent |
|
||||
| [[reference/services/teslamate|TeslaMate]] | https://tesla.ops.eblu.me | Tesla logger |
|
||||
| [[reference/services/navidrome|Navidrome]] | https://dj.ops.eblu.me | Music streaming |
|
||||
| [[reference/services/jellyfin|Jellyfin]] | https://jellyfin.ops.eblu.me | Media server |
|
||||
| [[reference/services/postgresql|PostgreSQL]] | pg.ops.eblu.me:5432 | Database |
|
||||
| [[reference/storage/sifaka|Sifaka]] | https://nas.ops.eblu.me | NAS dashboard |
|
||||
| [[Forgejo]] | https://forge.ops.eblu.me | Git hosting (SSH: 2222) |
|
||||
| [[Zot]] | https://registry.ops.eblu.me | Container registry |
|
||||
| [[Grafana]] | https://grafana.ops.eblu.me | Dashboards |
|
||||
| [[ArgoCD]] | https://argocd.ops.eblu.me | GitOps CD |
|
||||
| [[Prometheus]] | https://prometheus.ops.eblu.me | Metrics |
|
||||
| [[Loki]] | https://loki.ops.eblu.me | Logs |
|
||||
| [[Miniflux]] | https://feed.ops.eblu.me | RSS reader |
|
||||
| [[Kiwix]] | https://kiwix.ops.eblu.me | Offline Wikipedia |
|
||||
| [[Transmission]] | https://torrent.ops.eblu.me | BitTorrent |
|
||||
| [[TeslaMate]] | https://tesla.ops.eblu.me | Tesla logger |
|
||||
| [[Navidrome]] | https://dj.ops.eblu.me | Music streaming |
|
||||
| [[Jellyfin]] | https://jellyfin.ops.eblu.me | Media server |
|
||||
| [[PostgreSQL]] | pg.ops.eblu.me:5432 | Database |
|
||||
| [[Sifaka NAS|Sifaka]] | https://nas.ops.eblu.me | NAS dashboard |
|
||||
|
||||
## Tailscale-Only Services
|
||||
|
||||
|
|
@ -61,5 +61,5 @@ DNS points to indri's Tailscale IP (100.98.163.89). TLS via Let's Encrypt (ACME
|
|||
|
||||
## Related
|
||||
|
||||
- [[reference/infrastructure/tailscale|Tailscale]] - ACL configuration
|
||||
- [[reference/infrastructure/indri|Indri]] - Where services run
|
||||
- [[Tailscale]] - ACL configuration
|
||||
- [[Indri]] - Where services run
|
||||
|
|
|
|||
|
|
@ -17,7 +17,7 @@ ACLs managed via Pulumi in `pulumi/policy.hujson`.
|
|||
|
||||
| Group | Members | Purpose |
|
||||
|-------|---------|---------|
|
||||
| `group:allisonflix` | admin, member | [[reference/services/jellyfin|Jellyfin]] media access |
|
||||
| `group:allisonflix` | admin, member | [[Jellyfin]] media access |
|
||||
|
||||
## Device Tags
|
||||
|
||||
|
|
@ -58,5 +58,5 @@ Pulumi uses OAuth client from 1Password (blumeops vault):
|
|||
|
||||
## Related
|
||||
|
||||
- [[reference/infrastructure/routing|Routing]] - Service URLs
|
||||
- [[reference/infrastructure/hosts|Hosts]] - Device inventory
|
||||
- [[Service Routing|Routing]] - Service URLs
|
||||
- [[Host Inventory|Hosts]] - Device inventory
|
||||
|
|
|
|||
|
|
@ -7,33 +7,33 @@ tags:
|
|||
|
||||
# ArgoCD Applications
|
||||
|
||||
Registry of all applications deployed via [[reference/services/argocd|ArgoCD]].
|
||||
Registry of all applications deployed via [[ArgoCD]].
|
||||
|
||||
## Application Registry
|
||||
|
||||
| App | Namespace | Path/Source | Service |
|
||||
|-----|-----------|-------------|---------|
|
||||
| `apps` | argocd | `argocd/apps/` | App-of-apps root |
|
||||
| `argocd` | argocd | `argocd/manifests/argocd/` | [[reference/services/argocd|ArgoCD]] |
|
||||
| `argocd` | argocd | `argocd/manifests/argocd/` | [[ArgoCD]] |
|
||||
| `tailscale-operator` | tailscale | `argocd/manifests/tailscale-operator/` | Tailscale k8s operator |
|
||||
| `1password-connect` | 1password | `argocd/manifests/1password-connect/` | [[reference/services/1password|1Password]] |
|
||||
| `external-secrets` | external-secrets | Helm chart | [[reference/services/1password|1Password]] |
|
||||
| `external-secrets-config` | external-secrets | `argocd/manifests/external-secrets-config/` | [[reference/services/1password|1Password]] |
|
||||
| `1password-connect` | 1password | `argocd/manifests/1password-connect/` | [[1Password]] |
|
||||
| `external-secrets` | external-secrets | Helm chart | [[1Password]] |
|
||||
| `external-secrets-config` | external-secrets | `argocd/manifests/external-secrets-config/` | [[1Password]] |
|
||||
| `cloudnative-pg` | cnpg-system | Helm chart (forge mirror) | PostgreSQL operator |
|
||||
| `blumeops-pg` | databases | `argocd/manifests/databases/` | [[reference/services/postgresql|PostgreSQL]] |
|
||||
| `prometheus` | monitoring | `argocd/manifests/prometheus/` | [[reference/services/prometheus|Prometheus]] |
|
||||
| `loki` | monitoring | `argocd/manifests/loki/` | [[reference/services/loki|Loki]] |
|
||||
| `grafana` | monitoring | Helm chart (forge mirror) | [[reference/services/grafana|Grafana]] |
|
||||
| `grafana-config` | monitoring | `argocd/manifests/grafana-config/` | [[reference/services/grafana|Grafana]] |
|
||||
| `immich` | immich | Helm chart | [[reference/services/immich|Immich]] |
|
||||
| `alloy-k8s` | alloy | `argocd/manifests/alloy-k8s/` | [[reference/services/alloy|Alloy]] |
|
||||
| `blumeops-pg` | databases | `argocd/manifests/databases/` | [[PostgreSQL]] |
|
||||
| `prometheus` | monitoring | `argocd/manifests/prometheus/` | [[Prometheus]] |
|
||||
| `loki` | monitoring | `argocd/manifests/loki/` | [[Loki]] |
|
||||
| `grafana` | monitoring | Helm chart (forge mirror) | [[Grafana]] |
|
||||
| `grafana-config` | monitoring | `argocd/manifests/grafana-config/` | [[Grafana]] |
|
||||
| `immich` | immich | Helm chart | [[Immich]] |
|
||||
| `alloy-k8s` | alloy | `argocd/manifests/alloy-k8s/` | [[Grafana Alloy|Alloy]] |
|
||||
| `kube-state-metrics` | monitoring | `argocd/manifests/kube-state-metrics/` | K8s metrics |
|
||||
| `miniflux` | miniflux | `argocd/manifests/miniflux/` | [[reference/services/miniflux|Miniflux]] |
|
||||
| `kiwix` | kiwix | `argocd/manifests/kiwix/` | [[reference/services/kiwix|Kiwix]] |
|
||||
| `torrent` | torrent | `argocd/manifests/torrent/` | [[reference/services/transmission|Transmission]] |
|
||||
| `navidrome` | navidrome | `argocd/manifests/navidrome/` | [[reference/services/navidrome|Navidrome]] |
|
||||
| `teslamate` | teslamate | `argocd/manifests/teslamate/` | [[reference/services/teslamate|TeslaMate]] |
|
||||
| `forgejo-runner` | forgejo-runner | `argocd/manifests/forgejo-runner/` | [[reference/services/forgejo|Forgejo]] CI |
|
||||
| `miniflux` | miniflux | `argocd/manifests/miniflux/` | [[Miniflux]] |
|
||||
| `kiwix` | kiwix | `argocd/manifests/kiwix/` | [[Kiwix]] |
|
||||
| `torrent` | torrent | `argocd/manifests/torrent/` | [[Transmission]] |
|
||||
| `navidrome` | navidrome | `argocd/manifests/navidrome/` | [[Navidrome]] |
|
||||
| `teslamate` | teslamate | `argocd/manifests/teslamate/` | [[TeslaMate]] |
|
||||
| `forgejo-runner` | forgejo-runner | `argocd/manifests/forgejo-runner/` | [[Forgejo]] CI |
|
||||
|
||||
## Sync Policies
|
||||
|
||||
|
|
@ -44,5 +44,5 @@ Registry of all applications deployed via [[reference/services/argocd|ArgoCD]].
|
|||
|
||||
## Related
|
||||
|
||||
- [[reference/services/argocd|ArgoCD]] - GitOps platform details
|
||||
- [[reference/kubernetes/cluster|Cluster]] - Kubernetes infrastructure
|
||||
- [[ArgoCD]] - GitOps platform details
|
||||
- [[Kubernetes Cluster|Cluster]] - Kubernetes infrastructure
|
||||
|
|
|
|||
|
|
@ -6,7 +6,7 @@ tags:
|
|||
|
||||
# Kubernetes Cluster
|
||||
|
||||
Single-node Minikube cluster running on [[reference/infrastructure/indri|Indri]].
|
||||
Single-node Minikube cluster running on [[Indri]].
|
||||
|
||||
## Cluster Specifications
|
||||
|
||||
|
|
@ -24,16 +24,16 @@ Single-node Minikube cluster running on [[reference/infrastructure/indri|Indri]]
|
|||
|
||||
## Volume Mounting
|
||||
|
||||
Pods mount NFS directly from [[reference/storage/sifaka|Sifaka]]. Docker NATs outbound traffic through indri's LAN IP (192.168.1.50), allowing access to Sifaka's NFS exports.
|
||||
Pods mount NFS directly from [[Sifaka NAS|Sifaka]]. Docker NATs outbound traffic through indri's LAN IP (192.168.1.50), allowing access to Sifaka's NFS exports.
|
||||
|
||||
## Registry Mirror
|
||||
|
||||
Containerd uses [[reference/services/zot|Zot]] as a pull-through cache at `host.minikube.internal:5050`.
|
||||
Containerd uses [[Zot]] as a pull-through cache at `host.minikube.internal:5050`.
|
||||
|
||||
Mirrors configured: `registry.ops.eblu.me`, `docker.io`, `ghcr.io`, `quay.io`
|
||||
|
||||
## Related
|
||||
|
||||
- [[reference/kubernetes/apps|Apps]] - ArgoCD applications
|
||||
- [[reference/services/argocd|ArgoCD]] - GitOps deployment
|
||||
- [[reference/services/zot|Zot]] - Registry mirror
|
||||
- [[ArgoCD Applications|Apps]] - ArgoCD applications
|
||||
- [[ArgoCD]] - GitOps deployment
|
||||
- [[Zot]] - Registry mirror
|
||||
|
|
|
|||
|
|
@ -7,4 +7,4 @@ tags:
|
|||
|
||||
# External Secrets
|
||||
|
||||
See [[reference/services/1password|1Password]] in Services.
|
||||
See [[1Password]] in Services.
|
||||
|
|
|
|||
|
|
@ -10,6 +10,6 @@ Daily automated backups of BlumeOps data.
|
|||
|
||||
## Components
|
||||
|
||||
- [[reference/services/borgmatic|Borgmatic]] - Backup orchestration
|
||||
- [[reference/storage/sifaka|Sifaka]] - Backup target (NAS)
|
||||
- [[reference/storage/backups|Backup Policy]] - What gets backed up and retention
|
||||
- [[Borgmatic]] - Backup orchestration
|
||||
- [[Sifaka NAS|Sifaka]] - Backup target (NAS)
|
||||
- [[Backup Policy]] - What gets backed up and retention
|
||||
|
|
|
|||
|
|
@ -8,12 +8,12 @@ tags:
|
|||
|
||||
TBD. Current state:
|
||||
|
||||
- [[reference/services/borgmatic|Borgmatic]] provides daily backups to [[reference/storage/sifaka|Sifaka]]
|
||||
- [[Borgmatic]] provides daily backups to [[Sifaka NAS|Sifaka]]
|
||||
- Infrastructure can be rebootstrapped using the blumeops repo
|
||||
- Detailed DR procedures not yet documented
|
||||
|
||||
## Components
|
||||
|
||||
- [[reference/services/borgmatic|Borgmatic]] - Backup restoration
|
||||
- [[reference/services/1password|1Password]] - Credential recovery
|
||||
- [[reference/services/forgejo|Forgejo]] - Source of truth for infrastructure code
|
||||
- [[Borgmatic]] - Backup restoration
|
||||
- [[1Password]] - Credential recovery
|
||||
- [[Forgejo]] - Source of truth for infrastructure code
|
||||
|
|
|
|||
|
|
@ -10,7 +10,7 @@ Metrics, logs, and dashboards for BlumeOps infrastructure.
|
|||
|
||||
## Components
|
||||
|
||||
- [[reference/services/prometheus|Prometheus]] - Metrics storage and querying
|
||||
- [[reference/services/loki|Loki]] - Log aggregation
|
||||
- [[reference/services/alloy|Alloy]] - Metrics and log collection
|
||||
- [[reference/services/grafana|Grafana]] - Dashboards and visualization
|
||||
- [[Prometheus]] - Metrics storage and querying
|
||||
- [[Loki]] - Log aggregation
|
||||
- [[Grafana Alloy|Alloy]] - Metrics and log collection
|
||||
- [[Grafana]] - Dashboards and visualization
|
||||
|
|
|
|||
|
|
@ -36,5 +36,5 @@ Services reference 1Password items via `ExternalSecret` manifests.
|
|||
|
||||
## Related
|
||||
|
||||
- [[reference/services/argocd|ArgoCD]] - Uses secrets for git access
|
||||
- [[reference/services/postgresql|PostgreSQL]] - Database credentials
|
||||
- [[ArgoCD]] - Uses secrets for git access
|
||||
- [[PostgreSQL]] - Database credentials
|
||||
|
|
|
|||
|
|
@ -7,7 +7,7 @@ tags:
|
|||
|
||||
# ArgoCD
|
||||
|
||||
GitOps continuous delivery platform for the [[reference/kubernetes/cluster|Kubernetes cluster]].
|
||||
GitOps continuous delivery platform for the [[Kubernetes Cluster|Kubernetes cluster]].
|
||||
|
||||
## Quick Reference
|
||||
|
||||
|
|
@ -33,5 +33,5 @@ GitOps continuous delivery platform for the [[reference/kubernetes/cluster|Kuber
|
|||
|
||||
## Related
|
||||
|
||||
- [[reference/kubernetes/apps|Apps]] - Full application registry
|
||||
- [[reference/services/forgejo|Forgejo]] - Git source
|
||||
- [[ArgoCD Applications|Apps]] - Full application registry
|
||||
- [[Forgejo]] - Git source
|
||||
|
|
|
|||
|
|
@ -16,7 +16,7 @@ Daily backup system using Borg backup, running on indri.
|
|||
| **Install** | mise (pipx) |
|
||||
| **Config** | `~/.config/borgmatic/config.yaml` |
|
||||
| **Schedule** | Daily at 2:00 AM |
|
||||
| **Repository** | `/Volumes/backups/borg/` on [[reference/storage/sifaka|Sifaka]] |
|
||||
| **Repository** | `/Volumes/backups/borg/` on [[Sifaka NAS|Sifaka]] |
|
||||
|
||||
## What Gets Backed Up
|
||||
|
||||
|
|
@ -55,6 +55,6 @@ Dashboard: "Borgmatic Backups" in [[grafana|Grafana]]
|
|||
|
||||
## Related
|
||||
|
||||
- [[reference/storage/backups|Backups]] - Full backup policy
|
||||
- [[reference/storage/sifaka|Sifaka]] - Backup target
|
||||
- [[Backup Policy|Backups]] - Full backup policy
|
||||
- [[Sifaka NAS|Sifaka]] - Backup target
|
||||
- [[postgresql|PostgreSQL]] - Database backups
|
||||
|
|
|
|||
|
|
@ -44,5 +44,5 @@ Managed via 1Password: `lfs-jwt-secret`, `internal-token`, `oauth2-jwt-secret`,
|
|||
|
||||
## Related
|
||||
|
||||
- [[reference/services/argocd|ArgoCD]] - Uses Forgejo as git source
|
||||
- [[reference/services/zot|Zot]] - Container registry for built images
|
||||
- [[ArgoCD]] - Uses Forgejo as git source
|
||||
- [[Zot]] - Container registry for built images
|
||||
|
|
|
|||
|
|
@ -16,11 +16,11 @@ Self-hosted photo and video management.
|
|||
| **URL** | https://photos.ops.eblu.me |
|
||||
| **Namespace** | `immich` |
|
||||
| **Deployment** | Helm chart (k8s) |
|
||||
| **Database** | [[reference/services/postgresql|PostgreSQL]] (CNPG) |
|
||||
| **Storage** | [[reference/storage/sifaka|Sifaka]] photos volume |
|
||||
| **Database** | [[PostgreSQL]] (CNPG) |
|
||||
| **Storage** | [[Sifaka NAS|Sifaka]] photos volume |
|
||||
|
||||
## Related
|
||||
|
||||
- [[reference/services/postgresql|PostgreSQL]] - Database backend
|
||||
- [[reference/storage/sifaka|Sifaka]] - Photo storage
|
||||
- [[reference/services/jellyfin|Jellyfin]] - Video streaming (separate service)
|
||||
- [[PostgreSQL]] - Database backend
|
||||
- [[Sifaka NAS|Sifaka]] - Photo storage
|
||||
- [[Jellyfin]] - Video streaming (separate service)
|
||||
|
|
|
|||
|
|
@ -48,4 +48,4 @@ Dashboard > Playback:
|
|||
## Related
|
||||
|
||||
- [[navidrome|Navidrome]] - Music streaming
|
||||
- [[reference/storage/sifaka|Sifaka]] - Media storage
|
||||
- [[Sifaka NAS|Sifaka]] - Media storage
|
||||
|
|
|
|||
|
|
@ -17,7 +17,7 @@ Offline Wikipedia and ZIM archive server.
|
|||
| **Tailscale URL** | https://kiwix.tail8d86e.ts.net |
|
||||
| **Namespace** | `kiwix` |
|
||||
| **Image** | `ghcr.io/kiwix/kiwix-serve:3.8.1` |
|
||||
| **Storage** | NFS from [[reference/storage/sifaka|Sifaka]] (`/volume1/torrents`) |
|
||||
| **Storage** | NFS from [[Sifaka NAS|Sifaka]] (`/volume1/torrents`) |
|
||||
|
||||
## Architecture
|
||||
|
||||
|
|
@ -49,4 +49,4 @@ Full list: `argocd/manifests/kiwix/configmap-zim-torrents.yaml`
|
|||
## Related
|
||||
|
||||
- [[transmission|Transmission]] - Downloads ZIM files
|
||||
- [[reference/storage/sifaka|Sifaka]] - ZIM storage
|
||||
- [[Sifaka NAS|Sifaka]] - ZIM storage
|
||||
|
|
|
|||
|
|
@ -17,7 +17,7 @@ Minimalist RSS/Atom feed reader.
|
|||
| **Tailscale URL** | https://feed.tail8d86e.ts.net |
|
||||
| **Namespace** | `miniflux` |
|
||||
| **Image** | `ghcr.io/miniflux/miniflux:latest` |
|
||||
| **Database** | [[reference/services/postgresql|PostgreSQL]] |
|
||||
| **Database** | [[PostgreSQL]] |
|
||||
|
||||
## Features
|
||||
|
||||
|
|
@ -33,9 +33,9 @@ Uses CloudNativePG cluster at `pg.ops.eblu.me`. Database user password stored in
|
|||
|
||||
## Backup
|
||||
|
||||
Feed subscriptions and read state backed up via [[reference/services/borgmatic|Borgmatic]] PostgreSQL hook.
|
||||
Feed subscriptions and read state backed up via [[Borgmatic]] PostgreSQL hook.
|
||||
|
||||
## Related
|
||||
|
||||
- [[reference/services/postgresql|PostgreSQL]] - Database backend
|
||||
- [[reference/services/borgmatic|Borgmatic]] - Data backup
|
||||
- [[PostgreSQL]] - Database backend
|
||||
- [[Borgmatic]] - Data backup
|
||||
|
|
|
|||
|
|
@ -38,5 +38,5 @@ The `/data` directory contains SQLite database, configuration, and cache.
|
|||
|
||||
## Related
|
||||
|
||||
- [[reference/services/jellyfin|Jellyfin]] - Video streaming
|
||||
- [[reference/storage/sifaka|Sifaka]] - Music storage
|
||||
- [[Jellyfin]] - Video streaming
|
||||
- [[Sifaka NAS|Sifaka]] - Music storage
|
||||
|
|
|
|||
|
|
@ -23,8 +23,8 @@ Database cluster via CloudNativePG operator.
|
|||
|
||||
| Database | Owner | Purpose |
|
||||
|----------|-------|---------|
|
||||
| miniflux | miniflux | [[reference/services/miniflux|Miniflux]] feed data |
|
||||
| teslamate | teslamate | [[reference/services/teslamate|TeslaMate]] vehicle data |
|
||||
| miniflux | miniflux | [[Miniflux]] feed data |
|
||||
| teslamate | teslamate | [[TeslaMate]] vehicle data |
|
||||
|
||||
## Users
|
||||
|
||||
|
|
@ -34,11 +34,11 @@ Database cluster via CloudNativePG operator.
|
|||
| miniflux | app owner | Owns miniflux database |
|
||||
| teslamate | superuser | TeslaMate (needs extensions) |
|
||||
| eblume | superuser | Admin access |
|
||||
| borgmatic | pg_read_all_data | [[reference/services/borgmatic|Backup]] access |
|
||||
| borgmatic | pg_read_all_data | [[Borgmatic|Backup]] access |
|
||||
|
||||
## Backup
|
||||
|
||||
Backed up via [[reference/services/borgmatic|Borgmatic]] `postgresql_databases` hook. Streams `pg_dump` directly to Borg (no intermediate files, no downtime). See [[reference/operations/backup|Backup]] for overall backup policy.
|
||||
Backed up via [[Borgmatic]] `postgresql_databases` hook. Streams `pg_dump` directly to Borg (no intermediate files, no downtime). See [[Backup]] for overall backup policy.
|
||||
|
||||
## Credentials
|
||||
|
||||
|
|
@ -54,6 +54,6 @@ Backed up via [[reference/services/borgmatic|Borgmatic]] `postgresql_databases`
|
|||
|
||||
## Related
|
||||
|
||||
- [[reference/services/miniflux|Miniflux]] - Feed reader database
|
||||
- [[reference/services/teslamate|TeslaMate]] - Vehicle data database
|
||||
- [[reference/services/borgmatic|Borgmatic]] - Database backup
|
||||
- [[Miniflux]] - Feed reader database
|
||||
- [[TeslaMate]] - Vehicle data database
|
||||
- [[Borgmatic]] - Database backup
|
||||
|
|
|
|||
|
|
@ -23,19 +23,19 @@ Metrics storage and querying for BlumeOps infrastructure.
|
|||
## Data Sources
|
||||
|
||||
### Remote Write (from Alloy)
|
||||
- Indri system metrics via [[reference/services/alloy|Alloy]] remote_write
|
||||
- Indri system metrics via [[Grafana Alloy|Alloy]] remote_write
|
||||
- Textfile metrics: minikube, borgmatic, zot, jellyfin
|
||||
|
||||
### Scrape Targets
|
||||
|
||||
| Target | Metrics |
|
||||
|--------|---------|
|
||||
| `sifaka:9100` | [[reference/storage/sifaka|Sifaka]] NAS (node_exporter) |
|
||||
| `cnpg-metrics.tail8d86e.ts.net:9187` | [[reference/services/postgresql|CloudNativePG]] metrics |
|
||||
| `sifaka:9100` | [[Sifaka NAS|Sifaka]] NAS (node_exporter) |
|
||||
| `cnpg-metrics.tail8d86e.ts.net:9187` | [[PostgreSQL|CloudNativePG]] metrics |
|
||||
| `kube-state-metrics.monitoring.svc:8080` | Kubernetes resource metrics |
|
||||
|
||||
## Related
|
||||
|
||||
- [[reference/services/alloy|Alloy]] - Metrics collector
|
||||
- [[reference/services/grafana|Grafana]] - Visualization
|
||||
- [[reference/services/loki|Loki]] - Logs counterpart
|
||||
- [[Grafana Alloy|Alloy]] - Metrics collector
|
||||
- [[Grafana]] - Visualization
|
||||
- [[Loki]] - Logs counterpart
|
||||
|
|
|
|||
|
|
@ -17,7 +17,7 @@ BitTorrent daemon, primarily for downloading ZIM archives for [[kiwix|Kiwix]].
|
|||
| **Tailscale URL** | https://torrent.tail8d86e.ts.net |
|
||||
| **Namespace** | `torrent` |
|
||||
| **Image** | `lscr.io/linuxserver/transmission:latest` |
|
||||
| **Storage** | NFS PVC from [[reference/storage/sifaka|Sifaka]] |
|
||||
| **Storage** | NFS PVC from [[Sifaka NAS|Sifaka]] |
|
||||
|
||||
## Storage Layout
|
||||
|
||||
|
|
@ -50,4 +50,4 @@ Web UI shows: active/seeding/paused counts, speeds, disk usage.
|
|||
## Related
|
||||
|
||||
- [[kiwix|Kiwix]] - ZIM archive consumer
|
||||
- [[reference/storage/sifaka|Sifaka]] - Download storage
|
||||
- [[Sifaka NAS|Sifaka]] - Download storage
|
||||
|
|
|
|||
|
|
@ -30,7 +30,7 @@ OCI-native container registry providing pull-through cache and private image sto
|
|||
|
||||
## Pull-Through Cache
|
||||
|
||||
When [[reference/kubernetes/cluster|minikube]] pulls an image, containerd checks zot first. If cached, returns immediately. If not, zot fetches from upstream, caches it, then returns.
|
||||
When [[Kubernetes Cluster|minikube]] pulls an image, containerd checks zot first. If cached, returns immediately. If not, zot fetches from upstream, caches it, then returns.
|
||||
|
||||
## Security Model
|
||||
|
||||
|
|
@ -38,5 +38,5 @@ Network access only (no authentication). Defense is the Tailscale ACL boundary.
|
|||
|
||||
## Related
|
||||
|
||||
- [[reference/services/forgejo|Forgejo]] - Container build CI
|
||||
- [[reference/kubernetes/cluster|Cluster]] - Registry consumer
|
||||
- [[Forgejo]] - Container build CI
|
||||
- [[Kubernetes Cluster|Cluster]] - Registry consumer
|
||||
|
|
|
|||
|
|
@ -7,13 +7,13 @@ tags:
|
|||
|
||||
# Backup Policy
|
||||
|
||||
Daily automated backups from [[reference/infrastructure/indri|Indri]] to [[reference/storage/sifaka|Sifaka]] NAS.
|
||||
Daily automated backups from [[Indri]] to [[Sifaka NAS|Sifaka]] NAS.
|
||||
|
||||
## Schedule
|
||||
|
||||
| Time | Frequency | System |
|
||||
|------|-----------|--------|
|
||||
| 2:00 AM | Daily | [[reference/services/borgmatic|Borgmatic]] |
|
||||
| 2:00 AM | Daily | [[Borgmatic]] |
|
||||
|
||||
## What Gets Backed Up
|
||||
|
||||
|
|
@ -31,8 +31,8 @@ Daily automated backups from [[reference/infrastructure/indri|Indri]] to [[refer
|
|||
|
||||
| Database | Host | Method |
|
||||
|----------|------|--------|
|
||||
| miniflux | [[reference/services/postgresql|pg.ops.eblu.me]] | pg_dump stream |
|
||||
| teslamate | [[reference/services/postgresql|pg.ops.eblu.me]] | pg_dump stream |
|
||||
| miniflux | [[PostgreSQL|pg.ops.eblu.me]] | pg_dump stream |
|
||||
| teslamate | [[PostgreSQL|pg.ops.eblu.me]] | pg_dump stream |
|
||||
|
||||
## What Is NOT Backed Up
|
||||
|
||||
|
|
@ -53,19 +53,19 @@ Daily automated backups from [[reference/infrastructure/indri|Indri]] to [[refer
|
|||
|
||||
## Backup Target
|
||||
|
||||
Repository: `/Volumes/backups/borg/` on [[reference/storage/sifaka|Sifaka]]
|
||||
Repository: `/Volumes/backups/borg/` on [[Sifaka NAS|Sifaka]]
|
||||
|
||||
## Monitoring
|
||||
|
||||
Metrics exposed to [[reference/services/prometheus|Prometheus]]:
|
||||
Metrics exposed to [[Prometheus]]:
|
||||
- `borgmatic_up` - Repository accessible
|
||||
- `borgmatic_last_archive_timestamp` - Last backup time
|
||||
- `borgmatic_repo_deduplicated_size_bytes` - Disk usage
|
||||
|
||||
Dashboard: "Borgmatic Backups" in [[reference/services/grafana|Grafana]]
|
||||
Dashboard: "Borgmatic Backups" in [[Grafana]]
|
||||
|
||||
## Related
|
||||
|
||||
- [[reference/services/borgmatic|Borgmatic]] - Backup system details
|
||||
- [[reference/storage/sifaka|Sifaka]] - Backup storage
|
||||
- [[reference/services/postgresql|PostgreSQL]] - Database backups
|
||||
- [[Borgmatic]] - Backup system details
|
||||
- [[Sifaka NAS|Sifaka]] - Backup storage
|
||||
- [[PostgreSQL]] - Database backups
|
||||
|
|
|
|||
|
|
@ -1,10 +1,10 @@
|
|||
---
|
||||
title: PostgreSQL
|
||||
title: PostgreSQL Storage
|
||||
tags:
|
||||
- storage
|
||||
- database
|
||||
---
|
||||
|
||||
# PostgreSQL
|
||||
# PostgreSQL Storage
|
||||
|
||||
See [[reference/services/postgresql|PostgreSQL]] in Services.
|
||||
See [[PostgreSQL]] in Services.
|
||||
|
|
|
|||
|
|
@ -21,11 +21,11 @@ Synology NAS providing network storage and backup target.
|
|||
|
||||
| Share | Path | Purpose | Consumers |
|
||||
|-------|------|---------|-----------|
|
||||
| backups | `/volume1/backups` | Borg backup repository | [[reference/services/borgmatic|Borgmatic]] |
|
||||
| torrents | `/volume1/torrents` | ZIM downloads | [[reference/services/kiwix|Kiwix]], [[reference/services/transmission|Transmission]] |
|
||||
| music | `/volume1/music` | Music library | [[reference/services/navidrome|Navidrome]] |
|
||||
| allisonflix | `/volume1/allisonflix` | Video library | [[reference/services/jellyfin|Jellyfin]] |
|
||||
| photos | `/volume1/photos` | Photo library | [[reference/services/immich|Immich]] |
|
||||
| backups | `/volume1/backups` | Borg backup repository | [[Borgmatic]] |
|
||||
| torrents | `/volume1/torrents` | ZIM downloads | [[Kiwix]], [[Transmission]] |
|
||||
| music | `/volume1/music` | Music library | [[Navidrome]] |
|
||||
| allisonflix | `/volume1/allisonflix` | Video library | [[Jellyfin]] |
|
||||
| photos | `/volume1/photos` | Photo library | [[Immich]] |
|
||||
|
||||
## NFS Exports
|
||||
|
||||
|
|
@ -37,7 +37,7 @@ Synology NAS providing network storage and backup target.
|
|||
|
||||
## Monitoring
|
||||
|
||||
Node exporter running in Docker container, scraped by [[reference/services/prometheus|Prometheus]] at `sifaka:9100`.
|
||||
Node exporter running in Docker container, scraped by [[Prometheus]] at `sifaka:9100`.
|
||||
|
||||
## Tailscale
|
||||
|
||||
|
|
@ -46,14 +46,14 @@ Node exporter running in Docker container, scraped by [[reference/services/prome
|
|||
|
||||
## Backup
|
||||
|
||||
Sifaka is the **target** for [[reference/operations/backup|backups]], not a backup source. [[reference/services/borgmatic|Borgmatic]] sends backups TO sifaka, not OF sifaka.
|
||||
Sifaka is the **target** for [[Backup|backups]], not a backup source. [[Borgmatic]] sends backups TO sifaka, not OF sifaka.
|
||||
|
||||
Data protection for sifaka itself currently relies on the Synology RAID 5 configuration, which provides single-disk fault tolerance. Future plans include offsite duplication for additional resiliency.
|
||||
|
||||
## Related
|
||||
|
||||
- [[reference/storage/backups|Backups]] - Backup policy
|
||||
- [[reference/services/borgmatic|Borgmatic]] - Backup system
|
||||
- [[reference/services/immich|Immich]] - Photo consumer
|
||||
- [[reference/services/jellyfin|Jellyfin]] - Media consumer
|
||||
- [[reference/services/navidrome|Navidrome]] - Music consumer
|
||||
- [[Backup Policy|Backups]] - Backup policy
|
||||
- [[Borgmatic]] - Backup system
|
||||
- [[Immich]] - Photo consumer
|
||||
- [[Jellyfin]] - Media consumer
|
||||
- [[Navidrome]] - Music consumer
|
||||
|
|
|
|||
|
|
@ -1,7 +1,6 @@
|
|||
---
|
||||
id: argocd
|
||||
aliases:
|
||||
- argocd
|
||||
- argo-cd
|
||||
tags:
|
||||
- blumeops
|
||||
|
|
|
|||
|
|
@ -1,7 +1,6 @@
|
|||
---
|
||||
id: borgmatic
|
||||
aliases:
|
||||
- borgmatic
|
||||
- borg-backup
|
||||
tags:
|
||||
- blumeops
|
||||
|
|
|
|||
|
|
@ -1,7 +1,6 @@
|
|||
---
|
||||
id: external-secrets
|
||||
aliases:
|
||||
- external-secrets
|
||||
- eso
|
||||
- external-secrets-operator
|
||||
tags:
|
||||
|
|
|
|||
|
|
@ -1,7 +1,5 @@
|
|||
---
|
||||
id: grafana
|
||||
aliases:
|
||||
- grafana
|
||||
tags:
|
||||
- blumeops
|
||||
---
|
||||
|
|
|
|||
|
|
@ -1,7 +1,6 @@
|
|||
---
|
||||
id: indri
|
||||
aliases:
|
||||
- indri
|
||||
- mac-mini
|
||||
tags:
|
||||
- blumeops
|
||||
|
|
|
|||
|
|
@ -1,7 +1,5 @@
|
|||
---
|
||||
id: jellyfin
|
||||
aliases:
|
||||
- jellyfin
|
||||
tags:
|
||||
- blumeops
|
||||
---
|
||||
|
|
|
|||
|
|
@ -1,7 +1,5 @@
|
|||
---
|
||||
id: kiwix
|
||||
aliases:
|
||||
- kiwix
|
||||
tags:
|
||||
- blumeops
|
||||
---
|
||||
|
|
|
|||
|
|
@ -1,7 +1,6 @@
|
|||
---
|
||||
id: miniflux
|
||||
aliases:
|
||||
- miniflux
|
||||
- feed
|
||||
- rss
|
||||
tags:
|
||||
|
|
|
|||
|
|
@ -1,7 +1,6 @@
|
|||
---
|
||||
id: minikube
|
||||
aliases:
|
||||
- minikube
|
||||
- kubernetes
|
||||
- k8s
|
||||
tags:
|
||||
|
|
|
|||
|
|
@ -1,7 +1,6 @@
|
|||
---
|
||||
id: postgresql
|
||||
aliases:
|
||||
- postgresql
|
||||
- postgres
|
||||
- pg
|
||||
tags:
|
||||
|
|
|
|||
|
|
@ -1,7 +1,6 @@
|
|||
---
|
||||
id: pulumi
|
||||
aliases:
|
||||
- pulumi
|
||||
- tailnet-iac
|
||||
tags:
|
||||
- blumeops
|
||||
|
|
|
|||
|
|
@ -1,7 +1,6 @@
|
|||
---
|
||||
id: teslamate
|
||||
aliases:
|
||||
- teslamate
|
||||
- tesla
|
||||
tags:
|
||||
- blumeops
|
||||
|
|
|
|||
|
|
@ -1,7 +1,5 @@
|
|||
---
|
||||
id: transmission
|
||||
aliases:
|
||||
- transmission
|
||||
tags:
|
||||
- blumeops
|
||||
---
|
||||
|
|
|
|||
|
|
@ -1,7 +1,6 @@
|
|||
---
|
||||
id: zot
|
||||
aliases:
|
||||
- zot
|
||||
- container-registry
|
||||
tags:
|
||||
- blumeops
|
||||
|
|
|
|||
154
mise-tasks/doc-card-titles
Executable file
154
mise-tasks/doc-card-titles
Executable file
|
|
@ -0,0 +1,154 @@
|
|||
#!/usr/bin/env -S uv run --script
|
||||
# /// script
|
||||
# requires-python = ">=3.12"
|
||||
# dependencies = ["pyyaml>=6.0", "rich>=13.0.0"]
|
||||
# ///
|
||||
#MISE description="List all doc card titles and detect duplicates"
|
||||
"""List all documentation card titles/IDs and detect duplicates.
|
||||
|
||||
This script scans all markdown files in the docs/ directory (excluding
|
||||
changelog.d/), extracts frontmatter titles, IDs, and aliases, and reports
|
||||
any duplicates or conflicts that could cause wiki-link resolution issues.
|
||||
|
||||
Usage: mise run doc-card-titles
|
||||
"""
|
||||
|
||||
import sys
|
||||
from collections import defaultdict
|
||||
from pathlib import Path
|
||||
|
||||
import yaml
|
||||
from rich.console import Console
|
||||
from rich.table import Table
|
||||
|
||||
DOCS_DIR = Path(__file__).parent.parent / "docs"
|
||||
|
||||
|
||||
def extract_frontmatter(file_path: Path) -> dict | None:
|
||||
"""Extract YAML frontmatter from a markdown file."""
|
||||
content = file_path.read_text()
|
||||
if not content.startswith("---"):
|
||||
return None
|
||||
|
||||
# Find the closing ---
|
||||
end_idx = content.find("---", 3)
|
||||
if end_idx == -1:
|
||||
return None
|
||||
|
||||
frontmatter_text = content[3:end_idx].strip()
|
||||
try:
|
||||
return yaml.safe_load(frontmatter_text) or {}
|
||||
except yaml.YAMLError:
|
||||
return None
|
||||
|
||||
|
||||
def main() -> int:
|
||||
console = Console()
|
||||
|
||||
# Collect all titles/IDs and their source files
|
||||
# Key: identifier (title, id, or alias), Value: list of (file_path, identifier_type)
|
||||
identifiers: dict[str, list[tuple[str, str]]] = defaultdict(list)
|
||||
|
||||
# Scan all markdown files
|
||||
for md_file in sorted(DOCS_DIR.rglob("*.md")):
|
||||
# Skip changelog fragments
|
||||
if "changelog.d" in md_file.parts:
|
||||
continue
|
||||
|
||||
rel_path = md_file.relative_to(DOCS_DIR)
|
||||
frontmatter = extract_frontmatter(md_file)
|
||||
|
||||
if not frontmatter:
|
||||
continue
|
||||
|
||||
# Extract title (used by reference docs)
|
||||
title = frontmatter.get("title")
|
||||
if title:
|
||||
identifiers[title].append((str(rel_path), "title"))
|
||||
|
||||
# Extract id (used by zk cards)
|
||||
card_id = frontmatter.get("id")
|
||||
if card_id:
|
||||
identifiers[card_id].append((str(rel_path), "id"))
|
||||
|
||||
# Extract aliases
|
||||
aliases = frontmatter.get("aliases", [])
|
||||
if aliases:
|
||||
for alias in aliases:
|
||||
identifiers[alias].append((str(rel_path), "alias"))
|
||||
|
||||
# Separate into duplicates and unique
|
||||
duplicates: dict[str, list[tuple[str, str]]] = {}
|
||||
unique: dict[str, tuple[str, str]] = {}
|
||||
|
||||
for identifier, sources in identifiers.items():
|
||||
if len(sources) > 1:
|
||||
duplicates[identifier] = sources
|
||||
else:
|
||||
unique[identifier] = sources[0]
|
||||
|
||||
# Print results
|
||||
console.print("[bold]Doc Card Title Inventory[/bold]")
|
||||
console.print()
|
||||
|
||||
# Duplicates table (if any)
|
||||
if duplicates:
|
||||
console.print("[bold red]Duplicates Found[/bold red]")
|
||||
dup_table = Table(show_header=True, header_style="bold")
|
||||
dup_table.add_column("Identifier")
|
||||
dup_table.add_column("Type")
|
||||
dup_table.add_column("File")
|
||||
|
||||
for identifier in sorted(duplicates.keys()):
|
||||
sources = duplicates[identifier]
|
||||
first = True
|
||||
for file_path, id_type in sources:
|
||||
dup_table.add_row(
|
||||
identifier if first else "",
|
||||
id_type,
|
||||
file_path,
|
||||
)
|
||||
first = False
|
||||
|
||||
console.print(dup_table)
|
||||
console.print()
|
||||
|
||||
# All identifiers table
|
||||
console.print("[bold]All Identifiers[/bold]")
|
||||
all_table = Table(show_header=True, header_style="bold")
|
||||
all_table.add_column("Identifier")
|
||||
all_table.add_column("Type")
|
||||
all_table.add_column("File")
|
||||
all_table.add_column("Status")
|
||||
|
||||
for identifier in sorted(identifiers.keys()):
|
||||
sources = identifiers[identifier]
|
||||
is_dup = identifier in duplicates
|
||||
first = True
|
||||
for file_path, id_type in sources:
|
||||
status = "[red]DUPLICATE[/red]" if is_dup else "[green]OK[/green]"
|
||||
all_table.add_row(
|
||||
identifier if first else "",
|
||||
id_type,
|
||||
file_path,
|
||||
status if first else "",
|
||||
)
|
||||
first = False
|
||||
|
||||
console.print(all_table)
|
||||
|
||||
# Summary
|
||||
console.print()
|
||||
console.print(f"Total identifiers: {len(identifiers)}")
|
||||
console.print(f"Duplicates: {len(duplicates)}")
|
||||
|
||||
if duplicates:
|
||||
console.print()
|
||||
console.print("[bold red]Action required:[/bold red] Resolve duplicates to ensure wiki-links work correctly.")
|
||||
return 1
|
||||
|
||||
return 0
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
sys.exit(main())
|
||||
Loading…
Add table
Add a link
Reference in a new issue