Skip to content

Plugin version sourced from build-time ldflags + registry-side semver validation (architecture) #758

@intel352

Description

@intel352

Context

Today every plugin repo carries a duplicated `plugin.json.version` field that must be kept in sync with the git tag. The `sync-plugin-version.yml` workflow opens a PR after each tag to bump the field, but those PRs accumulate (13 stale in `workflow-plugin-digitalocean` alone before sweep 2026-05-23). The whole class of drift is preventable by not committing the version at all.

Proposed direction

Adopt an architecture where:

  1. Plugin binary version comes from build-time `-ldflags` at release time. The `version` field is removed from committed `plugin.json`. Plugin contract requires every plugin binary expose its version via a standard symbol (e.g. `pluginsdk.Version()` backed by an `-X` linker var).
  2. Registry-side validation rejects publish of any plugin whose version string does not match strict semver (`vN.N.N` or `vN.N.N-prerelease`). Branch-tagged or dirty builds (e.g. `v0.1.0-feat-foo.dirty`) are allowed locally and in test installs but rejected from public registry publish.
  3. wfctl grows a publish-gate validation (e.g. `wfctl plugin validate --for-publish`) that performs the same semver check before push to the registry. Local installs / test branches do not trigger the gate.
  4. All plugin repos audited to adopt the new approach: drop `plugin.json.version`, ensure goreleaser `-ldflags -X` is wired, ensure plugin binary surfaces version via the contract symbol.
  5. `sync-plugin-version.yml` workflow removed from every repo where it currently exists.

Affected surfaces

  • workflow (this repo): wfctl validation + plugin contract symbol definition
  • workflow-registry: publish-time semver gate
  • workflow-plugin-{admin, agent, auth, authz, authz-ui, aws, azure, bento, ci-generator, cloud-ui, compute, cms, data-protection, digitalocean, edge-compute, edge-risk, gcp, github, payments, sandbox, security, supply-chain, tofu, waf, ...}: audit + drop committed version + verify ldflags wiring
  • Any plugin repo running `sync-plugin-version.yml`: workflow removal

Why now

Surfaced 2026-05-23 by user when 13 stale sync-PRs piled up in workflow-plugin-digitalocean. Closing those was a sweep; this issue eliminates the root cause.

Acceptance criteria

  • Plugin contract documents the version-symbol requirement
  • wfctl `plugin validate --for-publish` rejects non-semver versions
  • workflow-registry rejects non-semver publishes
  • All public plugins migrated; `plugin.json.version` removed; goreleaser ldflags verified
  • All private plugins migrated
  • `sync-plugin-version.yml` removed from every plugin repo
  • One full release cycle on one plugin proves end-to-end (tag → ldflags-baked version → install → contract surface)

Out of scope here

Refer to workflow-plugin-digitalocean#159 for unrelated true-blue/green deploy work.

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type
    No fields configured for issues without a type.

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions