Skip to content

Repository files navigation

Devin Pulumi Provider

A Pulumi provider for Devin, bridged from the official CognitionAI/terraform-provider-devin using the Pulumi Terraform Bridge.

Because it bridges the upstream Terraform provider directly, resources and data sources come from the same schema rather than a parallel reimplementation, so the two stay in lockstep as the upstream provider evolves.

Installation

npm install @pulumiverse/devin
pip install pulumiverse-devin
dotnet add package Pulumiverse.Devin
go get github.com/pulumiverse/pulumi-devin/sdk

The plugin binary is resolved from this repository's GitHub releases via the PluginDownloadURL baked into the schema, so pulumi up fetches it with no extra configuration.

The provider is not in the Pulumi Registry, so a manual pulumi plugin install needs the server spelled out. Installing the SDK is the normal path and needs none of this:

pulumi plugin install resource devin 0.1.0 --server github://api.github.com/pulumiverse

Building from source

Prerequisites: Go 1.25+, pulumictl, mise, the Pulumi CLI, Node.js, Yarn, Python 3, and the .NET SDK.

mise install      # installs the toolchain, including the terraform converter
make tfgen        # generate the Pulumi schema from the upstream Terraform provider
make provider     # build bin/pulumi-resource-devin
make build_sdks   # generate and build the dotnet, go, nodejs and python SDKs

Schema generation runs the terraform converter, and the generated Makefile sets PULUMI_DISABLE_AUTOMATIC_PLUGIN_ACQUISITION, so pulumi cannot fetch it on demand. The root mise.toml declares it for that reason. Without it make tfgen fails with no converter plugin 'pulumi-converter-terraform' found. See pulumiverse/projen-pulumi-providers#8.

Configuration

Option Environment variable Notes
apiUrl DEVIN_API_URL Devin API base URL; upstream default is https://api.devin.ai
token DEVIN_TOKEN Enterprise or organization service user token (cog_ prefix); marked secret

The upstream shim

The bridge has to construct the upstream terraform-plugin-framework provider in-process to generate its schema, but upstream's constructor lives in internal/provider and Go's module visibility rules put it out of reach.

Until CognitionAI/terraform-provider-devin#3 lands, provider/shim supplies it: a module declaring the path github.com/cognitionai/terraform-provider-devin/shim, which satisfies the internal-visibility check because that path sits inside the upstream module's tree, wired in through a replace directive in provider/go.mod.

When the upstream package is released, drop provider/shim and the replace, then bump the upstream require. The import path in provider/resources.go is deliberately identical either way, so nothing else changes.

Resource coverage and test status

All 18 resources and 6 data sources from the upstream provider are bridged and present in the generated schema, with descriptions for all 85 resource inputs.

Layer Coverage
Provider loads, configures and plans a resource TestBasicTs / TestBasicPy, preview-only, in CI
Schema surface schema-baseline.json drift guard
Docs edit rule unit test in provider/resources_test.go
Create, update, delete against a real account none

There is no live create/update/delete coverage, and no realistic path to it. Every Devin API call needs an enterprise or organization service user token, and most resources (Organization, IpAccessList, IdpGroup, the *Role mappings) mutate real enterprise configuration, so there is no free-tier or containerized equivalent of the throwaway server that bridged providers normally test against. A token secret is also unavailable to pull requests from forks, so fork CI could not exercise live resources even if one existed.

What is covered runs on every CI push and needs no credentials. TestBasicTs and TestBasicPy plan a Playbook with SkipUpdate, so the programs are previewed and never applied. They prove the built provider binary loads and serves, the generated schema is consumable by the Pulumi CLI, each SDK constructs a resource, and provider configuration resolves from DEVIN_TOKEN / DEVIN_API_URL. That last part is hand-written mapping in provider/resources.go rather than generated code, so it is worth a test: deleting the token from the test environment makes both tests fail with Missing token.

Two details in previewOnly are deliberate. The token is fake, and DEVIN_API_URL points at a closed port, so if a future change ever makes these tests reach the network they fail instead of touching a real account. Note this is also why the examples create a resource rather than reading a data source: a data source is invoked during preview and does call the API, so a getRoles example cannot be tested without real credentials.

Contributions widening this are welcome.

Schema drift

schema-baseline.json is a committed snapshot of the generated schema, so an upstream bump cannot change the public surface unnoticed. Upstream is pre-1.0 and moving fast, which is exactly when that matters:

./scripts/check-schema-drift.sh   # regenerates and diffs against the baseline

Review any diff, then update the baseline deliberately in the same commit as the upstream bump.

Docs handling

Upstream descriptions name JSON members as bare snake_case (max_concurrent_runs). The docs parser reads the inner underscores as markdown emphasis, which rendered as max*concurrent*runs in every generated SDK. provider/resources.go adds a DocRules edit that backticks bare identifiers before parsing, which both fixes the emphasis and lets the bridge translate them to Pulumi names, so the same description now reads `maxConcurrentRuns`.

Known limitation: example conversion

make tfgen converts 64 of 168 upstream HCL examples (38%). Two distinct causes, both outside this repository:

  • 10 examples fail to resolve the provider. Upstream's docs examples are bare resource snippets with no terraform { required_providers { ... } } block, so the converter assumes registry.terraform.io/hashicorp/devin and drops the example. Injecting a provider block via a DocRules edit would recover them, but the converter would then have to fetch cognitionai/devin from the Terraform Registry during codegen, making schema generation network-dependent and CI non-hermetic. Fixing it upstream (adding the block to the docs templates) is the better route.
  • The rest hit converter feature gaps. one() is unimplemented (pulumi-converter-terraform#65) and for expressions are unsupported in Go and YAML.

The failures are deterministic, giving the same 38% and the same 10 warnings on every run, cold cache or warm, so the schema baseline above is stable.

Versioning

The upstream provider is pre-1.0 and moving quickly, so this provider tracks it on a 0.x line and makes no Go module stability promise yet. The bare module path (sdk, not sdk/v2) is correct for both 0.x and 1.x.

License

Apache-2.0. See LICENSE.

About

Pulumi provider for Devin

Topics

Resources

Code of conduct

Contributing

Stars

0 stars

Watchers

0 watching

Forks

Releases

Packages

Used by

Contributors

Languages