export function getSystemUpgrades(): Promise<{ | export function getSystemUpgrades(): Promise<{ | ||||
upgrades: SystemUpgrade[]; | upgrades: SystemUpgrade[]; | ||||
latestLTS: string; | |||||
latestLTA: string; | |||||
installedVersionActive: boolean; | |||||
updateCenterRefresh: string; | updateCenterRefresh: string; | ||||
}> { | }> { | ||||
return getJSON('/api/system/upgrades'); | return getJSON('/api/system/upgrades'); |
} | } | ||||
}; | }; | ||||
} | } | ||||
export function useAppState() { | |||||
return React.useContext(AppStateContext); | |||||
} |
* along with this program; if not, write to the Free Software Foundation, | * along with this program; if not, write to the Free Software Foundation, | ||||
* Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. | * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. | ||||
*/ | */ | ||||
import { Banner, Variant } from 'design-system'; | |||||
import { Banner } from 'design-system'; | |||||
import { groupBy, isEmpty, mapValues } from 'lodash'; | import { groupBy, isEmpty, mapValues } from 'lodash'; | ||||
import * as React from 'react'; | import * as React from 'react'; | ||||
import DismissableAlert from '../../../components/ui/DismissableAlert'; | import DismissableAlert from '../../../components/ui/DismissableAlert'; | ||||
import { translate } from '../../../helpers/l10n'; | import { translate } from '../../../helpers/l10n'; | ||||
import { hasGlobalPermission } from '../../../helpers/users'; | import { hasGlobalPermission } from '../../../helpers/users'; | ||||
import { useSystemUpgrades } from '../../../queries/system'; | import { useSystemUpgrades } from '../../../queries/system'; | ||||
import { AppState } from '../../../types/appstate'; | |||||
import { Permissions } from '../../../types/permissions'; | import { Permissions } from '../../../types/permissions'; | ||||
import { Dict } from '../../../types/types'; | |||||
import { CurrentUser, isLoggedIn } from '../../../types/users'; | |||||
import withAppStateContext from '../app-state/withAppStateContext'; | |||||
import withCurrentUserContext from '../current-user/withCurrentUserContext'; | |||||
import { isMinorUpdate, isPatchUpdate, isPreLTSUpdate, isPreviousLTSUpdate } from './helpers'; | |||||
const MAP_VARIANT: Dict<Variant> = { | |||||
[UpdateUseCase.NewMinorVersion]: 'info', | |||||
[UpdateUseCase.NewPatch]: 'warning', | |||||
[UpdateUseCase.PreLTS]: 'warning', | |||||
[UpdateUseCase.PreviousLTS]: 'error', | |||||
}; | |||||
import { isLoggedIn } from '../../../types/users'; | |||||
import { useAppState } from '../app-state/withAppStateContext'; | |||||
import { useCurrentUser } from '../current-user/CurrentUserContext'; | |||||
import { BANNER_VARIANT, isCurrentVersionLTA, isMinorUpdate, isPatchUpdate } from './helpers'; | |||||
interface Props { | interface Props { | ||||
dismissable: boolean; | |||||
appState: AppState; | |||||
currentUser: CurrentUser; | |||||
dismissable?: boolean; | |||||
} | } | ||||
const VERSION_PARSER = /^(\d+)\.(\d+)(\.(\d+))?/; | const VERSION_PARSER = /^(\d+)\.(\d+)(\.(\d+))?/; | ||||
export function UpdateNotification({ dismissable, appState, currentUser }: Readonly<Props>) { | |||||
export default function UpdateNotification({ dismissable }: Readonly<Props>) { | |||||
const appState = useAppState(); | |||||
const { currentUser } = useCurrentUser(); | |||||
const canUserSeeNotification = | const canUserSeeNotification = | ||||
isLoggedIn(currentUser) && hasGlobalPermission(currentUser, Permissions.Admin); | isLoggedIn(currentUser) && hasGlobalPermission(currentUser, Permissions.Admin); | ||||
const regExpParsedVersion = VERSION_PARSER.exec(appState.version); | const regExpParsedVersion = VERSION_PARSER.exec(appState.version); | ||||
const { data } = useSystemUpgrades({ | const { data } = useSystemUpgrades({ | ||||
enabled: canUserSeeNotification && regExpParsedVersion !== null, | enabled: canUserSeeNotification && regExpParsedVersion !== null, | ||||
}); | }); | ||||
return null; | return null; | ||||
} | } | ||||
const { upgrades, latestLTS } = data; | |||||
const { upgrades, installedVersionActive, latestLTA } = data; | |||||
const parsedVersion = regExpParsedVersion | const parsedVersion = regExpParsedVersion | ||||
.slice(1) | .slice(1) | ||||
.map(Number) | .map(Number) | ||||
}), | }), | ||||
); | ); | ||||
let useCase = UpdateUseCase.NewMinorVersion; | |||||
let useCase = UpdateUseCase.NewVersion; | |||||
if (isPreviousLTSUpdate(parsedVersion, latestLTS, systemUpgrades)) { | |||||
useCase = UpdateUseCase.PreviousLTS; | |||||
} else if (isPreLTSUpdate(parsedVersion, latestLTS)) { | |||||
useCase = UpdateUseCase.PreLTS; | |||||
} else if (isPatchUpdate(parsedVersion, systemUpgrades)) { | |||||
if (!installedVersionActive) { | |||||
useCase = UpdateUseCase.CurrentVersionInactive; | |||||
} else if ( | |||||
isPatchUpdate(parsedVersion, systemUpgrades) && | |||||
(isCurrentVersionLTA(parsedVersion, latestLTA) || !isMinorUpdate(parsedVersion, systemUpgrades)) | |||||
) { | |||||
useCase = UpdateUseCase.NewPatch; | useCase = UpdateUseCase.NewPatch; | ||||
} else if (isMinorUpdate(parsedVersion, systemUpgrades)) { | |||||
useCase = UpdateUseCase.NewMinorVersion; | |||||
} | } | ||||
const latest = [...upgrades].sort( | const latest = [...upgrades].sort( | ||||
return dismissable ? ( | return dismissable ? ( | ||||
<DismissableAlert | <DismissableAlert | ||||
alertKey={dismissKey} | alertKey={dismissKey} | ||||
variant={MAP_VARIANT[useCase]} | |||||
variant={BANNER_VARIANT[useCase]} | |||||
className={`it__promote-update-notification it__upgrade-prompt-${useCase}`} | className={`it__promote-update-notification it__upgrade-prompt-${useCase}`} | ||||
> | > | ||||
{translate('admin_notification.update', useCase)} | {translate('admin_notification.update', useCase)} | ||||
<SystemUpgradeButton | <SystemUpgradeButton | ||||
systemUpgrades={upgrades} | systemUpgrades={upgrades} | ||||
updateUseCase={useCase} | updateUseCase={useCase} | ||||
latestLTS={latestLTS} | |||||
latestLTA={latestLTA} | |||||
/> | /> | ||||
</DismissableAlert> | </DismissableAlert> | ||||
) : ( | ) : ( | ||||
<Banner variant={MAP_VARIANT[useCase]} className={`it__upgrade-prompt-${useCase}`}> | |||||
<Banner variant={BANNER_VARIANT[useCase]} className={`it__upgrade-prompt-${useCase}`}> | |||||
{translate('admin_notification.update', useCase)} | {translate('admin_notification.update', useCase)} | ||||
<SystemUpgradeButton | <SystemUpgradeButton | ||||
systemUpgrades={upgrades} | systemUpgrades={upgrades} | ||||
updateUseCase={useCase} | updateUseCase={useCase} | ||||
latestLTS={latestLTS} | |||||
latestLTA={latestLTA} | |||||
/> | /> | ||||
</Banner> | </Banner> | ||||
); | ); | ||||
} | } | ||||
export default withCurrentUserContext(withAppStateContext(UpdateNotification)); |
* Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. | * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. | ||||
*/ | */ | ||||
import { Variant } from 'design-system'; | |||||
import { isEmpty } from 'lodash'; | import { isEmpty } from 'lodash'; | ||||
import { sortUpgrades } from '../../../components/upgrade/utils'; | |||||
import { UpdateUseCase, sortUpgrades } from '../../../components/upgrade/utils'; | |||||
import { SystemUpgrade } from '../../../types/system'; | import { SystemUpgrade } from '../../../types/system'; | ||||
const MONTH_BEFOR_PREVIOUS_LTS_NOTIFICATION = 6; | |||||
import { Dict } from '../../../types/types'; | |||||
type GroupedSystemUpdate = { | type GroupedSystemUpdate = { | ||||
[x: string]: Record<string, SystemUpgrade[]>; | [x: string]: Record<string, SystemUpgrade[]>; | ||||
}; | }; | ||||
export const isPreLTSUpdate = (parsedVersion: number[], latestLTS: string) => { | |||||
export const isCurrentVersionLTA = (parsedVersion: number[], latestLTS: string) => { | |||||
const [currentMajor, currentMinor] = parsedVersion; | const [currentMajor, currentMinor] = parsedVersion; | ||||
const [ltsMajor, ltsMinor] = latestLTS.split('.').map(Number); | const [ltsMajor, ltsMinor] = latestLTS.split('.').map(Number); | ||||
return currentMajor < ltsMajor || (currentMajor === ltsMajor && currentMinor < ltsMinor); | |||||
}; | |||||
export const isPreviousLTSUpdate = ( | |||||
parsedVersion: number[], | |||||
latestLTS: string, | |||||
systemUpgrades: GroupedSystemUpdate, | |||||
) => { | |||||
const [ltsMajor, ltsMinor] = latestLTS.split('.').map(Number); | |||||
let ltsOlderThan6Month = false; | |||||
const beforeLts = isPreLTSUpdate(parsedVersion, latestLTS); | |||||
if (beforeLts) { | |||||
const allLTS = sortUpgrades(systemUpgrades[ltsMajor][ltsMinor]); | |||||
const ltsReleaseDate = new Date(allLTS[allLTS.length - 1]?.releaseDate ?? ''); | |||||
if (isNaN(ltsReleaseDate.getTime())) { | |||||
// We can not parse the LTS date. | |||||
// It is unlikly that this could happen but consider LTS to be old. | |||||
return true; | |||||
} | |||||
ltsOlderThan6Month = | |||||
ltsReleaseDate.setMonth(ltsReleaseDate.getMonth() + MONTH_BEFOR_PREVIOUS_LTS_NOTIFICATION) - | |||||
Date.now() < | |||||
0; | |||||
} | |||||
return ltsOlderThan6Month && beforeLts; | |||||
return currentMajor === ltsMajor && currentMinor === ltsMinor; | |||||
}; | }; | ||||
export const isMinorUpdate = (parsedVersion: number[], systemUpgrades: GroupedSystemUpdate) => { | export const isMinorUpdate = (parsedVersion: number[], systemUpgrades: GroupedSystemUpdate) => { | ||||
export const isPatchUpdate = (parsedVersion: number[], systemUpgrades: GroupedSystemUpdate) => { | export const isPatchUpdate = (parsedVersion: number[], systemUpgrades: GroupedSystemUpdate) => { | ||||
const [currentMajor, currentMinor, currentPatch] = parsedVersion; | const [currentMajor, currentMinor, currentPatch] = parsedVersion; | ||||
const allMinor = systemUpgrades[currentMajor]; | const allMinor = systemUpgrades[currentMajor]; | ||||
const allPatch = sortUpgrades(allMinor[currentMinor] || []); | |||||
const allPatch = sortUpgrades(allMinor?.[currentMinor] ?? []); | |||||
if (!isEmpty(allPatch)) { | if (!isEmpty(allPatch)) { | ||||
const [, , latestPatch] = allPatch[0].version.split('.').map(Number); | const [, , latestPatch] = allPatch[0].version.split('.').map(Number); | ||||
} | } | ||||
return false; | return false; | ||||
}; | }; | ||||
export const BANNER_VARIANT: Dict<Variant> = { | |||||
[UpdateUseCase.NewVersion]: 'info', | |||||
[UpdateUseCase.CurrentVersionInactive]: 'error', | |||||
[UpdateUseCase.NewPatch]: 'warning', | |||||
}; |
<Helmet defer={false} title={translate('system_info.page')} /> | <Helmet defer={false} title={translate('system_info.page')} /> | ||||
<PageContentFontWrapper className="sw-body-sm sw-pb-8"> | <PageContentFontWrapper className="sw-body-sm sw-pb-8"> | ||||
<div> | <div> | ||||
<UpdateNotification dismissable={false} /> | |||||
<UpdateNotification /> | |||||
</div> | </div> | ||||
{sysInfoData && ( | {sysInfoData && ( | ||||
<PageHeader | <PageHeader |
import { groupUpgrades, sortUpgrades, UpdateUseCase } from './utils'; | import { groupUpgrades, sortUpgrades, UpdateUseCase } from './utils'; | ||||
interface Props { | interface Props { | ||||
latestLTS: string; | |||||
latestLTA: string; | |||||
systemUpgrades: SystemUpgrade[]; | systemUpgrades: SystemUpgrade[]; | ||||
updateUseCase?: UpdateUseCase; | |||||
updateUseCase: UpdateUseCase; | |||||
} | } | ||||
export default function SystemUpgradeButton(props: Readonly<Props>) { | export default function SystemUpgradeButton(props: Readonly<Props>) { | ||||
const { latestLTS, systemUpgrades, updateUseCase } = props; | |||||
const { latestLTA, systemUpgrades, updateUseCase } = props; | |||||
const [isSystemUpgradeFormOpen, setSystemUpgradeFormOpen] = React.useState(false); | const [isSystemUpgradeFormOpen, setSystemUpgradeFormOpen] = React.useState(false); | ||||
<SystemUpgradeForm | <SystemUpgradeForm | ||||
onClose={closeSystemUpgradeForm} | onClose={closeSystemUpgradeForm} | ||||
systemUpgrades={groupUpgrades(sortUpgrades(systemUpgrades))} | systemUpgrades={groupUpgrades(sortUpgrades(systemUpgrades))} | ||||
latestLTS={latestLTS} | |||||
latestLTA={latestLTA} | |||||
updateUseCase={updateUseCase} | updateUseCase={updateUseCase} | ||||
/> | /> | ||||
)} | )} |
* along with this program; if not, write to the Free Software Foundation, | * along with this program; if not, write to the Free Software Foundation, | ||||
* Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. | * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. | ||||
*/ | */ | ||||
import { FlagMessage, Link, Modal, Variant } from 'design-system'; | |||||
import { FlagMessage, Link, Modal } from 'design-system'; | |||||
import { filter, flatMap, isEmpty, negate } from 'lodash'; | import { filter, flatMap, isEmpty, negate } from 'lodash'; | ||||
import * as React from 'react'; | import * as React from 'react'; | ||||
import withAppStateContext from '../../app/components/app-state/withAppStateContext'; | |||||
import { useAppState } from '../../app/components/app-state/withAppStateContext'; | |||||
import { BANNER_VARIANT } from '../../app/components/update-notification/helpers'; | |||||
import { translate } from '../../helpers/l10n'; | import { translate } from '../../helpers/l10n'; | ||||
import { AppState } from '../../types/appstate'; | |||||
import { SystemUpgrade } from '../../types/system'; | import { SystemUpgrade } from '../../types/system'; | ||||
import SystemUpgradeItem from './SystemUpgradeItem'; | import SystemUpgradeItem from './SystemUpgradeItem'; | ||||
import { SYSTEM_VERSION_REGEXP, UpdateUseCase } from './utils'; | import { SYSTEM_VERSION_REGEXP, UpdateUseCase } from './utils'; | ||||
interface Props { | interface Props { | ||||
appState: AppState; | |||||
onClose: () => void; | onClose: () => void; | ||||
systemUpgrades: SystemUpgrade[][]; | systemUpgrades: SystemUpgrade[][]; | ||||
latestLTS: string; | |||||
updateUseCase?: UpdateUseCase; | |||||
latestLTA: string; | |||||
updateUseCase: UpdateUseCase; | |||||
} | } | ||||
const MAP_ALERT: { [key in UpdateUseCase]?: Variant } = { | |||||
[UpdateUseCase.NewPatch]: 'warning', | |||||
[UpdateUseCase.PreLTS]: 'warning', | |||||
[UpdateUseCase.PreviousLTS]: 'error', | |||||
}; | |||||
export function SystemUpgradeForm(props: Readonly<Props>) { | |||||
const { appState, latestLTS, onClose, updateUseCase, systemUpgrades } = props; | |||||
export default function SystemUpgradeForm(props: Readonly<Props>) { | |||||
const appState = useAppState(); | |||||
const { latestLTA, onClose, updateUseCase, systemUpgrades } = props; | |||||
let systemUpgradesWithPatch: SystemUpgrade[][] = []; | let systemUpgradesWithPatch: SystemUpgrade[][] = []; | ||||
const alertVariant = updateUseCase ? MAP_ALERT[updateUseCase] : undefined; | |||||
const alertVariant = | |||||
updateUseCase !== UpdateUseCase.NewVersion ? BANNER_VARIANT[updateUseCase] : undefined; | |||||
const header = translate('system.system_upgrade'); | const header = translate('system.system_upgrade'); | ||||
const parsedVersion = SYSTEM_VERSION_REGEXP.exec(appState.version); | const parsedVersion = SYSTEM_VERSION_REGEXP.exec(appState.version); | ||||
let patches: SystemUpgrade[] = []; | let patches: SystemUpgrade[] = []; | ||||
systemUpgradesWithPatch.push(patches); | systemUpgradesWithPatch.push(patches); | ||||
} else { | } else { | ||||
let untilLTS = false; | |||||
let untilLTA = false; | |||||
for (const upgrades of systemUpgrades) { | for (const upgrades of systemUpgrades) { | ||||
if (untilLTS === false) { | |||||
if (untilLTA === false) { | |||||
systemUpgradesWithPatch.push(upgrades); | systemUpgradesWithPatch.push(upgrades); | ||||
untilLTS = upgrades.some((upgrade) => upgrade.version.startsWith(latestLTS)); | |||||
untilLTA = upgrades.some((upgrade) => upgrade.version.startsWith(latestLTA)); | |||||
} | } | ||||
} | } | ||||
} | } | ||||
onClose={onClose} | onClose={onClose} | ||||
body={ | body={ | ||||
<> | <> | ||||
{alertVariant && updateUseCase && ( | |||||
{alertVariant && ( | |||||
<FlagMessage variant={alertVariant} className={`it__upgrade-alert-${updateUseCase}`}> | <FlagMessage variant={alertVariant} className={`it__upgrade-alert-${updateUseCase}`}> | ||||
{translate('admin_notification.update', updateUseCase)} | {translate('admin_notification.update', updateUseCase)} | ||||
</FlagMessage> | </FlagMessage> | ||||
key={upgrades[upgrades.length - 1].version} | key={upgrades[upgrades.length - 1].version} | ||||
systemUpgrades={upgrades} | systemUpgrades={upgrades} | ||||
isPatch={upgrades === patches} | isPatch={upgrades === patches} | ||||
isLTSVersion={upgrades.some((upgrade) => upgrade.version.startsWith(latestLTS))} | |||||
isLTAVersion={upgrades.some((upgrade) => upgrade.version.startsWith(latestLTA))} | |||||
/> | /> | ||||
))} | ))} | ||||
</> | </> | ||||
/> | /> | ||||
); | ); | ||||
} | } | ||||
export default withAppStateContext(SystemUpgradeForm); |
export interface SystemUpgradeItemProps { | export interface SystemUpgradeItemProps { | ||||
edition: EditionKey | undefined; | edition: EditionKey | undefined; | ||||
isLTSVersion: boolean; | |||||
isLTAVersion: boolean; | |||||
isPatch: boolean; | isPatch: boolean; | ||||
systemUpgrades: SystemUpgrade[]; | systemUpgrades: SystemUpgrade[]; | ||||
} | } | ||||
export default function SystemUpgradeItem(props: SystemUpgradeItemProps) { | export default function SystemUpgradeItem(props: SystemUpgradeItemProps) { | ||||
const { edition, isPatch, isLTSVersion, systemUpgrades } = props; | |||||
const { edition, isPatch, isLTAVersion, systemUpgrades } = props; | |||||
const lastUpgrade = systemUpgrades[0]; | const lastUpgrade = systemUpgrades[0]; | ||||
const downloadUrl = getEditionDownloadUrl( | const downloadUrl = getEditionDownloadUrl( | ||||
getEdition(edition || EditionKey.community), | getEdition(edition || EditionKey.community), | ||||
lastUpgrade, | lastUpgrade, | ||||
); | ); | ||||
let header = translate('system.latest_version'); | let header = translate('system.latest_version'); | ||||
if (isLTSVersion) { | |||||
header = translate('system.lts_version'); | |||||
if (isLTAVersion) { | |||||
header = translate('system.lta_version'); | |||||
} else if (isPatch) { | } else if (isPatch) { | ||||
header = translate('system.latest_patch'); | header = translate('system.latest_patch'); | ||||
} | } |
header: byRole('heading', { name: 'system.system_upgrade' }), | header: byRole('heading', { name: 'system.system_upgrade' }), | ||||
downloadLink: byRole('link', { name: /system.see_sonarqube_downloads/ }), | downloadLink: byRole('link', { name: /system.see_sonarqube_downloads/ }), | ||||
ltsVersionHeader: byRole('heading', { name: /system.lts_version/ }), | |||||
ltaVersionHeader: byRole('heading', { name: /system.lta_version/ }), | |||||
newPatchWarning: byText(/admin_notification.update/), | newPatchWarning: byText(/admin_notification.update/), | ||||
}; | }; | ||||
await user.click(ui.learnMoreButton.get()); | await user.click(ui.learnMoreButton.get()); | ||||
expect(ui.header.get()).toBeInTheDocument(); | expect(ui.header.get()).toBeInTheDocument(); | ||||
expect(ui.ltsVersionHeader.get()).toBeInTheDocument(); | |||||
expect(ui.ltaVersionHeader.get()).toBeInTheDocument(); | |||||
expect(ui.downloadLink.get()).toBeInTheDocument(); | expect(ui.downloadLink.get()).toBeInTheDocument(); | ||||
}); | }); | ||||
renderSystemUpgradeButton( | renderSystemUpgradeButton( | ||||
{ | { | ||||
updateUseCase: UpdateUseCase.NewPatch, | updateUseCase: UpdateUseCase.NewPatch, | ||||
latestLTS: '9.9', | |||||
latestLTA: '9.9', | |||||
systemUpgrades: [{ downloadUrl: '', version: '9.9.1' }], | systemUpgrades: [{ downloadUrl: '', version: '9.9.1' }], | ||||
}, | }, | ||||
'9.9', | '9.9', | ||||
expect(ui.header.get()).toBeInTheDocument(); | expect(ui.header.get()).toBeInTheDocument(); | ||||
expect(ui.newPatchWarning.get()).toBeInTheDocument(); | expect(ui.newPatchWarning.get()).toBeInTheDocument(); | ||||
expect(ui.ltsVersionHeader.get()).toBeInTheDocument(); | |||||
expect(ui.ltaVersionHeader.get()).toBeInTheDocument(); | |||||
expect(ui.downloadLink.get()).toBeInTheDocument(); | expect(ui.downloadLink.get()).toBeInTheDocument(); | ||||
}); | }); | ||||
) { | ) { | ||||
renderComponent( | renderComponent( | ||||
<SystemUpgradeButton | <SystemUpgradeButton | ||||
latestLTS="9.9" | |||||
updateUseCase={UpdateUseCase.NewVersion} | |||||
latestLTA="9.9" | |||||
systemUpgrades={[ | systemUpgrades={[ | ||||
{ downloadUrl: 'eight', version: '9.8' }, | { downloadUrl: 'eight', version: '9.8' }, | ||||
{ downloadUrl: 'lts', version: '9.9' }, | { downloadUrl: 'lts', version: '9.9' }, |
import { SystemUpgrade } from '../../types/system'; | import { SystemUpgrade } from '../../types/system'; | ||||
export enum UpdateUseCase { | export enum UpdateUseCase { | ||||
NewMinorVersion = 'new_minor_version', | |||||
NewVersion = 'new_version', | |||||
CurrentVersionInactive = 'current_version_inactive', | |||||
NewPatch = 'new_patch', | NewPatch = 'new_patch', | ||||
PreLTS = 'pre_lts', | |||||
PreviousLTS = 'previous_lts', | |||||
} | } | ||||
export const SYSTEM_VERSION_REGEXP = /^(\d+)\.(\d+)(\.(\d+))?/; | export const SYSTEM_VERSION_REGEXP = /^(\d+)\.(\d+)(\.(\d+))?/; |
# Admin notification | # Admin notification | ||||
# | # | ||||
#------------------------------------------------------------------------------ | #------------------------------------------------------------------------------ | ||||
admin_notification.update.new_minor_version=There’s a new version of SonarQube available. Update to enjoy the latest updates and features. | |||||
admin_notification.update.new_patch=There’s an update available for your SonarQube instance. Please update to make sure you benefit from the latest security and bug fixes. | admin_notification.update.new_patch=There’s an update available for your SonarQube instance. Please update to make sure you benefit from the latest security and bug fixes. | ||||
admin_notification.update.pre_lts=You’re running a version of SonarQube that has reached end of life. Please upgrade to a supported version at your earliest convenience. | |||||
admin_notification.update.previous_lts=You’re running a version of SonarQube that is past end of life. Please upgrade to a supported version immediately. | |||||
admin_notification.update.new_version=There’s a new version of SonarQube available. Upgrade to the latest active version to access new updates and features. | |||||
admin_notification.update.current_version_inactive=You’re running a version of SonarQube that is no longer active. Please upgrade to an active version immediately. | |||||
#------------------------------------------------------------------------------ | #------------------------------------------------------------------------------ | ||||
# | # | ||||
system.how_to_upgrade=How to upgrade? | system.how_to_upgrade=How to upgrade? | ||||
system.latest_version=Latest Version | system.latest_version=Latest Version | ||||
system.latest_patch=Patch Release | system.latest_patch=Patch Release | ||||
system.lts_version=Latest LTS Version | |||||
system.lta_version=Latest LTA Version | |||||
system.log_level.warning=This level has performance impacts, please make sure to get back to INFO level once your investigation is done. Please note that when the server is restarted, logging will revert to the level configured in sonar.properties. | system.log_level.warning=This level has performance impacts, please make sure to get back to INFO level once your investigation is done. Please note that when the server is restarted, logging will revert to the level configured in sonar.properties. | ||||
system.log_level.warning.short=Current logs level has performance impacts, get back to INFO level. | system.log_level.warning.short=Current logs level has performance impacts, get back to INFO level. | ||||
system.log_level.info=Your selection does not affect the Search Engine. | system.log_level.info=Your selection does not affect the Search Engine. |