Add support for importing Swagger 2.0 specifications into Bruno collections (#7622)

* feat: support Swagger 2.0 OpenAPI import

* feat: support Swagger 2.0 OpenAPI import

* fix: refactor swagger2 converter, fix env creation, and update import UI labels

* fix: coderabbit comments

* fix: address coderabbit comments for body type handling

* fix: disallow OpenAPI Sync for Swagger 2.0 specs in UI

---------

Co-authored-by: naman-bruno <naman@usebruno.com>
This commit is contained in:
gopu-bruno
2026-04-01 21:19:47 +05:30
committed by GitHub
parent 00bc93d3ac
commit 8e978ae305
17 changed files with 4009 additions and 625 deletions

View File

@@ -80,6 +80,10 @@ const ConnectSpecForm = ({ sourceUrl, setSourceUrl, isLoading, error, setError,
setError('The selected file is not a valid OpenAPI 3.x specification');
return;
}
if (data.swagger && String(data.swagger).startsWith('2')) {
setError('Swagger 2.0 is not supported. Please convert your spec to OpenAPI 3.x.');
return;
}
const filePath = window.ipcRenderer.getFilePath(file);
if (filePath) setSourceUrl(filePath);
} catch (err) {

View File

@@ -32,7 +32,7 @@ const IMPORT_TYPE = {
};
const groupingOptions = [
{ value: 'tags', label: 'Tags', description: 'Group requests by OpenAPI tags', testId: 'grouping-option-tags' },
{ value: 'tags', label: 'Tags', description: 'Group requests by OpenAPI/Swagger tags', testId: 'grouping-option-tags' },
{ value: 'path', label: 'Paths', description: 'Group requests by URL path structure', testId: 'grouping-option-path' }
];

View File

@@ -271,7 +271,7 @@ const FileTab = ({
</button>
</p>
<p className="text-xs text-gray-500 dark:text-gray-400 text-center">
Supports Bruno, OpenCollection, Postman, Insomnia, OpenAPI v3, WSDL, and ZIP formats
Supports Bruno, OpenCollection, Postman, Insomnia, OpenAPI 3.x / Swagger 2.0, WSDL, and ZIP formats
</p>
</div>
</div>

View File

@@ -93,7 +93,7 @@ const convertCollection = async (format, rawData, groupingType, collectionFormat
};
const groupingOptions = [
{ value: 'tags', label: 'Tags', description: 'Group requests by OpenAPI tags', testId: 'grouping-option-tags' },
{ value: 'tags', label: 'Tags', description: 'Group requests by OpenAPI/Swagger tags', testId: 'grouping-option-tags' },
{ value: 'path', label: 'Paths', description: 'Group requests by URL path structure', testId: 'grouping-option-path' }
];
@@ -109,6 +109,7 @@ const ImportCollectionLocation = ({ onClose, handleSubmit, rawData, format, sour
const isZipImport = format === 'bruno-zip';
const isOpenApiFromUrl = isOpenApi && !!sourceUrl && !filePath;
const isOpenApiFromFile = isOpenApi && !!filePath && !sourceUrl;
const isSwagger2 = isOpenApi && rawData?.swagger && String(rawData.swagger).startsWith('2');
const showCheckForSpecUpdatesOption = isOpenAPISyncEnabled && (isOpenApiFromUrl || isOpenApiFromFile);
const { workspaces, activeWorkspaceUid } = useSelector((state) => state.workspaces);
@@ -324,18 +325,21 @@ const ImportCollectionLocation = ({ onClose, handleSubmit, rawData, format, sour
)}
{showCheckForSpecUpdatesOption && (
<div className="mt-4">
<label className="flex items-center gap-2 cursor-pointer">
<div className={`mt-4 ${isSwagger2 ? 'opacity-50 pointer-events-none' : ''}`}>
<label className={`flex items-center gap-2 ${isSwagger2 ? '' : 'cursor-pointer'}`}>
<input
type="checkbox"
checked={enableCheckForSpecUpdates}
checked={isSwagger2 ? false : enableCheckForSpecUpdates}
onChange={(e) => setEnableCheckForSpecUpdates(e.target.checked)}
className="cursor-pointer checkbox"
disabled={isSwagger2}
className={`checkbox ${isSwagger2 ? '' : 'cursor-pointer'}`}
/>
<span className="font-medium">Check for Spec Updates</span>
</label>
<p className="text-muted text-xs mt-1">
Stay notified of spec changes and sync your collection with the spec.
{isSwagger2
? 'OpenAPI Sync is not supported for Swagger 2.0 specs.'
: 'Stay notified of spec changes and sync your collection with the spec.'}
</p>
</div>
)}

View File

@@ -24,7 +24,7 @@ const GetStartedStep = ({ onCreateCollection, onImportCollection, onOpenCollecti
<IconDownload size={20} stroke={1.5} />
</div>
<div className="card-title">Import Collection</div>
<div className="card-desc">Bring in Postman, OpenAPI, or Insomnia</div>
<div className="card-desc">Bring in Postman, OpenAPI/Swagger, or Insomnia</div>
</button>
</div>