fix(components): parse gcs uniform bucket access env#6136
fix(components): parse gcs uniform bucket access env#6136haimingZZ wants to merge 2 commits intoFlowiseAI:mainfrom
Conversation
There was a problem hiding this comment.
Code Review
This pull request improves the handling of the GOOGLE_CLOUD_UNIFORM_BUCKET_ACCESS environment variable in GCSStorageProvider by adding whitespace trimming and case-insensitive comparison, and introduces a corresponding test suite. Review feedback notes that the change alters the default behavior when the variable is unset and suggests using idiomatic top-level imports in the test file.
| } | ||
|
|
||
| getMulterStorage(): multer.Multer { | ||
| const uniformBucketLevelAccess = process.env.GOOGLE_CLOUD_UNIFORM_BUCKET_ACCESS?.trim().toLowerCase() !== 'false' |
There was a problem hiding this comment.
The logic !== 'false' effectively defaults the value to true when the environment variable is unset or empty. While the PR description mentions "keeping" the default enabled behavior, the previous implementation (Boolean(process.env.GOOGLE_CLOUD_UNIFORM_BUCKET_ACCESS) ?? true) actually evaluated to false when the variable was unset (since Boolean(undefined) is false).
If the intention is to change the default to true (which is generally recommended for modern GCS buckets), this implementation is correct. However, if you intended to maintain the previous default of false, the logic should be adjusted to check for 'true' explicitly.
| const bucketMock = {} | ||
| const multerMock = jest.fn((config) => config) | ||
| const storageCtorMock = jest.fn(() => ({ | ||
| bucket: jest.fn(() => bucketMock) | ||
| })) | ||
| const multerGoogleCloudStorageMock = jest.fn((config) => config) | ||
|
|
||
| jest.mock('@google-cloud/storage', () => ({ | ||
| Storage: storageCtorMock | ||
| })) | ||
|
|
||
| jest.mock('multer', () => multerMock) | ||
|
|
||
| jest.mock('multer-cloud-storage', () => multerGoogleCloudStorageMock) | ||
|
|
||
| jest.mock('@google-cloud/logging-winston', () => ({ | ||
| LoggingWinston: jest.fn() | ||
| })) | ||
|
|
||
| describe('GCSStorageProvider', () => { | ||
| const originalEnv = process.env | ||
|
|
||
| beforeEach(() => { | ||
| jest.clearAllMocks() | ||
| process.env = { | ||
| ...originalEnv, | ||
| GOOGLE_CLOUD_STORAGE_BUCKET_NAME: 'test-bucket', | ||
| GOOGLE_CLOUD_STORAGE_PROJ_ID: 'test-project', | ||
| GOOGLE_CLOUD_STORAGE_CREDENTIAL: '/tmp/gcs.json' | ||
| } | ||
| }) | ||
|
|
||
| afterAll(() => { | ||
| process.env = originalEnv | ||
| }) | ||
|
|
||
| it('treats whitespace-padded false as disabled uniform bucket access', () => { | ||
| process.env.GOOGLE_CLOUD_UNIFORM_BUCKET_ACCESS = ' false ' | ||
|
|
||
| const { GCSStorageProvider } = require('./GCSStorageProvider') | ||
| const provider = new GCSStorageProvider() | ||
|
|
||
| provider.getMulterStorage() | ||
|
|
||
| expect(multerGoogleCloudStorageMock).toHaveBeenCalledWith( | ||
| expect.objectContaining({ | ||
| uniformBucketLevelAccess: false | ||
| }) | ||
| ) | ||
| }) | ||
| }) |
There was a problem hiding this comment.
The test uses require inside the it block, which is non-idiomatic and redundant here as the module is not being re-evaluated with jest.resetModules(). It is better to use a standard top-level import. Additionally, adding a test case for the default (unset) behavior would verify the "default enabled" requirement mentioned in the PR description.
import { GCSStorageProvider } from './GCSStorageProvider'
const bucketMock = {}
const multerMock = jest.fn((config) => config)
const storageCtorMock = jest.fn(() => ({
bucket: jest.fn(() => bucketMock)
}))
const multerGoogleCloudStorageMock = jest.fn((config) => config)
jest.mock('@google-cloud/storage', () => ({
Storage: storageCtorMock
}))
jest.mock('multer', () => multerMock)
jest.mock('multer-cloud-storage', () => multerGoogleCloudStorageMock)
jest.mock('@google-cloud/logging-winston', () => ({
LoggingWinston: jest.fn()
}))
describe('GCSStorageProvider', () => {
const originalEnv = process.env
beforeEach(() => {
jest.clearAllMocks()
process.env = {
...originalEnv,
GOOGLE_CLOUD_STORAGE_BUCKET_NAME: 'test-bucket',
GOOGLE_CLOUD_STORAGE_PROJ_ID: 'test-project',
GOOGLE_CLOUD_STORAGE_CREDENTIAL: '/tmp/gcs.json'
}
})
afterAll(() => {
process.env = originalEnv
})
it('treats whitespace-padded false as disabled uniform bucket access', () => {
process.env.GOOGLE_CLOUD_UNIFORM_BUCKET_ACCESS = ' false '
const provider = new GCSStorageProvider()
provider.getMulterStorage()
expect(multerGoogleCloudStorageMock).toHaveBeenCalledWith(
expect.objectContaining({
uniformBucketLevelAccess: false
})
)
})
it('defaults to enabled uniform bucket access when env is unset', () => {
delete process.env.GOOGLE_CLOUD_UNIFORM_BUCKET_ACCESS
const provider = new GCSStorageProvider()
provider.getMulterStorage()
expect(multerGoogleCloudStorageMock).toHaveBeenCalledWith(
expect.objectContaining({
uniformBucketLevelAccess: true
})
)
})
})|
Addressed the Gemini follow-up in the existing PR branch.
Local validation remains limited in this checkout because |
Summary
GOOGLE_CLOUD_UNIFORM_BUCKET_ACCESSinstead of coercing any non-empty string totruefalsevaluesValidation
git diff --checkpnpm test -- --runInBand src/storage/GCSStorageProvider.test.ts(fails locally becausepackages/components/node_modulesis missing in this checkout;jestis not installed yet)