mirror of
https://github.com/unraid/api.git
synced 2026-01-08 01:29:49 -06:00
feat(onboarding): update OnboardingTracker to support dynamic OS version path
- Refactored `OnboardingTracker` to utilize a configurable OS version file path based on the data directory. - Enhanced tests to verify behavior when the data directory is unavailable, ensuring fallback to the default version path. - Updated related logic to improve version tracking and persistence during application bootstrap. This update improves flexibility in OS version management and enhances the reliability of onboarding processes.
This commit is contained in:
@@ -106,6 +106,8 @@ describe('ApiConfigPersistence', () => {
|
||||
|
||||
describe('OnboardingTracker', () => {
|
||||
const trackerPath = path.join(PATHS_CONFIG_MODULES, 'onboarding-tracker.json');
|
||||
const dataDir = '/tmp/unraid-data';
|
||||
const versionFilePath = path.join(dataDir, 'unraid-version');
|
||||
let configService: ConfigService;
|
||||
let setMock: ReturnType<typeof vi.fn>;
|
||||
let configStore: Record<string, unknown>;
|
||||
@@ -115,6 +117,7 @@ describe('OnboardingTracker', () => {
|
||||
setMock = vi.fn((key: string, value: unknown) => {
|
||||
configStore[key] = value;
|
||||
});
|
||||
configStore['PATHS_UNRAID_DATA'] = dataDir;
|
||||
configService = {
|
||||
set: setMock,
|
||||
get: vi.fn((key: string) => configStore[key]),
|
||||
@@ -127,7 +130,7 @@ describe('OnboardingTracker', () => {
|
||||
|
||||
it('defers persisting last seen version until shutdown', async () => {
|
||||
mockReadFile.mockImplementation(async (filePath) => {
|
||||
if (filePath === '/etc/unraid-version') {
|
||||
if (filePath === versionFilePath) {
|
||||
return 'version="7.2.0-beta.3.4"\n';
|
||||
}
|
||||
throw Object.assign(new Error('Not found'), { code: 'ENOENT' });
|
||||
@@ -154,7 +157,7 @@ describe('OnboardingTracker', () => {
|
||||
|
||||
it('does not rewrite when version has not changed', async () => {
|
||||
mockReadFile.mockImplementation(async (filePath) => {
|
||||
if (filePath === '/etc/unraid-version') {
|
||||
if (filePath === versionFilePath) {
|
||||
return 'version="6.12.0"\n';
|
||||
}
|
||||
if (filePath === trackerPath) {
|
||||
@@ -192,9 +195,25 @@ describe('OnboardingTracker', () => {
|
||||
expect(mockAtomicWriteFile).not.toHaveBeenCalled();
|
||||
});
|
||||
|
||||
it('keeps previous version available to signal upgrade until shutdown', async () => {
|
||||
it('falls back to default version path when data directory is unavailable', async () => {
|
||||
delete configStore['PATHS_UNRAID_DATA'];
|
||||
|
||||
mockReadFile.mockImplementation(async (filePath) => {
|
||||
if (filePath === '/etc/unraid-version') {
|
||||
return 'version="7.3.0"\n';
|
||||
}
|
||||
throw Object.assign(new Error('Not found'), { code: 'ENOENT' });
|
||||
});
|
||||
|
||||
const tracker = new OnboardingTracker(configService);
|
||||
await tracker.onApplicationBootstrap();
|
||||
|
||||
expect(setMock).toHaveBeenCalledWith('onboardingTracker.currentVersion', '7.3.0');
|
||||
});
|
||||
|
||||
it('keeps previous version available to signal upgrade until shutdown', async () => {
|
||||
mockReadFile.mockImplementation(async (filePath) => {
|
||||
if (filePath === versionFilePath) {
|
||||
return 'version="7.1.0"\n';
|
||||
}
|
||||
if (filePath === trackerPath) {
|
||||
@@ -239,7 +258,7 @@ describe('OnboardingTracker', () => {
|
||||
|
||||
it('marks onboarding steps complete for the current version without clearing upgrade flag', async () => {
|
||||
mockReadFile.mockImplementation(async (filePath) => {
|
||||
if (filePath === '/etc/unraid-version') {
|
||||
if (filePath === versionFilePath) {
|
||||
return 'version="7.2.0"\n';
|
||||
}
|
||||
if (filePath === trackerPath) {
|
||||
|
||||
@@ -15,7 +15,7 @@ import { PATHS_CONFIG_MODULES } from '@app/environment.js';
|
||||
|
||||
const TRACKER_FILE_NAME = 'onboarding-tracker.json';
|
||||
const CONFIG_PREFIX = 'onboardingTracker';
|
||||
const OS_VERSION_FILE_PATH = '/etc/unraid-version';
|
||||
const DEFAULT_OS_VERSION_FILE_PATH = '/etc/unraid-version';
|
||||
|
||||
type CompletedStepState = {
|
||||
version: string;
|
||||
@@ -41,8 +41,14 @@ export class OnboardingTracker implements OnApplicationBootstrap, OnApplicationS
|
||||
private state: TrackerState = {};
|
||||
private sessionLastTrackedVersion?: string;
|
||||
private currentVersion?: string;
|
||||
private readonly versionFilePath: string;
|
||||
|
||||
constructor(private readonly configService: ConfigService) {}
|
||||
constructor(private readonly configService: ConfigService) {
|
||||
const unraidDataDir = this.configService.get<string>('PATHS_UNRAID_DATA');
|
||||
this.versionFilePath = unraidDataDir
|
||||
? path.join(unraidDataDir, 'unraid-version')
|
||||
: DEFAULT_OS_VERSION_FILE_PATH;
|
||||
}
|
||||
|
||||
async onApplicationBootstrap() {
|
||||
this.currentVersion = await this.readCurrentVersion();
|
||||
@@ -164,11 +170,11 @@ export class OnboardingTracker implements OnApplicationBootstrap, OnApplicationS
|
||||
|
||||
private async readCurrentVersion(): Promise<string | undefined> {
|
||||
try {
|
||||
const contents = await readFile(OS_VERSION_FILE_PATH, 'utf8');
|
||||
const contents = await readFile(this.versionFilePath, 'utf8');
|
||||
const match = contents.match(/^\s*version\s*=\s*"([^"]+)"\s*$/m);
|
||||
return match?.[1]?.trim() || undefined;
|
||||
} catch (error) {
|
||||
this.logger.error(error, `Failed to read current OS version from ${OS_VERSION_FILE_PATH}`);
|
||||
this.logger.error(error, `Failed to read current OS version from ${this.versionFilePath}`);
|
||||
return undefined;
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user