Level 8: Real Issue Contribution
Every level before this one was curated. You built Tez from source against a known-good master, you
traced state machines someone chose for you, and you ran labs with a known answer. Level 8 is
different. Here you work the way Tez contributors actually work: you mine
issues.apache.org/jira/projects/TEZ for a real open issue, reproduce it deterministically,
root-cause it, fix it with a minimal diff, write the test that fails-then-passes, and open a GitHub
pull request that a committer will actually merge.
There is no answer key. The JIRA may be mis-triaged, five years stale, or already half-fixed. The "obvious" fix may be wrong. The repro may be intermittent. That is the job. This level teaches you the loop the rest of your contributor life runs on — the same loop the Capstone grades you on — and it hands you less scaffolding than any prior level.
Learning Objectives
By the end of Level 8 you must be able to:
- Mine the TEZ JIRA with real JQL for tractable open issues and triage them by reproducibility signals (stack trace, version, component, reporter responsiveness).
- Choose the right reproduction harness for a bug class: the
tez-dagunit-test state-machine harness, a local-mode DAG, or aMiniTezClusterintegration test. - Implement a minimal-diff fix that survives the build gates Tez actually enforces: Spotless
(bound to the
validatephase — it runs on every build), RAT, Checkstyle, and SpotBugs. - Write the fails-then-passes test in the same harness the module already uses.
- Open a merge-quality PR against
apache/teztitledTEZ-XXXX: <description>, link it to the JIRA, and read the Yetus precommit report it triggers. - Improve DAG failure diagnostics as a focused, low-risk, high-value contribution type.
The Real Tez Contribution Workflow
Tez is a JIRA-plus-GitHub project. The issue of record lives in Apache JIRA; the code review happens on a GitHub pull request. You need both halves.
flowchart LR
J[JIRA: TEZ-XXXX<br/>issues.apache.org] --> R[Reproduce<br/>fails on master]
R --> F[Fix + test<br/>minimal diff]
F --> P["PR to apache/tez<br/>title: TEZ-XXXX: ..."]
P --> CI[GitHub Actions build<br/>+ Jenkins/Yetus precommit]
CI -->|comments posted to PR| REV[Committer review]
REV -->|changes requested| F
REV -->|approved| M["Squash-merge:<br/>TEZ-XXXX: ... (#PR) (Author reviewed by Reviewer)"]
Verify this yourself in your checkout — the git history is the process documentation:
cd ~/src/oss-repos/tez # your real checkout
git log --oneline -5
330fdc8f1 TEZ-4711: Normalize ASF license header (#488) (Raghav Aggarwal reviewed by Laszlo Bodor)
b6b5d42fe TEZ-4718: Modernize Jenkins and Yetus integration to ensure full build and UT run on every PR (#498) ...
d0fa41151 [INFRA] Set up default rulesets for default and release branches (#499) (reviewed by Laszlo Bodor)
Read the pattern: TEZ-XXXX: <summary> (#<PR number>) (<Author> reviewed by <Reviewer>). The
committer squash-merges your PR and appends the review credit. Your job is the first half of that
line: a JIRA number, a one-line summary, and a PR.
Note: Older TEZ JIRAs are littered with attached
.patchfiles and the "Patch Available" status — that was the pre-GitHub workflow, and you will still see it when you read old issues in Lab 8.1. Do not imitate it. The current process, verified from the repository's ownJenkinsfileand commit history, is a GitHub PR; the JIRA stays the discussion and tracking record.
What CI actually runs
Two independent systems examine your PR. Know them before you push:
| System | Definition | What it does |
|---|---|---|
| GitHub Actions | .github/workflows/build.yml | Matrix build: Java 21 and 25 × ubuntu-latest and macos-latest, running mvn --batch-mode clean install -DskipTests -Dmaven.javadoc.skip=true on every push/PR to master |
| Jenkins + Apache Yetus | Jenkinsfile + dev-support/tez-personality.sh | The real precommit: diffs your PR against origin/master, runs Yetus test-patch.sh (rel/0.15.1) inside Docker (build-tools/docker/Dockerfile) — compile, javac warnings, javadoc, checkstyle, SpotBugs, shellcheck, codespell, and the full unit test run at the project root — then posts the verdict back to your PR as a comment with an emoji vote |
Details worth knowing from dev-support/tez-personality.sh (read it — it is short): the personality
forces compile and unit to run against the whole project, adds the -Ptest-patch profile (Xlint,
9999 max warnings) during the compile phase, and adds -Pspotbugs for the SpotBugs pass. The
Jenkinsfile passes --tests-filter=checkstyle, meaning checkstyle findings are reported — a
checkstyle nit will draw a reviewer comment even when it does not turn the build red.
The local gates
These run on your machine, driven by the root pom.xml (verified — read the <plugins> sections):
| Gate | Plugin | When it runs | Command |
|---|---|---|---|
| License headers + formatting | spotless-maven-plugin (import order java,javax,org.apache,com,net,io, removeUnusedImports, trimTrailingWhitespace, endWithNewline, license header from dev-support/spotless/license.java) | Every build — spotless-check is bound to the validate phase | mvn spotless:apply to fix |
| ASF license audit | apache-rat-plugin | On demand | mvn apache-rat:check |
| Style | maven-checkstyle-plugin (rules in tez-build-tools/src/main/resources/checkstyle/checkstyle.xml) | On demand / Yetus | mvn compile checkstyle:checkstyle |
| Static analysis | spotbugs-maven-plugin (per-module findbugs-exclude.xml) | On demand / Yetus | mvn compile spotbugs:spotbugs |
Because Spotless runs at validate, a stray trailing space or a missing license header fails
mvn clean install before it compiles a single class. Run mvn spotless:apply before every commit
and this class of CI failure disappears.
Required Reading
Before the labs, read these in your Tez checkout — none is long:
| What | Where | Why |
|---|---|---|
| Build + toolchain requirements | README.md (JDK 21+, Maven 3.9.14+, the full command list) | Your pre-PR checklist comes from here |
| The precommit pipeline | Jenkinsfile | So a Yetus comment on your PR is legible, not magic |
| The Yetus personality | dev-support/tez-personality.sh | Which checks run for which changed files |
| The contribution wiki | linked from README.md ("How to Contribute" on cwiki.apache.org) | Account setup, JIRA conventions |
| Project by-laws | docs/src/site/markdown/by-laws.md | Who can commit, how votes work |
And from this book: patch quality, JIRA review, and the Capstone overview — Level 8 is the Capstone's dress rehearsal.
Source Areas You Will Touch
| Area | Module | Typical Level 8 work |
|---|---|---|
| DAG/Vertex/TaskAttempt state machines | tez-dag (org.apache.tez.dag.app.dag.impl) | State-machine bugs, diagnostics quality (Lab 8.3) |
| Shuffle and fetchers | tez-runtime-library (...runtime.library.common.shuffle) | Fetch-failure handling, error reporting |
| Schedulers | tez-dag (org.apache.tez.dag.app.rm) | NPEs and edge cases (e.g. TEZ-4440) |
| Test harnesses | tez-dag tests (TestVertexImpl, TestTaskAttempt), tez-tests (MiniTezCluster, TestLocalMode, TestFaultTolerance) | Where your repro and regression test live |
| Example DAGs | tez-examples (WordCount, OrderedWordCount, JoinValidate, ...) | Minimal repro DAGs, all runnable with -local |
Choosing the Right Issue
Good first contributions, in rough order of acceptance likelihood:
| Type | Difficulty | Acceptance rate | Real precedent (verify with git log) |
|---|---|---|---|
| Error/log message improvement | Low | High | TEZ-4308 (whitespace + brackets in a shuffle error message — merged) |
| Missing test coverage | Low | High | TEZ-4699 shipped a 136-line test with a small fix |
| Flaky/broken test fix | Low–Medium | High | TEZ-4475 (NPE in TestLocalMode when the DAG finished early) |
| NPE in an edge case | Medium | High | TEZ-4566, TEZ-4440 |
| Deadlock/race fix | High | Medium | TEZ-4334 (needed a thread-dump-level repro) |
| New feature | High | Low — needs design discussion on JIRA first | see design via JIRA |
Rule: start with Minor or Trivial priority JIRAs, and with bug classes that have a deterministic repro. Do not attempt Blocker/Critical issues until you have merged patches behind you — you would be occupying an issue a committer needs fixed now.
Labs
| Lab | Title | Output |
|---|---|---|
| 8.1 | Find and Reproduce a Real JIRA Issue | A deterministic repro that fails on master, documented on the JIRA |
| 8.2 | Implement the Fix, Write the Test, Format the Patch | A merge-quality PR with a fails-then-passes test |
| 8.3 | Improve Error Messages for Failed DAGs | A diagnostics PR with a message-asserting unit test |
Deliverables
You must demonstrate all of the following before moving on:
- A triage note for a real open TEZ JIRA: symptom, suspected component, reproducibility signals, assignee check, plan.
-
A deterministic reproducer that fails on current master, in the correct harness (unit /
local-mode DAG /
MiniTezCluster), with the master commit hash recorded (Lab 8.1). - A minimal-diff fix plus a test that fails without the fix and passes with it (Lab 8.2).
-
Local gates green:
mvn spotless:applythenmvn clean install -DskipTests,mvn test -pl <module> -Dtest=<YourTest>,mvn apache-rat:check. -
A PR (or complete PR-ready branch) titled
TEZ-XXXX: <description>, with the JIRA and PR cross-linked. - One diagnostics improvement with a unit test asserting the new message (Lab 8.3).
Common Mistakes
| Mistake | Consequence | Fix |
|---|---|---|
| Fixing before reproducing | You "fix" the wrong thing and cannot prove otherwise | Build the repro first; it must fail on master |
| Test that passes before the fix | Proves nothing; reviewer rejects | Revert the fix locally and watch the test go red |
| Drive-by reformatting | Diff noise hides the real change | Spotless already enforces format; touch only what the bug requires |
Skipping mvn spotless:apply | mvn clean install fails at validate — before compiling a single class | Run it before every commit |
| PR title without the JIRA id | Yetus matches ^TEZ-[0-9]+$; humans triage by it | Title is TEZ-XXXX: <summary>, always |
| Working a claimed issue | Duplicate work, wasted weeks | Check assignee + linked PRs; comment your intent first |
Attaching a .patch to JIRA | That workflow is historical | Open a GitHub PR; link it on the JIRA |
| Picking a feature as a first contribution | Needs consensus-building first | Bugs and diagnostics first; features go through JIRA design discussion |
How to Verify You Are Done
cd ~/src/oss-repos/tez
# 1. Your repro exists and fails on clean master
git stash && mvn test -pl <module> -Dtest=<YourReproTest> ; git stash pop # expect FAIL
# 2. Fix applied: same test passes
mvn test -pl <module> -Dtest=<YourReproTest> # expect PASS
# 3. Gates
mvn spotless:apply && mvn clean install -DskipTests -Dmaven.javadoc.skip=true
mvn apache-rat:check
# 4. The PR exists, titled correctly, and the JIRA links to it
If all four hold, you have produced the same artifact set as every commit in git log --oneline.
PR Profile: Level 8 Graduate
A Level 8 graduate's first merged Tez PR looks like the small, real ones already in history — go
read them (git show <hash> --stat):
- Scope: one JIRA, one logical change, a handful of files. TEZ-4308 changed one file (+6/−5) and was merged. TEZ-4699 changed one class and added one test class.
- Test discipline: the fix and its test land together — TEZ-4699's
CSVResult.javachange shipped with a newTestCSVResult.java; TEZ-4569'sVertexImplfix shipped with a 509-line recovery test. - Process fluency: JIRA filed/claimed, PR titled
TEZ-XXXX: ..., Yetus report read and acted on, review comments answered with commits, committer squash-merges with the(Author reviewed by Reviewer)credit.
That profile — small, proven, process-clean — is what earns you the benefit of the doubt on your second, larger PR.
Next: Level 9 takes you into harder, release-relevant work — scheduler test coverage and performance regressions. The full graded version of this level's loop is the Capstone.