Project Management
Manage epics and tasks in Code for Life.
GitHub
Code for Life is managed using GitHub Issues and GitHub Projects.
An issue is a task (most common) or epic that is assigned to a repo (see issue types).
Simply put, a GitHub project allows you to collect issues from one or more repos, visualize them in a variety of views, and create your own custom workflows. From GitHub's docs:
A project is an adaptable table, board, and roadmap that integrates with your issues and pull requests on GitHub to help you plan and track your work effectively at the user or organization level. You can create and customize multiple views by filtering, sorting, slicing, and grouping your issues and pull requests to manage your team backlogs and roadmaps, visualize work with configurable charts, add custom fields to track metadata specific to your team, create templates, share status updates, and automate your projects.
Custom Project Fields
GitHub Projects supports creating custom fields to track different values per issue. Below are the custom fields we define.

Status
[single select] The current status of a task in our Definition of Done.
Options:
To Do - To be completed but haven't started yet.
In Progress - Actively being worked on (unless blocked).
Ready For Review - Ready to be reviewed but haven't started yet.
In Review - Actively being reviewed.
Staging - Has been deployed to staging and needs testing.
Production - Has been deployed to production and needs testing.
Closed - Has been completed.
Size
[single select] Approximately how many man-hours is needed to close a task.
Epics should NOT be sized; their size may be inferred by summing the sizes of their sub-issues.
Options:
XS - Extra small (approx. 2hrs / ¼ working day).
S - Small (approx. 4hrs / ½ working day).
M - Medium (approx. 8hrs / 1 working day).
L - Large (approx. 16hrs / 2 working days).
XL - Extra large (approx. 24hrs / 3 working days).
Sprint
[iteration] The sprint the task is scheduled to be worked on. Our sprints are 2-week intervals.
Epics should NOT be assigned to a sprint.
Est. start
[date] The estimated start-date of an epic. Used in our Epic Roadmap.
ONLY epics' timelines should be estimated when roadmapping.
Est. end
[date] The estimated end-date of an epic. Used in our Epic Roadmap.
ONLY epics' timelines should be estimated when roadmapping.
Category
[single select] The type of work involved in a task.
Epics should NOT be categorized; sub-issues may span multiple categories.
Options:
💻 ( a.k.a. :computer: ) - Software development.
🎨 ( a.k.a. :art: ) - Design.
🔍 ( a.k.a. :mag: ) - Research.
📚 ( a.k.a. :books: ) - Educational resources.
⚙️ ( a.k.a. :gear: ) - Operations.
Definition of Done
Our Definition of Done is defined using our custom Status field. The order of the statuses matter as each subsequent status is one step closer to a task being "closed". As seen on our Task Board, the leftmost/first (No Status) column is where you find newly created tasks and the rightmost column is where you find Closed tasks; the general idea is to move the tasks from the left side of the board to the right.

Here's a high-level overview of how tasks move throughout the columns (not all possible paths).
Below are the statuses in order, each with:
a description of the conditions under which a task qualifies for the status;
general do's & do-not's for tasks in this status;
a list of acceptable previous/next status changes.
1. No Status
Technically this is the absence of a status and not an actual status. Newly created tasks go here.
When a task is first created, it should NOT be allocated a status.
Acceptable status changes:
➡️ In Progress - if a task is actively being worked on, regardless of sprint.
2. To Do
Tasks that have been prioritized for this sprint and are aimed to be completed by end-of-sprint. Tasks not started from previous sprints will remain in this column.
Acceptable status changes:
➡️ In Progress - if a task is actively being worked on, regardless of sprint.
3. In Progress
Tasks actively being worked on, regardless if they're assigned to a sprint or not.
If a task is blocked, by which we mean it cannot be progressed by the assignee(s), it should be labelled with (search "blocked" in labels to find these):
"🛑" if the task can be unblocked by someone inside of Ocado;
"🌍🛑" if the task can ONLY be unblocked by someone outside of Ocado.
Acceptable status changes:
➡️ Ready For Review - if a task's assignee(s) believe they have delivered the requirements.
4. Ready For Review
Tasks that are ready to be reviewed but haven't started being reviewed yet.
Acceptable status changes:
In Progress ⬅️ - if a task's assignee(s) realize that changes are required to the deliverables.
5. In Review
Tasks that are actively being reviewed.
Assignees should NOT review their own task; we do peer reviewing.
When a task is reviewed, the task's deliverables will either be accepted or the reviewer will request changes. If changes are requested, the task will go back to In Progress and the assignee(s) must request another review. It's normal for a task to go through multiple rounds of review before its deliverables are accepted. If a reviewer accepts, they should comment "LGTM" (an acronym for "looks good to me").
Acceptable status changes:
In Progress ⬅️ - if a reviewer requests changes on a task's deliverables.
6. Staging
Dev-tasks (💻) that have been deployed to our staging environment and require manual testing.
A clear description of how to manually test a task's deliverables should be provided by the assignee(s) in a comment. At least 2 different testers (not including the assignees) should test the task's deliverables. If a tester approves, they should comment "LGTM" (an acronym for "looks good to me").
Acceptable status changes:
In Progress ⬅️ - if a bug or missing requirement managed to slip through the reviews.
➡️ Production - if a dev-task (💻) was accepted in our staging environment.
7. Production
Dev-tasks (💻) that have been deployed to our production environment and require manual testing.
A clear description of how to manually test a task's deliverables should be provided by the assignee(s) in a comment. At least 2 different testers (not including the assignees) should test the task's deliverables. If a tester approves, they should comment "LGTM" (an acronym for "looks good to me").
Acceptable status changes:
In Progress ⬅️ - if a bug or missing requirement managed to slip through the reviews.
8. Closed
Tasks that have been completed.
Acceptable status changes:
In Progress ⬅️ - if a task's requirements weren't delivered and are actively being worked on.
Issue Relationships & Types
As documented by GitHub, you can add sub-issues to an issue which creates a child & parent relationship between issues. Depending on these relationships, we define different types of issues.
Below is an example relationship-graph between various issues.
Legend:
--🛑-- > = blocking relationship ("this issue is blocking that issue").
—👶— > = child relationship ("this issue has that issue as a child").
Epics
(In graph: A, B, G) Issues that...
...do have a sub-issue.
Epics are not tasks to be completed in themselves. Rather, epics represent initiatives that comprise multiple tasks. Epics are closed by closing all the sub-issues within them.
Top [Level] Epics
(In graph: A, G) Issues that...
...do have a sub-issue...
...and do NOT have a parent-issue.
Top-level epics contain sub-epics and/or tasks. These are useful for breaking down larger initiatives into smaller ones, each with their own tasks.
Tasks
(In graph: C, D, E, F, H, I, J, K) Issues that...
...do NOT have a sub-issue.
Tasks are the actual work that needs to be completed.
Orphan Tasks
(In graph: J, K) Issues that...
...do NOT have a sub-issue...
...and do NOT have a parent-issue.
Orphan tasks are one-off tasks that are NOT part of an epic.
Ideally, we should have few of these; we want tasks to work towards initiatives set out in our roadmap.
(In graph: C, D) Issues that...
...do NOT have a sub-issue...
...and are blocking another issue.
Blocking tasks define a sequence in which tasks must be closed ("this task must be done before that task").
(In graph: D, E) Issues that...
...do NOT have a sub-issue...
...and are being blocked by another issue.
Blocked tasks define a sequence in which tasks must be closed ("this task must be done after that task").
Project Views
In GitHub, a project-view is a way to visualize the issues in a project. A project can have 1 or more views, where each view has its own visualization-customizations and preset filters. Fundamentally, GitHub supports 3 different view types:
Table - a spreadsheet comprised of issues.
Board - spreads issues across customizable columns.
Roadmap - a high-level visualization of issues across a configurable timespan.
Common Filters
There are a few filters common across our views. It's highly recommended you memorize them.
is:open- An issue that has not been closed.has:sub-issues-progress- An issue that has sub-issues (a.k.a. child-issues).has:parent-issue- An issue that is a sub-issue (and therefore has a parent).
Our Custom Views
Below are our custom project-views, each with:
a short description of the insight it gives us into our project;
the preset filters (and what they do).

This helps us to explore all the tasks in our project (also see Open Task Table).
Preset filters ("Filter to issues that..."):
-has:sub-issues-progress- ...do NOT have sub-issues.
All open tasks assigned to the current or a previous Sprint, grouped by Status and by Assignee.
This helps to see how many open tasks are remaining in the current sprint, including tasks carried over from previous sprints.
Preset filters ("Filter to issues that..."):
-has:sub-issues-progress- ...do NOT have sub-issues...sprint:<=@current- ...and are in the current or previous sprints...has:status- ...and have a status (aren't in the No Status column)...-status:Closed- ...and are NOT in the Closed column (this hides the column).
All open tasks.
Similar to our Task Board, this helps us to explore all the open tasks in our project but see them in a dense spreadsheet format that supports bulk-editing field values by multi-selecting cells.
Preset filters ("Filter to issues that..."):
-has:sub-issues-progress- ...do NOT have sub-issues...is:open- ...and are open.
All open top-level epics.
This helps us to estimate the timelines (start & end) of each top-level epic so that we can roughly plan the year ahead. Generally, the next quarter (3 months) should be understood to be well planned, with each proceeding quarter having rougher estimations.
The only thing that is constant is change — Heraclitus
Preset filters ("Filter to issues that..."):
has:sub-issues-progress- ...have sub-issues...-has:parent-issue- ...and do NOT have a parent-issue...is:open- ...and are open.
Roles & Responsibilities
Below are the roles we define when managing our project, each with their own responsibilities and assignee(s).
[Sprint] Planner 🧭
Prioritizes tasks by assigning them to the current or upcoming sprints.
Responsibilities:
(Un)assigns tasks to a sprint.
Chases CFL team members to curate tasks which are assigned to next sprint.
Consults CFL team members for potential blocking tasks.
Assignees: CFL's team lead, Sidi Jow.
[House] Keeper 🧹
Curates tasks to maintain a clean project with well defined requirements.
Responsibilities:
Writes a full description.
Writes the required deliverables.
Sets the correct labels.
Sets the correct Size.
Sets the correct Category.
Sets the correct relationships.
Checks with other CFL team members if there are any doubts on any details.
Closes tasks that are no longer relevant.
Assignees: Everyone in CFL.
[Trouble] Maker 💣
Creates new tasks to track work that needs to be done at some point.
Responsibilities:
Creates new tasks with full descriptions and correct field values.
Assignees: Everyone in CFL.
[Project] Contributor 💪
Is assigned to tasks, delivers their requirements, and follows our Definition of Done [to close tasks].
Responsibilities:
Updates the Status to reflect the current situation.
Regularly comments significant progress-updates.
Comments any discoveries which are perceived to be 'blockers'.
Comments any discoveries which are believed to change the required deliverables.
Attaches or links to the required deliverables in a comment.
Addresses all feedback (through multiple review rounds if necessary) until the reviewer accepts.
Avoids sharing PII of others and security vulnerabilities, which others could use to exploit.
Is kind, collaborative and patient with everyone.
Assignees: Anyone.
Automated Workflows
To keep our project 'clean' we've created @cfl-bot whose job it is to monitor to all issues and:
nudge user(s) or team(s) to create clean issues by commenting on them with change requests;
perform actions on others' behalf when prompted;
enforce rules (unless ignored).
Prompts
Contributors can instruct @cfl-bot to perform actions on their behalf by commenting one of the following prompts:
"assign me"
Description: Assigns you to an issue.
Use When: You want to work on an issue.
"unassign me"
Description: Unassigns you from an issue.
Use When: You no longer want to work on an issue.
"ready for review"
Description: Sets the status of an issue to Ready For Review.
Use When: You've attached deliverables to an issue and you would like a CFL team member to review it.
"requires changes"
Description: Sets the status of an issue to In Progress.
Use When: You've realized that your deliverables are missing something.
"link pr <number> <repo?>"
Description: Links a pull request to an issue.
Arguments:
<number> The number of the PR to link.
<repo?> The repo the PR is in.* Defaults to the issue's repo.
Use When: You want to associate your code changes with an issue.
Examples:
link pr 1link pr 1 codeforlife-portallink pr 1 portal
"unlink pr <number> <repo?>"
Description: Unlinks a pull request from an issue.
Arguments:
<number> The number of the PR to unlink.
<repo?> The repo the PR is in.* Defaults to the issue's repo.
Use When: You want to disassociate your code changes with an issue.
Examples:
unlink pr 1unlink pr 1 codeforlife-portalunlink pr 1 portal
Prompt Notes
*Only CFL repos may be specified. You can optionally omit the "codeforlife-" prefix.
Bot-Ignore Labels
If a CFL team member wants an issue to be ignored by the bot, they can add the bot-ignore label.
"🤖" ( a.k.a. :robot: ) - ignores all rules.
Bot-ignore labels should be used sparingly! We should not lightly abandon the rules that help us keep order.
Last updated
Was this helpful?