xpkg build: GoTemplate function input kind field buried after large block scalar due to JSON key reordering
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:
- Source YAML is parsed → stored as `*v1.Composition` with `Input.Raw` = JSON bytes
- `sigs.k8s.io/yaml.YAMLToJSON()` converts the YAML map to JSON with alphabetically sorted keys
- Original YAML field order: `apiVersion → kind → source → inline`
- 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
- Create a Composition with a `function-go-templating` step whose `inline.template` is >100 lines
- Run `crossplane xpkg build`
- Extract `package.yaml` from the built `.xpkg`:
tar xf package.xpkg tar xzf <layer>.tar.gz - Search for `kind: GoTemplate` — it is present but appears after the entire template block, not next to `apiVersion:`
- 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
First steps
- Read the whole issue, then the project's contributing guide.
- Comment on the issue to say you are picking it up — it saves two people doing the same work.
- Fork the repository and make your change on a branch.
- Open a pull request that references the issue number.
More from crossplane/cli
-
bug
Difficulty 2/5 1-3 hours Newbie friendliness 84/100
crossplane/cli#282 ·
-
Difficulty 4/5 3-5 days Newbie friendliness 52/100
crossplane/cli#384 ·
-
crossplane/cli#379 · 1 assignee ·
-
bug
Difficulty 4/5 3-5 days Newbie friendliness 68/100
crossplane/cli#370 · 1 reaction ·
-
enhancement
Difficulty 5/5 Over a week Newbie friendliness 28/100
crossplane/cli#369 ·
Similar issues
-
agentic-workflows
Difficulty 2/5 1-3 hours Newbie friendliness 76/100
-
agentic-workflows
Difficulty 2/5 1-3 hours Newbie friendliness 70/100
microsoft/agent-framework-go#1179 ·
-
bug
Difficulty 2/5 1-3 hours Newbie friendliness 76/100
-
[Bug]: OLLAMA_KEEP_ALIVE="5m" / "24h" crashes Ollama embedding and vision models with ValueError Open
Difficulty 2/5 1-3 hours Newbie friendliness 75/100
infiniflow/ragflow#20223 · 1 reaction ·
-
bug needs triage pkg/translator/faro
Difficulty 2/5 1-3 hours Newbie friendliness 88/100
open-telemetry/opentelemetry-collector-contrib#51484 · 1 comment ·