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.
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 reviewfor 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.
\, 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."
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"
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?
It teaches the review mechanics, but the same identity that authored the change is not an independent reviewer control.
What should you verify before depending on CODEOWNERS routing?
That the file is in a supported base-branch location, its patterns/owners are valid, and the listed owners have the required access.
What observable state must change when a suggestion is applied?
A commit is created on the PR compare/head branch, so the head OID changes.
Why compare review commit_id with current headRefOid?
It shows whether a submitted review was attached to the same head commit that is currently proposed.
Does resolving a thread automatically change reviewDecision?
Not necessarily. Conversation resolution and submitted review disposition/policy are separate states.
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.
0x716c4Ab160C4B66F31a28AE2448BfF68fc3a2ef0
Send only Ethereum/ERC-20 compatible assets to this
address.