blob: 30a7571ac53586a884990916f1feb41bd72919e2 [file] [log] [blame] [edit]
/* This file is a part of @mdn/browser-compat-data
* See LICENSE file for more information. */
import * as fs from 'node:fs';
import { compareVersions } from 'compare-versions';
import stringify from '../lib/stringify-and-order-properties.js';
import { newBrowserEntry, updateBrowserEntry } from './utils.js';
import type { ReleaseStatement } from '../../types/types.js';
/**
* getFirefoxReleaseNotesURL - Guess the URL of the release notes
* @param version release version
* @returns The URL of the release notes or the empty string if not found
*/
const getFirefoxReleaseNotesURL = async (version) => {
if (version === '1') {
return 'https://website-archive.mozilla.org/www.mozilla.org/firefox_releasenotes/en-US/firefox/releases/1.0.html';
}
return `https://developer.mozilla.org/docs/Mozilla/Firefox/Releases/${version}`;
};
/**
* updateFirefoxFile - Update the json file listing the browser version of a firefox entry
* @param options The list of options for this type of chromiums.
* @returns The log of what has been generated (empty if nothing)
*/
export const updateFirefoxReleases = async (options) => {
let result = '';
//
// Get the firefox.json from the local BCD
//
const file = fs.readFileSync(`${options.bcdFile}`);
const firefoxBCD = JSON.parse(file.toString());
//
// Update the three channels
//
const channels = new Map([
['current', options.releaseBranch],
['beta', options.betaBranch],
['nightly', options.nightlyBranch],
]);
const data = {};
let stableRelease = 1; // We will need this info afterwards; it will be calculated in the loop.
for (const [key, value] of channels) {
let releaseNotesURL;
// Extract version and release date
if (key !== 'current') {
// Get the JSON for the given train
const trainInfo = await fetch(`${options.firefoxScheduleURL}${value}`);
const train = await trainInfo.json();
releaseNotesURL = await getFirefoxReleaseNotesURL(
parseFloat(train.version).toString(),
);
data[value] = {};
data[value].version = parseFloat(train.version).toString();
data[value].releaseDate = train.release.substring(0, 10); // Remove the time part
} else {
// Get the JSON with all released versions and their dates
const firefoxVersions = await fetch(options.firefoxReleaseDateURL);
const releasedFirefoxVersions = await firefoxVersions.json();
// Extract the current stable version and its release date
Object.entries(releasedFirefoxVersions).forEach(([key]) => {
if (parseFloat(key) > stableRelease) {
stableRelease = parseFloat(key);
}
});
releaseNotesURL = await getFirefoxReleaseNotesURL(stableRelease);
data[value] = {};
data[value].version = stableRelease;
data[value].releaseDate = releasedFirefoxVersions[stableRelease + '.0'];
}
if (
firefoxBCD.browsers[options.bcdBrowserName].releases[data[value].version]
) {
result += updateBrowserEntry(
firefoxBCD,
options.bcdBrowserName,
data[value].version,
data[value].releaseDate,
key,
releaseNotesURL,
'',
);
} else {
// New entry
result += newBrowserEntry(
firefoxBCD,
options.bcdBrowserName,
data[value].version,
key,
'Gecko',
data[value].releaseDate,
releaseNotesURL,
data[value].version,
);
}
}
//
// Set all older releases are 'retired' (and the current ESR to 'esr')
//
// Find latest ESR
// Get the JSON with all released versions and their dates
const firefoxESRVersions = await fetch(options.firefoxESRDateURL);
const esrFirefoxVersions = await firefoxESRVersions.json();
// Extract the current esr version
let esrRelease = 1;
Object.entries(esrFirefoxVersions).forEach(([key]) => {
if (parseInt(key) > esrRelease) {
esrRelease = parseInt(key);
}
});
// Replace all old entries with 'retired' or 'esr'
Object.entries(
firefoxBCD.browsers[options.bcdBrowserName].releases as Record<
string,
ReleaseStatement
>,
).forEach(([key, entry]) => {
if (key === String(esrRelease)) {
if (key === String(stableRelease)) {
// If the current release is also considered the ESR release, "current" status takes priority
return;
}
result += updateBrowserEntry(
firefoxBCD,
options.bcdBrowserName,
key,
entry.release_date,
'esr',
'',
'',
);
} else if (parseFloat(key) < stableRelease) {
result += updateBrowserEntry(
firefoxBCD,
options.bcdBrowserName,
key,
entry.release_date,
'retired',
'',
'',
);
}
});
//
// Avoid duplicate Nightly release.
//
const nightlyReleases = Object.entries(
firefoxBCD.browsers[options.bcdBrowserName].releases as Record<
string,
ReleaseStatement
>,
)
.filter(([, release]) => release.status === 'nightly')
.sort(([a], [b]) => compareVersions(a, b));
if (nightlyReleases.length > 1) {
const [nightlyVersion, nightlyRelease] = nightlyReleases.shift() as [
string,
ReleaseStatement,
];
data[options.nightlyBranch].version = nightlyVersion;
data[options.nightlyBranch].releaseDate = nightlyRelease.release_date;
for (const [, release] of nightlyReleases) {
release.status = 'planned';
}
}
//
// Add a planned version entry
//
const planned = String(Number(data[options.nightlyBranch].version) + 1);
// Get the JSON for the planned version train
const trainInfo = await fetch(`${options.firefoxScheduleURL}${planned}`);
const train = await trainInfo.json();
if (firefoxBCD.browsers[options.bcdBrowserName].releases[planned]) {
result += updateBrowserEntry(
firefoxBCD,
options.bcdBrowserName,
planned,
train.release.substring(0, 10),
'planned',
'',
'',
);
} else {
// New entry
result += newBrowserEntry(
firefoxBCD,
options.bcdBrowserName,
planned,
'planned',
'Gecko',
train.release?.substring(0, 10), // Remove the time part
await getFirefoxReleaseNotesURL(planned),
planned,
);
}
//
// Write the update browser's json to file
//
fs.writeFileSync(`./${options.bcdFile}`, stringify(firefoxBCD) + '\n');
// Returns the log
if (result) {
result = `### Updates for ${options.browserName}\n${result}`;
}
return result;
};