GitHub milestones and issues can be used to track and coordinate multiple teams working on parallel projects. You can use custom projmgr plans to set up a group of repos with a standard set of milestones and issues. This is useful whenever you’re overseeing a large group of people who should be following some similar process – for example, at a hackathon, unconf, group working session, or training.

Configuring Issues and Milestones

Imagine you are planning a hackathon or working session with 5 teams, each with their own GitHub repo within your organization named “team{i}” (for i from 1 to 5).

Suppose there is a specific set of steps you wish each team to progress through. These can be specified as a custom plan. For example, in a separate YAML file, suppose you save the following plan in a file “plan.yml”.

- title: Pre-Work
  description: Tasks to be completed before the hackathon
  due_on: 2019-12-31
  issue:
    - title: Introductions
      body: Each team member should post a brief introduction of themselves here
    - title: Project brainstorming
      body: >
        Each team member should post at least 1 project idea here and attempt to
        provide at least 1 constructive comment on another project idea shared.
        
- title: Project Specification
  description: Tasks for Day 1 AM to help ease the project management burdens
  due_on: 2020-01-15T11:59:59Z
  issue:
    - title: Set scope of project
      body: Define what success means for your project, bearing in mind the time constraints!
    - title: Assign roles
      body: >
        Roles can and should be fluid, but deciding upfront what team member take
        certain leading roles will save time throughout the day.
        
- title: Heads-Down Work Time
  due_on: 2020-01-16T10:00:00Z
  description: The bulk of your time goes here! Please add custom issues related to you project.
  issue:
    - title: Define API
      body: Consider the problem you are trying to solve and the best interface for it
        
- title: Presentation Preparation
  description: Tasks for Day 2 PM to help prepare for final read out
  due_on: 2020-01-16T13:00:00Z
  issue:
    - title: Outline key points
      body: >
        Decide what you want to share about your process and results. 
        Remember that you only have 15 minutes!
    - title: Make deck
      body: Make xaringan deck about your project
plan <- read_plan("plan.yml")

We can check that our plan was read correctly by printing it back out.

print(plan)
#> Plan: 
#> 1. Pre-Work (2 issues) 
#> 2. Project Specification (2 issues) 
#> 3. Heads-Down Work Time (1 issues) 
#> 4. Presentation Preparation (2 issues)

Next, create repository references for each repo, using purrr::map() for iteration.

repo_names <- paste0("team", 1:5)
repo_refs <- purrr::map(repo_names, ~create_repo_ref("emilyriederer", .))

Finally, we can again use purrr::walk() to post the project plan to each GitHub repository. (Note that purrr::map() would also work here, but purrr::walk() executes silently which is convenient when we don’t care about the return values.)

purrr::walk(repo_refs, ~post_plan(., plan))

Each repo is now populated with a set of milestones and related issues for the respective team to work through.

Example team repo

Communication

Posting project plans in this way has numerous benefits. Participants in your event may be interested to know ahead what they will be doing. Using the report_plan() function, you can convert all of the same information on GitHub into an aesthetic and readable list that could be shared in a website or an email

Pre-Work ( 0 / 7 )
  • ☐ Introductions
  • ☐ Project brainstorming

Project Specification ( 0 / 7 )
  • ☐ Set scope of project
  • ☐ Assign roles

Heads-Down Work Time ( 0 / 7 )
  • ☐ Define API

Presentation Preparation ( 0 / 7 )
  • ☐ Outline key points
  • ☐ Make deck

Tracking

You can also use this to monitor participant progress throughout the event, potentially noticing groups that are falling behind and might need assistance. We can apply our get_milestones() and parse_milestones() functions by mapping over the repository references.

milestone_lists <- purrr::map(repo_refs, get_milestones)
milestones <- purrr::map_dfr(milestone_lists, parse_milestones, .id = 'team')

This gives us data on all teams:

milestones
#>    team                    title number
#> 1     1                 Pre-Work      1
#> 2     1    Project Specification      2
#> 3     1     Heads-Down Work Time      3
#> 4     1 Presentation Preparation      4
#> 5     2                 Pre-Work      1
#> 6     2    Project Specification      2
#> 7     2     Heads-Down Work Time      3
#> 8     2 Presentation Preparation      4
#> 9     3                 Pre-Work      1
#> 10    3    Project Specification      2
#> 11    3     Heads-Down Work Time      3
#> 12    3 Presentation Preparation      4
#> 13    4                 Pre-Work      1
#> 14    4    Project Specification      2
#> 15    4     Heads-Down Work Time      3
#> 16    4 Presentation Preparation      4
#> 17    5                 Pre-Work      1
#> 18    5    Project Specification      2
#> 19    5     Heads-Down Work Time      3
#> 20    5 Presentation Preparation      4
#>                                                                          description
#> 1                                         Tasks to be completed before the hackathon
#> 2                     Tasks for Day 1 AM to help ease the project management burdens
#> 3  The bulk of your time goes here! Please add custom issues related to you project.
#> 4                              Tasks for Day 2 PM to help prepare for final read out
#> 5                                         Tasks to be completed before the hackathon
#> 6                     Tasks for Day 1 AM to help ease the project management burdens
#> 7  The bulk of your time goes here! Please add custom issues related to you project.
#> 8                              Tasks for Day 2 PM to help prepare for final read out
#> 9                                         Tasks to be completed before the hackathon
#> 10                    Tasks for Day 1 AM to help ease the project management burdens
#> 11 The bulk of your time goes here! Please add custom issues related to you project.
#> 12                             Tasks for Day 2 PM to help prepare for final read out
#> 13                                        Tasks to be completed before the hackathon
#> 14                    Tasks for Day 1 AM to help ease the project management burdens
#> 15 The bulk of your time goes here! Please add custom issues related to you project.
#> 16                             Tasks for Day 2 PM to help prepare for final read out
#> 17                                        Tasks to be completed before the hackathon
#> 18                    Tasks for Day 1 AM to help ease the project management burdens
#> 19 The bulk of your time goes here! Please add custom issues related to you project.
#> 20                             Tasks for Day 2 PM to help prepare for final read out
#>    creator_login n_open_issues n_closed_issues state created_at updated_at
#> 1  emilyriederer             0               2  open 2018-12-30 2018-12-30
#> 2  emilyriederer             0               2  open 2018-12-30 2018-12-30
#> 3  emilyriederer             1               0  open 2018-12-30 2018-12-30
#> 4  emilyriederer             2               0  open 2018-12-30 2018-12-30
#> 5  emilyriederer             0               2  open 2018-12-30 2018-12-30
#> 6  emilyriederer             1               1  open 2018-12-30 2018-12-30
#> 7  emilyriederer             1               0  open 2018-12-30 2018-12-30
#> 8  emilyriederer             2               0  open 2018-12-30 2018-12-30
#> 9  emilyriederer             0               2  open 2018-12-30 2018-12-30
#> 10 emilyriederer             0               2  open 2018-12-30 2018-12-30
#> 11 emilyriederer             0               1  open 2018-12-30 2018-12-30
#> 12 emilyriederer             0               2  open 2018-12-30 2018-12-30
#> 13 emilyriederer             0               2  open 2018-12-30 2018-12-30
#> 14 emilyriederer             2               0  open 2018-12-30 2018-12-30
#> 15 emilyriederer             1               0  open 2018-12-30 2018-12-30
#> 16 emilyriederer             2               0  open 2018-12-30 2018-12-30
#> 17 emilyriederer             2               0  open 2018-12-30 2018-12-30
#> 18 emilyriederer             2               0  open 2018-12-30 2018-12-30
#> 19 emilyriederer             1               0  open 2018-12-30 2018-12-30
#> 20 emilyriederer             2               0  open 2018-12-30 2018-12-30
#>        due_on closed_at
#> 1  2019-12-31     18261
#> 2  2020-01-15     18276
#> 3  2020-01-16        NA
#> 4  2020-01-16        NA
#> 5  2019-12-31     18261
#> 6  2020-01-15        NA
#> 7  2020-01-16        NA
#> 8  2020-01-16        NA
#> 9  2019-12-31     18261
#> 10 2020-01-15     18276
#> 11 2020-01-16     18277
#> 12 2020-01-16     18277
#> 13 2019-12-31     18261
#> 14 2020-01-15        NA
#> 15 2020-01-16        NA
#> 16 2020-01-16        NA
#> 17 2019-12-31        NA
#> 18 2020-01-15        NA
#> 19 2020-01-16        NA
#> 20 2020-01-16        NA

Which we can wrangle for quick summary views:

milestones %>%
  dplyr::mutate(percent_complete = n_closed_issues * 100 / (n_closed_issues + n_open_issues)) %>%
  dplyr::select(team, title, percent_complete, number) %>%
  tidyr::spread(team, percent_complete) %>%
  dplyr::arrange(number) %>%
  dplyr::select(-number)
#> # A tibble: 4 x 6
#>   title                      `1`   `2`   `3`   `4`   `5`
#>   <chr>                    <dbl> <dbl> <dbl> <dbl> <dbl>
#> 1 Pre-Work                   100   100   100   100     0
#> 2 Project Specification      100    50   100     0     0
#> 3 Heads-Down Work Time         0     0   100     0     0
#> 4 Presentation Preparation     0     0   100     0     0

In some cases a GitHub Project Board might be a better choice, but R provides easy integration with tweets, emails, Shiny apps, or other tools you may be using to communicate throughout your event.