From f5168a5016d2e8ffe42f5fd2af803e91d784fae2 Mon Sep 17 00:00:00 2001 From: breken Date: Sat, 12 Sep 2026 02:47:05 -0700 Subject: [PATCH] fix(console): allow selecting .tar.gz files in manual deployment pickers on macOS The upload dropzones for manual function/site deployments passed extensions=['gz'], which builds a file picker accept attribute of '.gz'. On macOS a bare '.gz' token does not match 'code.tar.gz' files (their UTI is the compound tar+gzip type), so the picker greys them out and they cannot be selected or dropped. List the compound 'tar.gz' extension alongside 'gz' via a shared DEPLOYMENT_ARCHIVE_EXTENSIONS constant so accept becomes '.gz,.tar.gz'. Fixes appwrite/appwrite#13635 --- src/lib/helpers/files.test.ts | 25 +++++++++++++++++++ src/lib/helpers/files.ts | 10 ++++++++ .../create-function/manual/+page.svelte | 5 ++-- .../(modals)/createManual.svelte | 5 ++-- .../sites/create-site/manual/+page.svelte | 5 ++-- .../createManualDeploymentModal.svelte | 5 ++-- 6 files changed, 47 insertions(+), 8 deletions(-) create mode 100644 src/lib/helpers/files.test.ts diff --git a/src/lib/helpers/files.test.ts b/src/lib/helpers/files.test.ts new file mode 100644 index 0000000000..1e27a7b8af --- /dev/null +++ b/src/lib/helpers/files.test.ts @@ -0,0 +1,25 @@ +import { describe, expect, it } from 'vitest'; +import { + DEPLOYMENT_ARCHIVE_EXTENSIONS, + getInvalidDeploymentArchiveReason +} from './files'; + +describe('deployment archive extensions', () => { + it('should include the compound tar.gz extension for the file picker accept attribute', () => { + // On macOS a bare '.gz' accept token does not match 'code.tar.gz' files + // (compound tar+gzip UTI), greying them out in the picker. + expect(DEPLOYMENT_ARCHIVE_EXTENSIONS).toContain('tar.gz'); + expect(DEPLOYMENT_ARCHIVE_EXTENSIONS).toContain('gz'); + }); + + it('should accept .tar.gz archives and reject other files', () => { + const ok = [new File(['x'], 'code.tar.gz')]; + expect(getInvalidDeploymentArchiveReason(ok)).toBeNull(); + + const upper = [new File(['x'], 'CODE.TAR.GZ')]; + expect(getInvalidDeploymentArchiveReason(upper)).toBeNull(); + + const zip = [new File(['x'], 'code.zip')]; + expect(getInvalidDeploymentArchiveReason(zip)).toBe('invalid_extension'); + }); +}); diff --git a/src/lib/helpers/files.ts b/src/lib/helpers/files.ts index 1efd2319ef..6c4b95e219 100644 --- a/src/lib/helpers/files.ts +++ b/src/lib/helpers/files.ts @@ -80,6 +80,16 @@ export async function gzipUpload(files: FileList) { return uploadFile; } +/** + * Extensions accepted for manual deployment archives. + * + * 'tar.gz' must be listed alongside 'gz': the file picker `accept` attribute is + * built from these extensions, and on macOS a bare '.gz' token does not match + * 'code.tar.gz' files (their UTI is the compound tar+gzip type), so the picker + * greys them out. + */ +export const DEPLOYMENT_ARCHIVE_EXTENSIONS = ['gz', 'tar.gz']; + export function getInvalidDeploymentArchiveReason( files: FileList | File[] | null | undefined, maxSize?: number diff --git a/src/routes/(console)/project-[region]-[project]/functions/create-function/manual/+page.svelte b/src/routes/(console)/project-[region]-[project]/functions/create-function/manual/+page.svelte index f49a5ded72..daf6b76311 100644 --- a/src/routes/(console)/project-[region]-[project]/functions/create-function/manual/+page.svelte +++ b/src/routes/(console)/project-[region]-[project]/functions/create-function/manual/+page.svelte @@ -22,7 +22,8 @@ import { getInvalidDeploymentArchiveReason, InvalidFileType, - removeFile + removeFile, + DEPLOYMENT_ARCHIVE_EXTENSIONS } from '$lib/helpers/files'; import { isCloud } from '$lib/system'; import { humanFileSize } from '$lib/helpers/sizeConvertion'; @@ -224,7 +225,7 @@ diff --git a/src/routes/(console)/project-[region]-[project]/functions/function-[function]/(modals)/createManual.svelte b/src/routes/(console)/project-[region]-[project]/functions/function-[function]/(modals)/createManual.svelte index 0ae9ada858..f18fc12ea0 100644 --- a/src/routes/(console)/project-[region]-[project]/functions/function-[function]/(modals)/createManual.svelte +++ b/src/routes/(console)/project-[region]-[project]/functions/function-[function]/(modals)/createManual.svelte @@ -7,7 +7,8 @@ import { getInvalidDeploymentArchiveReason, InvalidFileType, - removeFile + removeFile, + DEPLOYMENT_ARCHIVE_EXTENSIONS } from '$lib/helpers/files'; import { addNotification } from '$lib/stores/notifications'; import { IconInfo } from '@appwrite.io/pink-icons-svelte'; @@ -93,7 +94,7 @@ Upload a tar.gz file containing your function source code