Pull requests, code review & GitHub Actions CI
On a team, code reaches main through pull requests (PRs): a proposal to merge a branch, with discussion,
review and automated checks attached. Good PR habits keep a codebase healthy and make everyone faster.
Writing a good pull request
- Small and focused: one feature or fix. 200 changed lines get a real review; 2,000 get a rubber stamp.
- Clear title: "Add GST breakdown to invoice PDF", not "changes".
- Description: what and why, how to test it, screenshots for UI, and a link to the issue (
Closes #42closes the issue automatically on merge). - Open a draft PR early to get feedback on direction before polishing.
git switch -c feature/invoice-gst
# ...commit work...
git push -u origin feature/invoice-gst
gh pr create --fill --draft # or use the "Compare & pull request" button
Reviewing code
Reviewers look for correctness, readability, tests, security (unvalidated input, secrets) and consistency with the codebase. Useful habits:
| Do | Avoid |
|---|---|
| Ask questions: "What happens if the list is empty?" | "This is wrong." |
Mark optional points as nit: |
Blocking on personal style |
| Suggest code with GitHub's suggestion blocks | Rewriting the whole PR in comments |
| Approve when it is good enough | Waiting for perfection |
Authors should reply to every comment, push fixes as new commits during review, and avoid taking feedback
personally. Branch protection rules on main can require approvals and passing checks before merging.
Merge options on GitHub
Create a merge commit keeps every commit; squash and merge turns the PR into one commit on main (popular
for tidy history); rebase and merge replays commits linearly. Teams usually pick one and stick with it.
GitHub Actions CI basics
Continuous integration runs your tests automatically on every push and PR. Workflows are YAML files in
.github/workflows/. A workflow has triggers (on), jobs that run on a fresh virtual machine
(runs-on) and steps that either run shell commands or use ready-made actions.
# .github/workflows/tests.yml
name: tests
on:
push:
branches: [main]
pull_request:
jobs:
test:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- uses: actions/setup-python@v5
with:
python-version: "3.12"
cache: pip
- run: pip install -r requirements.txt
- run: python manage.py test
env:
DJANGO_SECRET_KEY: ${{ secrets.DJANGO_SECRET_KEY }}
Secrets are added under the repository's Settings, Secrets and variables, Actions, and are masked in logs. A
failing check shows a red cross on the PR, and with branch protection it blocks the merge. Add linting (for example
ruff check .) as another step so style issues are caught before review.
Common mistakes
- Huge PRs that mix refactoring with new features.
- Merging with failing checks "just this once".
- Hard-coding secrets in workflow files instead of using
secrets. - Workflows that only run on
pushtomain, so PRs are never tested.
Practice
Add the workflow above to a Django project, open a PR that deliberately breaks a test and watch the check
fail, then fix it. Ask a friend to review the PR and practise leaving one question, one suggestion and one
nit: comment on theirs.