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