Basic Workflow

The following chart illustrates the basic Ceph development workflow:

This page assumes that you are a new contributor with an idea for a bugfix or an enhancement, but you do not know how to proceed. Watch the Getting Started with Ceph Development video for a practical summary of this workflow.

Updating the tracker

Find the Issue Tracker (Redmine) number of the bug you intend to fix. If no tracker issue exists, create one. There is only one case in which you do not have to create a Redmine tracker issue: the case of minor documentation changes.

Simple documentation cleanup does not require a corresponding tracker issue. Major documenatation changes do require a tracker issue. Major documentation changes include adding new documentation chapters or files, and making substantial changes to the structure or content of the documentation.

A (Redmine) tracker ticket explains the issue (bug) to other Ceph developers to keep them informed as the bug nears resolution. Provide a useful, clear title and include detailed information in the description. When composing the title of the ticket, ask yourself “If I need to search for this ticket two years from now, which keywords am I likely to search for?” Then include those keywords in the title.

If your tracker permissions are elevated, assign the bug to yourself by setting the Assignee field. If your tracker permissions have not been elevated, just add a comment with a short message that says “I am working on this issue”.

Ceph Workflow Overview

Three repositories are involved in the Ceph workflow. They are:

  1. The upstream repository (ceph/ceph)

  2. Your fork of the upstream repository (your_github_id/ceph)

  3. Your local working copy of the repository (on your workstation)

The procedure for making changes to the Ceph repository is as follows:

  1. Configure your local environment

    1. Create a fork of the “upstream Ceph” repository.

    2. Clone the fork to your local filesystem.

  2. Fix the bug

    1. Synchronize local main with upstream main.

    2. Create a bugfix branch in your local working copy.

    3. Make alterations to the local working copy of the repository in your local filesystem.

    4. Push the changes in your local working copy to your fork.

  3. Create a Pull Request to push the change upstream.

    1. Create a Pull Request that asks for your changes to be added into the “upstream Ceph” repository.

Preparing Your Local Working Copy of the Ceph Repository

The procedures in this section, “Preparing Your Local Working Copy of the Ceph Repository”, must be followed only when you are first setting up your local environment. If this is your first time working with the Ceph project, then these commands are necessary and are the first commands that you should run.

Creating a Fork of the Ceph Repository

See the GitHub documentation for detailed instructions on forking. In short, if your GitHub username is “mygithubaccount”, your fork of the upstream repo will appear at https://github.com/mygithubaccount/ceph.

Cloning Your Fork

After you have created your fork, clone it by running the following command:

git clone https://github.com/mygithubaccount/ceph

You must fork the Ceph repository before you clone it. If you fail to fork, you cannot open a GitHub pull request.

For more information on using GitHub, refer to GitHub Help.

Configuring Your Local Environment

The commands in this section configure your local git environment so that it generates “Signed-off-by:” tags. These commands also set up your local environment so that it can stay synchronized with the upstream repository.

These commands are necessary only during the initial setup of your local working copy. Another way to say that is “These commands are necessary only the first time that you are working with the Ceph repository. They are, however, unavoidable, and if you fail to run them then you will not be able to work on the Ceph repository.”.

  1. Configure your local git environment with your name and email address.

    Note

    These commands will work only from within the ceph/ directory that was created when you cloned your fork.

    git config user.name "FIRST_NAME LAST_NAME"
    git config user.email "MY_NAME@example.com"
    
  2. Add the upstream repo as a “remote” and fetch it:

    git remote add ceph https://github.com/ceph/ceph.git
    git fetch ceph
    

    These commands fetch all the branches and commits from ceph/ceph.git to the local git repo as remotes/ceph/$BRANCH_NAME and can be referenced as ceph/$BRANCH_NAME in local git commands.

Fixing the Bug

Synchronizing Local Main with Upstream Main

In your local working copy, there is a copy of the main branch in remotes/origin/main. This is called “local main”. This copy of the main branch (https://github.com/your_github_id/ceph.git) is “frozen in time” at the moment that you cloned it, but the upstream repo (https://github.com/ceph/ceph.git, typically abbreviated to ceph/ceph.git) that it was forked from is not frozen in time: the upstream repo is still being updated by other contributors.

Because upstream main is continually receiving updates from other contributors, your fork will drift farther and farther from the state of the upstream repo when you cloned it.

Keep your fork’s main branch synchronized with upstream main to reduce drift between your fork’s main branch and the upstream main branch.

Here are the commands for keeping your fork synchronized with the upstream repository:

git fetch ceph
git checkout main
git reset --hard ceph/main
git push -u origin main

Follow this procedure often to keep your local main in sync with upstream main.

If the command git status returns a line that reads “Untracked files”, see the procedure on updating submodules.

Creating a Bugfix branch

Create a branch for your bugfix:

git checkout main
git checkout -b fix_1
git push -u origin fix_1

The first command (git checkout main) makes sure that the bugfix branch “fix_1” is created from the most recent state of the main branch of the upstream repository.

The second command (git checkout -b fix_1) creates a “bugfix branch” called “fix_1” in your local working copy of the repository. The changes that you make in order to fix the bug will be commited to this branch.

The third command (git push -u origin fix_1) pushes the bugfix branch from your local working repository to your fork of the upstream repository.

Fixing the bug in the local working copy

  1. Updating the tracker

    In the Ceph issue tracker, change the status of the tracker issue to “In progress”. This communicates to other Ceph contributors that you have begun working on a fix, which helps to avoid duplication of effort. If you don’t have permission to change that field, just comment that you are working on the issue.

  2. Fixing the bug itself

    This guide cannot tell you how to fix the bug that you have chosen to fix. This guide assumes that you know what required improvement, and that you know what to do to provide that improvement.

    It might be that your fix is simple and requires only minimal testing. But that’s unlikely. It is more likely that the process of fixing your bug will be iterative and will involve trial, error, skill, and patience.

    For a detailed discussion of the tools available for validating bugfixes, see the chapters on testing.

Pushing the Fix to Your Fork

You have finished work on the bugfix. You have tested the bugfix, and you believe that it works.

  1. Commit the changes to your local working copy.

    Commit the changes to the fix_1 branch of your local working copy by using the --signoff option (here represented as the s portion of the -as flag):

    git commit -as
    
  2. Push the changes to your fork:

    Push the changes from the fix_1 branch of your local working copy to the fix_1 branch of your fork of the upstream repository:

    git push origin fix_1
    

    Note

    In the command git push origin fix_1, origin is the name of your fork of the upstream Ceph repository, and can be thought of as a nickname for git@github.com:username/ceph.git, where username is your GitHub username.

    It is possible that origin is not the name of your fork. Discover the name of your fork by running git remote -v, as shown here:

    $ git remote -v
    ceph   https://github.com/ceph/ceph.git (fetch)
    ceph   https://github.com/ceph/ceph.git (push)
    origin git@github.com:username/ceph.git (fetch)
    origin git@github.com:username/ceph.git (push)
    

    The line:

    origin git@github.com:username/ceph.git (fetch)
    

    and the line:

    origin git@github.com:username/ceph.git (push)
    

    provide the information that “origin” is the name of your fork of the Ceph repository.

Opening a GitHub pull request

After you have pushed the bugfix to your fork, open a GitHub pull request (PR). This makes your bugfix visible to the community of Ceph contributors. They will review it. They may perform additional testing on your bugfix, and they might request changes to the bugfix.

Be prepared to receive suggestions and constructive criticism in the form of comments within the PR.

If you don’t know how to create and manage pull requests, read this GitHub pull request tutorial.

To learn what constitutes a “good” pull request, see the Git Commit Good Practice article at the OpenStack Project Wiki.

See also our own Submitting Patches document.

After your pull request (PR) has been opened, update the Issue Tracker by adding a comment directing other contributors to your PR. The comment can be as simple as this:

*PR*: https://github.com/ceph/ceph/pull/$NUMBER_OF_YOUR_PULL_REQUEST

Understanding Automated PR validation

When you create or update your PR, the Ceph project’s Continuous Integration (CI) infrastructure automatically tests it. At the time of this writing (May 2022), the automated CI testing included many tests. These five are among them:

  1. a test to check that the commits are properly signed (see Submitting patches):

  2. a test to check that the documentation builds

  3. a test to check that the submodules are unmodified

  4. a test to check that the API is in order

  5. a make check test

Additional tests may be run depending on which files your PR modifies.

The make check test builds the PR and runs it through a battery of tests. These tests run on servers that are operated by the Ceph Continuous Integration (CI) team. When the tests have completed their run, the result is shown on GitHub in the pull request itself.

Test your modifications before you open a PR. Refer to the chapters on testing for details.

Notes on PR make check test

The GitHub make check test is driven by a Jenkins instance.

Jenkins merges your PR branch into the latest version of the base branch before it starts any tests. This means that you don’t have to rebase the PR in order to pick up any fixes.

You can trigger PR tests at any time by adding a comment to the PR - the comment should contain the string “test this please”. Since a human who is subscribed to the PR might interpret that as a request for him or her to test the PR, you must address Jenkins directly. For example, write “jenkins retest this please”. If you need to run only one of the tests, you can request it with a command like “jenkins test signed”. A list of these requests is automatically added to the end of each new PR’s description, so check there to find the single test you need.

If there is a build failure and you aren’t sure what caused it, check the make check log. To access the make check log, click the “details” (next to the make check test in the PR) link to enter the Jenkins web GUI. Then click “Console Output” (on the left).

Jenkins is configured to search logs for strings that are known to have been associated with make check failures in the past. However, there is no guarantee that these known strings are associated with any given make check failure. You’ll have to read through the log to determine the cause of your specific failure.

Integration tests AKA ceph-qa-suite

Since Ceph is complex, it may be necessary to test your fix to see how it behaves on real clusters running on physical or virtual hardware. Tests designed for this purpose live in the ceph/qa sub-directory and are run via the teuthology framework.

The Ceph community has access to the Sepia lab where Testing - Integration Tests can be run on physical hardware. Other developers may add tags like “needs-qa” to your PR. This allows PRs that need testing to be merged into a single branch and tested all at the same time. Since teuthology suites can take hours (even days in some cases) to run, this can save a lot of time.

To request access to the Sepia lab, start here.

Integration testing is discussed in more detail in the Testing - Integration Tests chapter.

Code review

Once your bugfix has been thoroughly tested, or even during this process, it will be subjected to code review by other developers. This typically takes the form of comments in the PR itself, but can be supplemented by discussions on IRC and the Mailing lists.

Amending your PR

While your PR is going through testing and Code Review, you can modify it at any time by editing files in your local branch.

After updates are committed locally (to the fix_1 branch in our example), they need to be pushed to GitHub so they appear in the PR.

Modifying the PR is done by adding commits to the fix_1 branch upon which it is based, often followed by rebasing to modify the branch’s git history. See this tutorial for a good introduction to rebasing. When you are done with your modifications, you will need to force push your branch with:

git push --force origin fix_1

Why do we take these extra steps instead of simply adding additional commits the PR? It is best practice for a PR to consist of a single commit; this makes for clean history, eases peer review of your changes, and facilitates merges. In rare circumstances it also makes it easier to cleanly revert changes.

Merging

The bugfix process completes when a project lead merges your PR.

When this happens, it is a signal for you (or the lead who merged the PR) to change the Issue Tracker status to “Resolved”. Some issues may be flagged for backporting, in which case the status should be changed to “Pending Backport” (see the Backporting chapter for details).

See also Commit merging: scope and cadence for more information on merging.

Proper Merge Commit Format

This is the most basic form of a merge commit:

doc/component: title of the commit

Reviewed-by: Reviewer Name <rname@example.com>

This consists of two parts:

  1. The title of the commit / PR to be merged.

  2. The name and email address of the reviewer. Enclose the reviewer’s email address in angle brackets.

Using .githubmap to Find a Reviewer’s Email Address

If you cannot find the email address of the reviewer on his or her GitHub page, you can look it up in the .githubmap file, which can be found in the repository at /ceph/.githubmap.

Using “git log” to find a Reviewer’s Email Address

If you cannot find a reviewer’s email address by using the above methods, you can search the git log for their email address. Reviewers are likely to have committed something before. If they have made previous contributions, the git log will probably contain their email address.

Use the following command

git log

Using ptl-tool to Generate Merge Commits

Another method of generating merge commits involves using Patrick Donnelly’s ptl-tool pull commits. This tool can be found at /ceph/src/script/ptl-tool.py. Merge commits that have been generated by the ptl-tool have the following form:

Merge PR #36257 into main
* refs/pull/36257/head:
        client: move client_lock to _unmount()
        client: add timer_lock support
Reviewed-by: Patrick Donnelly <pdonnell@redhat.com>

Miscellaneous

–set-upstream

If you forget to include the --set-upstream origin x option in your git push command, you will see the following error message:

fatal: The current branch {x} has no upstream branch.
To push the current branch and set the remote as upstream, use
   git push --set-upstream origin {x}

To set up git to automatically create the upstream branch that corresponds to the branch in your local working copy, run this command from within the ceph/ directory:

git config --global push.autoSetupRemote true

Deleting a Branch Locally

To delete the branch named localBranchName from the local working copy, run a command of this form:

git branch -d localBranchName

Deleting a Branch Remotely

To delete the branch named remoteBranchName from the remote upstream branch (which is also your fork of ceph/ceph, as described in Creating a Fork of the Ceph Repository), run a command of this form:

git push origin --delete remoteBranchName

Searching a File Longitudinally for a String

To search for the commit that introduced a given string (in this example, that string is foo) into a given file (in this example, that file is file.rst), run a command of this form:

git log -S 'foo' file.rst