Level 2: OpenSearch Contributor Onboarding

Level 1 gave you a working OpenSearch you can build, test, and run. This level turns that capability into merged pull requests. You will learn how OpenSearch is actually contributed to: the GitHub-based model (issues and PRs, no JIRA), the DCO sign-off that replaces a CLA, the mandatory CHANGELOG.md entry, the precommit/CI gate, the review loop, and the backport mechanism. By the end you will have walked a trivial change, a realistic good-first-issue fix, and a code review from the maintainer's side of the table.

This is deliberately a workflow level. The contributions are surgical — a doc fix, a validation message, a missing test. Nothing here will surprise a reviewer. That is the point: you drill the mechanics now so that Levels 3–9 can be about the engine.


Learning Objectives

By the end of Level 2 you must be able to:

  1. Describe the OpenSearch contribution model end-to-end: issue → fork → branch → signed commit → PR → CI → review → merge → backport.
  2. Find and qualify a good first issue without stepping on another contributor.
  3. Make a clean, signed (git commit -s) commit that passes the DCO check.
  4. Add a correct CHANGELOG.md entry under ## [Unreleased].
  5. Run ./gradlew spotlessApply and ./gradlew precommit locally so CI passes on the first push.
  6. Open a PR that satisfies the PR template, understand each CI check, and respond to review without thrashing.
  7. Explain what the backport 2.x label does and when to apply it.

The OpenSearch Contribution Model

OpenSearch development happens entirely on GitHub at github.com/opensearch-project/OpenSearch. There is no Apache JIRA, no patch files, and no CLA. If you have contributed to an Apache project (like the Tez curriculum's JIRA + .patch flow), unlearn that here — OpenSearch is a fork-and-pull-request project.

The pieces you must internalize:

ArtifactWhat it isWhere
IssueA bug, enhancement, or task. The unit of "what should change."GitHub Issues, labeled (good first issue, bug, flaky-test, …).
Pull Request (PR)Your proposed change, against main.GitHub PRs, from your fork's branch.
DCODeveloper Certificate of Origin. Replaces a CLA. Asserted by a Signed-off-by line.Every commit: git commit -s. Enforced by the DCO check.
CHANGELOG.mdA human-readable log; every user-facing PR adds one line.Under ## [Unreleased], in an Added/Changed/Fixed/… section.
MAINTAINERS.mdWho can approve/merge, and who owns which areas.Repo root.
PR template.github/pull_request_template.md — the checklist your PR must satisfy.Auto-filled into the PR body.
SPDX headerThe Apache-2.0 license header every source file carries.Top of every .java file (precommit enforces it).

The governance context — TSC, the OpenSearch Software Foundation under the Linux Foundation, the forum and Slack — is covered in release-governance and community interaction. For contribution mechanics, GitHub + DCO + CHANGELOG is all you need.

DCO, not CLA

The DCO is a lightweight assertion — by signing off, you certify you wrote the change or have the right to submit it under the project's license. You assert it per-commit:

git commit -s -m "Your message"

-s appends a trailer:

Signed-off-by: Your Name <your.email@example.com>

The name and email must match your git config user.name / user.email. A bot enforces this on every PR; a commit without a valid Signed-off-by blocks the merge. There is no separate agreement to sign — this line is the agreement. You will do this for real in Lab 2.2.

The CHANGELOG entry

OpenSearch keeps a CHANGELOG.md (Keep-a-Changelog style). Almost every PR must add one line under the ## [Unreleased] heading, in the right subsection, with a link to the PR:

## [Unreleased 3.x]
### Added
- Add `foo` parameter to the `_bar` API ([#12345](https://github.com/opensearch-project/OpenSearch/pull/12345))
### Fixed
- Fix misleading validation message in `RestSomethingAction` ([#12346](https://github.com/opensearch-project/OpenSearch/pull/12346))

A missing CHANGELOG entry is the single most common reason a first PR gets a "please add a changelog entry" comment and an extra review round. (Purely internal changes — e.g. a test-only refactor — can sometimes use the "skip changelog" label, but default to adding one.)


Finding a Good First Issue

Restrict yourself, at this level, to issues labeled good first issue. They are curated to be scoped, self-contained, and low-risk.

# Browser:
#   https://github.com/opensearch-project/OpenSearch/issues?q=is:open+label:%22good+first+issue%22

# gh CLI — list and inspect:
gh issue list --repo opensearch-project/OpenSearch \
  --label "good first issue" --state open --limit 30

gh issue view 12345 --repo opensearch-project/OpenSearch --comments

Qualify before you claim. A good Level 2 issue:

  • has the good first issue label and is not assigned to anyone;
  • has no open linked PR (gh issue view shows linked PRs);
  • has a clear, bounded description — you can state the fix in one sentence;
  • has no unresolved design debate in the comments.

When you find one, leave a short comment ("I'd like to work on this") before you start, so you do not duplicate someone's in-flight work. Etiquette is detailed in Community Interaction.

Warning: Do not open a PR and then find out two other people already did. Read the full comment thread and the linked-PR list first. This is the same discipline as the Tez "read all comments before claiming" rule — the platform changed, the etiquette did not.


The PR Lifecycle

flowchart TD
    A["Find/claim a good first issue"] --> B["Fork opensearch-project/OpenSearch"]
    B --> C["git clone your fork; add upstream remote"]
    C --> D["git checkout -b fix/issue-12345"]
    D --> E["Make the surgical change"]
    E --> F["Add a CHANGELOG.md entry under [Unreleased]"]
    F --> G["./gradlew spotlessApply"]
    G --> H["./gradlew precommit + scoped tests"]
    H --> I["git commit -s  (DCO sign-off)"]
    I --> J["git push origin fix/issue-12345"]
    J --> K["Open PR against main; fill the template"]
    K --> L["CI runs: gradle-check, assemble, precommit, DCO, CHANGELOG"]
    L -->|red| H
    L -->|green| M["Maintainer review"]
    M -->|changes requested| E
    M -->|approved| N["Maintainer merges (squash) to main"]
    N --> O["Add 'backport 2.x' label -> bot opens backport PR"]

The full state machine in words:

  1. Fork the repo to your account; clone your fork; add the canonical repo as the upstream remote so you can keep main current.
  2. Branch from an up-to-date main (fix/... or feature/...).
  3. Change exactly what the issue asks — nothing more (scope creep kills first PRs).
  4. CHANGELOG: add one line under ## [Unreleased].
  5. Format and gate locally: spotlessApply, then precommit, then the scoped tests for what you touched. (From Lab 1.2.)
  6. Commit with -s so the DCO check passes.
  7. Push and open a PR against main; complete the PR template.
  8. CI runs the checks (below). Green is required.
  9. Review: a maintainer (from MAINTAINERS.md) reviews. Respond to every comment; push more signed commits (do not force-push away the review history unless asked).
  10. Merge: a maintainer squash-merges. If the fix belongs on the maintenance line, they (or you, if you have rights) add the backport 2.x label and a bot opens the backport PR.

The CI checks you will see

CheckWhat it verifiesLocal equivalent
DCOEvery commit has a valid Signed-off-by.git commit -s
ChangelogA CHANGELOG.md entry was added (or the skip label applied).edit CHANGELOG.md
gradle-checkThe big one: builds + runs the relevant tests + precommit across affected projects../gradlew :server:check (subset)
assembleThe distribution still builds../gradlew assemble
precommitStatic analysis: checkstyle, forbidden APIs, SPDX headers, etc../gradlew precommit

Running spotlessApply + precommit + the scoped tests locally before you push is the single biggest lever on review speed. Detail on quality expectations is in PR Quality and Preparation.


Deliverables

Demonstrate all of the following before advancing to Level 3:

  • A fork of opensearch-project/OpenSearch with upstream configured, and a topic branch off an up-to-date main (Lab 2.1, Lab 2.2).
  • A signed commit whose Signed-off-by matches your git identity (a passing local DCO check).
  • A correct CHANGELOG.md entry under ## [Unreleased].
  • A clean local ./gradlew spotlessApply + ./gradlew precommit.
  • A walked good-first-issue fix with a unit test using assertThrows/assertEquals (Lab 2.3).
  • A completed review of the flawed example PR — you found every issue a maintainer would flag (Lab 2.4).
  • A written explanation of what backport 2.x does and when to apply it.

Common Mistakes

MistakeConsequenceFix
Forgetting -s on the commitDCO check fails; PR blockedgit commit -s; fix history with git commit --amend -s or git rebase --signoff.
Signed-off-by email ≠ git emailDCO check failsSet git config user.email to match; re-sign.
No CHANGELOG.md entryChangelog check fails; extra review roundAdd one line under ## [Unreleased] linking your PR.
Skipping spotlessApplyprecommit/CI fails on formattingRun ./gradlew spotlessApply before committing.
Scope creep ("while I'm here…")Reviewer asks for a split; PR stalls for weeksOne logical change per PR. File a follow-up issue for the rest.
Force-pushing over review historyReviewers lose the thread of what changedAdd new signed commits during review; squash happens at merge.
Opening a PR for a claimed issueDuplicate work, community frictionCheck assignee and linked PRs; comment before starting.
Treating the PR template as boilerplateMissing checkboxes; reviewer asks you to redo itFill it honestly — tests, CHANGELOG, related issues, DCO.

PR Profile: Level 2 Graduate

A Level 2 graduate can credibly open these PRs end-to-end, with passing CI on the first or second push:

PR typeExampleTest requirement
Doc/example fixCorrect an outdated curl or a wrong Javadoc @paramNone — docs only; still needs DCO + (often) CHANGELOG
Validation-message fixClarify a confusing error from a *Request.validate() or a REST parserA unit test asserting the new message (Lab 2.3)
Missing-assertion / test clarityAdd an assertEquals with a message to an under-checked testRe-run the test class
Misleading log lineConvert a string-concat LOG.info to placeholders; add contextUsually none; manual run noted in the PR

You are not yet ready to submit: changes to coordination, allocation, the engine, the search path, or anything touching the wire protocol / BWC. Those are Levels 3–9. What you are ready for is the thing most contributors get wrong: a clean, focused, well-tested, properly-signed PR with a CHANGELOG entry that a maintainer can merge without a five-round back-and-forth.

Next: Lab 2.1 — Navigate the OpenSearch Repository Structure.