Solution
Reference solution for the Compose a Sandcastle request lab.
Reference solution
A working solution consists of:
- The lab’s shipped
xr-request.yamlused as input. - An emitted
work/compose-sandcastle-request/task/engineering-task.yamlwhose fields matchexpected-task.yamlonkind,metadata.name,spec.requestedBy.{apiVersion,kind,name},spec.artifact.kind,spec.inputs.greeting, andspec.target.branch. - A durable branch (
sandcastle/hello-world-pico-greetings-de) on the local target repo atwork/compose-sandcastle-request/target-repo, containing exactly one committed file (rules/hello.yaml). - A
results/pico-output.txtcapturingHallo, Pico!printed by the recomposed Pico artifact. - A disposed sandbox (
work/compose-sandcastle-request/sandbox/no longer exists).
engineering-task.yaml (compose-side output)
kind: EngineeringTask
metadata:
name: greetings-de
spec:
requestedBy:
apiVersion: oe.academy/v1alpha1
kind: XHelloWorldPico
name: greetings-de
artifact:
kind: hello-world-pico
producesFiles:
- rules/hello.yaml
inputs:
greeting: "Hallo, Pico!"
target:
repo: file://./work/compose-sandcastle-request/target-repo
branch: sandcastle/hello-world-pico-greetings-de
workspace:
sandboxProvider: local-scratch-dir
tools: [pico, git, python3]
permissions:
- git.read:file:./target-repo
- git.write:branch:sandcastle/hello-world-pico-greetings-de
- fs.write:workspace-only
artifactBoundary:
survives: [branch]
disposed: [workspace, tools, scratch_state]rules/hello.yaml (on sandcastle/hello-world-pico-greetings-de)
id: rule.hello
kind: greeting
value: "Hallo, Pico!"Commands
Run from the root of your local clone of the academy repository, with the one-time setup applied so pico resolves to this repository’s bin/pico:
bash labs/compose-sandcastle-request/downloads/compose.sh \
labs/compose-sandcastle-request/downloads/xr-request.yaml \
work/compose-sandcastle-request
bash labs/compose-sandcastle-request/downloads/sandcastle-run.sh \
work/compose-sandcastle-request/task/engineering-task.yaml \
work/compose-sandcastle-request
bash labs/compose-sandcastle-request/downloads/verify.shExpected verify.sh output (final line)
verify: OK — branch=sandcastle/hello-world-pico-greetings-de commit=<sha> greeting=Hallo\,\ Pico\! task=…/engineering-task.yaml sandbox=disposed
<sha> is the commit hash of the single agent commit on the branch.
Why this satisfies the objectives
- Compose → construct boundary preserved:
compose.shonly reads the XR and writes YAML; it neither touches the repo nor generates a Pico rule. The Sandcastle only reads the EngineeringTask; the XR is never copied into the sandbox. - Parametric construction: the greeting comes from
spec.inputs.greetingin the task, which came fromspec.valuein the XR. Changespec.valuein the XR and both the task and the branch’s rule change with no other edits. - Artifact boundary intact (from Sandcastle · Part 1 · Lesson 1): only
rules/hello.yamlwasgit added and committed; the.engineering-task.yaml, the sandbox’sbuild/, itsbin-allowlist/, and everything else were disposed with the workspace. - Provenance retained:
spec.requestedByin the task lets a reviewer trace the branch back to the exact XR that requested it, without the Sandcastle needing to reason about the XR shape.
Verification
You can verify the solution matches this reference by:
- Running
bash labs/compose-sandcastle-request/downloads/verify.shand checking the finalverify: OKline and exit status0. - Diffing the emitted task against the reference:
diff -u labs/compose-sandcastle-request/downloads/expected-task.yaml work/compose-sandcastle-request/task/engineering-task.yaml. Comments and the provenance header line will differ; the fields above should match. - Confirming
test ! -d work/compose-sandcastle-request/sandbox. - Confirming
grep -Fqx 'Hallo, Pico!' work/compose-sandcastle-request/results/pico-output.txt.
Variations
- Different greeting: change
spec.valueinxr-request.yamland re-run the three commands above. UpdateEXPECTED_VALUEinverify.shinvocations only if you also change the referenceexpected-task.yaml. - Different request name: change
metadata.namein the XR. The target branch becomessandcastle/hello-world-pico-<new-name>automatically. Updateexpected-task.yamlto match if you want assertion 1 to keep passing. - Wire into the Kubernetes lab: the branch this lab produces has the same
rules/hello.yamlshape as the Hello World Pico Sandcastle lab. SetBRANCH=sandcastle/hello-world-pico-greetings-deandSANDCASTLE_WORK=work/compose-sandcastle-requestwhen callinglabs/handoff-sandcastle-to-kubernetes/downloads/handoff.shto promote the greeting into anXHelloWorldPicoXR for the Hello Pico on Kubernetes lab.
Not covered by this lab (intentional)
- A container-backed sandbox provider — this lab uses
local-scratch-dirfor the same reasons the Hello World Pico Sandcastle lab does. Only theworkspace.sandboxProviderfield in the emitted EngineeringTask needs to change when a container-backed provider lands. - A real Crossplane cluster running a real Composition emitting a real EngineeringTask CR — that is scoped to a later Part 2 lesson.
compose.shis deliberately a local simulation of the Composition step so the boundary can be studied end-to-end without a cluster. - Multi-artifact requests — one XR could ask for more than one file, or for multiple related artifacts. Multi-artifact requests are a natural extension but are out of scope for the first runnable compose → construct lab.