Provider compatibility

Dealing with provider shenanigans.

Heckle pins exact provider versions. Provider defaults, import behaviour and API semantics can differ even when the forge itself has not changed, so provider upgrades should be planned carefully.

Audited provider pins

ForgeProviderAudited version
GitHubintegrations/github6.13.0
GitLabgitlabhq/gitlab19.3.0
Giteago-gitea/gitea0.8.1
Forgejosvalabs/forgejo1.6.0
heckle compatibility
heckle compatibility github
heckle compatibility --json

Compatibility policy

Heckle does not resolve provider latest at runtime. A provider version is considered supported only after its import IDs, schema and relevant read/update behaviour have been reviewed for the resources Heckle manages.

--provider-version can override a pin for investigation, but an unaudited version also requires --allow-untested-provider. That opt-in means Heckle's compatibility knowledge may be incomplete.

Why pin so tightly? A provider can change defaults, import IDs, computed/optional semantics or update payloads without the forge API changing. Heckle treats those changes as compatibility work, not ordinary dependency updates.

What “known provider behaviour” means

Heckle records narrow, version-specific provider behaviours when it has evidence that a plan difference is associated with a particular parent-feature condition or provider limitation. Recognition is descriptive only. It is not a guarantee that applying the plan is safe or appropriate.

Create, delete and replacement actions are never accepted by a known-behaviour rule. Unrecognised updates remain adoption failures.

GitHub — integrations/github 6.13.0

Organization repository-creation settings are deliberately unmanaged

The provider can update GitHub's coupled repository-creation booleans independently even though GitHub treats them as a related set. Heckle therefore leaves these fields unmanaged:

  • members_can_create_repositories
  • members_can_create_public_repositories
  • members_can_create_private_repositories
  • members_can_create_internal_repositories

Upstream: terraform-provider-github #3429.

Explicit empty Actions pattern lists are not enforced

An explicit empty allowed_actions_config.patterns_allowed list is not reliably sent by this provider version. Heckle does not try to enforce an empty list.

Upstream: terraform-provider-github #3458.

GitLab — gitlabhq/gitlab 19.3.0

Heckle has reviewed every GitLab resource family it currently manages against provider 19.3.0: groups and projects, memberships, branch/tag protections, hooks, deploy keys, environments, approval rules, labels and badges. The exact field-level rules are available with heckle compatibility gitlab --json.

Unset API values are not always valid configuration values

Several optional GitLab values can be returned by the API/provider as an empty string even though provider 19.3.0 validates the configured form against an enum or date format. Heckle treats only those empty values as unset and preserves valid configured values. This covers project/group enum settings, membership expiry dates, deploy-key expiry, branch-protection legacy access levels, hook branch-filter strategy, environment settings, approval-rule report type and container-expiration cadence.

Create, import and destroy controls are not remote state

Heckle leaves out controls whose meaning belongs to resource creation, import or destruction rather than the existing GitLab object. Examples include project import/template/bootstrap options, destructive lifecycle switches, group membership destroy controls, environment stop_before_destroy, project/group avatar inputs that cannot be reconstructed, and the deprecated project public_builds alias.

Coupled and mutually-exclusive fields

Provider 19.3.0 has several schema relationships that imported state can otherwise violate. Heckle normalizes these before rendering:

  • Fork-only project settings are omitted unless their required fork relationship can be represented.
  • Environment Kubernetes/Flux child settings are omitted when their required parent values are absent.
  • An all_branches webhook does not retain an explicit branch filter.
  • Approval-rule type/report and protected-branch settings are kept in provider-valid combinations; imported forms provider 19.3.0 cannot recreate are inventory-only.
  • Each protected-tag ACL entry uses either an access level or an explicit user/group/deploy-key identity, not both.

Known provider limitations kept out of managed HCL

Group push_rules remain unmanaged for this provider pin because the provider has a known round-trip problem with false, zero and empty values (provider issue #6832). Webhook secrets and import-unavailable custom header/URL-variable values are also not reconstructed. Changing or removing a custom membership role is affected by provider issue #6619, so Heckle surfaces that limitation rather than pretending it can safely normalize the update.

Branch and tag protection takeover

GitLab's provider documentation warns that taking management of existing branch/tag protection can involve unprotecting and re-protecting the target. Heckle therefore adopts existing protection through state and relies on the final plan rather than deliberately recreating it.

Dependent merge settings

Heckle can recognise specific subordinate plan differences only while their controlling feature remains disabled before and after the proposed update:

  • allow_merge_on_skipped_pipeline when only_allow_merge_if_pipeline_succeeds = false.
  • merge_trains_enabled and merge_trains_skip_train_allowed when merge_pipelines_enabled = false.

Recognition describes known provider behaviour; it does not decide whether you should apply the plan.

Gitea — go-gitea/gitea 0.8.1

Organization discovery requires read:admin

Hydrating an imported gitea_org uses a provider/API path that requires the token's read:admin scope. Organization and repository write scopes alone are not sufficient. If that scope is missing, Heckle stops during provider hydration rather than publishing an incomplete project.

Manual-merge repository settings are deliberately unmanaged

Provider 0.8.1 does not populate allow_manual_merge or autodetect_manual_merge reliably when reading an imported repository. Its schema defaults can consequently appear as proposed live updates even though Heckle did not discover a corresponding change.

Heckle leaves those two attributes unmanaged for this exact provider version. Other readable repository and pull-request settings remain managed.

Team definitions are inventory-only

Imported Gitea teams cannot be updated safely through provider 0.8.1. Modern granular teams are returned by Gitea with permission = "none" and their actual access levels in units_map, but the provider can lose that map and stringify units with unstable ordering. A later update can then fail with permission mode invalid, even when the intended change is unrelated, such as a description update. Owner teams exhibit the same unreliable import representation.

Heckle therefore records team definitions, unit permissions and team repository grants in inventory and coverage reporting, but does not emit managed gitea_team resources. This is a fail-closed provider limitation, not a claim that those settings are unimportant.

Team membership remains manageable

When discovery reads a team's complete member list, Heckle can still emit the authoritative gitea_team_members resource using the existing team's numeric ID. If member discovery is incomplete or permission-denied, Heckle does not emit that authoritative resource. Review any planned membership removals particularly carefully.

Upstream references: repository resource implementation and team resource implementation.

Forgejo — svalabs/forgejo 1.6.0

Pull-request settings when pull requests are disabled

This provider can round-trip subordinate merge settings to provider defaults while has_pull_requests = false. Heckle recognises the affected attributes only while that parent flag remains false before and after the proposed update.

The affected family includes merge/rebase/squash options, default merge/update styles, whitespace-conflict handling and related pull-request defaults.

Always check the plan. These differences may be reasonable to reconcile because the parent feature is disabled, but Heckle cannot decide whether that is appropriate in your environment. Review the actual plan.

Other disabled-feature relationships

  • Issue-tracker subordinate settings when has_issues = false.
  • Wiki subordinate settings when has_wiki = false.
  • Mirror subordinate settings when mirror = false.

Repository creation/migration fields

Heckle does not copy repository creation/migration options such as migration service/clone controls into ongoing configuration for an already-existing repository. Mirror settings the provider cannot faithfully reconstruct are also left out.

Organizations

Forgejo organizations are inventory-only in this adapter because the selected provider's organization resource does not provide the import contract Heckle needs for adoption.

How and when we adopt a new provider version as the default in Heckle

As part of developing Heckle, we:

  1. Read release notes and import/state-related upstream issues since the audited version.
  2. Compare provider schemas, especially Optional/Computed/default/ForceNew changes.
  3. Run the complete Heckle suite and provider-specific fixtures.
  4. Rehearse discovery/adoption against a disposable namespace.
  5. Review every compatibility entry: keep it, update its version scope, or remove it only when the upstream behaviour is demonstrated fixed.
  6. Update both the provider pin and Heckle's separate audited-version allowlist.

The release pin is the maintenance boundary. A new upstream provider release does not change an existing Heckle release until we deliberately adopt it into Heckle.