Apache DevLake is an open source platform that collects engineering data from tools like GitHub, GitLab, Jira, Jenkins and PagerDuty. It has a REST API but no Terraform provider, so setting it up meant clicking through the web UI for every project, connection and scope, with nothing written down.
I built a Terraform provider for it in Go, on the Terraform Plugin Framework, with 13 resource types including the GitHub, GitLab and Jira integrations. A small pipeline sits on top. Anyone who wants a repo or board tracked gives a few plain inputs, the pipeline applies them, and they never need to know Terraform or DevLake are involved. I plan to contribute the provider upstream to Apache DevLake.
Terraform expects an API that is declarative and idempotent, and most real APIs are neither. In the version I worked against, DevLake’s PATCH treated a missing field as empty, so one update could silently wipe a project’s description. Deleting a project returned a 500 if its blueprint was missing. Deleting a scope returned a 409 while a blueprint still referred to it. I found each of these by hitting it, and the provider absorbs all of them so the user never has to.
The talk covers how a provider is put together, why reading state back correctly matters more than creating things, and where the line sits between working around an upstream bug and hiding it. I used AI coding tools heavily and will say honestly where they helped and where they did not.