PRs are not bureaucracy — they are your team's primary tool for knowledge sharing, bug catching, and building a culture of quality. A good PR process makes teams faster, not slower.
/health endpoint returning JSON with service status, version, and timestamp. Required by the load balancer health check config (Day 9 nginx setup).healthcheck.sh script returning status + version + timestampCloses #42. Answers "why are we doing this?"nit: — Minor style or naming preference. Non-blocking. Author can ignore.suggestion: — Optional improvement. Not required to merge.question: — Asking for clarification, not requiring change.issue: — Something that must be fixed before merge.blocking: — Critical issue. Merge is blocked until resolved.praise: — Explicitly positive. "Great approach here!"nit: "Consider renaming fn to fetchUserById for clarity."suggestion: "Optional: Array.from() would be more readable than [...x] here."issue: "This will throw a NullPointerException if user is null — add a guard clause."blocking: "The DB password is hardcoded on line 47. Must be moved to env var before merge."question: "Is there a reason we're using setTimeout here instead of async/await?"praise: "Smart use of early returns — this is much cleaner than nested ifs."## Summary ## Motivation & Context ## Type of Change - [ ] 🐛 Bug fix (non-breaking change that fixes an issue) - [ ] ✨ New feature (non-breaking change adding functionality) - [ ] 💥 Breaking change (fix or feature causing existing functionality to break) - [ ] 📚 Documentation update - [ ] 🏗 Infrastructure / DevOps change - [ ] 🔒 Security fix ## Changes Made - - ## How Has This Been Tested? - [ ] Unit tests pass locally (`npm test`) - [ ] Manual testing steps: 1. 2. - [ ] No regressions in existing functionality ## Checklist - [ ] My code follows the project's style guide - [ ] I have added/updated relevant documentation - [ ] No secrets, passwords, or API keys in this PR - [ ] CI pipeline passes (tests + lint + security scan) - [ ] PR size is under 400 changed lines ## Screenshots (if applicable)
.github/PULL_REQUEST_TEMPLATE.md. Commit and push to main. From now on, every new PR on GitHub will automatically pre-fill the description box with this template. Zero effort for authors — consistent quality by default.
For different PR types, use a directory:
.github/
PULL_REQUEST_TEMPLATE/
feature.md
bugfix.md
hotfix.md
Access via URL param: ?template=hotfix.md
Closes #42 in the PR description. When the PR is merged, GitHub automatically closes issue #42. Also works: Fixes #42, Resolves #42. The Kanban card moves to Done automatically.
# === Required Settings === ✅ Require a pull request before merging Required approvals: 1 Dismiss stale reviews on new commit: ON Require review from code owners: ON (if CODEOWNERS exists) ✅ Require status checks before merging Search for and add your CI job name e.g. "build-and-test" from your GitHub Actions workflow Require branches to be up to date: ON ✅ Require conversation resolution before merging All review comments must be resolved ✅ Restrict who can push to matching branches Only designated team leads for emergency merges ✅ Do not allow bypassing the above settings Even repo admins must follow the rules # === Auto-delete Branches === ✅ Automatically delete head branches after merge No dangling branches after PR is merged # === Allowed Merge Types (pick one) === ✅ Allow squash merging ← Recommended for GitHub Flow ❌ Allow merge commits ← Disable for clean history ❌ Allow rebase merging ← Optional
Create .github/CODEOWNERS to auto-request reviews from the right people:
# Global: all files → team lead * @org/team-leads # Frontend: UI directory /src/components/ @org/frontend # Infrastructure: IaC + K8s /terraform/ @org/platform /k8s/ @org/platform /.github/workflows/ @org/platform # Security-sensitive files /src/auth/ @org/security-team
When someone opens a PR that touches these paths, the specified team is automatically added as a required reviewer.
"LGTM 👍" on a 1200-line PR that was open for 4 hours.
This defeats the entire purpose. The reviewer didn't actually review. A bug shipped in that PR will be blamed on the "reviewer who approved it." Don't be that person.
Fix: Set a PR size limit. Anything over 400 lines requires a genuine review justification.
Blocking a PR because of trailing spaces, import ordering, or naming conventions when automated linters should catch these.
Fix: Automate style checks with Prettier, ESLint, commitlint. Run them in CI. If a linter didn't catch it, it doesn't block the PR. Day 9 covers this.
Assigned as reviewer. Never reviews. PR waits for days. Author pings twice, no response. PR eventually merges without review to meet the sprint deadline.
Fix: Define SLA — reviews must happen within 4 business hours. Automate reminders. Don't assign busy people as sole reviewer.
A reviewer comments "the entire architecture here is wrong — we should use event-sourcing instead" on a 3000-line PR after 5 days of work.
Fix: Discuss architecture before coding. Use design documents, RFC (Request for Comments) processes, or a 15-min sync. Save large design feedback for planning, not PR review.
Add a PR template, enable branch protection, and submit a complete, well-described PR that you review yourself
.github/PULL_REQUEST_TEMPLATE.md with the template from Slide 7. Commit directly to main: chore: add PR template..github/CODEOWNERS with * @YOUR_GITHUB_USERNAME. This makes you the required reviewer for all files.main. Enable: Require PR, dismiss stale reviews, require conversations resolved. Allow Squash only. Save.git switch -c feat/add-env-config → create .env.example → commit → push → open PR. Notice the template pre-fills the description. Fill it in fully.nit: and one suggestion:. Resolve them both.# === 1. Add PR template === cd my-devops-app mkdir -p .github cat > .github/PULL_REQUEST_TEMPLATE.md << 'EOF' ## Summary <!-- What does this PR do? --> ## Motivation & Context <!-- Why is this needed? Closes #ISSUE --> ## Type of Change - [ ] Bug fix - [ ] New feature - [ ] Documentation update - [ ] Infrastructure change ## Changes Made - ## Testing - [ ] Tests pass - [ ] Manual testing done ## Checklist - [ ] No secrets in this PR - [ ] CI passes - [ ] Under 400 lines changed EOF git add .github/PULL_REQUEST_TEMPLATE.md git commit -m "chore: add PR description template" # === 2. Add CODEOWNERS === echo "* @YOUR_GITHUB_USERNAME" > .github/CODEOWNERS git add .github/CODEOWNERS git commit -m "chore: add CODEOWNERS for all files" git push origin main # === 3. Verify .github/ directory === ls .github/ # CODEOWNERS PULL_REQUEST_TEMPLATE.md
# === 4. Create feature for the PR === git switch main && git pull git switch -c feat/add-env-config # Create .env.example (never commit real .env) cat > .env.example << 'EOF' # Application configuration NODE_ENV=development PORT=8080 LOG_LEVEL=info # Database (fill these in for local dev) DB_HOST=localhost DB_PORT=5432 DB_NAME=myapp DB_USER=appuser DB_PASS= # Never commit real passwords! # External APIs API_KEY= # Get from team secrets manager EOF git add .env.example git commit -m "chore: add env config example file" echo "## Environment Setup" >> README.md echo "Copy .env.example to .env and fill in values." >> README.md git add README.md git commit -m "docs: add environment setup instructions" git push -u origin feat/add-env-config # → Open PR on GitHub → template auto-fills! # → Fill in all sections → Submit # → Review inline → Add 2 comments → Resolve # → Approve → Squash and merge
git push origin main directly. GitHub should reject with: "error: remote: — You cannot push to a protected branch." This confirms protection is active.
3 questions · 5 minutes · PR size, merge strategies, and squash merging
.github/PULL_REQUEST_TEMPLATE.mdProblems: No description. Vague title. 1200+ lines — impossible to review properly. Rubber-stamped. Bugs shipped.
Good: Clear title with issue link. Concise description. Small diff (47 lines). Explains the why. Tested. Reviewable in 5 minutes.
# In PR description or commit message body: Closes #42 # Auto-closes issue 42 on merge Fixes #42 # Same effect Resolves #42 # Same effect # Multiple issues: Closes #42, #43, #44 # Cross-repo: Closes org/other-repo#42 # In commit messages (also works): git commit -m "feat: add health check Closes #12" # What happens on merge: # → Issue #42 automatically closed # → Issue moves to "Done" in GitHub Projects # → Your Kanban card moves to Done # GitHub Actions that trigger on PR events: on: pull_request: types: [opened, synchronize, reopened] branches: [main] pull_request_review: types: [submitted]
If your Kanban board (from Day 3) is linked to your repo:
Your board is now a live view of your workflow — zero manual card moving needed.
Create labels in your repo and add them to PRs:
Labels power GitHub search: is:pr is:open label:hotfix
| Situation | ❌ Don't | ✅ Do |
|---|---|---|
| You spot a bug | "This is wrong." | "issue: This will throw a NullPointerException if user is null — consider adding a guard clause on line 12." |
| Minor style preference | Block the PR until renamed | "nit: consider renaming 'x' to 'retryCount' — not blocking, your call." |
| You don't understand code | "This makes no sense." | "question: I'm not familiar with this pattern — could you add a comment explaining why setTimeout is used here instead of a Promise?" |
| You see good code | Stay silent (only comment on problems) | "praise: really clean use of early returns here — makes the happy path obvious." |
| You have an alternative idea | "Do it my way." | "suggestion: Array.reduce() would be slightly more idiomatic here — happy to discuss which approach fits the codebase style better." |
| Large architecture change needed | List 20 architectural comments in the PR | Approve the current PR with a "question:" comment, and open a design discussion separately before the next PR. |
| You're the author and receive criticism | Get defensive or ignore comments | Thank for the feedback, address all comments (fix or explain why not), resolve all conversations before requesting re-review. |
| Day | Topic | Lab Output | Status |
|---|---|---|---|
| Day 6 ✅ | Git Fundamentals | my-devops-app on GitHub, SSH + aliases | Done |
| Day 7 ✅ | Branching Strategies | GitHub Flow PR merged, conflict resolved | Done |
| Day 8 ✅ | Pull Requests & Code Review | PR template + branch protection + reviewed PR | Done |
| Day 9 → | Git Hooks & Automation | Husky + lint-staged + commitlint pre-commit hook | Tomorrow |
| Day 10 | Git Advanced Lab | rebase -i, cherry-pick, bisect, reflog | Friday |
.gitignore preventing secret leaks.github/PULL_REQUEST_TEMPLATE.md.github/CODEOWNERS