github.com/m3db/m3@v1.5.1-0.20231129193456-75a402aa583b/DEVELOPMENT.md (about) 1 # Development Guide 2 3 M3 is a large, active codebase. This guide is for all potential code 4 contributors, designed to make it easier to get started with contributing to M3. 5 6 ## Setup Development Environment 7 8 Fork <https://github.com/m3db/m3> to your own user or org account on GitHub. 9 10 Clone the fork: 11 12 ```bash 13 mkdir -p $GOPATH/src/github.com/m3db 14 cd $GOPATH/src/github.com/m3db 15 git clone git@github.com:<fork_user_or_org>/m3.git 16 ``` 17 18 **Note**: You must push all commits/branches/etc to the fork, not to the upstream repository. 19 20 Verify that `git clone` set the repository's upstream: 21 22 ```shell 23 $ git remote -v 24 origin git@github.com:<fork_user_or_org>/m3.git (fetch) 25 origin git@github.com:<fork_user_or_org>/m3.git (push) 26 ``` 27 28 Install dependencies: 29 30 ```bash 31 cd m3 32 make install-vendor-m3 33 ``` 34 35 You can build each M3 component using `make` and the relevant task 36 37 - A single combined database and coordinator node ideal for local development: `make m3dbnode` 38 - An M3 Coordinator node: `make m3coordinator` 39 - An M3 Aggregator node: `make m3aggregator` 40 - An M3 Query node: `make m3query` 41 42 <!-- TODO: Why? What is this? Why do I need it? --> 43 44 ## Running the M3 Stack Locally 45 46 Follow the instructions in [this README][local-readme]. 47 48 [local-readme]: ./scripts/development/m3_stack/README.md 49 50 ## Updating Mocks and Generated Files 51 52 <!-- TODO: What might these be? --> 53 54 If changes require updates to mocks or other generated files, make sure to 55 update those files. There are `make` targets to help with generation: 56 57 - Mocks: `make mock-gen` 58 - Protobuf: `make proto-gen` (Requires Docker) 59 - Thrift: `make thrift-gen` (Requires Docker) 60 61 Don't forget to account for changes to generated files in tests. 62 63 You can build mocks/protos etc. for a single component with: 64 65 ``` 66 make mock-gen-<component> 67 68 e.g. 69 make mock-gen-aggregator 70 ``` 71 72 ### Adding new mocks 73 74 `mockgen` statements are centralized in a single generate.go file per component. The convention is: 75 76 `src/<component>/generated/mocks/generate.go` 77 78 e.g. for the aggregator 79 `src/aggregator/generated/mocks/generate.go` 80 81 ### Adding new proto definitions 82 83 Proto definitions should be placed in: 84 85 ``` 86 src/<component>/generated/proto` 87 ``` 88 89 ## Scoping Pull Requests 90 91 Inspired by Phabricator's article about 92 [Recommendations on Revision Control][phab-one-idea], and particularly 93 because pull requests tend to be squash-merged, try to keep PRs focused 94 on one idea (or the minimal number of ideas for the change to be viable). 95 96 The advantages of smaller PRs are: 97 98 - Quicker to write + quicker to review = faster iteration 99 - Easier to spot errors 100 - Less cognitive overhead (and net time invested) for reviewers due to 101 reduced scope 102 - Avoids scope creep 103 - Clearly establishes that all parts of the PR are related 104 105 Because of this, contributors are encouraged to keep PRs as small as 106 possible. Given that this does introduce some developer overhead (e.g. 107 needing to manage more PRs), _how_ small is unspecified; reviewers 108 can request breaking PRs down further as necessary, and contributors 109 should work with reviewers to find the right balance. 110 111 [phab-one-idea]: https://secure.phabricator.com/book/phabflavor/article/recommendations_on_revision_control/#one-idea-is-one-commit 112 113 ## Testing Changes 114 115 M3 has an extensive test suite to ensure that we're able to validate changes. You can find more notes about the testing strategies employed in [TESTING][TESTING.md]. 116 117 While the CI suite runs all tests before allowing the merging of pull requests 118 , developers should test their changes during development and before 119 pushing updates. 120 121 To test code, use `go test` from the root directory: 122 123 ```shell 124 go test -v ./src/... 125 ``` 126 127 The time required to run the entire suite has increased significantly. We recommend only running tests for both (1) any packages with changes and (2) any packages that 128 import the changed packages. An example of this is: 129 130 ```bash 131 changed=$(git diff --name-only HEAD^ HEAD | xargs -I {} dirname {} | sort | uniq) 132 for pkg in $changed; do 133 affected=$(grep -r "$pkg" ./src | cut -d: -f1 | grep -v mock | xargs -I{} dirname {} | sort | uniq) 134 go test -v -race "./$pkg" $affected 135 done 136 ``` 137 138 Contributors are free to do whatever due diligence that they feel helps them to 139 be most productive. Our only request is that contributors don't use CI jobs as a first-pass filter to determine whether a change is sane or not. 140 141 Once tests are passing locally, push to a new remote branch to create a pull 142 request, or push to an existing branch to update a pull request. If the CI 143 suite reports any errors, attempt to reproduce failures locally and fix them 144 before continuing. 145 146 For larger or more intensive tests (e.g. "big" unit tests, integration tests), 147 you may need additional build tags to scope the tests down to a smaller 148 subset, for example: 149 150 ```shell 151 # example integration test 152 $ go test ./integration -tags integration -run TestIndexBlockRotation -v 153 154 # example big unit test 155 $ go test -tags big ./services/m3dbnode/main -run TestIndexEnabledServer -v 156 ``` 157 158 ## Code Review 159 160 Please follow the following guidelines when submitting or reviewing pull 161 requests: 162 163 - Merging is blocked on approval by 1 or more users with write access. We 164 recommend 2+ for large, complex, or nuanced changes. 165 - Pull requests should contain clear descriptions and context per the 166 pull request template. 167 - The [Technical Steering Committee (TSC)][GOVERNANCE.md] must approve breaking changes 168 under the current versioning guarantees (see [COMPATIBILITY][COMPATIBILITY.md]). 169 - You should follow the [STYLEGUIDE][STYLEGUIDE.md] to the extent reasonable 170 within the scope of the pull request. 171 - You should validate changed codepaths should by unit tests that cover at least one 172 nominal case and one error case. 173 - Pull requests are only merged with a green build. Don't merge with 174 build failures, even if they're known and unrelated. 175 - Flaky or otherwise unreliable CI failures count as hard failures. Commit fixes 176 or skips for flaky tests or other failures first. 177 178 Your pull request is most likely to be accepted if it: 179 180 - Includes tests for new functionality. 181 - Follows the guidelines in [Effective 182 Go](https://golang.org/doc/effective_go.html) and the [Go team's common code 183 review comments](https://github.com/golang/go/wiki/CodeReviewComments). 184 - Has a [good commit 185 message](http://tbaggery.com/2008/04/19/a-note-about-git-commit-messages.html). 186 - It prefixes the name of the pull request with the component you are updating in the format "[component] Change title" (for example "[dbnode] Support out of order writes"). 187 188 ## Updating the CHANGELOG 189 190 After a pull request is merged, summarize significant changes in the 191 [CHANGELOG][CHANGELOG.md]. Since the you don't know the PR number ahead of time, 192 do this as a subsequent commit after the merged PR (though you can prepare the 193 CHANGELOG PR in tandem with the referenced PR). 194 195 The format of the CHANGELOG entry should be: 196 197 ```text 198 - TYPE **COMPONENT**: Description (#PR_NUMBER) 199 ``` 200 201 Omit the `TYPE` should if it's a feature. If the change isn't a 202 feature, `TYPE` should be either `FIX` or `PERF`. Add new types of changes 203 to this document before used if you can't categorize them by the 204 existing types. 205 206 Add new CHANGELOG entries to the current "unreleased" section at 207 the top of the CHANGELOG as long as they're within the scope of that potential 208 version. If no unreleased section exists, add one using the 209 appropriate proposed semver. If an unreleased section exists but the new change 210 requires a different semver change (e.g. the unreleased version is a patch 211 version bump, but the new change requires a minor version bump), update the version 212 on the existing section. See [COMPATIBILITY][COMPATIBILITY.md] 213 for more information on versioning. 214 215 An example CHANGELOG addition: 216 217 ```text 218 # 0.4.5 (unreleased) 219 220 - FIX **DB**: Index data race in FST Segment reads (#938) 221 ``` 222 223 ## Cutting a Release 224 225 1. Check you have a GitHub API access token with the `repo` scope 226 2. Checkout the commit you want to release (all releases must be on master) 227 3. Create a tag with the version you want to release 228 - E.g. `git tag -a v0.7.0 -m "v0.7.0"` 229 - Read [COMPATIBILITY][COMPATIBILITY.md] for semver information. 230 4. Push the tag 231 - E.g. `git push origin v0.7.0` 232 5. Run `make GITHUB_TOKEN=<GITHUB_API_ACCESS_TOKEN> release` 233 6. Update [CHANGELOG.md](CHANGELOG.md) and commit it to master 234 7. Copy and paste the text from [CHANGELOG.md](CHANGELOG.md) into the release notes [on GitHub][releases]. 235 236 [CHANGELOG.md]: https://github.com/m3db/m3/blob/master/CHANGELOG.md 237 238 [COMPATIBILITY.md]: https://github.com/m3db/m3/blob/master/COMPATIBILITY.md 239 240 [GOVERNANCE.md]: https://github.com/m3db/m3/blob/master/GOVERNANCE.md 241 242 [STYLEGUIDE.md]: https://github.com/m3db/m3/blob/master/STYLEGUIDE.md 243 244 [TESTING.md]: https://github.com/m3db/m3/blob/master/TESTING.md 245 246 [m3db.io]: https://m3db.io/ 247 248 [releases]: https://github.com/m3db/m3/releases