Skip to main content

Repository: govuk-rota-generator

README

Generates a balanced rota, taking into account each developer’s availability and eligibility for different cover types.

There are some limitations to the generator, which we hope to resolve in future iterations:

  1. Currently no way of capping certain shift types.
  2. It doesn’t account for different working patterns (e.g. devs who don’t work Fridays currently have to find cover)
  3. The week is marked as ‘unavailable’ even if only one cover type is off limits. For example, a developer may say they’re unavailable to do on-call at the weekend, but they would still be available to do in-hours shifts.
  4. It doesn’t account for bank holidays.
  5. It doesn’t account for team burden (i.e. there’s nothing preventing it allocating multiple devs from the same team on one shift).
  6. It doesn’t give a perfectly balanced rota (some devs will be allocated more slots than others), but a ‘balancing’ step after a first pass could be something we look at in future.

We hope one day to make the rota generator think in terms of days rather than weeks, and also have tighter integration with the pay-pagerduty repo (e.g. merging together under a new name).

Setup

In GCP, there’s a govuk-rota-generator ‘project’ which has a google-sheet-fetcher ‘service account’ (which automatically has its own email address google-sheet-fetcher@govuk-rota-generator.iam.gserviceaccount.com).

The 2nd-line-support Google group is an ‘Owner’ of the service account, so anyone in that group should be able to create a service account key for local use. From the google-sheet-fetcher service account page:

  1. “Add Key” -> “JSON” -> “Create”
  2. This will download a JSON file.
  3. Store it as google_service_account_key.json (which is git-ignored) at the root of this repo.

Usage

Create a developer availability form

  1. Clone the form template
  2. Update the dates etc, but otherwise make no changes to the form structure
  3. Link it to a spreadsheet
  4. Share the spreadsheet with google-sheet-fetcher@govuk-rota-generator.iam.gserviceaccount.com, as an Editor. (Dismiss the warning about sharing with external email addresses)
  5. Add a worksheet / ‘tab’ called “Auto-generated draft rota” (which is where the draft rota will be pushed by govuk-rota-generator)
  6. Send out the form, gather responses

Get the data ready

Run the fetch_data script, passing the URL of your responses spreadsheet as a parameter, e.g.

ruby bin/fetch_data.rb https://docs.google.com/spreadsheets/d/abc123def456hij789/edit

This will generate a data/rota_inputs.yml file, combining your responses spreadsheet with the Technical Support Google Sheet.

The generated file will look something like:

---
dates:
- 01/04/2024
- 02/04/2024
- 03/04/2024
- 04/04/2024
- 05/04/2024
- 06/04/2024
- 07/04/2024
people:
- email: dev.eloper@digital.cabinet-office.gov.uk
  team: Unknown
  non_working_days: []
  can_do_roles:
  - :inhours_primary
  - :inhours_secondary
  - :inhours_primary_standby
  - :inhours_secondary_standby
  - :oncall_primary
  - :oncall_secondary
  forbidden_in_hours_days: []
  forbidden_on_call_days: []
  assigned_shifts: []

Generate the rota

Run ruby bin/generate_rota.rb https://docs.google.com/spreadsheets/d/abc123def456hij789/edit.

This generates a data/generated_rota.yml file, which has the same structure as the data/rota_inputs.yml file. But the script will also output a user-friendly CSV to the “Auto-generated draft rota” worksheet you set up earlier, or to STDOUT if you don’t provide the Google Sheet CLI parameter. The worksheet/CSV can be used as the data/rota.csv in pay-pagerduty (automating the overriding of PagerDuty schedules).

Note that you can tweak the weighting of each ‘role’ (e.g. oncall_primary) by editing the values in config/roles.yml, to influence how often folks are assigned to particular roles.

Check the fairness of the rota

Run ruby bin/calculate_fairness.rb https://docs.google.com/spreadsheets/d/abc123def456hij789/edit.

This summarises the fairness of the rota at the “Auto-generated draft rota” worksheet you set up earlier.

Synchronise the rota with PagerDuty

Export an API key

You’ll need a PagerDuty API key associated with PagerDuty account that has “Global Admin” access (which can be configured in govuk-user-reviewer):

  1. Log into PagerDuty
  2. Navigate to “My Profile”
  3. Click on “User Settings”
  4. Click “Create API User Token”

Export this token as an ENV variable:

export PAGER_DUTY_API_KEY=$(more ~/pagerduty_token.txt)

Run the synchroniser script

You can now synchronise a rota with PagerDuty using:

ruby bin/sync_pagerduty.rb

This will:

  1. Use the rota in data/tmp_rota.yml (created automatically by the “calculate fairness” script)
  2. Map the roles in that rota to the roles in config/roles.yml, where it finds the corresponding PagerDuty schedule IDs
  3. Fetch the list of PagerDuty users and match these up with the users in your rota, warning on any names that are missing from PagerDuty (and skipping over those shifts)±
  4. Find conflicts between the PagerDuty schedule and the local rota, and apply overrides to fix them

± These engineers either don’t have PagerDuty accounts yet (because they lack Production Admin access - you can provide temporary access via govuk-user-reviewer), or the name derived from their email address doesn’t match the name PagerDuty has for them. For the latter, you can specify the mapping of the names in config/pagerduty_config_overrides.yml.

By default, the script will ask you to approve each override: y to override, n to skip, and exit to close the script altogether. This means you can do a ‘dry run’ of the synchroniser by choosing n each time.

If you wish to approve all of the overrides at once, you can pass the --bulk option:

ruby bin/sync_pagerduty.rb --bulk