作者用AI辅助开发了Infra Lang——一种IaC DSL,可编译到K8s/Docker Compose/Helm/Terraform/GitHub Actions五种目标格式,同时自建了LSP和实时测试。
Every team I've worked with maintains the same application in at least three formats: Kubernetes manifests for production, a docker-compose.yml for local dev, and a GitHub Actions workflow for CI. Every change touches all of them. They drift. And bugs in the K8s YAML only surface when kubectl apply rejects them — not when you write them.
I wanted one file that compiles to all of them. So I built Infra Lang.
service api {
image: "myapp/api:v1.0.0"
replicas: 3
port 8080
health http("/health")
resources {
requests { cpu: 200m, memory: 256Mi }
limits { cpu: 1000m, memory: 512Mi }
}
}
That block compiles to a Kubernetes Deployment + Service, a Docker Compose service, a Helm chart, Terraform HCL, or a GitHub Actions workflow. One source of truth, five targets.
Templates Helm, Kustomize, and string interpolation in CI all push the same problem down the road: you still write YAML, just with placeholders. Validation still happens late.
A real DSL gives you three things:
A parser that catches errors immediately. Infra Lang uses a hand-written LALR(1) grammar with {} blocks. A typo is caught at parse time with a location and a helpful message — not after you deploy.
Compile-time linting. 10 security rules catch hardcoded secrets, mutable image tags, and privileged containers. 13 reliability rules catch thundering-herd replica counts, databases without backups, and single-replica Kafka. Error-severity findings block compilation entirely.
One mental model. You think in services, databases, queues, and pipelines — not in individual YAML documents for each platform.
I want to be transparent: this project was built with extensive AI assistance — about 40 sessions over 10 days using Claude as a coding partner.
Here's how the process actually worked:
I owned every architecture decision. The DSL syntax, which backends to support, what the LSP should do, how to structure tests. AI doesn't make those calls.
AI wrote implementation and tests. I reviewed, ran, and iterated. Every session had a specific scope: "add semantic tokens to LSP", "fix Compose secret mounting", not "build me a DSL".
I ran everything locally. Docker Desktop, kind for Kubernetes E2E, real helm lint, real docker compose up. AI can't do that.
27 real bugs were found through the process. Secret base64 encoding that passed unit tests but failed kubectl apply. Service port naming that Kubernetes rejected. Windows URI path conversion that crashed the LSP. These are things you only find by actually running the code against real targets.
Is there risk in AI-assisted development? Yes — I don't know 100% of the codebase intimately. But the code runs, tests pass on 3 operating systems and 3 Python versions, and the output is validated against real Kubernetes clusters.
Coverage lies. 93% line coverage sounded impressive. Then I ran mutation testing — automatically introducing bugs into the code and checking whether tests catch them.
Results: some modules had 34% mutation score despite high line coverage. The tests executed the code but didn't verify the output. A test that says assert result is not None gives you coverage but catches nothing.
After two sessions of targeted fixes, critical modules reached 82-100% mutation score. The lesson: line coverage tells you what code ran, not whether your tests actually work.
Cross-platform is harder than you think. My first CI run on Windows failed because .read_text() without encoding="utf-8" uses the system default (cp1252 on Windows). Every file read in the entire codebase needed explicit UTF-8.
Docker daemon detection needed special handling too — Windows CI runners have the Docker CLI installed but no running daemon. docker version succeeds but docker compose up fails. The fix: check docker info exit code, not just whether the binary exists.
Building a language server taught me more about developer experience than anything else in this project. Each feature had its own challenge:
db shouldn't touch main-dbThe result: completion, hover, diagnostics, go-to-definition, find-references, rename, semantic tokens, signature help, document highlight, and folding — all working across every .infra file in the project.
Three of the most serious bugs were invisible to unit tests:
Now there's an opt-in test suite that actually spins up a kind cluster, runs kubectl apply, starts docker compose up, and runs helm lint --strict. These tests found real bugs that 1800+ unit tests missed.
Start with PyPI from day 1. I spent the first week telling people to pip install git+https://github.com/.... The friction was enormous. Once I published to PyPI, installation became pip install infra-lang — 5 seconds instead of a paragraph of instructions.
Write blog posts before launching. SEO takes weeks to build. Dev.to articles, technical deep dives, comparison posts — all of these should exist before you post on HN, not after.
Build community before features. I built 5 backends, a full LSP, Helm chart generation, and live E2E tests. Then I posted on Hacker News and got 13 upvotes. Features don't create adoption. Reach does.
pip install infra-lang
infra --help
Or with the VS Code language server:
pip install 'infra-lang[lsp]'
If you maintain infrastructure in multiple formats, I'd love your feedback — especially on language design and which compilation targets matter most.