in app/classes/ReleaseInsights/Release.php [47:127]
public function getFutureSchedule(): array
{
$all_releases = new Data($this->product_details)->getMajorReleases();
if (! array_key_exists($this->version->normalized, $all_releases)) {
return ['error' => 'Not enough data for this version number.'];
}
// Future release date object
$release = new DateTime($all_releases[$this->version->normalized] . ' 06:00 PST');
$nightly_target = Version::decrement($this->version->normalized, 2);
// Calculate 1st day of the nightly cycle
$nightly = new DateTime($all_releases[$nightly_target]);
$nightly->modify('-1 day');
// Transform all the DateTime objects in the $schedule array into formated date strings
$date = fn(string|object $day): string => is_object($day) ? $day->format('Y-m-d H:i:sP') : $nightly->modify($day)->format('Y-m-d H:i:sP');
$schedule = [
#️⃣ Starting with Firefox 136, QA request deadline is before the start of the nightly cycle
'qa_request_deadline' => $date($nightly->modify('-3 days')),
'nightly_start' => $date($nightly->modify('+3 days')),
'a11y_request_deadline' => $date('Friday'),
'qa_feature_done' => $date('Friday +1 week 21:00'),
'qa_test_plan_due' => $date('Friday 21:00'),
'soft_code_freeze' => $date($nightly->modify('+1 week')->modify('Thursday 08:00')),
'qa_pre_merge_done' => $date('Friday 14:00'),
'string_freeze' => $date('Friday'),
'merge_day' => $date('Monday'),
'beta_1' => $date('Monday'),
'beta_2' => $date('Wednesday 13:00'),
'beta_3' => $date('Friday 13:00'),
'sumo_1' => $date('Friday 21:00'), // Friday of Beta week 1
'beta_4' => $date('Monday 13:00'),
'beta_5' => $date('Wednesday 13:00'),
'beta_6' => $date('Friday 13:00'),
'beta_7' => $date('Monday 13:00'),
'sumo_2' => $date('Monday 21:00'), // Monday of Beta Week 3
'beta_8' => $date('Wednesday 13:00'),
'qa_pre_rc_signoff' => $date('Wednesday 14:00'),
'beta_9' => $date('Friday 13:00'),
'rc_gtb' => match ($this->version->normalized) {
'147.0' => $date($nightly->modify('+1 week')->modify('Monday 21:00')),
default => $date('Monday 21:00'),
},
'rc' => $date('Tuesday'),
'release' => $date($release->setTimezone(new \DateTimeZone('UTC'))),
];
// Add the Android weekly release before the planned dot release mid-cycle
if (! in_array($this->version->int, $this->no_planned_dot_releases)) {
$schedule += ['mobile_dot_release' => $date($release->modify('+1 week 00:00'))];
}
// Add the planned dot release mid-cycle
if (! in_array($this->version->int, $this->no_planned_dot_releases)) {
if ($this->version->normalized === '146.0') {
$schedule += ['planned_dot_release' => $date($release->modify('December 18 00:00'))];
} else {
$schedule += ['planned_dot_release' => $date($release->modify('+1 week 00:00'))];
}
}
// Sort the schedule by date, needed for schedules with a fixup
asort($schedule);
// Dev mode: assert that qa_pre_rc_signoff happens before the last beta
// If not, this causes a 1 week shift in rc_gtb calculation
$post_qa_step = array_search('qa_pre_rc_signoff', array_keys($schedule)) + 1;
assert(
str_starts_with(
array_keys($schedule)[$post_qa_step],
'beta'
) === true
);
// The schedule starts with the release version number
return ['version' => $this->version->normalized] + $schedule;
}