Skip to content

Add Go and Terraform code samples to the API specs - #55

Merged
Rabsztok merged 9 commits into
mainfrom
MT-23475-go-and-opentofu-samples
Sep 4, 2026
Merged

Add Go and Terraform code samples to the API specs#55
Rabsztok merged 9 commits into
mainfrom
MT-23475-go-and-opentofu-samples

Conversation

@Rabsztok

@Rabsztok Rabsztok commented Sep 1, 2026

Copy link
Copy Markdown
Member

Motivation

MT-23475 — the API docs dropdown offers
seven tabs (cURL plus six SDKs), but two shipping tools are missing from it entirely: the
Go SDK (mailtrap/mailtrap-go) and the Terraform provider
(mailtrap/terraform-provider-mailtrap). The dropdown is driven purely by each operation's
x-codeSamples list, so adding a tab means adding an entry.

The ticket AC scopes this to "every supported endpoint", which is what keeps this at 142
samples rather than 260: no sample is written against a method, attribute or resource that
does not exist.

Changes

3,659 insertions, 5 deletions (the five are the CLAUDE.md SDK repository lines moved to the
mailtrap org). No existing sample, description, base URL or operation order changes.

  • CLAUDE.md: Go as sample entry 8 and Terraform as entry 9, plus the conventions for both
    (why lang: hcl, the leading lifecycle comment, the verification commands, and the rule
    that an unsupported operation gets no entry rather than a "not supported" comment).
  • 122 new samples across 9 spec files: 108 Go (83% of the 130 documented operations) and
    14 Terraform (11%).
Spec file Ops Go Terraform New
sandbox.openapi.yml 30 30 6 36
email-sending.openapi.yml 27 24 3 27
contacts.openapi.yml 19 19 2 21
inbound.openapi.yml 19 0 0 0
account-management.openapi.yml 13 13 2 15
email-campaigns.openapi.yml 11 11 0 11
templates.openapi.yml 5 5 1 6
email-sending-transactional.openapi.yml 2 2 0 2
email-sending-bulk.openapi.yml 2 2 0 2
sandbox-sending.openapi.yml 2 2 0 2
Total 130 108 14 122

Never covered, deliberately: all 19 inbound operations (the SDK has no inbound support,
and the provider has no inbound resources) and the 3 tracking_opt_outs operations. Those keep
the samples they have. A provider is declarative, so it covers no sending, no campaigns, no
message inspection, and manages contact lists and fields but never contact data. Terraform samples cover only creates
(8 resource blocks) and reads backed by a real data source (6 data blocks); update, delete and
import are native resource lifecycle documented once by the provider, so those operations get no
Terraform tab (review feedback).

Conventions

  • Go samples are complete package main programs. That is not decoration — it is what makes
    them compile-checkable, which is the whole quality argument here. Token from
    os.Getenv("MAILTRAP_API_TOKEN") (the idiom in all of the SDK's own examples; note it diverges
    from the sibling tabs' literal YOUR_API_KEY), context.Background() inline, response
    discarded as _, log.Fatal on error, mailtrap.Ptr for optional pointer fields, exported
    constants over string literals. Written against v0.3.0, the latest release, so go get
    gives a reader exactly what the sample compiles against.
  • Terraform samples use lang: hcl with label: Terraform. GitBook highlights with Prism,
    which has an hcl component and no terraform one; lang resolves through Prism identifiers
    rather than GitBook's documented linguist list, as the existing csharp and shell samples
    already demonstrate. The tab is titled by label, so it reads "Terraform" regardless.
    An HCL block is not an API call, so every sample opens with a comment naming the lifecycle
    command that fires the endpoint (# terraform apply creates the domain: POST /api/domains); create
    samples add a second comment linking the provider docs on the registry,
    where the lifecycle operations live. Each sample is self-contained down to required_providers
    that tab is where a reader learns the source string.
  • Attribute names come from the provider schema, not its published examples, which are stale
    in two places: the resource is mailtrap_domain (renamed from mailtrap_sending_domain), and
    every email_sending webhook sets the sending_stream the API requires. The samples also
    carry the provider's real footguns as comments (no update path on mailtrap_api_token, no
    secret after an import, a template body that cannot be cleared).

Merge order — two preconditions

  1. Add SDK code samples to email campaigns endpoints #54 (campaigns-sdk-samples) should merge first. It adds the six other languages to the
    very same 11 x-codeSamples lists in email-campaigns.openapi.yml. Once it lands, this
    branch rebases onto it and the last commit (8667411) is the only one that needs resolving —
    or it can be dropped and redone. Nothing on Add SDK code samples to email campaigns endpoints #54's branch was touched.
  2. The provider must be on the Terraform and OpenTofu registries before this merges. The
    Terraform samples are written against the real published form (source = "mailtrap/mailtrap"
    in a plain required_providers block) with no dev_overrides workaround and no "not yet
    published" caveat, on the understanding that mailtrap/terraform-provider-mailtrap is
    published ahead of this. Merging before that ships a config that does not terraform init.

How to test

CI runs Spectral, which is the only automated gate in this repo. The other two checks are local
and are the ones that catch real bugs, so they were run on the samples extracted back out of
the committed YAML
, not on drafts.

  • Spectral (same command as CI): npx -y @stoplight/spectral-cli lint "specs/*.openapi.yml" --verbose
    → "No results with a severity of 'error' found!"
  • Go compiles. Every lang: go sample extracted to its own package against
    github.com/mailtrap/mailtrap-go@v0.3.0: 108 packages, gofmt -l empty, go vet ./...
    clean, go build ./... clean. This caught a real defect — an email-logs filter operator
    of eq where the API takes equal.
  • HCL parses, formats and validates. Every lang: hcl sample extracted to its own
    config: 34 configs at the time (the 14 kept are a subset; the later cut only added a comment line), fmt -check -diff clean, and validate against a provider binary
    built from terraform-provider-mailtrap's origin/main under dev_overrides — the only
    mechanical check on attribute names. All 34 validate. (validate was originally run with
    the OpenTofu CLI; the two CLIs are drop-in for fmt/validate here, and the label
    rename touched only comments, so terraform fmt -check was re-run on all 34 after it.)
  • Spectral re-run after both formatting passes, since gofmt tabs live inside source: |
    block scalars. Tabs are legal in block-scalar content; the round-trip through
    extract → gofmt -l is the proof.
  • Sample ordering asserted programmatically: go is always the second-to-last entry when
    hcl follows, hcl is always last, no duplicate langs.
  • Rendered docs Test in QA gitbook. Open a templates operation on docs.mailtrap.io/developers
    and confirm the dropdown reads cURL, Node.js, PHP, Python, Ruby, .NET, Java, Go,
    Terraform, that Go is highlighted, and that Terraform renders. If hcl turns out
    unhighlighted the tab still appears — accept that rather than switching to
    lang: terraform, which Prism does not know either.

Images

Screenshot 2026-09-02 at 09 33 20

Worth a reviewer's eye

  • Go lands on five operations the other SDKs still skip: updateDomain, the three
    company_info operations, and createSuppression currently have only shell (+ruby).
    Those tabs will read cURL / Ruby / Go until the other five languages are back-filled, which
    deserves its own ticket.
  • Token idiom. Go samples read MAILTRAP_API_TOKEN from the environment; the sibling tabs
    use a literal YOUR_API_KEY. That follows the SDK's house style and CLAUDE.md's
    "use environment variables for API keys", but it is a visible inconsistency inside one
    dropdown and a one-line-per-sample change if you would rather it matched.
  • 14 self-contained HCL samples repeat ~10 lines of required_providers boilerplate. The
    alternative is the provider docs page, which the create samples now link to.
  • Terraform was cut from 34 to 14 samples on review: the 7 updates, 8 deletes and 5
    import-style reads are gone; only creates and genuine data-source reads remain.

Rabsztok and others added 6 commits September 1, 2026 11:42
Extends the sample conventions in CLAUDE.md with the two new tabs (Go as
entry 8, OpenTofu as entry 9) and applies them to the smallest spec as a
render canary: 5 Go samples and 4 OpenTofu ones.

lang: hcl with label: OpenTofu, because GitBook highlights with Prism,
which has an hcl component and no terraform one. Unsupported operations
get no entry at all rather than a limitation comment, so the templates
list operation has no OpenTofu tab (the provider has no list data source).

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
32 samples: all 30 operations in sandbox.openapi.yml plus the two
sandbox-sending ones. The sandbox sending client is constructed with
WithSandbox(true) and WithSandboxID(...), which is what routes Send and
SendBatch to the sandbox host.

The five body.* operations return raw bytes, so those samples print
string(body). The message list sample also shows the SandboxMessages.All
iterator, which is the idiomatic way to walk every page.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
28 samples: 24 of the 27 operations in email-sending.openapi.yml, plus
the two bulk and two transactional sending operations. Host selection is
a client option, so the bulk samples construct the client with
WithBulk(true) and the transactional ones use the default.

The three tracking opt-out operations get no Go sample: the SDK has no
support for them, and an absent tab is better than one that says so.

Go lands on five operations the other SDKs still skip (updateDomain, the
three company_info operations, and createSuppression), so those tabs will
show cURL, Ruby and Go only until the other languages are back-filled.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
32 samples covering all 19 contacts operations and all 13
account-management ones.

Contact identifiers are a UUID or an email address, and the contact
update endpoint is an upsert, so that sample prints the action the API
reports. The two sub-account samples construct the client with
WithOrganizationID, which those endpoints require.

The API token samples do not set an expiration, so they match what the
API applies by default.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
30 samples across sandbox, contacts, email-sending and account-management,
completing the provider's coverage at 34 of the 130 documented operations.

A resource block is not an API call, so every sample opens with a comment
naming the lifecycle command that fires the endpoint, and each sample is
self-contained down to the required_providers block. Where the provider
has a data source (project, sandbox, domain, account) the read samples use
it; the rest pair the resource block with a tofu import line.

Attribute names come from the provider schema rather than its published
examples, so the resource is mailtrap_domain and every email_sending
webhook sets sending_stream. The samples also carry the provider's real
footguns as comments: the API token has no update path, an imported token
or webhook has no secret, and a template body cannot be cleared.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
11 samples, one per campaign operation, covering the draft/schedule/start
lifecycle and the stats endpoint.

The update sample shows the pointer-to-slice fields: nil leaves the
contact lists and segments unchanged, while a pointer to an empty slice
clears them. The list sample also shows the EmailCampaigns.All iterator.

Deliberately the last commit on this branch: PR #54 is adding the six
other languages to these same x-codeSamples lists, so this commit is the
one to rebase or drop once #54 lands.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
@coderabbitai

coderabbitai Bot commented Sep 1, 2026

Copy link
Copy Markdown

Important

  • 🔍 Trigger review

This repository does not receive automatic reviews because it has fewer than 10 stars.

⚙️ Run configuration

Configuration used: Organization UI

Review profile: CHILL

Plan: Team

Run ID: 636e11a4-7b7e-4f4b-ba39-9d4b85bd4a35


Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands.

@Rabsztok
Rabsztok marked this pull request as ready for review September 1, 2026 10:19
The provider is `terraform-provider-mailtrap` and ships to both registries;
Terraform is the name readers of the docs dropdown will recognise.

- `label: OpenTofu` -> `label: Terraform` on all 34 hcl samples (`lang: hcl`
  is unchanged - Prism still has no `terraform` component).
- Lifecycle comments now name the terraform CLI: `terraform apply/plan/
  import/destroy`. The commands are interchangeable, so the configs are
  unaffected.
- CLAUDE.md conventions updated to match, so future samples are added as
  Terraform.

Re-verified: Spectral clean, and all 34 samples extracted back out of the
committed YAML are `terraform fmt -check` clean.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
@Rabsztok Rabsztok changed the title Add Go and OpenTofu code samples to the API specs Add Go and Terraform code samples to the API specs Sep 2, 2026
Comment thread CLAUDE.md Outdated
Comment thread specs/templates.openapi.yml Outdated

@IgorDobryn IgorDobryn left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Not sure how to document terraform for import/delete/update operations

All six SDKs now live under github.com/mailtrap; .NET and Java were still
listed as future references.
Update, delete and import are native resource lifecycle and are documented
once by the provider, so a per-endpoint sample repeats the resource block
without adding anything. Drop those 20 samples, keep the 8 creates and the
6 reads that map to a real data source, and point the create samples at the
provider docs on the Terraform registry (review feedback on #55).
@Rabsztok
Rabsztok requested a review from mklocek September 4, 2026 05:38
@Rabsztok
Rabsztok merged commit 80d2cde into main Sep 4, 2026
2 checks passed
@Rabsztok
Rabsztok deleted the MT-23475-go-and-opentofu-samples branch September 4, 2026 11:33
Rabsztok added a commit that referenced this pull request Sep 4, 2026
main added Go samples to the email campaigns endpoints (PR #55) while this
branch was adding the Node.js, PHP, Python, Ruby, .NET and Java samples, so
every one of the 11 x-codeSamples lists in specs/email-campaigns.openapi.yml
conflicted as an append-vs-append.

Resolved by keeping both sides in every list. Concatenating this branch's
languages before main's Go sample happens to land on the priority order
CLAUDE.md documents: cURL, Node.js, PHP, Python, Ruby, .NET, Java, Go.

The one place the two sides genuinely overlapped is the schedule endpoint's
cURL sample: main still carried the hardcoded "2026-06-01T09:00:00.000Z"
payload that this branch had already replaced with a computed $DATETIME
(dafe709, 294867a) precisely because the literal had gone stale and returned
422. This branch's version supersedes it, so main's line is dropped rather
than duplicated. Same reasoning for the Schedule schema example, which
auto-merged to this branch's 2026-10-01 literal.

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants