Educational RunWhen CodeCollection that discovers Crossplane GCP Bucket CRDs (storage.gcp.upbound.io/v1beta1) and generates one SLX per bucket. Ships only generation rules and Jinja templates; the runtime lives in rw-generic-codecollection/k8s-kubectl-cmd (already loaded by the airgap runner). Includes: - codebundles/gcp-bucket-crossplane-health with generation rule + 3 templates - docs/01..07 numbered training chapters with screenshot placeholders - README, .gitignore Co-authored-by: Cursor <cursoragent@cursor.com>
4.7 KiB
07 — Validate and observe
What you'll do
Confirm end-to-end that:
- The generation rule is schema-valid.
- Workspace-builder clones the private CC from Gitea.
- One SLX is rendered per Crossplane Bucket in the cluster.
- The RunWhen Platform receives the SLXs and the SLI + TaskSet run.
Step 1 — Local schema validation
If you have runwhen-local checked out, you can validate before pushing:
cd /path/to/runwhen-local/src
python3 validate_generation_rules.py /path/to/simple-private-codecollection -v
Expected:
No validation errors found.
Or a one-liner without cloning runwhen-local:
python3 -c "
import json, yaml, jsonschema, urllib.request
schema = json.loads(urllib.request.urlopen(
'https://raw.githubusercontent.com/runwhen-contrib/runwhen-local/main/src/generation-rule-schema.json'
).read())
with open('codebundles/gcp-bucket-crossplane-health/.runwhen/generation-rules/gcp-bucket-crossplane-health.yaml') as f:
jsonschema.validate(yaml.safe_load(f), schema)
print('OK')
"
Screenshot placeholder: images/07-schema-validation.png.
Step 2 — Push to Gitea
git add .
git commit -m "Initial codecollection: Crossplane GCP Bucket rules-only example"
git push -u origin main
Refresh the Gitea repo URL in a browser — you should see the file tree.
Screenshot placeholder: images/07-gitea-repo.png — Gitea file browser
showing codebundles/ and docs/.
Step 3 — Reconcile Flux
flux reconcile hr runwhen-local -n runwhen-env-airgap-runner --with-source
Step 4 — Watch workspace-builder logs
kubectl -n runwhen-env-airgap-runner logs \
-l runwhen.com/component=workspace-builder \
-c workspace-builder --tail=200 -f
Look for lines like:
Cloning from git source: https://.../simple-private-codecollection.gitLoading generation rules from ...gcp-bucket-crossplane-health.yamlRendered N SLXs(where N is the number of Buckets)
Common errors and their meaning:
| Error | Cause |
|---|---|
fatal: Authentication failed on clone |
Token in URL missing, expired, or lacks read scope |
KeyError: 'match_resource' in a template |
Jinja variable typo, or trying to use a variable that isn't populated for the platform |
Validation failed for ... generation rule ... required "outputItems" |
Schema drift — check the JSON schema |
No matches for resource type buckets.storage.gcp.upbound.io/v1beta1 |
The CRD isn't installed on this cluster, or the plural is wrong |
Forbidden ... cannot list buckets.storage.gcp.upbound.io |
Missing RBAC for workspace-builder SA |
Screenshot placeholder: images/07-workspace-builder-logs.png.
Step 5 — Inspect rendered SLXs in the runner filesystem
workspace-builder writes the rendered artifacts to disk before
uploading them. Peek at one:
kubectl -n runwhen-env-airgap-runner exec deploy/runwhen-local \
-c workspace-builder -- \
find /shared/output -type f | grep xp-bkt-hlth | head -5
Then read one:
kubectl -n runwhen-env-airgap-runner exec deploy/runwhen-local \
-c workspace-builder -- \
cat /shared/output/output/slx/<name>/sli.yaml
Confirm the codeBundle.repoUrl points at the internal
rw-generic-codecollection proxy and the KUBECTL_COMMAND includes
the bucket name.
Step 6 — See it in the RunWhen UI
Sign into the RunWhen workspace UI:
https://app.airgap.shared.runwhen.com/map/self
You should see one SLX per Bucket under the shared-cluster hierarchy.
Click into one — the SLI panel should already be graphing a value near
1.0 (assuming buckets are healthy). Trigger the TaskSet from the SLX
detail page and confirm the report includes Command stdout showing
the JSON envelope, and any non-True conditions become issues.
Screenshot placeholders:
images/07-runwhen-map.png— the map view with the new SLXs visible.images/07-sli-graph.png— the SLI panel graphing 1.0.images/07-taskset-report.png— the TaskSet execution report.images/07-issue-detail.png— a rendered issue (deliberately break a Bucket by editing the Crossplane spec to force aSynced=Falsecondition, so we can capture what an unhealthy report looks like).
Iteration checklist
- Iteration 1: end-to-end plumbing works, SLXs are generated, SLI graphs are populated. (You are here.)
- Iteration 2: screenshots captured and inlined in these chapters.
- Iteration 3: prose polish,
.test/harness for localrunwhen-localcontainer validation, migration to Option A (cc-catalog proxy) for production hygiene.
Where to file feedback
If something in these docs is confusing or wrong, edit the markdown directly and push. This is a living training guide — improvements are expected.