Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat: Synchronize deletions when pulling from source control #12170

Conversation

despairblue
Copy link
Contributor

@despairblue despairblue commented Dec 11, 2024

Summary

image

This PR changes how pulling changes from the git repo works. If workflows, credentials, tags or variables exist locally, but not in the remote, they will be deleted locally.

That is to keep production environment clean by keeping them more tightly in sync with the staging environments.

This PR contains the BE and FE changes, make sure to review them respectively.

Related Linear tickets, Github issues, and Community forum posts

PAY-2304 BE
PAY-2428 FE

Review / Merge checklist

@n8n-assistant n8n-assistant bot added core Enhancement outside /nodes-base and /editor-ui n8n team Authored by the n8n team ui Enhancement in /editor-ui or /design-system labels Dec 11, 2024
@despairblue despairblue force-pushed the pay-2304-spike-sync-deleting-workflows-and-moving-between-projects branch from 53630b1 to 002d0b6 Compare December 30, 2024 10:12
@despairblue despairblue force-pushed the pay-2304-spike-sync-deleting-workflows-and-moving-between-projects branch from 002d0b6 to b398a56 Compare January 9, 2025 11:47
@despairblue despairblue changed the title feature: synchronize deletions when pulling from source control feature: Synchronize deletions when pulling from source control Jan 9, 2025
@r00gm r00gm changed the title feature: Synchronize deletions when pulling from source control feat: Synchronize deletions when pulling from source control Jan 13, 2025
@despairblue despairblue marked this pull request as ready for review January 13, 2025 13:29
@@ -110,7 +111,7 @@ export class Reset extends BaseCommand {
}

for (const credential of ownedCredentials) {
await Container.get(CredentialsService).delete(credential);
await Container.get(CredentialsRepository).remove(credential);
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

this change means that we now do not run the credentials.delete hook.
I don't know if that is what we want or not. Just want to confirm that this change is intentional.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

That wasn't intentional.

I changed it back to calling CredentialsService.delete and passing the owner. That way it's in line with deleting the workflow above it:

for (const { workflowId } of ownedSharedWorkflows) {
await Container.get(WorkflowService).delete(owner, workflowId);
}
for (const credential of ownedCredentials) {
await Container.get(CredentialsService).delete(owner, credential.id);
}

async delete(user: User, credentialId: string) {
await this.externalHooks.run('credentials.delete', [credentialId]);

const credential = await this.sharedCredentialsRepository.findCredentialForUser(
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The check for if a user has access to a credential belongs in the controller (or in a middleware) IMO.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Oh, I've moved that to the services as much as possible with RBAC, because

  1. it's more reusable: every controller that wants to get, update or delete a resource does not need access to the repositories to first get that resource and then pass it into a service function, although that would make service functions easier to test
  2. it's safer: e.g. you can call credService.remove(user, ids) from any place and be certain that it will check if the user is allowed to do that action or not, otherwise we put the onus of not creating security flows on the caller, not the callee
  3. transaction handling is easier, the controller does not need to create a transaction, use repositories to get the resources that the user can use in that context, then pass this to one or multiple service functions passing the transaction context as well
  4. at least workflows currently work like that
    /**
    * Deletes a workflow and returns it.
    *
    * If the workflow is active this will deactivate the workflow.
    * If the user does not have the permissions to delete the workflow this does
    * nothing and returns void.
    */
    async delete(user: User, workflowId: string): Promise<WorkflowEntity | undefined> {

That said, I can change it, if we already have a consensus about this.

cstuncsik
cstuncsik previously approved these changes Jan 14, 2025
@netroy netroy self-requested a review January 14, 2025 08:26
Copy link

cypress bot commented Jan 14, 2025

n8n    Run #8845

Run Properties:  status check passed Passed #8845  •  git commit 9b9c452aa6: 🌳 🖥️ browsers:node18.12.0-chrome107 🤖 despairblue 🗃️ e2e/*
Project n8n
Branch Review pay-2304-spike-sync-deleting-workflows-and-moving-between-projects
Run status status check passed Passed #8845
Run duration 04m 49s
Commit git commit 9b9c452aa6: 🌳 🖥️ browsers:node18.12.0-chrome107 🤖 despairblue 🗃️ e2e/*
Committer r00gm
View all properties for this run ↗︎

Test results
Tests that failed  Failures 0
Tests that were flaky  Flaky 1
Tests that did not run due to a developer annotating a test with .skip  Pending 0
Tests that did not run due to a failure in a mocha hook  Skipped 0
Tests that passed  Passing 489
View all changes introduced in this branch ↗︎

Copy link
Contributor

✅ All Cypress E2E specs passed

Copy link
Member

@netroy netroy left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'm not familiar enough with a lot of this code, but the parts I do understand, look fine to me. but left a comment about the deletion queries.

Comment on lines +510 to +533
async deleteWorkflowsNotInWorkfolder(user: User, candidates: SourceControlledFile[]) {
for (const candidate of candidates) {
await this.workflowService.delete(user, candidate.id);
}
}

async deleteCredentialsNotInWorkfolder(user: User, candidates: SourceControlledFile[]) {
for (const candidate of candidates) {
await this.credentialsService.delete(user, candidate.id);
}
}

async deleteVariablesNotInWorkfolder(candidates: SourceControlledFile[]) {
for (const candidate of candidates) {
await this.variablesService.delete(candidate.id);
}
}

async deleteTagsNotInWorkfolder(candidates: SourceControlledFile[]) {
for (const candidate of candidates) {
await this.tagService.delete(candidate.id);
}
}

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

these currently fire multiple read and then delete queries. maybe we should add a deleteMany method in all these services, and use that to call a single delete query for each resource type.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I can do that. Honestly I avoided this because I don't think this is a hot path and being correct was more important to me than being efficient and those functions will always work and there is no chance that they get out of sync with the deleteMany and vice versa.

What I could do is create a deleteMany and implement the delete using that, similar to this: 307ede1 (#12329)

If you approve I'll do that, let's just agree on what we want before we start to work on it.

Copy link
Contributor

✅ All Cypress E2E specs passed

@despairblue despairblue merged commit 967ee4b into master Jan 20, 2025
63 checks passed
@despairblue despairblue deleted the pay-2304-spike-sync-deleting-workflows-and-moving-between-projects branch January 20, 2025 15:53
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
core Enhancement outside /nodes-base and /editor-ui n8n team Authored by the n8n team ui Enhancement in /editor-ui or /design-system
Projects
None yet
Development

Successfully merging this pull request may close these issues.

4 participants