public function getFutureSchedule()

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;
    }