fix: add fake migration to skip the duplicated UpdateWebPush migration

This commit is contained in:
gauthier-th
2025-07-20 23:50:33 +02:00
parent 33f1e01650
commit d7b5be4bad
4 changed files with 83 additions and 32 deletions

View File

@@ -16,6 +16,7 @@ import SlackAgent from '@server/lib/notifications/agents/slack';
import TelegramAgent from '@server/lib/notifications/agents/telegram';
import WebhookAgent from '@server/lib/notifications/agents/webhook';
import WebPushAgent from '@server/lib/notifications/agents/webpush';
import checkOverseerrMerge from '@server/lib/overseerrMerge';
import { getSettings } from '@server/lib/settings';
import logger from '@server/logger';
import clearCookies from '@server/middleware/clearcookies';
@@ -61,6 +62,9 @@ app
.then(async () => {
const dbConnection = await dataSource.initialize();
// Run Overseerr to Seerr migration
await checkOverseerrMerge(dbConnection);
// Run migrations in production
if (process.env.NODE_ENV === 'production') {
if (isPgsql) {

View File

@@ -0,0 +1,71 @@
import { MediaServerType } from '@server/constants/server';
import { getRepository } from '@server/datasource';
import Media from '@server/entity/Media';
import Settings from '@server/lib/settings';
import logger from '@server/logger';
import type { DataSource } from 'typeorm';
const checkOverseerrMerge = async (dbConnection: DataSource) => {
// Load settings without running migrations
const settings = await new Settings().load(undefined, true);
if (settings.main.mediaServerType) {
return; // The application has already been migrated
}
// Add fake migration record to prevent running migrations again
try {
await dbConnection.query(
`INSERT INTO migrations (timestamp,name) VALUES (1743023610704, 'UpdateWebPush1743023610704')`
);
} catch (error) {
logger.error(
'Failed to insert migration record for UpdateWebPush1743023610704',
{
label: 'Seerr Migration',
message: error.message,
}
);
}
// Set media server type to Plex (default for Overseerr)
settings.main.mediaServerType = MediaServerType.PLEX;
// Replace default Overseerr values with Seerr values
if (settings.main.applicationTitle === 'Overseerr') {
settings.main.applicationTitle = 'Seerr';
}
if (settings.notifications.agents.email.options.senderName === 'Overseerr') {
settings.notifications.agents.email.options.senderName = 'Seerr';
}
// MediaStatus.Blacklisted was added before MediaStatus.Deleted in Jellyseerr
try {
const mediaRepository = getRepository(Media);
const mediaToUpdate = await mediaRepository.find({ where: { status: 6 } });
for (const media of mediaToUpdate) {
media.status = 7;
await mediaRepository.save(media);
}
} catch (error) {
logger.error('Failed to update Media status from Blacklisted to Deleted', {
label: 'Seerr Migration',
message: error.message,
});
}
// Save updated settings
try {
await settings.save();
logger.info('Successfully migrated Overseerr to Seerr', {
label: 'Seerr Migration',
});
} catch (error) {
logger.error('Failed to save updated settings after Overseerr migration', {
label: 'Seerr Migration',
message: error.message,
});
}
};
export default checkOverseerrMerge;

View File

@@ -764,9 +764,13 @@ class Settings {
* This will load settings from file unless an optional argument of the object structure
* is passed in.
* @param overrideSettings If passed in, will override all existing settings with these
* @param skipMigrations If true, will skip running migrations on the loaded settings
* values
*/
public async load(overrideSettings?: AllSettings): Promise<Settings> {
public async load(
overrideSettings?: AllSettings,
raw = false
): Promise<Settings> {
if (overrideSettings) {
this.data = overrideSettings;
return this;
@@ -779,10 +783,12 @@ class Settings {
await this.save();
}
if (data) {
if (data && !raw) {
const parsedJson = JSON.parse(data);
const migratedData = await runMigrations(parsedJson, SETTINGS_PATH);
this.data = merge(this.data, migratedData);
} else if (data) {
this.data = JSON.parse(data);
}
// generate keys and ids if it's missing

View File

@@ -1,30 +0,0 @@
import { MediaServerType } from '@server/constants/server';
import type { AllSettings } from '@server/lib/settings';
import { getRepository } from '@server/datasource';
import Media from '@server/entity/Media';
const overseerrMerge = async (settings: any): Promise<AllSettings> => {
if (settings.main.mediaServerType) {
return settings; // already migrated
}
const newSettings = { ...settings };
newSettings.main.mediaServerType = MediaServerType.PLEX;
// New name
newSettings.main.applicationTitle = 'Seerr';
newSettings.notifications.agents.email.options.senderName = 'Seerr';
// MediaStatus.Blacklisted was added before MediaStatus.Deleted in Jellyseerr
const mediaRepository = getRepository(Media);
const mediaToUpdate = await mediaRepository.find({ where: { status: 6 } });
for (const media of mediaToUpdate) {
media.status = 7;
await mediaRepository.save(media);
}
return newSettings;
};
export default overseerrMerge;