Contributing Guidelines
How to submit a high-quality challenge to the Kubeasy challenges repository.
Thank you for contributing to Kubeasy! This guide explains the process and standards for submitting challenges.
Before you start
Browse existing challenges
Check the challenges repository to:
- Avoid duplicating existing challenges
- Understand the current challenge structure and quality bar
- Get inspiration from well-designed examples
Propose your idea first
Open a GitHub Issue before investing time building a challenge. Use the "Challenge Proposal" template at kubeasy-dev/challenges/issues and describe:
- What Kubernetes concept it teaches
- The challenge type (fix, build, or migrate)
- The broken/initial scenario
- Why it's a valuable learning experience
- Estimated difficulty and time
This avoids duplicate work and ensures your idea aligns with Kubeasy's goals.
Contribution process
1. Fork and clone
# Fork the repository on GitHub, then:
git clone https://github.com/<your-username>/challenges.git
cd challenges2. Create a branch
git checkout -b challenge/<challenge-slug>Use the challenge slug as the branch name (e.g., challenge/rbac-service-account, challenge/network-policy-egress).
3. Build the challenge
Follow Challenge Structure and Creating Your First Challenge.
Your folder must contain:
<challenge-slug>/
├── challenge.yaml
├── manifests/
│ └── ...
├── policies/
│ └── protect.yaml
└── image/ # optional
└── Dockerfile4. Test thoroughly
See Testing Challenges for the full testing workflow.
Minimum requirements before submitting:
-
kubeasy dev lintpasses - Broken state is reproducible
- All validations fail before the fix
- All validations pass after applying the fix
- Kyverno policies prevent bypasses
- Multiple valid solutions are accepted (where applicable)
- Estimated time is accurate
5. Commit and push
git add <challenge-slug>/
git commit -m "feat: add <challenge-slug> challenge"
git push origin challenge/<challenge-slug>6. Open a pull request
Use this template for your PR description:
## Challenge: <Challenge Title>
### What does this challenge teach?
Brief explanation of the Kubernetes concept and why it matters.
### Challenge type
fix | build | migrate
### Difficulty and estimated time
- Difficulty: easy | medium | hard
- Estimated time: X minutes
### Theme
resources-scaling | networking | rbac-security | volumes-secrets | monitoring-debugging
### Testing
- [x] Tested on fresh Kind cluster (`kubeasy dev test --clean`)
- [x] Broken state is reproducible
- [x] All validations fail before fix
- [x] All validations pass after fix
- [x] Kyverno policies prevent bypasses
- [x] Multiple valid solutions accepted
- [x] Objective titles don't reveal the solution
- [x] Estimated time is accurateQuality standards
Design principles
One clear concept per challenge
A good challenge teaches one specific thing. If you find yourself adding RBAC and networking and storage issues, split them into separate challenges.
Realistic scenarios
Challenges should mirror real production incidents, not artificial puzzles.
GOOD: "A deployment fails because the ServiceAccount lacks permissions to read ConfigMaps"
BAD: "Find the 3 typos in these YAML files"Appropriate difficulty
| Difficulty | Description |
|---|---|
easy | Single issue, clear error messages, common scenarios |
medium | Multiple related issues, requires systematic debugging |
hard | Complex interactions, subtle issues, production-level |
Mystery-preserving descriptions
Descriptions show symptoms, not causes. Objective titles check outcomes, not implementations.
Code quality
Manifests
- Use stable, widely-available images (nginx, python, busybox, etc.)
- Comment intentional bugs for your own reference (comments won't be seen by users in the repo, but help reviewers)
- Keep resource usage minimal — challenges run on a shared local cluster
- Avoid external dependencies (no calls to external APIs or services)
Objectives
Every objective should:
- Have a generic title that doesn't reveal the solution
- Validate an outcome, not a specific implementation
- Accept all valid solutions, not just the one you designed for
# GOOD: generic title, outcome-based
- key: stable-operation
title: "Stable Operation"
description: "The pod runs without being killed"
type: event
spec:
target:
kind: Pod
labelSelector:
app: my-app
forbiddenReasons:
- "OOMKilled"
# BAD: reveals solution, checks implementation
- key: memory-check
title: "Memory Limit Set to 256Mi"
description: "Increase the memory limit"
type: spec
spec:
target:
kind: Deployment
name: my-app
checks:
- path: "spec.template.spec.containers[0].resources.limits.memory"
value: "256Mi"Bypass protection
Every challenge must include Kyverno policies to prevent at minimum:
- Swapping the container image for a working one
- Deleting and recreating the resource to bypass its broken configuration
apiVersion: kyverno.io/v1
kind: Policy
metadata:
name: protect-<challenge-slug>
namespace: <challenge-slug> # matches the challenge namespace (same as the slug)
spec:
validationFailureAction: Enforce
rules:
- name: preserve-image
match:
resources:
kinds: ["Deployment"]
names: ["<deployment-name>"]
validate:
message: "Cannot change the container image"
pattern:
spec:
template:
spec:
containers:
- image: "<original-image>"Review process
Reviewers look for:
- Correctness — does the broken state deploy reliably? Do all objectives pass after applying the fix?
- Educational value — is the concept clearly taught? Is it appropriate for the stated difficulty?
- Quality — are manifests minimal and clean? Do objective titles avoid revealing solutions?
- Testing — has it been tested end-to-end on a fresh cluster?
Addressing feedback
# Make requested changes, then:
git add .
git commit -m "fix: address review feedback for <challenge-slug>"
git push origin challenge/<challenge-slug>Respond to review comments in the PR — the updated diff will be reviewed automatically.
After merge
Once your challenge is merged to main, CI automatically:
- Packages it as an OCI artifact
- Publishes it to
ghcr.io/kubeasy-dev/challenges/<slug>:latest - Makes it available via
kubeasy challenge start <slug>
If your challenge has an image/ directory, the custom Docker image is also built and published.
Get help
- GitHub Discussions: kubeasy-dev/challenges/discussions
- GitHub Issues: kubeasy-dev/challenges/issues