Time: 25 minutes. Code is only half of a project; the other half is
knowing what to do next, who does it and when it is done. You plan the
first release of calc-app with issues, labels, a milestone and a project
board, then fix a bug with a pull request that closes its issue
automatically.
The ideas in two minutes¶
| Tool | What it is | In our project |
|---|---|---|
| Issue | One unit of work: a bug, a feature, a task. It has a discussion, an assignee, and is open or closed | “Dividing by zero crashes” |
| Label | A coloured tag to classify issues | bug, enhancement, ci |
| Milestone | A group of issues with a due date, usually a release, with a progress bar | v1.0 |
| Project | A board or table that shows the issues of one or more repositories, with custom fields and automation | “Calc App roadmap” |
| Closing keyword | Closes #12 in a pull request: merging it closes issue #12 | the bug-fix PR |
2.1 Create the issues¶
Open the Issues tab of your repository and click New issue. You are
offered a Bug report and a Feature request form. They come from the
.github/ISSUE_TEMPLATE/ folder of the project: issue templates are just
files in the repository.
Create these four issues:
#3: the bug. Choose Bug report:
Title:
[Bug]: Dividing by zero shows "Internal Server Error"Steps to reproduce:
Open the app and compute 1 divide 0, or open /api/divide?a=1&b=0Expected:
A clear error message, such as "Cannot divide by zero"Actual:
500 INTERNAL SERVER ERROR
The form adds the bug label for you.
#4: a feature. Choose Feature request:
Title:
[Feature]: Add a power operationProblem:
As a user, I want to compute a to the power b.Proposed solution:
A "power" operation, so that /api/power?a=2&b=3 returns 8.
#5: documentation. Choose Blank issue:
Title:
Explain how to run the app with DockerLabel:
documentation
#6: a task, with a new label. First create the label: Issues →
Labels → New label, name ci, description Automation and pipelines, pick a colour → Create label. Then a blank issue:
Title:
Set up continuous integrationBody, a task list (it renders as checkboxes that track progress):
- [ ] Run the tests on every push and pull request - [ ] Block merging into main when the tests failLabel:
ci
On each issue, under Assignees, click assign yourself. In a comment,
you could notify a teammate by writing @ and their username, or reference
another issue by typing # and its number.
2.2 Plan a release with a milestone¶
Issues → Milestones → New milestone.
Title:
v1.0. Due date: next week. Description:First release: no known bugs, a power operation, CI and a Docker image.Create milestone.
Now put the four issues in it: in the Issues list, tick the checkbox of
all four, open the Milestone menu above the list, and choose v1.0.
The milestone page shows 0% complete, with 4 open issues.
2.3 Visualise the work on a project board¶
Open the Projects tab of your repository and click New project (it may be under the Link a project menu).
Choose Board, name it
Calc App roadmap, and click Create project.The board has three columns: Todo, In Progress and Done. At the bottom of Todo, click + Add item, type
#, pick yourcalc-apprepository, and select an issue. Repeat for all four.Drag the bug issue to In Progress: that’s what you work on next.
Try the other views: the Table layout (⋯ next to the view name → Layout) shows the same items as a spreadsheet, where you can add fields such as Priority or Estimate.
The board updates itself: open ⋯ (top right) → Workflows. The Item closed and Pull request merged workflows are on, so when an issue closes, its card moves to Done by itself.
2.4 Fix the bug with a pull request that closes the issue¶
Start from an up-to-date main, on a new branch:
git switch main
git pull
git switch -c fix-divide-by-zeroThe fix. In app/calculator.py, make divide refuse a zero divisor:
def divide(a, b):
if b == 0:
raise ValueError("Cannot divide by zero")
return a / bIn app/main.py, at the end of calculate, turn that error into a clean
400 Bad Request answer instead of a crash:
try:
result = OPERATIONS[operation](a, b)
except ValueError as error:
return jsonify(error=str(error)), 400
return jsonify(operation=operation, a=a, b=b, result=result)The tests. A fixed bug deserves a test, so that it can never come back
unnoticed. In tests/test_calculator.py, add import pytest as the first
line, and this test at the end:
def test_divide_by_zero():
with pytest.raises(ValueError):
divide(1, 0)And at the end of tests/test_api.py:
def test_divide_by_zero_is_a_client_error():
response = client.get("/api/divide?a=1&b=0")
assert response.status_code == 400
assert response.get_json()["error"] == "Cannot divide by zero"If you have Python, run pytest -v: 10 tests pass. Then commit and push:
git add .
git commit -m "Return a clear error when dividing by zero"
git push -u origin fix-divide-by-zeroOpen a pull request. In its description, link the issue with a closing keyword:
Dividing by zero now returns a 400 error with a clear message,
instead of a 500 Internal Server Error.
Closes #3Open issue #3: in its sidebar, under Development, the pull request is linked. Back in the PR, Merge pull request → Confirm merge → Delete branch. Then watch three things happen by themselves:
Issue #3 is closed, with a note that the PR closed it.
On the project board, its card moved to Done.
The
v1.0milestone is now 25% complete.
Update your local copy:
git switch main
git pullWhat you learned¶
Issues and issue templates, labels, task lists, assignees, milestones, project boards and their automation, and closing issues from pull requests. Every change now has a reason (an issue) and a review (a pull request). But nothing checks that a change doesn’t break the code. That is next. Continue with Part 3.