Metadata-Version: 2.4
Name: pulumiverse_devin
Version: 0.1.0
Summary: A Pulumi package for creating and managing Devin resources.
License: Apache-2.0
Project-URL: Homepage, https://www.pulumi.com
Project-URL: Repository, https://github.com/pulumiverse/pulumi-devin
Keywords: devin,category/cloud
Requires-Python: >=3.9
Description-Content-Type: text/markdown
Requires-Dist: parver>=0.2.1
Requires-Dist: pulumi<4.0.0,>=3.231.0
Requires-Dist: semver>=2.8.1
Requires-Dist: typing-extensions<5,>=4.11; python_version < "3.11"

# Devin Pulumi Provider

A [Pulumi](https://www.pulumi.com) provider for [Devin](https://devin.ai), bridged from the official
[`CognitionAI/terraform-provider-devin`](https://github.com/CognitionAI/terraform-provider-devin)
using the [Pulumi Terraform Bridge](https://github.com/pulumi/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

```bash
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:

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

## Building from source

Prerequisites: Go 1.25+, [`pulumictl`](https://github.com/pulumi/pulumictl),
[`mise`](https://mise.jdx.dev), the Pulumi CLI, Node.js, Yarn, Python 3, and the .NET SDK.

```bash
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`](./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](https://github.com/pulumiverse/projen-pulumi-providers/issues/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](https://github.com/CognitionAI/terraform-provider-devin/pull/3)
lands, [`provider/shim`](./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`](./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`](./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`](./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:

```bash
./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`](./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](https://github.com/pulumi/pulumi-converter-terraform/issues/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](./LICENSE).
