github.com/pingcap/tiflow@v0.0.0-20240520035814-5bf52d54e205/dm/step_by_step_contribute.md (about)

     1  # Step By Step Contribute Example
     2  
     3  This document introduces a step by step example of contriuting to DM.
     4  
     5  Please perform the following steps to create your Pull Request to this repository. If don't like to use command, you can also use [GitHub Desktop](https://desktop.github.com/), which is easier to get started.
     6  
     7  > **Note:**
     8  >
     9  > This section takes creating a PR to the `master` branch as an example. Steps of creating PRs to other branches are similar.
    10  
    11  ### Step 1: Fork the repository
    12  
    13  1. Visit the project: <https://github.com/pingcap/dm>
    14  2. Click the **Fork** button on the top right and wait it to finish.
    15  
    16  ### Step 2: Clone the forked repository to local storage
    17  
    18  ```sh
    19  cd $working_dir # Comes to the directory that you want put the fork in, for example, "cd ~/code"
    20  git clone git@github.com:$user/dm.git # Replace "$user" with your GitHub ID
    21  
    22  cd $working_dir/dm
    23  git remote add upstream git@github.com:pingcap/dm.git # Adds the upstream repo
    24  git remote -v # Confirms that your remote makes sense
    25  ```
    26  
    27  ### Step 3: Setting up your development environment
    28  
    29  1. Setting up a Go development environment: [How to Write Go Code](http://golang.org/doc/code.html).
    30  
    31      > **Note:**
    32      >
    33      > DM uses [`Go Modules`](https://github.com/golang/go/wiki/Modules) to manage dependencies. The version of Go should be **1.16** or above.
    34  
    35      You'll need `GOPATH` defined, and `PATH` modified to access your Go binaries. A
    36      common setup is the following but you could always google a setup for your own
    37      flavor.
    38  
    39      ```sh
    40      export GOPATH=$HOME/go
    41      export PATH=$PATH:$GOPATH/bin
    42      ```
    43  
    44      Then you can use `make` command to build DM.
    45  
    46      ```sh
    47      make build
    48      ```
    49  
    50  2. Setting up test environment. See [Test Preparations](tests/README.md#Preparations) for more details.
    51  
    52  ### Step 4: Pick up a issue
    53  
    54  You can start by finding an existing issue with the
    55  [help wanted](https://github.com/pingcap/dm/labels/help%20wanted)
    56  label in the DM repository. These issues are well suited for new contributors.
    57  
    58  > **Note:**
    59  >
    60  > This section takes issue [UCP: retrieve the configuration of the running task from the DM cluster](https://github.com/pingcap/dm/issues/182) as an example. Steps of pick up other issues are similar.
    61  
    62  ### Step 5: Create a new branch
    63  
    64  1. Get your local master up-to-date with upstream/master.
    65  
    66      ```bash
    67      cd $working_dir/dm
    68      git fetch upstream
    69      git checkout master
    70      git rebase upstream/master
    71      ```
    72  
    73  2. Create a new branch based on the master branch.
    74  
    75      ```bash
    76      git checkout -b new-branch-name
    77      ```
    78  
    79  ### Step 6: Edit your code
    80  
    81  Edit some code on the `new-branch-name` branch and save your changes to fix the issure. Below is a example to add `get-task-config` command for DM.
    82  
    83  1. Update the [proto code](dm/proto/dmmaster.proto) for grpc
    84  
    85      ```protobuf
    86      // GetTaskCfg implements a rpc method to get task config
    87      rpc GetTaskCfg(GetTaskCfgRequest) returns(GetTaskCfgResponse) {
    88          ...
    89      }
    90  
    91      // GetTaskCfgRequest is a rpc request for GetTaskCfg
    92      message GetTaskCfgRequest {
    93          ...
    94      }
    95  
    96      // GetTaskCfgRequest is a rpc response for GetTaskCfg
    97      message GetTaskCfgResponse {
    98          ...
    99      }
   100      ```
   101  
   102  2. Generate proto code
   103  
   104      ```sh
   105      make generate_proto
   106      ```
   107  
   108  3. Generate mock code
   109  
   110      ```sh
   111      make generate_mock
   112      ```
   113  
   114  4. Add new command for dmctl in [root commnd](dm/ctl/ctl.go)
   115  
   116      ```go
   117      master.NewGetTaskCfgCmd()
   118      ```
   119  
   120  5. Implement new command for [dmctl](dm/ctl/master/get_task_config.go)
   121  
   122      ```go
   123      // NewGetTaskCfgCmd creates a getTaskCfg command
   124      func NewGetTaskCfgCmd() *cobra.Command {
   125          ...
   126          cmd := &cobra.Command{
   127              Run:   getTaskCfgFunc,
   128          }
   129          return cmd
   130      }
   131  
   132      // getTaskCfgFunc does get task's config
   133      func getTaskCfgFunc(cmd *cobra.Command, _ []string) {
   134          ...
   135          cli := common.MasterClient()
   136          resp, err := cli.GetTaskCfg(ctx, &pb.GetTaskCfgRequest{
   137              Name: taskName,
   138          })
   139          common.PrettyPrintResponse(resp)
   140      }
   141      ```
   142  
   143  6. Implement new command for [dm-master](dm/master/server.go)
   144  
   145      ```go
   146      // GetTaskCfg implements MasterServer.GetSubTaskCfg
   147      func (s *Server) GetTaskCfg(ctx context.Context, req *pb.GetTaskCfgRequest) (*pb.GetTaskCfgResponse, error) {
   148          ...
   149          cfg := s.scheduler.GetTaskCfg(req.Name)
   150          return &pb.GetTaskCfgResponse{
   151              Result: true,
   152              Cfg:    cfg,
   153          }, nil
   154      }
   155      ```
   156  
   157  7. Add some error instance for your new command in [error_list](pkg/terror/error_list.go)
   158  
   159      ```go
   160      ErrSchedulerTaskNotExist = New(codeSchedulerTaskNotExist, ClassScheduler, ScopeInternal, LevelMedium, "task with name %s not exist", "Please use `query-status` command to see tasks.")
   161      ```
   162  
   163  8. Generate new [errors.toml](errors.toml)
   164  
   165      ```sh
   166      make terror_check
   167      ```
   168  
   169  9. Build your code
   170  
   171      ```sh
   172      make build
   173      ```
   174  
   175  ### Step 7: Add Unit Test
   176  
   177  1. Add unit test for [dm-master server](dm/master/server_test.go)
   178  
   179      ```go
   180      func (t *testMaster) TestGetTaskCfg(c *check.C) {
   181          ...
   182      }
   183      ```
   184  
   185  
   186  2. Run unit test
   187  
   188      ```sh
   189      make unit_test
   190      ```
   191  
   192  ### Step 8: Add Integration Test
   193  
   194  1. Add integration test for [dmctl command](tests/dmctl_basic/check_list/get_task_config.sh)
   195  
   196      ```sh
   197      function get_task_config_to_file() {
   198          ...
   199      }
   200      ```
   201  
   202  2. Setup two MySQL server with binlog enabled first and set `GITD_MODE=ON`
   203  
   204      ```sh
   205      docker run --rm --name mysql-3306 -p 3306:3306 -e MYSQL_ROOT_PASSWORD=123456 mysql:5.7.22 --log-bin=mysql-bin --port=3306 --bind-address=0.0.0.0 --binlog-format=ROW --server-id=1 --gtid_mode=ON --enforce-gtid-consistency=true > mysql.3306.log 2>&1 &
   206      docker run --rm --name mysql-3307 -p 3307:3307 -e MYSQL_ROOT_PASSWORD=123456 mysql:8.0.21 --log-bin=mysql-bin --port=3307 --bind-address=0.0.0.0 --binlog-format=ROW --server-id=1 --gtid_mode=ON --enforce-gtid-consistency=true > mysql.3307.log 2>&1 &
   207      ```
   208  
   209  3. Run integration test
   210  
   211      ```sh
   212      make integration_test
   213      ```
   214  
   215  ### Step 9: Commit your changes
   216  
   217  ```sh
   218  git status # Checks the local status
   219  git add <file> ... # Adds the file(s) you want to commit. If you want to commit all changes, you can directly use `git add .`
   220  git commit -m "commit-message: update the xx"
   221  ```
   222  
   223  ### Step 10: Keep your branch in sync with upstream/master
   224  
   225  ```sh
   226  # While on your new branch
   227  git fetch upstream
   228  git rebase upstream/master
   229  ```
   230  
   231  ### Step 11: Push your changes to the remote
   232  
   233  ```sh
   234  git push -u origin new-branch-name # "-u" is used to track the remote branch from origin
   235  ```
   236  
   237  ### Step 12: Create a pull request
   238  
   239  1. Visit your fork at <https://github.com/$user/dm> (replace `$user` with your GitHub ID)
   240  2. Click the `Compare & pull request` button next to your `new-branch-name` branch to create your PR.
   241  
   242  Now, your PR is successfully submitted! After this PR is merged, you will automatically become a contributor to DM.
   243  
   244  > **Note:**
   245  >
   246  > You can find this contribute example in PR [#798](https://github.com/pingcap/dm/pull/798)
   247  
   248  ## Contact
   249  
   250  Join the Slack channel: [#sig-tools](https://tidbcommunity.slack.com/archives/C013HGZMBAR)