1# Contributing to librdkafka 2 3(This document is based on [curl's CONTRIBUTE.md](https://github.com/curl/curl/blob/master/docs/CONTRIBUTE.md) - thank you!) 4 5This document is intended to offer guidelines on how to best contribute to the 6librdkafka project. This concerns new features as well as bug fixes and 7general improvements. 8 9### License and copyright 10 11When contributing with code, you agree to put your changes and new code under 12the same license librdkafka is already using unless stated and agreed 13otherwise. 14 15When changing existing source code, you do not alter the copyright of the 16original file(s). The copyright will still be owned by the original creator(s) 17or those who have been assigned copyright by the original author(s). 18 19By submitting a patch to the librdkafka, you are assumed to have the right 20to the code and to be allowed by your employer or whatever to hand over that 21patch/code to us. We will credit you for your changes as far as possible, to 22give credit but also to keep a trace back to who made what changes. Please 23always provide us with your full real name when contributing! 24 25Official librdkafka project maintainer(s) assume ownership of all accepted 26submissions. 27 28## Write a good patch 29 30### Follow code style 31 32When writing C code, follow the code style already established in 33the project. Consistent style makes code easier to read and mistakes less 34likely to happen. 35 36See the end of this document for the C style guide to use in librdkafka. 37 38 39### Write Separate Changes 40 41It is annoying when you get a huge patch from someone that is said to fix 511 42odd problems, but discussions and opinions don't agree with 510 of them - or 43509 of them were already fixed in a different way. Then the person merging 44this change needs to extract the single interesting patch from somewhere 45within the huge pile of source, and that gives a lot of extra work. 46 47Preferably, each fix that correct a problem should be in its own patch/commit 48with its own description/commit message stating exactly what they correct so 49that all changes can be selectively applied by the maintainer or other 50interested parties. 51 52Also, separate changes enable bisecting much better when we track problems 53and regression in the future. 54 55### Patch Against Recent Sources 56 57Please try to make your patches against latest master branch. 58 59### Test Cases 60 61Bugfixes should also include a new test case in the regression test suite 62that verifies the bug is fixed. 63Create a new tests/00<freenumber>-<short_bug_description>.c file and 64try to reproduce the issue in its most simple form. 65Verify that the test case fails for earlier versions and passes with your 66bugfix in-place. 67 68New features and APIs should also result in an added test case. 69 70Submitted patches must pass all existing tests. 71For more information on the test suite see [tests/README.md] 72 73 74 75## How to get your changes into the main sources 76 77File a [pull request on github](https://github.com/edenhill/librdkafka/pulls) 78 79Your change will be reviewed and discussed there and you will be 80expected to correct flaws pointed out and update accordingly, or the change 81risk stalling and eventually just get deleted without action. As a submitter 82of a change, you are the owner of that change until it has been merged. 83 84Make sure to monitor your PR on github and answer questions and/or 85fix nits/flaws. This is very important. We will take lack of replies as a 86sign that you're not very anxious to get your patch accepted and we tend to 87simply drop such changes. 88 89When you adjust your pull requests after review, please squash the 90commits so that we can review the full updated version more easily 91and keep history cleaner. 92 93For example: 94 95 # Interactive rebase to let you squash/fixup commits 96 $ git rebase -i master 97 98 # Mark fixes-on-fixes commits as 'fixup' (or just 'f') in the 99 # first column. These will be silently integrated into the 100 # previous commit, so make sure to move the fixup-commit to 101 # the line beneath the parent commit. 102 103 # Since this probably rewrote the history of previously pushed 104 # commits you will need to make a force push, which is usually 105 # a bad idea but works good for pull requests. 106 $ git push --force origin your_feature_branch 107 108 109### Write good commit messages 110 111A short guide to how to write good commit messages. 112 113 ---- start ---- 114 [area]: [short line describing the main effect] [(#issuenumber)] 115 -- empty line -- 116 [full description, no wider than 72 columns that describe as much as 117 possible as to why this change is made, and possibly what things 118 it fixes and everything else that is related] 119 ---- stop ---- 120 121Example: 122 123 cgrp: Restart query timer on all heartbeat failures (#10023) 124 125 If unhandled errors were received in HeartbeatResponse 126 the cgrp could get stuck in a state where it would not 127 refresh its coordinator. 128 129 130**Important**: Rebase your PR branch on top of master (`git rebase -i master`) 131 and squash interim commits (to make a clean and readable git history) 132 before pushing. Use force push to keep your history clean even after 133 the initial PR push. 134 135**Note**: Good PRs with bad commit messages or messy commit history 136 such as "fixed review comment", will be squashed up in 137 to a single commit with a proper commit message. 138 139 140### Add changelog 141 142If the changes in the PR affects the end user in any way, such as for a user 143visible bug fix, new feature, API or doc change, etc, a release changelog item 144needs to be added to [CHANGELOG.md](CHANGELOG.md) for the next release. 145 146Add a single line to the appropriate section (Enhancements, Fixes, ..) 147outlining the change, an issue number (if any), and your name or GitHub 148user id for attribution. 149 150E.g.: 151``` 152## Enhancements 153 * Improve commit() async parameter documentation (Paul Nit, #123) 154``` 155 156 157 158# librdkafka C style guide 159 160## Function and globals naming 161 162Use self-explanatory hierarchical snake-case naming. 163Pretty much all symbols should start with `rd_kafka_`, followed by 164their subsystem (e.g., `cgrp`, `broker`, `buf`, etc..), followed by an 165action (e.g, `find`, `get`, `clear`, ..). 166 167 168## Variable naming 169 170For existing types use the type prefix as variable name. 171The type prefix is typically the first part of struct member fields. 172Example: 173 174 * `rd_kafka_broker_t` has field names starting with `rkb_..`, thus broker 175 variable names should be named `rkb` 176 177 178For other types use reasonably concise but descriptive names. 179`i` and `j` are typical int iterators. 180 181## Variable declaration 182 183Variables must be declared at the head of a scope, no in-line variable 184declarations are allowed. 185 186## Indenting 187 188Use 8 spaces indent, same as the Linux kernel. 189In emacs, use `c-set-style "linux`. 190For C++, use Google's C++ style. 191 192## Comments 193 194Use `/* .. */` comments, not `// ..` 195 196For functions, use doxygen syntax, e.g.: 197 198 /** 199 * @brief <short description> 200 * .. 201 * @returns <something..> 202 */ 203 204 205Make sure to comment non-obvious code and situations where the full 206context of an operation is not easily graspable. 207 208Also make sure to update existing comments when the code changes. 209 210 211## Line length 212 213Try hard to keep line length below 80 characters, when this is not possible 214exceed it with reason. 215 216 217## Braces 218 219Braces go on the same line as their enveloping statement: 220 221 int some_func (..) { 222 while (1) { 223 if (1) { 224 do something; 225 .. 226 } else { 227 do something else; 228 .. 229 } 230 } 231 232 /* Single line scopes should not have braces */ 233 if (1) 234 hi(); 235 else if (2) 236 /* Say hello */ 237 hello(); 238 else 239 bye(); 240 241 242## Spaces 243 244All expression parentheses should be prefixed and suffixed with a single space: 245 246 int some_func (int a) { 247 248 if (1) 249 ....; 250 251 for (i = 0 ; i < 19 ; i++) { 252 253 254 } 255 } 256 257 258Use space around operators: 259 260 int a = 2; 261 262 if (b >= 3) 263 c += 2; 264 265Except for these: 266 267 d++; 268 --e; 269 270 271## New block on new line 272 273New blocks should be on a new line: 274 275 if (1) 276 new(); 277 else 278 old(); 279 280 281## Parentheses 282 283Don't assume the reader knows C operator precedence by heart for complex 284statements, add parentheses to ease readability. 285 286 287## ifdef hell 288 289Avoid ifdef's as much as possible. 290Platform support checking should be performed in configure.librdkafka. 291 292 293 294 295 296# librdkafka C++ style guide 297 298Follow [Google's C++ style guide](https://google.github.io/styleguide/cppguide.html) 299