feat: implement docs-site, legal docs, metrics standard, flux manifests
Closes leeworks-agents/api-company#5 (docs-site Astro scaffold) Closes leeworks-agents/api-company#9 (metrics instrumentation standard) Closes leeworks-agents/api-company#10 (Gitea Actions openapi aggregation pipeline) Closes leeworks-agents/api-company#11 (docs-site Flux HelmRelease) Closes leeworks-agents/api-company#12 (SEO blog posts x3) Closes leeworks-agents/api-company#13 (legal docs ToS/Privacy/AUP) Closes leeworks-agents/api-company#14 (DNS documentation) ## Changes ### docs/legal/ - terms-of-service.md — API usage, liability, account termination, governing law - privacy-policy.md — request log retention (90d), no PII sold, data sharing - acceptable-use-policy.md — rate limit abuse, scraping prohibition, resale ban ### docs/metrics-standard.md - Defines api_requests_total, api_response_duration_seconds, api_data_freshness_seconds - Fastify (TypeScript) and FastAPI (Python) reference middleware implementations - Prometheus scrape config and Grafana dashboard guidance ### docs/registry.md - Decision: use Gitea built-in container registry (no new infra) - Image naming convention, auth, Kubernetes imagePullSecrets, ingress config ### docs/dns.md - Required A records for all 6 subdomains - cert-manager ClusterIssuer and Ingress TLS examples - Verification commands and human-operator action items ### docs-site/ - Astro 4 + MDX + sitemap scaffold - Base layout with nav linking all APIs, blog, RapidAPI, status - Landing page with API cards - Per-API Redoc viewer pages (zip-enrichment, holidays, air-quality) - Blog index + 3 SEO blog posts (~1000 words each with JSON-LD) - Dockerfile (multi-stage: node build + nginx serve) - nginx.conf with gzip, caching, health endpoint ### flux/ - gitea-runner/: gitea-act-runner HelmRelease (org-scope, dind) - monitoring/: kube-prometheus-stack + Gatus HelmReleases - Prometheus with pod annotation scraping - Grafana at grafana.leeworks.dev with persistence - Gatus status page at status.leeworks.dev, 90-day retention - docs-site/: Deployment + Service + Ingress via raw chart - api-company-source/: GitRepository + Kustomization reference manifests - kustomization.yaml: root kustomize entry point (build validated) ### .gitea/workflows/build-docs.yaml - Aggregates openapi.yaml from zip-enrichment, holidays, air-quality repos - Builds Astro docs-site - Pushes image to registry.leeworks.dev/leeworks-agents/docs-site - Triggered on push to main, schedule daily 02:00 UTC, workflow_dispatch
This commit is contained in:
@@ -1 +0,0 @@
|
||||
# placeholder — populated by Phase-4/5 issues
|
||||
@@ -0,0 +1,17 @@
|
||||
# This manifest is FOR REFERENCE — the live version must be committed to
|
||||
# 0xWheatyz/Talos at testing1/first-cluster/cluster/flux/api-company/
|
||||
#
|
||||
# See leeworks-agents/api-company#2
|
||||
|
||||
apiVersion: source.toolkit.fluxcd.io/v1
|
||||
kind: GitRepository
|
||||
metadata:
|
||||
name: api-company
|
||||
namespace: flux-system
|
||||
spec:
|
||||
interval: 5m
|
||||
url: https://gitea.leeworks.dev/leeworks-agents/api-company
|
||||
ref:
|
||||
branch: main
|
||||
secretRef:
|
||||
name: gitea-leeworks-agents-token # must pre-exist in flux-system ns
|
||||
@@ -0,0 +1,19 @@
|
||||
# This manifest is FOR REFERENCE — the live version must be committed to
|
||||
# 0xWheatyz/Talos at testing1/first-cluster/cluster/flux/api-company/
|
||||
#
|
||||
# See leeworks-agents/api-company#2
|
||||
|
||||
apiVersion: kustomize.toolkit.fluxcd.io/v1
|
||||
kind: Kustomization
|
||||
metadata:
|
||||
name: api-company
|
||||
namespace: flux-system
|
||||
spec:
|
||||
interval: 5m
|
||||
sourceRef:
|
||||
kind: GitRepository
|
||||
name: api-company
|
||||
path: ./flux
|
||||
prune: true
|
||||
wait: true
|
||||
timeout: 5m
|
||||
@@ -0,0 +1,89 @@
|
||||
apiVersion: helm.toolkit.fluxcd.io/v2
|
||||
kind: HelmRelease
|
||||
metadata:
|
||||
name: docs-site
|
||||
namespace: docs-site
|
||||
spec:
|
||||
interval: 10m
|
||||
chart:
|
||||
spec:
|
||||
chart: raw
|
||||
version: ">=0.2.0"
|
||||
sourceRef:
|
||||
kind: HelmRepository
|
||||
name: bedag
|
||||
namespace: flux-system
|
||||
interval: 60m
|
||||
values:
|
||||
resources:
|
||||
- apiVersion: apps/v1
|
||||
kind: Deployment
|
||||
metadata:
|
||||
name: docs-site
|
||||
namespace: docs-site
|
||||
spec:
|
||||
replicas: 1
|
||||
selector:
|
||||
matchLabels:
|
||||
app: docs-site
|
||||
template:
|
||||
metadata:
|
||||
labels:
|
||||
app: docs-site
|
||||
spec:
|
||||
imagePullSecrets:
|
||||
- name: gitea-registry
|
||||
containers:
|
||||
- name: docs-site
|
||||
image: registry.leeworks.dev/leeworks-agents/docs-site:latest
|
||||
ports:
|
||||
- containerPort: 80
|
||||
resources:
|
||||
requests:
|
||||
cpu: 50m
|
||||
memory: 64Mi
|
||||
limits:
|
||||
cpu: 200m
|
||||
memory: 128Mi
|
||||
livenessProbe:
|
||||
httpGet:
|
||||
path: /health
|
||||
port: 80
|
||||
initialDelaySeconds: 5
|
||||
periodSeconds: 30
|
||||
- apiVersion: v1
|
||||
kind: Service
|
||||
metadata:
|
||||
name: docs-site
|
||||
namespace: docs-site
|
||||
spec:
|
||||
selector:
|
||||
app: docs-site
|
||||
ports:
|
||||
- port: 80
|
||||
targetPort: 80
|
||||
- apiVersion: networking.k8s.io/v1
|
||||
kind: Ingress
|
||||
metadata:
|
||||
name: docs-site
|
||||
namespace: docs-site
|
||||
annotations:
|
||||
cert-manager.io/cluster-issuer: letsencrypt-prod
|
||||
nginx.ingress.kubernetes.io/ssl-redirect: "true"
|
||||
spec:
|
||||
ingressClassName: nginx
|
||||
tls:
|
||||
- hosts:
|
||||
- docs.leeworks.dev
|
||||
secretName: docs-site-tls
|
||||
rules:
|
||||
- host: docs.leeworks.dev
|
||||
http:
|
||||
paths:
|
||||
- path: /
|
||||
pathType: Prefix
|
||||
backend:
|
||||
service:
|
||||
name: docs-site
|
||||
port:
|
||||
number: 80
|
||||
@@ -0,0 +1,8 @@
|
||||
apiVersion: source.toolkit.fluxcd.io/v1
|
||||
kind: HelmRepository
|
||||
metadata:
|
||||
name: bedag
|
||||
namespace: flux-system
|
||||
spec:
|
||||
interval: 60m
|
||||
url: https://bedag.github.io/helm-charts/
|
||||
@@ -0,0 +1,6 @@
|
||||
apiVersion: kustomize.config.k8s.io/v1beta1
|
||||
kind: Kustomization
|
||||
resources:
|
||||
- namespace.yaml
|
||||
- helmrepository.yaml
|
||||
- helmrelease.yaml
|
||||
@@ -0,0 +1,4 @@
|
||||
apiVersion: v1
|
||||
kind: Namespace
|
||||
metadata:
|
||||
name: docs-site
|
||||
@@ -0,0 +1,42 @@
|
||||
apiVersion: helm.toolkit.fluxcd.io/v2
|
||||
kind: HelmRelease
|
||||
metadata:
|
||||
name: gitea-act-runner
|
||||
namespace: gitea-runner
|
||||
spec:
|
||||
interval: 10m
|
||||
chart:
|
||||
spec:
|
||||
chart: gitea-act-runner
|
||||
version: ">=0.1.0"
|
||||
sourceRef:
|
||||
kind: HelmRepository
|
||||
name: gitea-charts
|
||||
namespace: flux-system
|
||||
interval: 60m
|
||||
values:
|
||||
replicaCount: 1
|
||||
config:
|
||||
registration:
|
||||
# Gitea instance URL
|
||||
instanceUrl: "https://gitea.leeworks.dev"
|
||||
# Token from Gitea admin → Actions → Runners → New Runner
|
||||
# Store in a Kubernetes Secret named gitea-runner-token
|
||||
tokenFromSecret:
|
||||
secretName: gitea-runner-token
|
||||
secretKey: token
|
||||
runner:
|
||||
# Register at org scope so all leeworks-agents repos can use it
|
||||
labels:
|
||||
- "ubuntu-latest:docker://node:20-bookworm"
|
||||
- "ubuntu-22.04:docker://node:20-bookworm"
|
||||
resources:
|
||||
requests:
|
||||
cpu: 200m
|
||||
memory: 256Mi
|
||||
limits:
|
||||
cpu: 2000m
|
||||
memory: 2Gi
|
||||
# Runner needs Docker socket or dind
|
||||
dind:
|
||||
enabled: true
|
||||
@@ -0,0 +1,8 @@
|
||||
apiVersion: source.toolkit.fluxcd.io/v1
|
||||
kind: HelmRepository
|
||||
metadata:
|
||||
name: gitea-charts
|
||||
namespace: flux-system
|
||||
spec:
|
||||
interval: 60m
|
||||
url: https://dl.gitea.com/charts/
|
||||
@@ -0,0 +1,6 @@
|
||||
apiVersion: kustomize.config.k8s.io/v1beta1
|
||||
kind: Kustomization
|
||||
resources:
|
||||
- namespace.yaml
|
||||
- helmrepository.yaml
|
||||
- helmrelease.yaml
|
||||
@@ -0,0 +1,4 @@
|
||||
apiVersion: v1
|
||||
kind: Namespace
|
||||
metadata:
|
||||
name: gitea-runner
|
||||
@@ -0,0 +1,6 @@
|
||||
apiVersion: kustomize.config.k8s.io/v1beta1
|
||||
kind: Kustomization
|
||||
resources:
|
||||
- gitea-runner
|
||||
- monitoring
|
||||
- docs-site
|
||||
@@ -0,0 +1,94 @@
|
||||
apiVersion: helm.toolkit.fluxcd.io/v2
|
||||
kind: HelmRelease
|
||||
metadata:
|
||||
name: gatus
|
||||
namespace: monitoring
|
||||
spec:
|
||||
interval: 15m
|
||||
chart:
|
||||
spec:
|
||||
chart: gatus
|
||||
version: ">=1.0.0"
|
||||
sourceRef:
|
||||
kind: HelmRepository
|
||||
name: minicloudlabs
|
||||
namespace: flux-system
|
||||
interval: 60m
|
||||
values:
|
||||
ingress:
|
||||
enabled: true
|
||||
ingressClassName: nginx
|
||||
annotations:
|
||||
cert-manager.io/cluster-issuer: letsencrypt-prod
|
||||
nginx.ingress.kubernetes.io/ssl-redirect: "true"
|
||||
hosts:
|
||||
- host: status.leeworks.dev
|
||||
paths:
|
||||
- path: /
|
||||
pathType: Prefix
|
||||
tls:
|
||||
- secretName: gatus-tls
|
||||
hosts:
|
||||
- status.leeworks.dev
|
||||
config:
|
||||
storage:
|
||||
type: sqlite
|
||||
path: /data/gatus.db
|
||||
endpoints:
|
||||
- name: ZIP Enrichment API
|
||||
url: https://zip.leeworks.dev/health
|
||||
interval: 1m
|
||||
conditions:
|
||||
- "[STATUS] == 200"
|
||||
- "[RESPONSE_TIME] < 1000"
|
||||
alerts:
|
||||
- type: slack
|
||||
description: "ZIP Enrichment API is down"
|
||||
send-on-resolved: true
|
||||
|
||||
- name: Holidays API
|
||||
url: https://holidays.leeworks.dev/health
|
||||
interval: 1m
|
||||
conditions:
|
||||
- "[STATUS] == 200"
|
||||
- "[RESPONSE_TIME] < 1000"
|
||||
alerts:
|
||||
- type: slack
|
||||
description: "Holidays API is down"
|
||||
send-on-resolved: true
|
||||
|
||||
- name: Air Quality API
|
||||
url: https://aqi.leeworks.dev/health
|
||||
interval: 1m
|
||||
conditions:
|
||||
- "[STATUS] == 200"
|
||||
- "[RESPONSE_TIME] < 1000"
|
||||
alerts:
|
||||
- type: slack
|
||||
description: "Air Quality API is down"
|
||||
send-on-resolved: true
|
||||
|
||||
- name: Docs Site
|
||||
url: https://docs.leeworks.dev
|
||||
interval: 5m
|
||||
conditions:
|
||||
- "[STATUS] == 200"
|
||||
|
||||
- name: Container Registry
|
||||
url: https://registry.leeworks.dev/v2/
|
||||
interval: 5m
|
||||
conditions:
|
||||
- "[STATUS] == 200"
|
||||
|
||||
ui:
|
||||
title: "leeworks.dev API Status"
|
||||
description: "Real-time status for all leeworks.dev APIs"
|
||||
logo: ""
|
||||
# Retention: 90 days
|
||||
retention:
|
||||
days: 90
|
||||
|
||||
persistence:
|
||||
enabled: true
|
||||
size: 1Gi
|
||||
mountPath: /data
|
||||
@@ -0,0 +1,8 @@
|
||||
apiVersion: source.toolkit.fluxcd.io/v1
|
||||
kind: HelmRepository
|
||||
metadata:
|
||||
name: minicloudlabs
|
||||
namespace: flux-system
|
||||
spec:
|
||||
interval: 60m
|
||||
url: https://minicloudlabs.github.io/helm-charts
|
||||
@@ -0,0 +1,92 @@
|
||||
apiVersion: helm.toolkit.fluxcd.io/v2
|
||||
kind: HelmRelease
|
||||
metadata:
|
||||
name: kube-prometheus-stack
|
||||
namespace: monitoring
|
||||
spec:
|
||||
interval: 15m
|
||||
chart:
|
||||
spec:
|
||||
chart: kube-prometheus-stack
|
||||
version: ">=58.0.0 <60.0.0"
|
||||
sourceRef:
|
||||
kind: HelmRepository
|
||||
name: prometheus-community
|
||||
namespace: flux-system
|
||||
interval: 60m
|
||||
install:
|
||||
crds: CreateReplace
|
||||
remediation:
|
||||
retries: 3
|
||||
upgrade:
|
||||
crds: CreateReplace
|
||||
remediation:
|
||||
retries: 3
|
||||
values:
|
||||
grafana:
|
||||
enabled: true
|
||||
adminPassword: "${GRAFANA_ADMIN_PASSWORD}" # inject via Secret/substitution
|
||||
ingress:
|
||||
enabled: true
|
||||
ingressClassName: nginx
|
||||
annotations:
|
||||
cert-manager.io/cluster-issuer: letsencrypt-prod
|
||||
nginx.ingress.kubernetes.io/ssl-redirect: "true"
|
||||
hosts:
|
||||
- grafana.leeworks.dev
|
||||
tls:
|
||||
- secretName: grafana-tls
|
||||
hosts:
|
||||
- grafana.leeworks.dev
|
||||
persistence:
|
||||
enabled: true
|
||||
size: 5Gi
|
||||
sidecar:
|
||||
dashboards:
|
||||
enabled: true
|
||||
prometheus:
|
||||
prometheusSpec:
|
||||
retention: 30d
|
||||
storageSpec:
|
||||
volumeClaimTemplate:
|
||||
spec:
|
||||
resources:
|
||||
requests:
|
||||
storage: 20Gi
|
||||
# Scrape pods with prometheus.io/scrape=true annotations
|
||||
podMonitorNamespaceSelector: {}
|
||||
podMonitorSelector: {}
|
||||
serviceMonitorNamespaceSelector: {}
|
||||
serviceMonitorSelector: {}
|
||||
# Additional scrape configs for annotation-based discovery
|
||||
additionalScrapeConfigs:
|
||||
- job_name: 'kubernetes-pods'
|
||||
kubernetes_sd_configs:
|
||||
- role: pod
|
||||
relabel_configs:
|
||||
- source_labels: [__meta_kubernetes_pod_annotation_prometheus_io_scrape]
|
||||
action: keep
|
||||
regex: "true"
|
||||
- source_labels: [__meta_kubernetes_pod_annotation_prometheus_io_path]
|
||||
action: replace
|
||||
target_label: __metrics_path__
|
||||
regex: (.+)
|
||||
- source_labels: [__address__, __meta_kubernetes_pod_annotation_prometheus_io_port]
|
||||
action: replace
|
||||
regex: ([^:]+)(?::\d+)?;(\d+)
|
||||
replacement: $1:$2
|
||||
target_label: __address__
|
||||
- action: labelmap
|
||||
regex: __meta_kubernetes_pod_label_(.+)
|
||||
- source_labels: [__meta_kubernetes_namespace]
|
||||
action: replace
|
||||
target_label: kubernetes_namespace
|
||||
- source_labels: [__meta_kubernetes_pod_name]
|
||||
action: replace
|
||||
target_label: kubernetes_pod_name
|
||||
alertmanager:
|
||||
enabled: false # Enable when alert routing is configured
|
||||
kubeStateMetrics:
|
||||
enabled: true
|
||||
nodeExporter:
|
||||
enabled: true
|
||||
@@ -0,0 +1,8 @@
|
||||
apiVersion: source.toolkit.fluxcd.io/v1
|
||||
kind: HelmRepository
|
||||
metadata:
|
||||
name: prometheus-community
|
||||
namespace: flux-system
|
||||
spec:
|
||||
interval: 60m
|
||||
url: https://prometheus-community.github.io/helm-charts
|
||||
@@ -0,0 +1,8 @@
|
||||
apiVersion: kustomize.config.k8s.io/v1beta1
|
||||
kind: Kustomization
|
||||
resources:
|
||||
- namespace.yaml
|
||||
- helmrepository.yaml
|
||||
- helmrelease.yaml
|
||||
- gatus-helmrepository.yaml
|
||||
- gatus-helmrelease.yaml
|
||||
@@ -0,0 +1,4 @@
|
||||
apiVersion: v1
|
||||
kind: Namespace
|
||||
metadata:
|
||||
name: monitoring
|
||||
Reference in New Issue
Block a user