Skip to content

Commit 1b5dcda

Browse files
committed
Reorganize contributing section and document community roles correctly
On-behalf-of: SAP <[email protected]> Signed-off-by: Marvin Beckers <[email protected]>
1 parent a22933b commit 1b5dcda

File tree

13 files changed

+238
-216
lines changed

13 files changed

+238
-216
lines changed
Lines changed: 89 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,89 @@
1+
---
2+
description: >
3+
Coding guidelines for kcp projects.
4+
---
5+
6+
# Coding Guidelines & Conventions
7+
8+
- Always be clear about what clients or client configs target. Never use an unqualified `client`. Instead, always qualify. For example:
9+
- `rootClient`
10+
- `orgClient`
11+
- `pclusterClient`
12+
- `rootKcpClient`
13+
- `orgKubeClient`
14+
- Configs intended for `NewForConfig` (i.e. today often called "admin workspace config") should uniformly be called `clusterConfig`
15+
- Note: with org workspaces, `kcp` will no longer default clients to the "root" ("admin") logical cluster
16+
- Note 2: sometimes we use clients for same purpose, but this can be harder to read
17+
- Cluster-aware clients should follow similar naming conventions:
18+
- `crdClusterClient`
19+
- `kcpClusterClient`
20+
- `kubeClusterClient`
21+
- `clusterName` is a kcp term. It is **NOT** a name of a physical cluster. If we mean the latter, use `pclusterName` or similar.
22+
- Qualify "namespace"s in code that handle up- and downstream, e.g. `upstreamNamespace`, `downstreamNamespace`, and also `upstreamObj`, `downstreamObj`.
23+
- Logging:
24+
- Use the `fmt.Sprintf("%s|%s/%s", clusterName, namespace, name` syntax.
25+
- Default log-level is 2.
26+
- Controllers should generally log (a) **one** line (not more) non-error progress per item with `klog.V(2)` (b) actions like create/update/delete via `klog.V(3)` and (c) skipped actions, i.e. what was not done for reasons via `klog.V(4)`.
27+
- When orgs land: `clusterName` or `fooClusterName` is always the fully qualified value that you can stick into obj.ObjectMeta.ClusterName. It's not necessarily the `(Cluster)Workspace.Name` from the object. For the latter, use `workspaceName` or `orgName`.
28+
- Generally do `klog.Errorf` or `return err`, but not both together. If you need to make it clear where an error came from, you can wrap it.
29+
- New features start under a feature-gate (`--feature-gate GateName=true`). (At some point in the future), new feature-gates are off by default *at least* until the APIs are promoted to beta (we are not there before we have reached MVP).
30+
- Feature-gated code can be incomplete. Also their e2e coverage can be incomplete. **We do not compromise on unit tests**. Every feature-gated code needs full unit tests as every other code-path.
31+
- Go Proverbs are good guidelines for style: https://go-proverbs.github.io/ – watch https://www.youtube.com/watch?v=PAAkCSZUG1c.
32+
- We use Testify's [require](https://pkg.go.dev/github.com/stretchr/testify/require) a
33+
lot in tests, and avoid
34+
[assert](https://pkg.go.dev/github.com/stretchr/testify/assert).
35+
36+
Note this subtle distinction of nested `require` statements:
37+
```Golang
38+
require.Eventually(t, func() bool {
39+
foos, err := client.List(...)
40+
require.NoError(err) // fail fast, including failing require.Eventually immediately
41+
return someCondition(foos)
42+
}, ...)
43+
```
44+
and
45+
```Golang
46+
require.Eventually(t, func() bool {
47+
foos, err := client.List(...)
48+
if err != nil {
49+
return false // keep trying
50+
}
51+
return someCondition(foos)
52+
}, ...)
53+
```
54+
The first fails fast on every client error. The second ignores client errors and keeps trying. Either
55+
has its place, depending on whether the client error is to be expected (e.g. because of asynchronicity making the resource available),
56+
or signals a real test problem.
57+
58+
### Using Kubebuilder CRD Validation Annotations
59+
60+
All of the built-in types for `kcp` are `CustomResourceDefinitions`, and we generate YAML spec for them from our Go types using [kubebuilder](https://github.com/kubernetes-sigs/kubebuilder).
61+
62+
When adding a field that requires validation, custom annotations are used to translate this logic into the generated OpenAPI spec. [This doc](https://book.kubebuilder.io/reference/markers/crd-validation.html) gives an overview of possible validations. These annotations map directly to concepts in the [OpenAPI Spec](https://swagger.io/specification/#data-type-format) so, for instance, the `format` of strings is defined there, not in kubebuilder. Furthermore, Kubernetes has forked the OpenAPI project [here](https://github.com/kubernetes/kube-openapi/tree/master/pkg/validation) and extends more formats in the extensions-apiserver [here](https://github.com/kubernetes/kubernetes/blob/master/staging/src/k8s.io/apiextensions-apiserver/pkg/apis/apiextensions/v1/types_jsonschema.go#L27).
63+
64+
65+
### Replicated Data Types
66+
67+
Some objects are replicated and cached amongst shards when `kcp` is run in a sharded configuration. When writing code to list or get these objects, be sure to reference both shard-local and cache informers. To make this more convenient, wrap the look up in a function pointer.
68+
69+
For example:
70+
71+
```Golang
72+
73+
func NewController(ctx,
74+
localAPIExportInformer, cacheAPIExportInformer apisinformers.APIExportClusterInformer
75+
) (*controller, error) {
76+
...
77+
return &controller{
78+
listAPIExports: func(clusterName logicalcluster.Name) ([]apisv1apha1.APIExport, error) {
79+
exports, err := localAPIExportInformer.Cluster(clusterName).Lister().List(labels.Everything())
80+
if err != nil {
81+
return cacheAPIExportInformer.Cluster(clusterName).Lister().List(labels.Everything())
82+
}
83+
return exports, nil
84+
...
85+
}
86+
}
87+
```
88+
89+
A full list of replicated resources is currently outlined in the [replication controller](https://github.com/kcp-dev/kcp/blob/main/pkg/reconciler/cache/replication/replication_controller.go).
Lines changed: 59 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,59 @@
1+
# Continuous Integration (CI)
2+
3+
kcp uses a combination of [GitHub Actions](https://help.github.com/en/actions/automating-your-workflow-with-github-actions) and
4+
and [prow](https://github.com/kubernetes/test-infra/tree/master/prow) to automate the build process.
5+
6+
Here are the most important links:
7+
8+
- [.github/workflows/](https://github.com/kcp-dev/kcp/blob/main/.github/workflows/) defines the Github Actions based jobs.
9+
- [kcp-dev/kcp/.prow.yaml](https://github.com/kcp-dev/kcp/blob/main/.prow.yaml) defines the prow based jobs.
10+
11+
## Debugging Flakes
12+
13+
Tests that sometimes pass and sometimes fail are known as flakes. Sometimes, there is only an issue with the test, while
14+
other times, there is an actual bug in the main code. Regardless of the root cause, it's important to try to eliminate
15+
as many flakes as possible.
16+
17+
### Unit Test Flakes
18+
19+
If you're trying to debug a unit test flake, you can try to do something like this:
20+
21+
```shell
22+
go test -race ./pkg/reconciler/apis/apibinding -run TestReconcileBinding -count 100 -failfast
23+
```
24+
25+
This tests one specific package, running only a single test case by name, 100 times in a row. It fails as soon as it
26+
encounters any failure. If this passes, it may still be possible there is a flake somewhere, so you may need to run
27+
it a few times to be certain. If it fails, that's a great sign - you've been able to reproduce it locally. Now you
28+
need to dig into the test condition that is failing. Work backwards from the condition and try to determine if the
29+
condition is correct, and if it should be that way all the time. Look at the code under test and see if there are any
30+
reasons things might not be deterministic.
31+
32+
### End to End Test Flakes
33+
34+
Debugging an end-to-end (e2e) test that is flaky can be a bit trickier than a unit test. Our e2e tests run in one of
35+
two modes:
36+
37+
1. Tests share a single kcp server
38+
2. Tests in a package share a single kcp server
39+
40+
The `e2e-shared-server` CI job uses mode 1, and the `e2e` CI job uses mode 2.
41+
42+
There are also a handful of tests that require a fully isolated kcp server, because they manipulate some configuration
43+
aspects that are system-wide and would break all the other tests. These tests run in both `e2e` and `e2e-shared-server`,
44+
separate from the other kcp instance(s).
45+
46+
You can use the same `run`, `-count`, and `-failfast` settings from the unit test section above for trying to reproduce
47+
e2e flakes locally. Additionally, if you would like to operate in mode 1 (all tests share a single kcp server), you can
48+
start a kcp instance locally in a separate terminal or tab:
49+
50+
```shell
51+
bin/test-server
52+
```
53+
54+
Then, to have your test use that shared kcp server, you add `-args --use-default-kcp-server` to your `go test` run:
55+
56+
```shell
57+
go test ./test/e2e/apibinding -count 20 -failfast -args --use-default-kcp-server
58+
```
59+
File renamed without changes.
Lines changed: 61 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,61 @@
1+
# Getting Started
2+
3+
## Prerequisites
4+
5+
1. Clone this repository.
6+
2. [Install Go](https://golang.org/doc/install) (currently 1.23.10).
7+
3. Install [kubectl](https://kubernetes.io/docs/tasks/tools/#kubectl).
8+
9+
Please note that the go language version numbers in these files must exactly agree: go/go.mod file, kcp/Dockerfile, and in all the kcp/.github/workflows yaml files that specify go-version. In kcp/Dockerfile it is indicated by the "golang" attribute. In go.mod it is indicated by the "go" directive." In the .github/workflows yaml files it is indicated by "go-version"
10+
11+
## Build & Verify
12+
13+
1. In one terminal, build and start `kcp`:
14+
```
15+
go run ./cmd/kcp start
16+
```
17+
18+
2. In another terminal, tell `kubectl` where to find the kubeconfig:
19+
20+
```
21+
export KUBECONFIG=.kcp/admin.kubeconfig
22+
```
23+
24+
3. Confirm you can connect to `kcp`:
25+
26+
```
27+
kubectl api-resources
28+
```
29+
30+
## Developer Certificate of Origin (DCO)
31+
32+
Contributing to kcp requires a [Developer Certificate of Origin (DCO)](https://developercertificate.org/) on all commits so we can be sure that you are allowed to contribute the code in your pull request.
33+
34+
To accept the DCO, your commits need to be signed off. When creating a commit via `git`, you should append the `--signoff` / `-s` flag to the command, like this:
35+
36+
```sh
37+
git commit -m "my commit message" --signoff
38+
```
39+
40+
This will add a line to your commit that looks like this, stating that you are committing under the DCO:
41+
42+
```
43+
Signed-off-by: Your Name <[email protected]>
44+
```
45+
46+
Please be aware that we cannot accept pull requests in which commits are missing the sign-off.
47+
48+
## Finding Areas to Contribute
49+
50+
Starting to participate in a new project can sometimes be overwhelming, and you may not know where to begin. Fortunately, we are here to help! We track all of our tasks here in GitHub, and we label our issues to categorize them. Here are a couple of handy links to check out:
51+
52+
* [Good first issue](https://github.com/kcp-dev/kcp/issues?q=is%3Aopen+is%3Aissue+label%3A%22good+first+issue%22) issues
53+
* [Help wanted](https://github.com/kcp-dev/kcp/issues?q=is%3Aopen+is%3Aissue+label%3A%22help+wanted%22) issues
54+
55+
You're certainly not limited to only these kinds of issues, though! If you're comfortable, please feel free to try working on anything that is open.
56+
57+
We do use the assignee feature in GitHub for issues. If you find an unassigned issue, comment asking if you can be assigned, and ideally wait for a maintainer to respond. If you find an assigned issue and you want to work on it or help out, please reach out to the assignee first.
58+
59+
Sometimes you might get an amazing idea and start working on a huge amount of code. We love and encourage excitement like this, but we do ask that before you embarking on a giant pull request, please reach out to the community first for an initial discussion. You could [file an issue](https://github.com/kcp-dev/kcp/issues/new/choose), send a discussion to our [mailing list](https://groups.google.com/g/kcp-dev), and/or join one of our [community meetings](https://docs.google.com/document/d/1PrEhbmq1WfxFv1fTikDBZzXEIJkUWVHdqDFxaY1Ply4).
60+
61+
Finally, we welcome and value all types of contributions, beyond "just code"! Other types include triaging bugs, tracking down and fixing flaky tests, improving our documentation, helping answer community questions, proposing and reviewing designs, etc.
File renamed without changes.
File renamed without changes.
File renamed without changes.

0 commit comments

Comments
 (0)