Skip to content

feat: Support custom fields (metadata) on features, segments and environments - #245

Merged
matthewelwell merged 4 commits into
feat/feature-and-segment-data-sourcesfrom
feat/custom-fields
Aug 26, 2026
Merged

feat: Support custom fields (metadata) on features, segments and environments#245
matthewelwell merged 4 commits into
feat/feature-and-segment-data-sourcesfrom
feat/custom-fields

Conversation

@matthewelwell

@matthewelwell matthewelwell commented Aug 25, 2026

Copy link
Copy Markdown
Contributor

Closes #215.

Warning

Draft, and stacked on #244 — review that one first. Base will change to main once it merges.
Also blocked on flagsmith-go-api-client#23: go.mod carries a local replace so this builds, so CI will fail on go mod download until that's merged and released.

Adds a metadata attribute to flagsmith_feature, flagsmith_segment and flagsmith_environment. Until now there was no way to set a custom field, so an organisation with a mandatory custom field couldn't create features through the provider at all — the symptom in the issue.

resource "flagsmith_feature" "my_flag" {
  feature_name = "my_flag"
  project_uuid = var.project_uuid

  metadata = {
    "Jira Ticket" = "PROD-123"
    "Owner Team"  = "platform"
  }
}

Keyed by name rather than by the numeric model field ID the API wants, since that ID is per (field, entity type) and isn't portable across organisations. The SDK resolves names to IDs and back.

⚠️ This also fixes silent data loss

Worth calling out separately, because it changes what existing users see in a plan.

MetadataSerializerMixin._update_metadata in the API deletes and recreates the whole metadata set on every write, and is called unconditionally with validated_data.pop("metadata", []). Because the provider has never sent metadata, and a missing key defaults to an empty list, every apply that updated a feature, segment or environment was already destroying its UI-set custom field values, silently.

This PR doesn't introduce that. It makes it visible: a value set in the UI now shows up in the plan as an explicit removal, which you can act on.

Consequence for existing users: the first plan after upgrading may show a removal on resources that have UI-set custom fields. Add them to metadata to keep them. This is in the CHANGELOG under NOTES.

Filing an upstream issue to make an absent metadata key mean "no change" instead of "wipe" is worth doing regardless — it affects every API client, not just Terraform.

🤖 Generated with Claude Code

@coderabbitai

coderabbitai Bot commented Aug 25, 2026

Copy link
Copy Markdown

Review Change Stack

Important

Review skipped

Auto reviews are disabled on base/target branches other than the default branch.

Please check the settings in the CodeRabbit UI or the .coderabbit.yaml file in this repository. To trigger a single review, invoke the @coderabbitai review command.

⚙️ Run configuration

Configuration used: Organization UI

Review profile: ASSERTIVE

Plan: Pro Plus

Run ID: 3d6bf347-9db6-45a0-a158-40762107b98f

You can disable this status message by setting the reviews.review_status to false in the CodeRabbit configuration file.

Use the checkbox below for a quick retry:

  • 🔍 Trigger review
📝 Walkthrough

Walkthrough

The provider adds custom metadata support for feature, segment, and environment resources and data sources. Metadata is validated against project custom fields, converted for API requests, and reconciled into Terraform state. Resources support metadata creation, updates, imports, and removal. Acceptance tests cover valid and invalid metadata. Documentation and examples describe configuration, validation, replacement behaviour, and imports.

Estimated code review effort: 4 (Complex) | ~45 minutes

Merge Risk: 🟡 Moderate · up to 4c3e0

The PR adds custom metadata management to features, segments, and environments, but it is not merge-ready while clean checkouts cannot resolve the required API client dependency; CI and downstream builds will fail until a published version replaces the local module path. The environment import example also needs a shell-safe placeholder to avoid copy-and-paste errors.


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.

@matthewelwell
matthewelwell force-pushed the feat/feature-and-segment-data-sources branch from 2896a73 to 8f080f2 Compare August 25, 2026 17:38
@matthewelwell
matthewelwell force-pushed the feat/custom-fields branch 3 times, most recently from fa7d38c to 092d965 Compare August 25, 2026 18:02
@matthewelwell
matthewelwell force-pushed the feat/feature-and-segment-data-sources branch from 8f080f2 to c4a3508 Compare August 25, 2026 18:58
@matthewelwell
matthewelwell force-pushed the feat/feature-and-segment-data-sources branch from c4a3508 to 63fdc61 Compare August 25, 2026 19:02

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Actionable comments posted: 2


ℹ️ Review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: ASSERTIVE

Plan: Pro Plus

Run ID: 19931e3e-2939-4689-935a-d43f989de9fa

📥 Commits

Reviewing files that changed from the base of the PR and between 63fdc61 and 4c3e001.

📒 Files selected for processing (23)
  • .github/workflows/test.yml
  • docs/data-sources/feature.md
  • docs/data-sources/segment.md
  • docs/resources/environment.md
  • docs/resources/feature.md
  • docs/resources/segment.md
  • examples/resources/flagsmith_environment/import-by-string-id.tf
  • examples/resources/flagsmith_environment/import.sh
  • examples/resources/flagsmith_environment/resource.tf
  • examples/resources/flagsmith_feature/resource.tf
  • examples/resources/flagsmith_segment/resource.tf
  • flagsmith/data_source_feature.go
  • flagsmith/data_source_segment.go
  • flagsmith/metadata.go
  • flagsmith/metadata_test.go
  • flagsmith/models.go
  • flagsmith/models_test.go
  • flagsmith/provider_test.go
  • flagsmith/resource_environment.go
  • flagsmith/resource_feature.go
  • flagsmith/resource_metadata_test.go
  • flagsmith/resource_segment.go
  • go.mod

Included review availability: Your plan provides up to 1 included review per hour; 0 remain after this review.

Comment thread examples/resources/flagsmith_environment/import.sh Outdated
Comment thread go.mod Outdated
Comment thread docs/resources/environment.md Outdated
Comment thread docs/resources/environment.md Outdated
Comment thread docs/resources/feature.md Outdated
Comment thread docs/resources/segment.md Outdated
Comment thread examples/resources/flagsmith_environment/import.sh Outdated
Comment thread flagsmith/models.go
Comment thread flagsmith/models.go
Comment thread flagsmith/models.go
Adds a `metadata` attribute to the flagsmith_feature, flagsmith_segment and
flagsmith_environment resources, so Flagsmith custom fields can be set from
Terraform. Fixes #215: until now there was no way to set one, so an organisation
with a mandatory custom field could not create features through the provider at
all.

Custom fields are keyed by name rather than by the numeric model field ID the
API expects, since that ID is per (field, entity type) and is not portable
across organisations:

    metadata = {
      "Jira Ticket" = "PROD-123"
    }

The attribute is Optional and deliberately not Computed. The API replaces the
whole set of custom field values on every write, so a value set in the UI on a
Terraform managed resource is going to be removed either way; Optional+Computed
would hide that in the plan and would also make it impossible to remove a value
by deleting it from the configuration.

That behaviour is worth calling out on its own: because the provider has never
sent `metadata`, and the API defaults a missing key to an empty list, every
apply that updated a feature, segment or environment was already destroying its
custom field values silently. This change does not introduce that data loss, it
makes it visible in the plan.

Null and empty are kept distinct in state. Writing an empty map where the
configuration had null produces "Provider produced inconsistent result after
apply", and writing null where the configuration had `{}` produces a perpetual
diff.

Name resolution and the metadata endpoints are only touched when there are
values to read or write, so anyone not using custom fields sees no additional
requests, and older self hosted versions without custom field support are
unaffected.

Requires flagsmith-go-api-client v0.13.0. go.mod currently carries a local
replace directive that must be swapped for the released version before this
merges.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
@matthewelwell
matthewelwell marked this pull request as ready for review August 25, 2026 19:28
@matthewelwell
matthewelwell requested a review from a team as a code owner August 25, 2026 19:28
@matthewelwell
matthewelwell requested review from khvn26 and removed request for a team August 25, 2026 19:28
matthewelwell and others added 2 commits August 26, 2026 07:33
Drops the local `replace` directive pointing at ../flagsmith-go-api-client,
which made a clean checkout unresolvable.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Terraform hard wraps diagnostic detail text, so "not enabled for features"
was split across a line break and never matched.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
@matthewelwell
matthewelwell requested review from gagantrivedi and removed request for khvn26 August 26, 2026 07:13
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
@matthewelwell
matthewelwell merged commit 6242f41 into feat/feature-and-segment-data-sources Aug 26, 2026
5 checks passed
@matthewelwell

Copy link
Copy Markdown
Contributor Author

Note for anyone following this: this PR was based on feat/feature-and-segment-data-sources and merged into that branch rather than main, after #244 had already been squash-merged — so this work never reached main. Superseded by #246, which is the same content rebased onto main.

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.

2 participants