Hacktoberfest 2026: the issues maintainers tagged for October, open and beginner-friendly. Browse Hacktoberfest issues

xpkg build: GoTemplate function input kind field buried after large block scalar due to JSON key reordering

Open
#344 0 comments 0 reactions 0 assignees View on GitHub

Nobody has claimed this yet.

Assessment

Difficulty
4/5
Estimated time
3-5 days
Newbie friendliness
55/100
Issue type
Bug
Clarity
Mostly clear
Activity status
Active
Tech stack
go
Domain
build-system, cli

Research direction

Start in crossplane-runtime/pkg/xpkg/build.go at encode() and trace how embedded RawExtension.Raw JSON is serialized through YAMLToJSON(). Reproduce the issue with xpkg build and inspect package.yaml, then verify that apiVersion and kind appear together before the large inline.template block and that the built package installs successfully.

Written by the indexing model from the issue text.

Description

Describe the bug

`crossplane xpkg build` reorders fields in embedded `RawExtension` objects alphabetically (via `sigs.k8s.io/yaml.YAMLToJSON()`) during YAML serialization. For a `function-go-templating` pipeline step input, this buries `kind: GoTemplate` after the entire `inline.template` block scalar — which can be hundreds or thousands of lines long.

Some YAML parsers and the Crossplane package reader fail to correctly handle a `kind` field that appears after a very large literal block scalar, causing installed ConfigurationRevisions to fail with:

spec.pipeline[N].input.kind: Required value

This became visible with Crossplane v2.2.0, which added strict validation requiring `kind` in all pipeline step inputs. See crossplane/crossplane#7819.

Root cause

The `encode()` function in `crossplane-runtime/pkg/xpkg/build.go` re-serializes all package objects through the Kubernetes JSON serializer:

  1. Source YAML is parsed → stored as `*v1.Composition` with `Input.Raw` = JSON bytes
  2. `sigs.k8s.io/yaml.YAMLToJSON()` converts the YAML map to JSON with alphabetically sorted keys
  3. Original YAML field order: `apiVersion → kind → source → inline`
  4. JSON (and final YAML) field order: `apiVersion → inline → kind → source`

Result in `package.yaml`:

```yaml
input:
apiVersion: gotemplating.fn.crossplane.io/v1beta1
inline:
template: |
{{- ... hundreds of lines of go template ... }}
kind: GoTemplate # ← buried after the block scalar
source: Inline
```

Steps to reproduce

  1. Create a Composition with a `function-go-templating` step whose `inline.template` is >100 lines
  2. Run `crossplane xpkg build`
  3. Extract `package.yaml` from the built `.xpkg`:
    tar xf package.xpkg
    tar xzf <layer>.tar.gz
    
  4. Search for `kind: GoTemplate` — it is present but appears after the entire template block, not next to `apiVersion:`
  5. Install the package on a Crossplane v2.2.0+ cluster → ConfigurationRevision fails

Expected behaviour

`kind: GoTemplate` appears adjacent to `apiVersion: gotemplating.fn.crossplane.io/v1beta1` in the serialized `package.yaml`, matching the source file and ensuring reliable parsing.

Suggested fix

In `crossplane-runtime/pkg/xpkg/build.go`, modify `encode()` to re-order keys in `RawExtension.Raw` JSON so that TypeMeta fields (`apiVersion`, `kind`) appear first before emitting. Concretely: after marshaling each object to JSON, walk any embedded `RawExtension` fields and produce a new JSON object with `apiVersion`/`kind` promoted to the front.

An alternative is to add a normalization pass in the `xpkg build` command (`cmd/crossplane/xpkg/build.go`) after `c.builder.Build()` — extract `package.yaml` from the built image, re-insert `kind`/`apiVersion` immediately after each other in embedded resource blocks, and rebuild the layer.

Workaround

Post-process the built `.xpkg` to insert `kind: GoTemplate` immediately after each `apiVersion: gotemplating.fn.crossplane.io/v1beta1` line. This is what the affected package repo currently does as a stop-gap.

Related

  • crossplane/crossplane#7819 — Crossplane v2.2.0 added the `kind` validation requirement that surfaces this bug
Dominant language
Go
Stars
19
Forks
31
Avg merge
2d 15h
Merged PRs (30d)
53

Contributor guide

Open the contributing guide

First steps

  1. Read the whole issue, then the project's contributing guide.
  2. Comment on the issue to say you are picking it up — it saves two people doing the same work.
  3. Fork the repository and make your change on a branch.
  4. Open a pull request that references the issue number.

More from crossplane/cli

All issues in crossplane/cli

Similar issues

More Go issues

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.