Skip to content

src: add and delete file webhooks when designs are attached or removed - #260

Merged
Isaiah-Turner merged 10 commits into
mainfrom
isaiah/file-webhooks-add-delete-on-design-interaction
Aug 20, 2025
Merged

src: add and delete file webhooks when designs are attached or removed#260
Isaiah-Turner merged 10 commits into
mainfrom
isaiah/file-webhooks-add-delete-on-design-interaction

Conversation

@Isaiah-Turner

@Isaiah-Turner Isaiah-Turner commented Jul 30, 2025

Copy link
Copy Markdown
Collaborator

This PR adds logic to manage creating and deleting webhooks for a file when it is associated or disassociated with a design. It also adds a FigmaFileRepository to make use of the new table from #259.

On association, we now call maybeCreateFigmaFileWebhooks. This function checks to see if the file already has file webhooks with the same file key. If not, we create a FILE_UPDATE and DEV_MODE_STATUS_UPDATE webhook for that file.

On disassociate, we call maybeTryDeleteFigmaFileWebhooks. If there are no longer any linked designs that rely on the webhook, we'll delete them.

Testing

  • This PR adds test
  • Manually test by linking and unlinking a design. Make sure webhooks show up in DB when design is linked, and get deleted when design is unlinked
Screen.Recording.2025-08-01.at.4.10.13.PM.mov
  • Attach same file to multiple issues. Make sure only one set of webhooks show up in DB, and still remain after one design is unlinked. After both are unlinked, they should be deleted
attaching-multiple-design.mov

@Isaiah-Turner Isaiah-Turner changed the title [NONE]: add and delete file webhooks when designs are attached or removed src: add and delete file webhooks when designs are attached or removed Aug 1, 2025
Comment thread package.json
"test:unit": "DOTENV_CONFIG_PATH=.env.test jest -c jest.config.unit.ts"
},
"dependencies": {
"@figma/rest-api-spec": "^0.33.0",

Copy link
Copy Markdown
Collaborator Author

Choose a reason for hiding this comment

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

I replaced some of our custom types with types from our official rest api spec where possible

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

praise: Amazing! Thank you for doing this, @Isaiah-Turner !

@Isaiah-Turner
Isaiah-Turner marked this pull request as ready for review August 1, 2025 23:08
DEV_MODE_STATUS_UPDATE = 'DEV_MODE_STATUS_UPDATE',
}

export class FigmaFileWebhook {

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

suggestion (npn-blocking): It seems we over-engineered a bit FigmaFileWebhook. This class is just holds data and does not have any business logic associated with it.

We could define FigmaFileWebhook as a read-only type without using classes.

export enum FigmaFileWebhookEventType {
	FILE_UPDATE = 'FILE_UPDATE',
	DEV_MODE_STATUS_UPDATE = 'DEV_MODE_STATUS_UPDATE',
}

export type FigmaFileWebhook = {
	readonly id: string;
	readonly webhookId: string;
	readonly webhookPasscode: string;
	readonly fileKey: string;
	readonly eventType: FigmaFileWebhookEventType;
	readonly createdBy: {
		readonly atlassianUserId: string;
		readonly connectInstallationId: string;
	};
};

export type FigmaFileWebhookCreateParams = {
	readonly webhookId: string;
	readonly webhookPasscode: string;
	readonly fileKey: string;
	readonly eventType: FigmaFileWebhookEventType;
	readonly createdBy: {
		readonly atlassianUserId: string;
		readonly connectInstallationId: string;
	};
};

Copy link
Copy Markdown
Collaborator Author

Choose a reason for hiding this comment

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

This is a great point! I fixed this in 6175d34

};

export const CREATE_WEBHOOK_RESPONSE: JSONSchemaTypeWithId<CreateWebhookResponse> =
export const CREATE_WEBHOOK_RESPONSE: JSONSchemaTypeWithId<PostWebhookResponse> =

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

nitpick Please, could you rename the schema to match the type name (CREATE_WEBHOOK_RESPONSE -> POST_WEBHOOK_RESPONSE) for consistency?

Copy link
Copy Markdown
Collaborator Author

Choose a reason for hiding this comment

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

Fixed in 6175d34!

readonly accessToken: string;
};

export type CreateWebhookRequest = {

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

praise: This is so good!

try {
const webhookPasscode = uuidv4();
const { fileWebhook, devModeStatusUpdateWebhook } =
await figmaService.createFileContextWebhooks(fileKey, webhookPasscode, {

@akostevich-atlassian akostevich-atlassian Aug 11, 2025

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

issue: The current behaviour can cause creating "dangling" webhooks in an edge case when the first webhook is successfully created but the creation of the second one fails. This being the case, no webhook will be recorded in our database. As a result, when the operation is retried by Atlassian's platform, the implementation will try to create a new set of webhooks.

In order to minimise the risk of this (it can still happens anyway if the database transaction fails), please, consider the following:

  1. Split FigmaService.createFileContextWebhooks into the methods: FigmaService.createFileUpdateWebHook and FigmaService.createDevModeStatusUpdateWebHook.
  2. Update maybeCreateFigmaFileWebhooks to accept an additional parameter of type FigmaFileWebhookEventType and take responsibility of the a creation of a single webhook. It could do the following:
    1. Check whether the webhook of the given type exists. If not -- return.
    2. Call FigmaService.createFileContextWebhooks.
    3. Call FigmaFileWebhookRepository.upsert for the created webhook.
  3. Call maybeCreateFigmaFileWebhooks for each supported webhook type (once for FILE_UPDATE andonce for DEV_MODE_STATUS_UPDATE).

What do you think, @Isaiah-Turner ?

Copy link
Copy Markdown
Collaborator Author

Choose a reason for hiding this comment

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

Yeah, this is a great call. I refactored this how you described in bf0acd7, and added a new test in src/web/routes/entities-v2/integration.test.ts

@akostevich-atlassian akostevich-atlassian Aug 11, 2025

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

suggestion (non-blocking): This use case is called on a PUT /entities/onEntityAssociated endpoint request. There are integration tests for this endpoint in src/web/routes/entities-v2/integration.test.ts, which are, likely, passing because the Launch Darkly client falls back to false for the feature gate.

I would highly recommend updating these tests in accordance with the new behaviour within this PR for extra safety.

Beware, that if we delay this work, we will not be able to clean up the feature gate without updating the affected tests.

This is totally fine to do this within a separate PR :)

@akostevich-atlassian

Copy link
Copy Markdown
Collaborator

praise: Great work, @Isaiah-Turner on the feature! And thank you so much for the detailed PR description and demos!

@akostevich-atlassian akostevich-atlassian left a comment

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

Please, see other comments for more details.

Base automatically changed from isaiah/file-webhooks-db-migration to main August 13, 2025 17:22
@Isaiah-Turner
Isaiah-Turner force-pushed the isaiah/file-webhooks-add-delete-on-design-interaction branch 7 times, most recently from f619d4b to bf0acd7 Compare August 18, 2025 21:48
@Isaiah-Turner
Isaiah-Turner force-pushed the isaiah/file-webhooks-add-delete-on-design-interaction branch from bf0acd7 to 0b25a17 Compare August 18, 2025 22:41
@akostevich-atlassian

Copy link
Copy Markdown
Collaborator

praise: This was a quite large and challenging work, @Isaiah-Turner ! Really love the changes and what they bring to the product. Great job!

@Isaiah-Turner
Isaiah-Turner merged commit a75228b into main Aug 20, 2025
2 checks passed
@Isaiah-Turner
Isaiah-Turner deleted the isaiah/file-webhooks-add-delete-on-design-interaction branch August 20, 2025 03:50
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants