Chapter 08Lesson 02~175 minutes

Code Review, Suggested Changes, CODEOWNERS, Review Requests, and Review Discipline: Guided Hands-On Workflow and Core Operations

Operate a disposable review workflow from scoped CODEOWNERS through PR comments, pending reviews, suggestions, review requests, structured inspection, an optional independent approval/change-request path, and evidence-based cleanup.

gh pr reviewSuggestionsReview requestsVerification

Learning objectives

  • Create a disposable public repository, scoped CODEOWNERS file, owned paths, topic branch, and pull request with observable ownership metadata.
  • Add inline feedback and a suggested change using the web review surface, then distinguish pending comments from a submitted review.
  • Use gh pr review for Comment/Approve/Request changes review submissions when the reviewer identity is eligible.
  • Inspect review requests, review decisions, submitted review commit IDs, checks, and CODEOWNERS parser errors through structured CLI/API output.
  • Apply or safely simulate a suggested change and verify the resulting head OID/commit movement.
  • Resolve a conversation only after the concern is addressed and finish with a mental-model challenge rather than a copy-only task.
Availability: Mandatory path: one GitHub Free account + one disposable public personal repository. CODEOWNERS and comments/suggestions are live. Because authors cannot supply an independent approval/change-request control for their own PR, the live Approve/Request changes step is optional and uses a second free collaborator identity with repository access. Organization teams and required-review enforcement are optional.
Shell portability: multi-line examples with trailing \, command substitution such as $(...), here-documents, and printf are labeled Git Bash/Bash/zsh. In PowerShell, place the same Git/gh arguments on one line or use the backtick for continuation; PowerShell-native file-writing alternatives are shown where the shell syntax materially differs. GitHub review semantics do not depend on the shell.

1. Scenario: review two ownership domains without touching production

Create c08-review-workflow-lab with docs/ and services/payments/. The repository owner is the default code owner. A topic branch modifies both areas and opens a PR. You will inspect CODEOWNERS matching, leave actionable feedback, stage a suggestion, and observe how a new commit changes the review evidence.

2. Preflight: authenticated identity and collision gate

gh auth status --active --hostname github.com
OWNER=$(gh api user --jq .login)
REPO="c08-review-workflow-lab"

gh repo view "$OWNER/$REPO" >/dev/null 2>&1 && {
  echo "STOP: $OWNER/$REPO already exists" >&2
  exit 2
}

git --version
gh --version

PowerShell equivalent: $OWNER = gh api user --jq .login and $REPO = "c08-review-workflow-lab". Never reuse a repository merely because a tutorial name already exists.

3. Create repository content and a valid CODEOWNERS file

gh repo create "$OWNER/$REPO" --public --add-readme --clone
cd "$REPO"
mkdir -p .github docs services/payments

cat > .github/CODEOWNERS <<EOF
*                         @$OWNER
/docs/                    @$OWNER
/services/payments/       @$OWNER
/.github/CODEOWNERS       @$OWNER
EOF

cat > docs/retry.md <<'EOF'
# Retry guidance

Retry operations must be bounded and observable.
EOF

cat > services/payments/config.txt <<'EOF'
max_retry_seconds=60
EOF

git add .github/CODEOWNERS docs/retry.md services/payments/config.txt
git commit -m "chore: establish review ownership domains"
git push
DEFAULT_BRANCH=$(git branch --show-current)
BASE_OID=$(git rev-parse HEAD)

The owner has write access to this personal repository, satisfying the CODEOWNERS owner requirement. The file is placed in .github/, the highest-priority supported location, and owns itself.

4. Verify parser state before depending on routing

gh api   -H "Accept: application/vnd.github+json"   -H "X-GitHub-Api-Version: 2026-03-10"   "repos/$OWNER/$REPO/codeowners/errors"   --jq '.errors'

Expected result: an empty array. If errors exist, fix them before opening the PR. A CODEOWNERS file with invalid lines may partially load, which is more dangerous than a clean failure because ownership can appear to work for some paths but not others.

5. Create the reviewable change and capture its head OID

git switch -c review/bounded-retry

cat >> docs/retry.md <<'EOF'

Production retries should stop after the configured maximum interval.
EOF

cat > services/payments/config.txt <<'EOF'
max_retry_seconds=90
EOF

git add docs/retry.md services/payments/config.txt
git commit -m "docs: clarify bounded retry policy"
git push -u origin review/bounded-retry
HEAD1=$(git rev-parse HEAD)

PR_URL=$(gh pr create   --base "$DEFAULT_BRANCH"   --head review/bounded-retry   --title "docs: review bounded retry policy"   --body "Chapter 08 disposable review lab. Do not merge yet.")
PR_NUMBER=${PR_URL##*/}

The command uses the default branch captured immediately after repository creation, so the workflow remains correct if your account or repository uses a name other than main.

6. Inspect ownership routing, review state, and checks before commenting

gh pr view "$PR_NUMBER" --json   number,isDraft,baseRefName,headRefName,headRefOid,reviewRequests,latestReviews,reviewDecision,statusCheckRollup,files,url

gh api   -H "Accept: application/vnd.github+json"   -H "X-GitHub-Api-Version: 2026-03-10"   "repos/$OWNER/$REPO/pulls/$PR_NUMBER/requested_reviewers"   --jq '{users:[.users[].login],teams:[.teams[].slug]}'

Because the only CODEOWNER is also the PR author, do not expect this one-account lab to manufacture an independent reviewer. The meaningful evidence is that the CODEOWNERS file parses and the changed paths match its documented patterns. If you have a second collaborator, add that user to the relevant CODEOWNERS line before opening a fresh test PR if you want to observe automatic review routing live.

7. Use Files changed: inline comment, pending review, and suggestion

Open the PR in the browser with gh pr view "$PR_NUMBER" --web. On services/payments/config.txt, add an inline comment that explains the risk rather than merely saying “wrong.” Start a review and keep it pending while adding a second comment on docs/retry.md. For the configuration line, use a suggestion block proposing max_retry_seconds=30.

This value expands the retry window beyond the documented bound. Please keep the configuration aligned with the operational policy.

```suggestion
max_retry_seconds=30
```

Before submitting, observe that the comments are part of a pending review. Submit as Comment in the one-account mandatory path. A self-review is useful for learning the UI, but it is not independent approval evidence.

8. Review submission through gh pr review

The CLI can submit the three review dispositions. Use --comment in the mandatory self path. Use --approve or --request-changes only from an eligible independent reviewer account.

# Mandatory self path: feedback without pretending it is independent approval.
gh pr review "$PR_NUMBER" --comment   --body "Review note: validate retry bound against the documented policy."

# OPTIONAL: run only from a second eligible collaborator identity.
# gh pr review "$PR_NUMBER" --request-changes #   --body "Please reduce max_retry_seconds before merge."
#
# Later, after the author fixes it, that reviewer may submit:
# gh pr review "$PR_NUMBER" --approve #   --body "Retry bound now matches the documented operating policy."
Identity boundary: never switch credentials silently. Run gh auth status --active --hostname github.com before reviewer actions and verify which account is active.

9. Manual review request: routing is not approval

If you have a disposable second collaborator with access, request that reviewer explicitly. The requester needs write access. Team review requests require an organization and have separate availability rules, so they are not part of the mandatory personal-repository path.

# OPTIONAL live collaborator path.
REVIEWER="SECOND_DISPOSABLE_REVIEWER"
gh pr edit "$PR_NUMBER" --add-reviewer "$REVIEWER"

gh pr view "$PR_NUMBER" --json reviewRequests,reviewDecision

10. Apply the suggestion or simulate author correction, then prove head movement

If the browser offers Commit suggestion to your author identity, apply the suggestion. GitHub will create a commit on the PR branch. If you prefer a shell-only reproducible path, make the same correction locally; the important lesson is the resulting head movement, not which UI generated the commit.

# Shell-only equivalent when not applying the web suggestion.
printf 'max_retry_seconds=30
' > services/payments/config.txt
git add services/payments/config.txt
git commit -m "fix: keep retry interval within policy"
git push
HEAD2=$(git rev-parse HEAD)

gh pr view "$PR_NUMBER" --json headRefOid,commits,latestReviews,reviewDecision
printf 'before=%s
after=%s
' "$HEAD1" "$HEAD2"

The head OID must change. Any approval or request-changes review submitted before this commit now needs to be interpreted under the repository freshness policy; GitHub does not let you assume the old review automatically covers new content.

11. Inspect submitted review evidence and check state

gh api   -H "Accept: application/vnd.github+json"   -H "X-GitHub-Api-Version: 2026-03-10"   "repos/$OWNER/$REPO/pulls/$PR_NUMBER/reviews"   --jq '.[] | {id,user:.user.login,state,commit_id,submitted_at}'

gh pr checks "$PR_NUMBER" || true

Compare each review commit_id with the current headRefOid. If they differ, ask which policy is intended: dismiss stale approvals, require newest-push approval, or rely on explicit human re-review.

12. Resolve conversations only after evidence exists

Return to the PR web UI. Reply with the fix commit or evidence, then resolve the conversation. If an independent reviewer requested changes, re-request their review after the correction. Resolution communicates “this thread is handled”; it should follow the repair, not replace it.

13. Challenge: choose the control, do not copy a command

Your team says: “Changes to services/payments/ should automatically reach the payments maintainers, but documentation edits should not block on them. Every material push after approval must receive fresh independent attention.” Which controls belong where?

  • Use scoped CODEOWNERS patterns for expertise routing; do not assign the payments team to all files.
  • Use required code-owner review only if that ownership must be a merge gate; automatic request alone is routing.
  • Choose stale-approval dismissal or most-recent-reviewable-push approval based on the team’s freshness semantics.
  • Keep CI/status checks separate from human ownership review.

14. Cleanup

Close the disposable PR without merging, archive the repository after verifying owner/name, then remove the local clone. If a second collaborator was added only for the lab, remove that access before archiving if you want the evidence package to reflect final least privilege.

gh pr close "$PR_NUMBER" --comment "Chapter 08 review lab complete; intentionally not merged."
cd ..
printf 'archive-check=%s/%s
' "$OWNER" "$REPO"
gh repo archive "$OWNER/$REPO"
rm -rf "$REPO"
Cleanup boundary: permanent deletion is optional and intentionally not required. Archiving is reversible and preserves review evidence.

15. Lesson summary

You built ownership metadata, verified it before relying on it, created actionable inline review feedback and a suggestion, inspected review requests/reviews/checks through structured interfaces, moved the PR head, and treated freshness as policy. The optional second-account path adds genuine independent approval/change-request semantics without making paid GitHub features mandatory.

Knowledge check

Why is a self-submitted Comment review useful but not sufficient independent approval evidence?

What should you verify before depending on CODEOWNERS routing?

What observable state must change when a suggestion is applied?

Why compare review commit_id with current headRefOid?

Does resolving a thread automatically change reviewDecision?

Next lesson

Design the policy instead of accumulating controls

Lesson 03 compares CODEOWNERS granularity, team ownership, required review, freshness rules, comment severity, and review SLAs as explicit production tradeoffs.

Authoritative references

 About code owners
 Reviewing proposed changes in a pull request
 Incorporating feedback in your pull request
 Requesting a pull request review
 gh pr review
 gh pr view
 gh pr checks
 REST API endpoints for pull request reviews
 REST API endpoints for review requests
 REST endpoint: list CODEOWNERS errors
 REST API versions

Keep the academy open

Support free, practical DevOps education.

Every lesson is designed to remain readable in a browser, downloadable from GitHub, and usable without a paid learning platform. Contributions help expand and maintain the curriculum.

Ethereum / ERC-20
0x716c4Ab160C4B66F31a28AE2448BfF68fc3a2ef0 Send only Ethereum/ERC-20 compatible assets to this address.