mirror of
https://github.com/Abdulazizzn/n8n-enterprise-unlocked.git
synced 2025-12-17 01:56:46 +00:00
chore(core): Ensure updatedAt is always set for tags in source control feature (#16949)
This commit is contained in:
@@ -139,6 +139,119 @@ describe('SourceControlService', () => {
|
|||||||
});
|
});
|
||||||
|
|
||||||
describe('getStatus', () => {
|
describe('getStatus', () => {
|
||||||
|
it('ensure updatedAt field for last deleted tag', async () => {
|
||||||
|
// ARRANGE
|
||||||
|
const user = mock<User>();
|
||||||
|
user.role = 'global:admin';
|
||||||
|
|
||||||
|
sourceControlImportService.getRemoteVersionIdsFromFiles.mockResolvedValue([]);
|
||||||
|
sourceControlImportService.getLocalVersionIdsFromDb.mockResolvedValue([]);
|
||||||
|
sourceControlImportService.getRemoteCredentialsFromFiles.mockResolvedValue([]);
|
||||||
|
sourceControlImportService.getLocalCredentialsFromDb.mockResolvedValue([]);
|
||||||
|
sourceControlImportService.getRemoteVariablesFromFile.mockResolvedValue([]);
|
||||||
|
sourceControlImportService.getLocalVariablesFromDb.mockResolvedValue([]);
|
||||||
|
|
||||||
|
tagRepository.find.mockResolvedValue([]);
|
||||||
|
|
||||||
|
// Define a tag that does only exist remotely.
|
||||||
|
// Pushing this means it was deleted.
|
||||||
|
sourceControlImportService.getRemoteTagsAndMappingsFromFile.mockResolvedValue({
|
||||||
|
tags: [
|
||||||
|
{
|
||||||
|
id: 'tag-id',
|
||||||
|
name: 'some name',
|
||||||
|
} as TagEntity,
|
||||||
|
],
|
||||||
|
mappings: [],
|
||||||
|
});
|
||||||
|
sourceControlImportService.getLocalTagsAndMappingsFromDb.mockResolvedValue({
|
||||||
|
tags: [],
|
||||||
|
mappings: [],
|
||||||
|
});
|
||||||
|
|
||||||
|
folderRepository.find.mockResolvedValue([]);
|
||||||
|
sourceControlImportService.getRemoteFoldersAndMappingsFromFile.mockResolvedValue({
|
||||||
|
folders: [],
|
||||||
|
});
|
||||||
|
sourceControlImportService.getLocalFoldersAndMappingsFromDb.mockResolvedValue({
|
||||||
|
folders: [],
|
||||||
|
});
|
||||||
|
|
||||||
|
// ACT
|
||||||
|
const pushResult = await sourceControlService.getStatus(user, {
|
||||||
|
direction: 'push',
|
||||||
|
verbose: false,
|
||||||
|
preferLocalVersion: false,
|
||||||
|
});
|
||||||
|
|
||||||
|
// ASSERT
|
||||||
|
|
||||||
|
if (!Array.isArray(pushResult)) {
|
||||||
|
fail('Expected pushResult to be an array.');
|
||||||
|
}
|
||||||
|
|
||||||
|
expect(pushResult).toHaveLength(1);
|
||||||
|
expect(pushResult.find((i) => i.type === 'tags')?.updatedAt).toBeDefined();
|
||||||
|
});
|
||||||
|
|
||||||
|
it('ensure updatedAt field for last deleted folder', async () => {
|
||||||
|
// ARRANGE
|
||||||
|
const user = mock<User>();
|
||||||
|
user.role = 'global:admin';
|
||||||
|
|
||||||
|
sourceControlImportService.getRemoteVersionIdsFromFiles.mockResolvedValue([]);
|
||||||
|
sourceControlImportService.getLocalVersionIdsFromDb.mockResolvedValue([]);
|
||||||
|
sourceControlImportService.getRemoteCredentialsFromFiles.mockResolvedValue([]);
|
||||||
|
sourceControlImportService.getLocalCredentialsFromDb.mockResolvedValue([]);
|
||||||
|
sourceControlImportService.getRemoteVariablesFromFile.mockResolvedValue([]);
|
||||||
|
sourceControlImportService.getLocalVariablesFromDb.mockResolvedValue([]);
|
||||||
|
|
||||||
|
tagRepository.find.mockResolvedValue([]);
|
||||||
|
sourceControlImportService.getRemoteTagsAndMappingsFromFile.mockResolvedValue({
|
||||||
|
tags: [],
|
||||||
|
mappings: [],
|
||||||
|
});
|
||||||
|
sourceControlImportService.getLocalTagsAndMappingsFromDb.mockResolvedValue({
|
||||||
|
tags: [],
|
||||||
|
mappings: [],
|
||||||
|
});
|
||||||
|
|
||||||
|
// Define a folder that does only exist remotely.
|
||||||
|
// Pushing this means it was deleted.
|
||||||
|
folderRepository.find.mockResolvedValue([]);
|
||||||
|
sourceControlImportService.getRemoteFoldersAndMappingsFromFile.mockResolvedValue({
|
||||||
|
folders: [
|
||||||
|
{
|
||||||
|
id: 'test-folder',
|
||||||
|
name: 'test folder name',
|
||||||
|
homeProjectId: 'some-id',
|
||||||
|
parentFolderId: null,
|
||||||
|
createdAt: '',
|
||||||
|
updatedAt: '',
|
||||||
|
},
|
||||||
|
],
|
||||||
|
});
|
||||||
|
sourceControlImportService.getLocalFoldersAndMappingsFromDb.mockResolvedValue({
|
||||||
|
folders: [],
|
||||||
|
});
|
||||||
|
|
||||||
|
// ACT
|
||||||
|
const pushResult = await sourceControlService.getStatus(user, {
|
||||||
|
direction: 'push',
|
||||||
|
verbose: false,
|
||||||
|
preferLocalVersion: false,
|
||||||
|
});
|
||||||
|
|
||||||
|
// ASSERT
|
||||||
|
|
||||||
|
if (!Array.isArray(pushResult)) {
|
||||||
|
fail('Expected pushResult to be an array.');
|
||||||
|
}
|
||||||
|
|
||||||
|
expect(pushResult).toHaveLength(1);
|
||||||
|
expect(pushResult.find((i) => i.type === 'folders')?.updatedAt).toBeDefined();
|
||||||
|
});
|
||||||
|
|
||||||
it('conflict depends on the value of `direction`', async () => {
|
it('conflict depends on the value of `direction`', async () => {
|
||||||
// ARRANGE
|
// ARRANGE
|
||||||
const user = mock<User>();
|
const user = mock<User>();
|
||||||
|
|||||||
@@ -869,6 +869,8 @@ export class SourceControlService {
|
|||||||
select: ['updatedAt'],
|
select: ['updatedAt'],
|
||||||
});
|
});
|
||||||
|
|
||||||
|
const lastUpdatedDate = lastUpdatedTag[0]?.updatedAt ?? new Date();
|
||||||
|
|
||||||
const tagMappingsRemote =
|
const tagMappingsRemote =
|
||||||
await this.sourceControlImportService.getRemoteTagsAndMappingsFromFile(context);
|
await this.sourceControlImportService.getRemoteTagsAndMappingsFromFile(context);
|
||||||
const tagMappingsLocal =
|
const tagMappingsLocal =
|
||||||
@@ -916,7 +918,7 @@ export class SourceControlService {
|
|||||||
location: options.direction === 'push' ? 'local' : 'remote',
|
location: options.direction === 'push' ? 'local' : 'remote',
|
||||||
conflict: false,
|
conflict: false,
|
||||||
file: getTagsPath(this.gitFolder),
|
file: getTagsPath(this.gitFolder),
|
||||||
updatedAt: lastUpdatedTag[0]?.updatedAt.toISOString(),
|
updatedAt: lastUpdatedDate.toISOString(),
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
tagsMissingInRemote.forEach((item) => {
|
tagsMissingInRemote.forEach((item) => {
|
||||||
@@ -928,7 +930,7 @@ export class SourceControlService {
|
|||||||
location: options.direction === 'push' ? 'local' : 'remote',
|
location: options.direction === 'push' ? 'local' : 'remote',
|
||||||
conflict: options.direction === 'push' ? false : true,
|
conflict: options.direction === 'push' ? false : true,
|
||||||
file: getTagsPath(this.gitFolder),
|
file: getTagsPath(this.gitFolder),
|
||||||
updatedAt: lastUpdatedTag[0]?.updatedAt.toISOString(),
|
updatedAt: lastUpdatedDate.toISOString(),
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
@@ -941,7 +943,7 @@ export class SourceControlService {
|
|||||||
location: options.direction === 'push' ? 'local' : 'remote',
|
location: options.direction === 'push' ? 'local' : 'remote',
|
||||||
conflict: true,
|
conflict: true,
|
||||||
file: getTagsPath(this.gitFolder),
|
file: getTagsPath(this.gitFolder),
|
||||||
updatedAt: lastUpdatedTag[0]?.updatedAt.toISOString(),
|
updatedAt: lastUpdatedDate.toISOString(),
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
@@ -1028,7 +1030,7 @@ export class SourceControlService {
|
|||||||
location: options.direction === 'push' ? 'local' : 'remote',
|
location: options.direction === 'push' ? 'local' : 'remote',
|
||||||
conflict: true,
|
conflict: true,
|
||||||
file: getFoldersPath(this.gitFolder),
|
file: getFoldersPath(this.gitFolder),
|
||||||
updatedAt: lastUpdatedFolder[0]?.updatedAt.toISOString(),
|
updatedAt: lastUpdatedDate.toISOString(),
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|||||||
@@ -1,4 +1,4 @@
|
|||||||
import { inDevelopment, inProduction, LicenseState } from '@n8n/backend-common';
|
import { inDevelopment, inProduction } from '@n8n/backend-common';
|
||||||
import { SecurityConfig } from '@n8n/config';
|
import { SecurityConfig } from '@n8n/config';
|
||||||
import { Time } from '@n8n/constants';
|
import { Time } from '@n8n/constants';
|
||||||
import type { APIRequest } from '@n8n/db';
|
import type { APIRequest } from '@n8n/db';
|
||||||
@@ -77,7 +77,6 @@ export class Server extends AbstractServer {
|
|||||||
private readonly postHogClient: PostHogClient,
|
private readonly postHogClient: PostHogClient,
|
||||||
private readonly eventService: EventService,
|
private readonly eventService: EventService,
|
||||||
private readonly instanceSettings: InstanceSettings,
|
private readonly instanceSettings: InstanceSettings,
|
||||||
private readonly licenseState: LicenseState,
|
|
||||||
) {
|
) {
|
||||||
super();
|
super();
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user