Skip to content

refactor(functions/v2/imagemagick): migrate from gm to sharp#4289

Closed
angelcaamal wants to merge 2 commits intoGoogleCloudPlatform:mainfrom
angelcaamal:refactor/imagemagick-v2-gm-to-sharp
Closed

refactor(functions/v2/imagemagick): migrate from gm to sharp#4289
angelcaamal wants to merge 2 commits intoGoogleCloudPlatform:mainfrom
angelcaamal:refactor/imagemagick-v2-gm-to-sharp

Conversation

@angelcaamal
Copy link
Copy Markdown
Contributor

@angelcaamal angelcaamal commented Apr 17, 2026

Description

Fixes Internal: b/503435756

Note: Before submitting a pull request, please open an issue for discussion if you are not associated with Google.

Checklist

  • I have followed guidelines from CONTRIBUTING.MD and Samples Style Guide
  • Tests pass: npm test (see Testing)
  • Lint pass: npm run lint (see Style)
  • Required CI tests pass (see CI testing)
  • These samples need a new API enabled in testing projects to pass (let us know which ones)
  • These samples need a new/updated env vars in testing projects set to pass (let us know which ones)
  • This pull request is from a branch created directly off of GoogleCloudPlatform/nodejs-docs-samples. Not a fork.
  • This sample adds a new sample directory, and I updated the CODEOWNERS file with the codeowners for this sample
  • This sample adds a new sample directory, and I created GitHub Actions workflow for this sample
  • This sample adds a new Product API, and I updated the Blunderbuss issue/PR auto-assigner with the codeowners for this sample
  • Please merge this PR for me once it is approved

Note: Any check with (dev), (experimental), or (legacy) can be ignored and should not block your PR from merging (see CI testing).

@angelcaamal angelcaamal requested a review from a team as a code owner April 17, 2026 21:07
@angelcaamal angelcaamal added the api: cloudfunctions Issues related to the Cloud Run functions API. label Apr 17, 2026
@angelcaamal angelcaamal requested a review from a team as a code owner April 17, 2026 21:07
@angelcaamal angelcaamal added the samples Issues that are directly related to samples. label Apr 17, 2026
Copy link
Copy Markdown
Contributor

@gemini-code-assist gemini-code-assist Bot left a comment

Choose a reason for hiding this comment

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

Code Review

This pull request migrates the image processing logic from the gm library to sharp, updating dependencies and test configurations accordingly. The review feedback identifies a potential resource leak where temporary files are not deleted if an error occurs during processing; it is recommended to use a try...finally block to ensure cleanup.

Comment on lines +78 to +101
try {
await sharp(tempLocalPath).blur(16).toFile(tempLocalBlurredPath);

console.log(`Blurred image: ${file.name}`);
} catch (err) {
console.error('Failed to blur image.', err);
throw err;
}

// Upload result to a different bucket, to avoid re-triggering this function.
const blurredBucket = storage.bucket(blurredBucketName);

// Upload the Blurred image back into the bucket.
const gcsPath = `gs://${blurredBucketName}/${file.name}`;
try {
await blurredBucket.upload(tempLocalPath, {destination: file.name});
await blurredBucket.upload(tempLocalBlurredPath, {destination: file.name});
console.log(`Uploaded blurred image to: ${gcsPath}`);
} catch (err) {
throw new Error(`Unable to upload blurred image to ${gcsPath}: ${err}`);
}

// Delete the temporary file.
return fs.unlink(tempLocalPath);
await fs.unlink(tempLocalPath);
return await fs.unlink(tempLocalBlurredPath);
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

high

Temporary files created in the /tmp directory should be deleted even if an error occurs during processing. Currently, if sharp or upload fails, the unlink calls are skipped, which can lead to memory exhaustion in the Cloud Function environment. Wrapping the processing logic in a try...finally block ensures cleanup.

  try {
    try {
      await sharp(tempLocalPath).blur(16).toFile(tempLocalBlurredPath);
      console.log('Blurred image: ' + file.name);
    } catch (err) {
      console.error('Failed to blur image.', err);
      throw err;
    }

    // Upload result to a different bucket, to avoid re-triggering this function.
    const blurredBucket = storage.bucket(blurredBucketName);

    // Upload the Blurred image back into the bucket.
    const gcsPath = 'gs://' + blurredBucketName + '/' + file.name;
    try {
      await blurredBucket.upload(tempLocalBlurredPath, {destination: file.name});
      console.log('Uploaded blurred image to: ' + gcsPath);
    } catch (err) {
      throw new Error('Unable to upload blurred image to ' + gcsPath + ': ' + err);
    }
  } finally {
    // Delete the temporary files.
    await Promise.allSettled([
      fs.unlink(tempLocalPath),
      fs.unlink(tempLocalBlurredPath),
    ]);
  }

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

api: cloudfunctions Issues related to the Cloud Run functions API. samples Issues that are directly related to samples.

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant