Skip to content

feat: nullplatform_artifact + nullplatform_package resources and data sources#129

Open
sebasnallar wants to merge 4 commits into
mainfrom
feat/packages-artifacts-resources
Open

feat: nullplatform_artifact + nullplatform_package resources and data sources#129
sebasnallar wants to merge 4 commits into
mainfrom
feat/packages-artifacts-resources

Conversation

@sebasnallar

@sebasnallar sebasnallar commented Jun 10, 2026

Copy link
Copy Markdown
Contributor

What

First-class Terraform support for the packages feature (nullplatform/main-service-api#286, #288).

Resources

  • nullplatform_artifact — registers a platform artifact revision via the idempotent POST /artifacts upsert. meta is a JSON object whose per-type stable subset identifies the artifact (git_repository: url; oci_image: registry+repository) and whose remaining fields pin the revision (reference, digest, …). The resource id is the revision id with artifact_id computed — both ready to wire into a package BOM. visible_to is updatable (re-register is the API's write path); everything else ForceNew. Artifacts are immutable content-addressed records the API never deletes, so destroy only forgets state.
resource "nullplatform_artifact" "scopes_source" {
  nrn  = "organization=1255165411:account=95118862"
  type = "git_repository"
  meta = jsonencode({
    url       = "https://github.com/nullplatform/scopes.git"
    reference = "1.10.0"
  })
}
  • nullplatform_package — publishes a package revision through the slug-keyed PUT /packages. Bump version together with components changes to publish; default = true promotes each publish to the package default. Envelope-only changes (name) PATCH. Computed: default/latest revision ids + versions and published_revision_id.

Data sources

  • data.nullplatform_artifact — read-only lookup by (nrn, type, meta): identity fields select the artifact, per-revision fields (e.g. reference) select the exact revision, identity-only resolves the latest. Never registers anything (uses the new GET /artifacts/:id/revisions).
  • data.nullplatform_package — lookup by (nrn, slug[, version]) → revision ids ready for service binding / composition pins.

Housekeeping

  • TestProvider_HasChild* expectations updated — the data-source list had already drifted from the registered map (asserting 6 of 10) before this change.
  • Examples added under examples/ for tfplugindocs generation.

Depends on

  • nullplatform/main-service-api#288 (visible_to + GET /artifacts/:id/revisions) for the data-source revision resolution and visibility fields. Resources work against current production minus visible_to.

Update: package release tags

nullplatform_package gains an optional tags map (name => published version), layered over default/latest via the new package_tags API (nullplatform/main-service-api#294):

resource "nullplatform_package" "app" {
  # ...
  tags = {
    beta       = "1.3.0"
    production = "1.2.0"
  }
}

Terraform manages exactly the declared tags — create/move points each name at its version, dropping a key deletes the tag. Read reflects the package's user tags (system default/latest excluded). Reserved names are rejected server-side. Adds SetPackageTag / DeletePackageTag client methods + NullOps entries.

… sources

New resources:
- nullplatform_artifact — registers a platform artifact revision via the
  idempotent POST /artifacts upsert. `meta` is a JSON object whose
  per-type stable subset identifies the artifact (git_repository: url;
  oci_image: registry+repository) and whose remaining fields pin the
  revision (reference, digest, ...). The resource id is the revision id,
  with artifact_id computed — both ready to wire into a package BOM.
  visible_to is updatable (re-register is the API's write path);
  everything else ForceNew. Artifacts are immutable content-addressed
  records the API never deletes, so destroy only forgets state.
- nullplatform_package — publishes a package revision through the
  slug-keyed PUT /packages. version + components describe the published
  BOM; `default = true` promotes each publish to the package default.
  Envelope-only changes (name) PATCH; version/components/visible_to
  changes publish. Computed: default/latest revision ids + versions and
  published_revision_id (the revision minted for the configured version).

New data sources:
- nullplatform_artifact — read-only lookup by (nrn, type, meta): identity
  fields select the artifact, per-revision fields (e.g. reference) select
  the exact revision, identity-only resolves the latest. Never registers.
- nullplatform_package — lookup by (nrn, slug), optionally resolving an
  exact published version; revision_id otherwise follows the package
  default. Exposes visibility + revision pointers.

Also updates TestProvider_HasChild* expectations, which had drifted from
the registered maps (data sources were asserting 6 of 10 even before
this change), and adds examples for docs generation.
…an exact published version

Besides `default = true` (promote whatever this resource publishes),
the package default can now be pinned declaratively:

  version         = "1.1.0"   # what this apply publishes
  default_version = "1.0.0"   # what consumers bind to

The provider resolves the version through GET /packages/:id/revisions
and PATCHes default_revision_id after each apply (idempotent; the API
validates the revision belongs to the package). Optional+Computed so
the attribute reflects server state when unset, with GetRawConfig used
to distinguish a configured pin from the computed value. Mutually
exclusive with `default` via ConflictsWith — promoting each publish
and pinning a fixed version are contradictory intents.

Covers staged rollouts (publish 1.1.0 while consumers stay on 1.0.0)
and rollbacks (point default_version back and apply).
Adds an optional tags map (name => published version) to the package
resource, layered over default/latest via the new package_tags API:

  resource "nullplatform_package" "app" {
    # ...
    tags = {
      beta       = "1.3.0"
      production = "1.2.0"
    }
  }

Terraform manages exactly the declared tags: create/move points each
name at its version, dropping a key deletes the tag. Read reflects the
package's user tags (system default/latest excluded). Adds SetPackageTag
/ DeletePackageTag client methods + NullOps interface entries. Reserved
names (default, latest) are rejected server-side.
…ts-resources

# Conflicts:
#	nullplatform/provider_test.go
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.

1 participant