scaffolder: fix binary file uploads during dry-run
Signed-off-by: Patrik Oldsberg <poldsberg@gmail.com>
This commit is contained in:
@@ -0,0 +1,5 @@
|
||||
---
|
||||
'@backstage/plugin-scaffolder': patch
|
||||
---
|
||||
|
||||
Handle binary files and files that are too large during dry-run content upload.
|
||||
@@ -0,0 +1,44 @@
|
||||
/*
|
||||
* Copyright 2022 The Backstage Authors
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
import { base64EncodeContent } from './DryRunContext';
|
||||
|
||||
// eslint-disable-next-line no-restricted-imports
|
||||
import { TextEncoder } from 'util';
|
||||
|
||||
window.TextEncoder = TextEncoder;
|
||||
|
||||
describe('base64EncodeContent', () => {
|
||||
it('encodes text files', () => {
|
||||
expect(base64EncodeContent('abc')).toBe('YWJj');
|
||||
expect(base64EncodeContent('abc'.repeat(1000000))).toBe(
|
||||
btoa('<file too large>'),
|
||||
);
|
||||
});
|
||||
|
||||
it('encodes binary files', () => {
|
||||
expect(base64EncodeContent('\x00\x01\x02')).toBe('AAEC');
|
||||
expect(base64EncodeContent('😅')).toBe('8J+YhQ==');
|
||||
// Triggers chunking
|
||||
expect(base64EncodeContent('😅'.repeat(18000))).toBe(
|
||||
'8J+YhfCfmIXwn5iF8J+YhfCfmIXwn5iF'.repeat(3000),
|
||||
);
|
||||
// Triggers size check
|
||||
expect(base64EncodeContent('😅'.repeat(1000000))).toBe(
|
||||
btoa('<file too large>'),
|
||||
);
|
||||
});
|
||||
});
|
||||
@@ -29,6 +29,9 @@ import React, {
|
||||
import { scaffolderApiRef } from '../../api';
|
||||
import { ScaffolderDryRunResponse } from '../../types';
|
||||
|
||||
const MAX_CONTENT_SIZE = 256 * 1024;
|
||||
const CHUNK_SIZE = 0x8000;
|
||||
|
||||
interface DryRunOptions {
|
||||
templateContent: string;
|
||||
values: JsonObject;
|
||||
@@ -54,6 +57,27 @@ interface DryRunProviderProps {
|
||||
children: ReactNode;
|
||||
}
|
||||
|
||||
export function base64EncodeContent(content: string): string {
|
||||
if (content.length > MAX_CONTENT_SIZE) {
|
||||
return btoa('<file too large>');
|
||||
}
|
||||
|
||||
try {
|
||||
return btoa(content);
|
||||
} catch {
|
||||
const decoder = new TextEncoder();
|
||||
const buffer = decoder.encode(content);
|
||||
|
||||
const chunks = new Array<string>();
|
||||
for (let offset = 0; offset < buffer.length; offset += CHUNK_SIZE) {
|
||||
chunks.push(
|
||||
String.fromCharCode(...buffer.slice(offset, offset + CHUNK_SIZE)),
|
||||
);
|
||||
}
|
||||
return btoa(chunks.join(''));
|
||||
}
|
||||
}
|
||||
|
||||
export function DryRunProvider(props: DryRunProviderProps) {
|
||||
const scaffolderApi = useApi(scaffolderApiRef);
|
||||
|
||||
@@ -110,7 +134,7 @@ export function DryRunProvider(props: DryRunProviderProps) {
|
||||
secrets: {},
|
||||
directoryContents: options.files.map(file => ({
|
||||
path: file.path,
|
||||
base64Content: btoa(file.content),
|
||||
base64Content: base64EncodeContent(file.content),
|
||||
})),
|
||||
});
|
||||
|
||||
|
||||
Reference in New Issue
Block a user