Skip to content

Commit add4191

Browse files
authored
chore: months old version banner (#9352)
https://linear.app/unleash/issue/2-3309/warn-users-of-lagging-versions-3-months-old Adds a banner warning users in case they are running an outdated Unleash version (>=3 months old) in case the build date data is present. When clicking "Changelog" the users are redirected to https://github.com/Unleash/unleash/releases. ![image](https://github.com/user-attachments/assets/f6b9b361-e780-4558-8b6c-5987b12efe68)
1 parent 000ee66 commit add4191

File tree

8 files changed

+58
-1
lines changed

8 files changed

+58
-1
lines changed

frontend/src/component/App.tsx

+2
Original file line numberDiff line numberDiff line change
@@ -23,6 +23,7 @@ import { LicenseBanner } from './banners/internalBanners/LicenseBanner';
2323
import { Demo } from './demo/Demo';
2424
import { LoginRedirect } from './common/LoginRedirect/LoginRedirect';
2525
import { SecurityBanner } from './banners/internalBanners/SecurityBanner';
26+
import { MonthsOldVersionBanner } from './banners/internalBanners/MonthsOldVersionBanner';
2627

2728
const StyledContainer = styled('div')(() => ({
2829
'& ul': {
@@ -67,6 +68,7 @@ export const App = () => {
6768
/>
6869
<LicenseBanner />
6970
<SecurityBanner />
71+
<MonthsOldVersionBanner />
7072
<ExternalBanners />
7173
<InternalBanners />
7274
<StyledContainer>
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,33 @@
1+
import { Banner } from '../Banner/Banner';
2+
import useUiConfig from 'hooks/api/getters/useUiConfig/useUiConfig';
3+
import { parseValidDate } from 'component/common/util';
4+
import { differenceInMonths } from 'date-fns';
5+
6+
export const MonthsOldVersionBanner = () => {
7+
const {
8+
uiConfig: { versionInfo },
9+
} = useUiConfig();
10+
11+
if (!versionInfo?.buildDate) return null;
12+
13+
const buildDate = parseValidDate(versionInfo.buildDate);
14+
15+
if (!buildDate) return null;
16+
17+
const monthsOld = differenceInMonths(new Date(), new Date(buildDate));
18+
19+
const isOldBuild = monthsOld >= 3;
20+
21+
if (!isOldBuild) return null;
22+
23+
return (
24+
<Banner
25+
banner={{
26+
message: `Your Unleash version is ${monthsOld} months old. Please consider upgrading.`,
27+
variant: 'warning',
28+
link: 'https://github.com/Unleash/unleash/releases',
29+
linkText: 'Changelog',
30+
}}
31+
/>
32+
);
33+
};

frontend/src/interfaces/uiConfig.ts

+1
Original file line numberDiff line numberDiff line change
@@ -102,6 +102,7 @@ export interface IVersionInfo {
102102
isLatest: boolean;
103103
latest: Partial<IVersion>;
104104
current: IVersion;
105+
buildDate?: string;
105106
}
106107

107108
export interface IVersion {

src/lib/__snapshots__/create-config.test.ts.snap

+1
Original file line numberDiff line numberDiff line change
@@ -23,6 +23,7 @@ exports[`should create default config 1`] = `
2323
"initialAdminUser": undefined,
2424
"type": "open-source",
2525
},
26+
"buildDate": undefined,
2627
"clientFeatureCaching": {
2728
"enabled": true,
2829
"maxAge": 3600000,

src/lib/create-config.ts

+1
Original file line numberDiff line numberDiff line change
@@ -795,6 +795,7 @@ export function createConfig(options: IUnleashOptions): IUnleashConfig {
795795
dailyMetricsStorageDays,
796796
openAIAPIKey,
797797
userInactivityThresholdInDays,
798+
buildDate: process.env.BUILD_DATE,
798799
};
799800
}
800801

src/lib/openapi/spec/version-schema.ts

+8
Original file line numberDiff line numberDiff line change
@@ -56,6 +56,14 @@ export const versionSchema = {
5656
description: 'The instance identifier of the Unleash instance',
5757
example: '0d652a82-43db-4144-8e02-864b0b030710',
5858
},
59+
buildDate: {
60+
description:
61+
'The date and time of when this Unleash instance version was built',
62+
type: 'string',
63+
format: 'date-time',
64+
nullable: true,
65+
example: '2023-06-30T11:41:00.123Z',
66+
},
5967
},
6068
components: {},
6169
} as const;

src/lib/services/version-service.ts

+11-1
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,7 @@ export interface IVersionHolder {
1515
latest: Partial<IVersionInfo>;
1616
isLatest: boolean;
1717
instanceId: string;
18+
buildDate?: string;
1819
}
1920

2021
export interface IVersionResponse {
@@ -72,16 +73,23 @@ export default class VersionService {
7273

7374
private timer: NodeJS.Timeout;
7475

76+
private readonly buildDate?: string;
77+
7578
constructor(
7679
{ settingStore }: Pick<IUnleashStores, 'settingStore'>,
7780
{
7881
getLogger,
7982
versionCheck,
8083
enterpriseVersion,
8184
telemetry,
85+
buildDate,
8286
}: Pick<
8387
IUnleashConfig,
84-
'getLogger' | 'versionCheck' | 'enterpriseVersion' | 'telemetry'
88+
| 'getLogger'
89+
| 'versionCheck'
90+
| 'enterpriseVersion'
91+
| 'telemetry'
92+
| 'buildDate'
8593
>,
8694
) {
8795
this.logger = getLogger('lib/services/version-service.js');
@@ -94,6 +102,7 @@ export default class VersionService {
94102
this.telemetryEnabled = telemetry;
95103
this.versionCheckUrl = versionCheck.url;
96104
this.isLatest = true;
105+
this.buildDate = buildDate;
97106
}
98107

99108
private async readInstanceId(): Promise<string | undefined> {
@@ -164,6 +173,7 @@ export default class VersionService {
164173
latest: this.latest || {},
165174
isLatest: this.isLatest,
166175
instanceId: instanceId || 'unresolved-instance-id',
176+
buildDate: this.buildDate,
167177
};
168178
}
169179
}

src/lib/types/option.ts

+1
Original file line numberDiff line numberDiff line change
@@ -286,4 +286,5 @@ export interface IUnleashConfig {
286286
feedbackUriPath?: string;
287287
openAIAPIKey?: string;
288288
userInactivityThresholdInDays: number;
289+
buildDate?: string;
289290
}

0 commit comments

Comments
 (0)