1"use strict";(self.webpackChunkig_website=self.webpackChunkig_website||[]).push([[7793],{75405:(e,n,t)=>{t.r(n),t.d(n,{assets:()=>d,contentTitle:()=>a,default:()=>h,frontMatter:()=>r,metadata:()=>i,toc:()=>l});const i=JSON.parse('{"id":"devel/contributing","title":"Contributing","description":"How to contribute to Inspektor Gadget.\\n","source":"@site/docs/devel/contributing.md","sourceDirName":"devel","slug":"/devel/contributing","permalink":"/docs/latest/devel/contributing","draft":false,"unlisted":false,"editUrl":"https://github.com/inspektor-gadget/inspektor-gadget/edit/main/docs/devel/contributing.md","tags":[],"version":"current","sidebarPosition":50,"frontMatter":{"title":"Contributing","sidebar_position":50,"description":"How to contribute to Inspektor Gadget.\\n"},"sidebar":"mainSidebar","previous":{"title":"Development","permalink":"/docs/latest/devel/"},"next":{"title":"Continuous Integration","permalink":"/docs/latest/devel/ci"}}');var s=t(74848),o=t(28453);const r={title:"Contributing",sidebar_position:50,description:"How to contribute to Inspektor Gadget.\n"},a=void 0,d={},l=[{value:"Getting started",id:"getting-started",level:2},{value:"Setup developer environment",id:"setup-developer-environment",level:3},{value:"Building the code",id:"building-the-code",level:2},{value:"Building the client executable",id:"building-the-client-executable",level:3},{value:"Building the gadget container image",id:"building-the-gadget-container-image",level:3},{value:"Notes",id:"notes",level:4},{value:"Building the eBPF object files",id:"building-the-ebpf-object-files",level:3},{value:"Building <code>ig</code>",id:"building-ig",level:3},{value:"Testing",id:"testing",level:2},{value:"Development environment on minikube",id:"development-environment-on-minikube",level:3},{value:"Unit tests",id:"unit-tests",level:3},{value:"Regenerating testdata",id:"regenerating-testdata",level:3},{value:"Integration tests",id:"integration-tests",level:3},{value:"Testing gadgets from a local registry",id:"testing-gadgets-from-a-local-registry",level:3},{value:"Integration tests for <code>ig</code>",id:"integration-tests-for-ig",level:3},{value:"Kubernetes",id:"kubernetes",level:4},{value:"Non-Kubernetes",id:"non-kubernetes",level:4},{value:"Benchmarks",id:"benchmarks",level:3},{value:"Running the benchmarks",id:"running-the-benchmarks",level:4},{value:"Analyzing the results",id:"analyzing-the-results",level:4},{value:"Continuous Integration",id:"continuous-integration",level:3},{value:"Documentation",id:"documentation",level:2},{value:"Getting Help",id:"getting-help",level:2},{value:"Contribution Guidelines",id:"contribution-guidelines",level:2},{value:"Code of Conduct",id:"code-of-conduct",level:3},{value:"Authoring PRs",id:"authoring-prs",level:3},{value:"Breaking Changes",id:"breaking-changes",level:3},{value:"Commit History Guidelines",id:"commit-history-guidelines",level:3},{value:"Good first issues",id:"good-first-issues",level:3},{value:"Proposing new features",id:"proposing-new-features",level:3},{value:"Writing tests",id:"writing-tests",level:3},{value:"Planning",id:"planning",level:2},{value:"BCC",id:"bcc",level:2},{value:"Porting BCC gadgets",id:"porting-bcc-gadgets",level:3},{value:"Security",id:"security",level:2}];function c(e){const n={a:"a",code:"code",h2:"h2",h3:"h3",h4:"h4",li:"li",ol:"ol",p:"p",pre:"pre",ul:"ul",...(0,o.R)(),...e.components};return(0,s.jsxs)(s.Fragment,{children:[(0,s.jsxs)(n.p,{children:["Here you can learn how you can contribute to Inspektor Gadget. If you are\nlooking to develop Gadgets, please check the ",(0,s.jsx)(n.a,{href:"../gadget-devel",children:"Gadget\nDevelopment"})," documentation."]}),"\n",(0,s.jsx)(n.h2,{id:"getting-started",children:"Getting started"}),"\n",(0,s.jsxs)(n.p,{children:["To better understand how the pieces fit together, we recommend reading the\n",(0,s.jsx)(n.a,{href:"/docs/latest/reference/architecture",children:"architecture"})," documentation before starting to play with\nInspektor Gadget."]}
1),"\n",(0,s.jsx)(n.h3,{id:"setup-developer-environment",children:"Setup developer environment"}),"\n",(0,s.jsxs)(n.ul,{children:["\n",(0,s.jsxs)(n.li,{children:[(0,s.jsx)(n.a,{href:"https://github.com/inspektor-gadget/inspektor-gadget/fork",children:"Fork"})," and clone this repo:\n",(0,s.jsxs)(n.ul,{children:["\n",(0,s.jsxs)(n.li,{children:[(0,s.jsx)(n.code,{children:"git clone [email protected]:your_account/inspektor-gadget.git"}),"."]}),"\n"]}),"\n"]}),"\n",(0,s.jsxs)(n.li,{children:["Install ",(0,s.jsx)(n.a,{href:"https://docs.docker.com/get-docker/",children:"Docker"}),", ",(0,s.jsx)(n.a,{href:"https://docs.docker.com/buildx/working-with-buildx",children:"Docker Buildx"})," and ",(0,s.jsx)(n.a,{href:"https://golang.org/doc/install",children:"Golang"}),"."]}),"\n",(0,s.jsxs)(n.li,{children:["To be able to cross build our different container images, you will also need ",(0,s.jsx)(n.a,{href:"https://github.com/multiarch/qemu-user-static",children:(0,s.jsx)(n.code,{children:"qemu-user-static"})}),"."]}),"\n"]}),"\n",(0,s.jsx)(n.h2,{id:"building-the-code",children:"Building the code"}),"\n",(0,s.jsx)(n.p,{children:"Inspektor Gadget is composed of a client executable that runs on the\noperator's machine, and a container image that runs in the Kubernetes\ncluster. They can be built together or independently."}),"\n",(0,s.jsx)(n.h3,{id:"building-the-client-executable",children:"Building the client executable"}),"\n",(0,s.jsxs)(n.p,{children:["You can compile the client executable for your platform by running ",(0,s.jsx)(n.code,{children:"make kubectl-gadget"}),"."]}),"\n",(0,s.jsxs)(n.p,{children:["To cross compile for all supported platforms, you can run ",(0,s.jsx)(n.code,{children:"make kubectl-gadget-all"})," or select a specific one with ",(0,s.jsx)(n.code,{children:"make kubectl-gadget-linux-amd64"})," or ",(0,s.jsx)(n.code,{children:"make kubectl-gadget-darwin-amd64"}),"."]}),"\n",(0,s.jsx)(n.h3,{id:"building-the-gadget-container-image",children:"Building the gadget container image"}),"\n",(0,s.jsx)(n.p,{children:"You can build and push the container gadget image by running the following commands:"}),"\n",(0,s.jsx)(n.pre,{children:(0,s.jsx)(n.code,{className:"language-bash",children:"$ make gadget-container\n$ make push-gadget-container\n"})}),"\n",(0,s.jsx)(n.p,{children:"The eBPF code is built using a Docker container, so you don't have to worry\ninstalling the compilers to build it."}),"\n",(0,s.jsxs)(n.p,{children:["If you push the container images to another registry, you can use the ",(0,s.jsx)(n.code,{children:"--image"}),"\nargument when deploying to the Kubernetes cluster."]}),"\n",(0,s.jsx)(n.h4,{id:"notes",children:"Notes"}),"\n",(0,s.jsxs)(n.ul,{children:["\n",(0,s.jsxs)(n.li,{children:["Using a locally built container image requires pushing it to a container\nregistry, either local or remote. The default registry can be overridden by\nchanging the value of the ",(0,s.jsx)(n.code,{children:"CONTAINER_REPO"})," env variable, which defaults to\n",(0,s.jsx)(n.code,{children:"ghcr.io/inspektor-gadget/inspektor-gadget"})," if not defined."]}),"\n",(0,s.jsxs)(n.li,{children:["You can generate the required BTF information for some well known\nkernel versions by setting ",(0,s.jsx)(n.code,{children:"ENABLE_BTFGEN=true"})]}),"\n"]}),"\n",(0,s.jsx)(n.h3,{id:"building-the-ebpf-object-files",children:"Building the eBPF object files"}),"\n",(0,s.jsx)(n.p,{children:"If you need to compile the eBPF code of the gadgets, the ebpf-objects target\nwill help you in this task:"}),"\n",(0,s.jsx)(n.pre,{children:(0,s.jsx)(n.code,{className:"language-bash",children:"$ make ebpf-objects\n...\ngo: downloading github.com/giantswarm/crd-docs-generator v0.7.1\n...\n"})}),"\n",(0,s.jsxs)(n.h3,{id:"building-ig",children:["Building ",(0,s.jsx)(n.code,{children:"ig"})]}),"\n",(0,s.jsxs)(n.p,{children:["Inspektor Gadget also provides the ",(0,s.jsx)(n.a,{href:"/docs/latest/reference/ig",children:(0,s.jsx)(n.code,{children:"ig"})})," tool to\ntrace containers without Kubernetes. It can be built independently from the\n",(0,s.jsx)(n.code,{children:"kubectl-gadget"})," and the gadget container image."]}),"\n",(0,s.jsx)(n.pre,{children:(0,s.jsx)(n.code,{className:"language-bash",children:"$ make ig\n"})}),"\n",(0,s.jsx)(n.h2,{id:"testing",children:"Testing"}),"\n",(0,s.jsx)(n.h3,{id:"development-environment-on-minikube",children:"Development environment on minikube"}),"\n",(0,s.jsx)(n.p,{children:"For faster iteration, it's possible to make changes to Inspektor Gadget and\ntest them on minikube locally without pushing container images to any\nregistry."}),"\n",(0,s.jsxs)(n.ul,{children:["\n",(0,s.jsxs)(n.li,{children:["Follow the specific ",(0,s.jsx)(n.a,{href:"/docs/latest/reference/install-kubernetes#minikube",children:"installation instructions"})," for minikube or use ",(0,s.jsx)(n.code,{children:"make minikube-start"})," to start it."]}),"\n",(0,s.jsxs)(n.li,{children:["Deploy the locally modified version of Inspektor Gadget to an already\nrunning minikube cluster with ",(0,s.jsx)(n.code,{children:"make minikube-deploy"}),"."]}),"\n"]}),"\n",(0,s.jsx)(n.h3,{id:"unit-tests",children:"Unit tests"}),"\n",(0,s.jsx)(n.p,{children:"You can run the different unit tests with:"}),"\n",(0,s.jsx)(n.pre,{children:(0,s.jsx)(n.code,{className:"language-bash",children:"$ make test\n"})}),"\n",(0,s.jsx)(n.h3,{id:"regenerating-testdata",children:"Regenerating testdata"}),"\n",(0,s.jsxs)(n.p,{children:["Some unit tests depend on precompiled files on\n",(0,s.jsx)(n.a,{href:"https://github.com/inspektor-gadget/inspektor-gadget/tree/main/testdata",children:"testdata"}),".\nThese files can be regenerated by running"]}),"\n",(0,s.jsx)(n.pre,{children:(0,s.jsx)(n.code,{className:"language-bash",children:"$ make testdata\n"})}),"\n",(0,s.jsx)(n.h3,{id:"integration-tests",children:"Integration tests"}),"\n",(0,s.jsx)(n.p,{children:"The integration tests use a Kubernetes cluster to deploy and test Inspektor Gadget.\nNote that, Inspektor Gadget must be deployed on the Kubernetes cluster before running the tests.\nBe sure that you have a valid kubeconfig and run:"}),"\n",(0,s.jsx)(n.pre,{children:(0,s.jsx)(n.code,{className:"language-bash",children:"$ export KUBECONFIG=... # not needed if valid config in $HOME/.kube/config\n$ make integration-tests\n"})}),"\n",(0,s.jsx)(n.h3,{id:"testing-gadgets-from-a-local-registry",children:"Testing gadgets from a local registry"}),"\n",(0,s.jsxs)(n.p,{children:["You can use minikube to test gadgets from a local registry. Once ",(0,s.jsx)(n.a,{href:"#development-environment-on-minikube",children:"Inspektor Gadget is deployed"})," you can run a gadget using:"]}),"\n",(0,s.jsx)(n.pre,{children:(0,s.jsx)(n.code,{className:"language-bash",children:'# build and run the gadget, in this case trace_dns\nGADGETS=trace_dns make -C gadgets minikube-gadget-run\n# run the gadget with a timeout of 10 seconds\nGADGETS=trace_dns GADGET_PARAMS="--timeout 10" make -C gadgets minikube-gadget-run\n'})}),"\n",(0,s.jsxs)(n.h3,{id:"integration-tests-for-ig",children:["Integration tests for ",(0,s.jsx)(n.code,{children:"ig"})]}),"\n",(0,s.jsx)(n.h4,{id:"kubernetes",children:"Kubernetes"}),"\n",(0,s.jsxs)(n.p,{children:["The integration tests for ",(0,s.jsx)(n.code,{children:"ig"}
1)," uses minikube for testing different container runtimes.\nThe default minikube driver used for testing is ",(0,s.jsx)(n.code,{children:"docker"}),". Currently supported\ncontainer runtimes are ",(0,s.jsx)(n.code,{children:"docker"}),", ",(0,s.jsx)(n.code,{children:"containerd"})," and ",(0,s.jsx)(n.code,{children:"cri-o"}),". You can start minikube using:"]}),"\n",(0,s.jsx)(n.pre,{children:(0,s.jsx)(n.code,{className:"language-bash",children:"$ make minikube-start-all\n# for single container runtime e.g containerd\n$ make CONTAINER_RUNTIME=containerd minikube-start\n# for minikube driver other than docker e.g kvm2\n$ make MINIKUBE_DRIVER=kvm2 minikube-start\n"})}),"\n",(0,s.jsx)(n.p,{children:"And run the test using:"}),"\n",(0,s.jsx)(n.pre,{children:(0,s.jsx)(n.code,{className:"language-bash",children:"$ make -C integration/k8s test-all\n# for single container runtime e.g containerd\n$ make -C integration/k8s CONTAINER_RUNTIME=containerd test\n"})}),"\n",(0,s.jsxs)(n.p,{children:["if no ",(0,s.jsx)(n.code,{children:"CONTAINER_RUNTIME"})," is specified ",(0,s.jsx)(n.code,{children:"docker"})," will be used as a default runtime."]}),"\n",(0,s.jsx)(n.h4,{id:"non-kubernetes",children:"Non-Kubernetes"}),"\n",(0,s.jsxs)(n.p,{children:["The ",(0,s.jsx)(n.code,{children:"ig"})," integration tests for non-Kubernetes containers directly interact\nwith container runtime. The tests assume that you already have the desired container\nruntime installed. Currently supported runtime is ",(0,s.jsx)(n.code,{children:"docker"})," only, You can run the test using:"]}),"\n",(0,s.jsx)(n.pre,{children:(0,s.jsx)(n.code,{className:"language-bash",children:"$ make -C integration/ig/non-k8s test-docker\n"})}),"\n",(0,s.jsx)(n.h3,{id:"benchmarks",children:"Benchmarks"}),"\n",(0,s.jsx)(n.h4,{id:"running-the-benchmarks",children:"Running the benchmarks"}),"\n",(0,s.jsxs)(n.ol,{children:["\n",(0,s.jsxs)(n.li,{children:["Make sure you have the ",(0,s.jsx)(n.code,{children:"integration/benchmarks/benchmarks.yaml"})," file\nconfigured correctly."]}),"\n",(0,s.jsx)(n.li,{children:"Run the benchmarks using the following command:"}),"\n"]}),"\n",(0,s.jsx)(n.pre,{children:(0,s.jsx)(n.code,{className:"language-bash",children:"$ make benchmarks-test\n"})}),"\n",(0,s.jsxs)(n.p,{children:["It'll generate a ",(0,s.jsx)(n.code,{children:"test_results_<date>.csv"})," file with the results of the\nbenchmarks."]}),"\n",(0,s.jsx)(n.h4,{id:"analyzing-the-results",children:"Analyzing the results"}),"\n",(0,s.jsxs)(n.p,{children:["You can analyze the results using the Jupyter notebook\n",(0,s.jsx)(n.code,{children:"integration/benchmarks/benchmarks_analysis.ipynb"}),". You can run it in different\napplications supporting Jupyter notebooks, such as VS Code with the Jupyter\nextension, JupyterLab, or Jupyter Notebook. Or you can generate an HTML report\nfrom the notebook using the following command:"]}),"\n",(0,s.jsx)(n.pre,{children:(0,s.jsx)(n.code,{className:"language-bash",children:"# Create a virtual environment\n$ python3 -m venv .venv\n$ source .venv/bin/activate\n\n# Install the requirements\n$ pip install -r requirements.txt\n\n# Generate the HTML report\n$ INTPUT_FILE=path_to_csv_file make make gen-html\n"})}),"\n",(0,s.jsx)(n.h3,{id:"continuous-integration",children:"Continuous Integration"}),"\n",(0,s.jsxs)(n.p,{children:["Inspektor Gadget uses GitHub Actions as CI. Please check dedicated ",(0,s.jsx)(n.a,{href:"/docs/latest/devel/ci",children:"CI\ndocumentation"})," for more details."]}),"\n",(0,s.jsxs)(n.p,{children:["Some integration tests (like AKS and ARO) are only run when a commit is pushed to the main branch or\na new tag is pushed. It's also possible to run those by pushing a branch named ",(0,s.jsx)(n.code,{children:"citest/..."}),". Please\nnotice that the container images will be pushed to\n",(0,s.jsx)(n.a,{href:"https://github.com/inspektor-gadget/inspektor-gadget/pkgs/container/inspektor-gadget",children:"https://github.com/inspektor-gadget/inspektor-gadget/pkgs/container/inspektor-gadget"})," and those\nshould be manually cleaned up."]}),"\n",(0,s.jsx)(n.h2,{id:"documentation",children:"Documentation"}),"\n",(0,s.jsx)(n.p,{children:"We kindly request that any contributions to the project also include updates to the respective portions of the documentation. This ensures that members of the community can easily learn about and utilize newly developed features."}),"\n",(0,s.jsx)(n.h2,{id:"getting-help",children:"Getting Help"}),"\n",(0,s.jsxs)(n.p,{children:["If you are having any issues with your contribution, or want to discu
1ss anything about it, feel free\nto reach out to us on ",(0,s.jsx)(n.a,{href:"https://kubernetes.slack.com/messages/inspektor-gadget/",children:"Slack"})," or on our\n",(0,s.jsx)(n.a,{href:"https://docs.google.com/document/d/1cbPYvYTsdRXd41PEDcwC89IZbcA8WneNt34oiu5s9VA/edit",children:"community\nmeeting"})]}),"\n",(0,s.jsx)(n.h2,{id:"contribution-guidelines",children:"Contribution Guidelines"}),"\n",(0,s.jsx)(n.h3,{id:"code-of-conduct",children:"Code of Conduct"}),"\n",(0,s.jsxs)(n.p,{children:["Inspektor Gadget follows the CNCF\n",(0,s.jsx)(n.a,{href:"https://github.com/cncf/foundation/blob/main/code-of-conduct.md",children:"Code of Conduct"}),"."]}),"\n",(0,s.jsx)(n.h3,{id:"authoring-prs",children:"Authoring PRs"}),"\n",(0,s.jsxs)(n.p,{children:["For making PRs/commits consistent and easier to review, please check out\nKinvolk's ",(0,s.jsx)(n.a,{href:"https://github.com/kinvolk/contribution/blob/master/topics/git.md",children:"contribution guidelines on git"}),"."]}),"\n",(0,s.jsxs)(n.p,{children:["We require all commits on a PR to be signed off certifying the ",(0,s.jsx)(n.a,{href:"https://developercertificate.org/",children:"Developer Certificate of Origin"}),":"]}),"\n",(0,s.jsx)(n.pre,{children:(0,s.jsx)(n.code,{children:"Developer Certificate of Origin\nVersion 1.1\n\nCopyright (C) 2004, 2006 The Linux Foundation and its contributors.\n\nEveryone is permitted to copy and distribute verbatim copies of this\nlicense document, but changing it is not allowed.\n\n\nDeveloper's Certificate of Origin 1.1\n\nBy making a contribution to this project, I certify that:\n\n(a) The contribution was created in whole or in part by me and I\n have the right to submit it under the open source license\n indicated in the file; or\n\n(b) The contribution is based upon previous work that, to the best\n of my knowledge, is covered under an appropriate open source\n license and I have the right under that license to submit that\n work with modifications, whether created in whole or in part\n by me, under the same open source license (unless I am\n permitted to submit under a different license), as indicated\n in the file; or\n\n(c) The contribution was provided directly to me by some other\n person who certified (a), (b) or (c) and I have not modified\n it.\n\n(d) I understand and agree that this project and the contribution\n are public and that a record of the contribution (including all\n personal information I submit with it, including my sign-off) is\n maintained indefinitely and may be redistributed consistent with\n this project or the open source license(s) involved.\n"})}),"\n",(0,s.jsxs)(n.p,{children:["It can be done by using ",(0,s.jsx)(n.code,{children:"git commit -s"}),", ",(0,s.jsx)(n.code,{children:"git commit --sign-off"})," or by manually adding a line like\nto the commit message."]}),"\n",(0,s.jsx)(n.pre,{children:(0,s.jsx)(n.code,{children:"Signed-off-by: Joe Smith <[email protected]>\n"})}),"\n",(0,s.jsx)(n.h3,{id:"breaking-changes",children:"Breaking Changes"}),"\n",(0,s.jsxs)(n.p,{children:["If a PR introduces a breaking change, please label it with the ",(0,s.jsx)(n.code,{children:"breaking-change"}),"\nlabel and provide the following information in the PR description:"]}),"\n",(0,s.jsxs)(n.ul,{children:["\n",(0,s.jsx)(n.li,{children:"What is the breaking change"}),"\n",(0,s.jsx)(n.li,{children:"Which users are impacted"}),"\n",(0,s.jsx)(n.li,{children:"How users should adapt to the breaking change"}),"\n"]}),"\n",(0,s.jsx)(n.h3,{id:"commit-history-guidelines",children:"Commit History Guidelines"}),"\n",(0,s.jsx)(n.p,{children:"When authoring a PR, ensure that the commit history is clean and\nwell-structured. Each commit should contain the following:"}),"\n",(0,s.jsxs)(n.ul,{children:["\n",(0,s.jsxs)(n.li,{children:["\n",(0,s.jsx)(n.p,{children:'Title: Describe the change in a concise and clear manner. The title should be\nprefixed with the area that it touches (e.g. gadgets/trace_open,\noperators/ebpf, docs/, etc.). Commit titles should be in the imperative mood,\ne.g. "gadgets: Add gadget to trace open calls", instead of "gadgets: Added\ngadget to trace open calls". Ideally the title should be 72 characters or\nless.'}),"\n"]}),"\n",(0,s.jsxs)(n.li,{children:["\n",(0,s.jsx)(n.p,{children:"Description: The commit description is used to explain the purpose and context\nof the changes. It's not mandatory, for instance simple c
1ommits fixing typos\ndon't need it."}),"\n"]}),"\n",(0,s.jsxs)(n.li,{children:["\n",(0,s.jsxs)(n.p,{children:["Use a ",(0,s.jsx)(n.code,{children:"Fixes:"})," tag if the commit fixes a bug. This tag should include the\nfirst 12 characters of the commit hash introducing the bug. This can be\ngenerated by including an alias in the .gitconfig file:"]}),"\n",(0,s.jsx)(n.pre,{children:(0,s.jsx)(n.code,{children:"[alias]\n fixline = log -1 --abbrev=12 --format='Fixes: %h (\\\"%s\\\")'\n"})}),"\n",(0,s.jsx)(n.p,{children:"Run it like this to obtain the line to add to the commit message:"}),"\n",(0,s.jsx)(n.pre,{children:(0,s.jsx)(n.code,{className:"language-bash",children:'$ git fixline b6c9380cde28\nFixes: b6c9380cde28 ("tcptracer: Add bpf program")\n'})}),"\n"]}),"\n",(0,s.jsxs)(n.li,{children:["\n",(0,s.jsxs)(n.p,{children:["Be signed off with the ",(0,s.jsx)(n.code,{children:"Signed-off-by:"})," line."]}),"\n"]}),"\n",(0,s.jsxs)(n.li,{children:["\n",(0,s.jsx)(n.p,{children:"Commits handling review comments should be squashed in the original commit.\nCheck how to do it in"}),"\n",(0,s.jsxs)(n.p,{children:[(0,s.jsx)(n.a,{href:"https://stackoverflow.com/a/3828861",children:"this StackOverflow answer"}),". This helps\nmaintainers and contributors understand the purpose of each commit and ensures traceability for bug fixes."]}),"\n"]}),"\n"]}),"\n",(0,s.jsx)(n.h3,{id:"good-first-issues",children:"Good first issues"}),"\n",(0,s.jsxs)(n.p,{children:["If you're looking where to start, you can check the issues with the\n",(0,s.jsx)(n.code,{children:"good first issue"})," label on\n",(0,s.jsx)(n.a,{href:"https://github.com/inspektor-gadget/inspektor-gadget/issues?q=is%3Aissue+is%3Aopen+label%3A%22good+first+issue%22",children:"Inspektor Gadget"}),".\nDon't hesitate to\n",(0,s.jsx)(n.a,{href:"https://github.com/inspektor-gadget/inspektor-gadget#discussions",children:"talk to us"}),"\nif you need further help."]}),"\n",(0,s.jsx)(n.h3,{id:"proposing-new-features",children:"Proposing new features"}),"\n",(0,s.jsx)(n.p,{children:"If you want to propose a new feature or do a big change in the architecture\nit's highly recommended to open an issue first to discuss it with the team."}),"\n",(0,s.jsx)(n.h3,{id:"writing-tests",children:"Writing tests"}),"\n",(0,s.jsxs)(n.p,{children:["We use ",(0,s.jsx)(n.code,{children:"github.com/stretchr/testify"})," to make tests less verbose."]}),"\n",(0,s.jsx)(n.h2,{id:"planning",children:"Planning"}),"\n",(0,s.jsx)(n.p,{children:"Our planning is published through two different project boards:"}),"\n",(0,s.jsxs)(n.ul,{children:["\n",(0,s.jsxs)(n.li,{children:[(0,s.jsx)(n.a,{href:"https://github.com/orgs/inspektor-gadget/projects/1",children:"Inspektor Gadget Roadmap"}),"\nhas the high level view of the big issues that we are planning to tackle\nin the upcoming months."]}),"\n",(0,s.jsxs)(n.li,{children:[(0,s.jsx)(n.a,{href:"https://github.com/orgs/inspektor-gadget/projects/2",children:"Inspektor Gadget Sprint Planning"}),"\nhas the week-to-week plans of which bugs we are currently working on,\nand the different priorities of the issues involved."]}),"\n"]}),"\n",(0,s.jsx)(n.h2,{id:"bcc",children:"BCC"}),"\n",(0,s.jsx)(n.h3,{id:"porting-bcc-gadgets",children:"Porting BCC gadgets"}),"\n",(0,s.jsxs)(n.p,{children:["This project uses some gadgets based on ",(0,s.jsx)(n.a,{href:"https://github.com/iovisor/bcc/",children:"BCC"}),". In the past, we\nmodified the BCC gadgets and executed them from our process, however it was very inflexible and we\ndecided to integrate those gadgets directly into our code base by rewriting their control plane in\nGolang."]}),"\n",(0,s.jsxs)(n.p,{children:["If you want to implement support for a BCC gadget, please read the ",(0,s.jsx)(n.a,{href:"https://www.inspektor-gadget.io/blog/2022/09/rewriting-the-control-plane-of-bcc-tools-in-golang/",children:"Rewriting the Control Plane of\nBCC Tools in Golang"}),"\nblogpost that contains all the details about this process."]}),"\n",(0,s.jsx)(n.h2,{id:"security",children:"Security"}),"\n",(0,s.jsxs)(n.p,{children:["For security, we invite you to take at look at the ",(0,s.jsx)(n.a,{href:"/docs/latest/SECURITY",children:"dedicated document"}),"."]})]})}function h(e={}){const{wrapper:n}={...(0,o.R)(),...e.components};return n?(0,s.jsx)(n,{...e,children:(0,s.jsx)(c,{...e})}):c(e)}},28453:(e,n,t)=>{t.d(n,{R:()=>r,x:()=>a});var i=t(96540);const s={},o=i.createContext(s);function r(e){const n=i.useContext(o);return i.useMemo((function(){return"function"==typeof e?e(n):{...n,...e}}),[n,e])}function a(e){let n;return n=e.disableParentContext?"function"==typeof e.components?e.components(s):e.components||s:r(e.components),i.createElement(o.Provider,{value:n},e.children)}}}]);
Line numbers count LF bytes from the start of the resource, as the search results do. Vendor segments are library code the classifier recognised; they are stored but not indexed. Bytes are shown as Latin1 characters, one per byte.