Skip to content

feat: add graphile-bucket-provisioner-plugin + wire into ConstructivePreset#962

Merged
pyramation merged 6 commits intomainfrom
devin/1775215835-bucket-provisioner-plugin
Apr 4, 2026
Merged

feat: add graphile-bucket-provisioner-plugin + wire into ConstructivePreset#962
pyramation merged 6 commits intomainfrom
devin/1775215835-bucket-provisioner-plugin

Conversation

@pyramation
Copy link
Copy Markdown
Contributor

@pyramation pyramation commented Apr 3, 2026

Summary

New PostGraphile v5 plugin that hooks into bucket creation mutations to automatically provision S3-compatible buckets using @constructive-io/bucket-provisioner.

Two provisioning pathways:

  1. Auto-provisioning hook — wraps create* mutations on tables tagged with @storageBuckets to provision S3 buckets after the DB row is created
  2. Explicit provisionBucket mutation — GraphQL mutation for manual/retry provisioning

Also adds packages/bucket-provisioner, packages/upload-client, and the new plugin to the CI test matrix.

Preset Integration (latest)

Wires BucketProvisionerPreset into ConstructivePreset following the same lazy-init pattern as the presigned URL plugin:

  • bucket-provisioner-resolver.ts — reads CDN config via getEnvOptions() from @constructive-io/graphql-env, lazily creates and caches a StorageConnectionConfig on first use
  • constructive-preset.ts — passes getBucketProvisionerConnection as a function ref (not called), so env vars are only read when the first provisioning operation runs
  • JSDoc examples updated to show getEnvOptions() pattern instead of raw process.env

Updates since last revision

  • Schema snapshot updatedschema-snapshot.test.ts.snap now includes the new provisionBucket mutation, ProvisionBucketInput, and ProvisionBucketPayload types added by the preset wiring. This confirms the plugin correctly extends the GraphQL schema when included in ConstructivePreset.

Review & Testing Checklist for Human

  • allowedOrigins: ['http://localhost:3000'] hardcoded in preset (constructive-preset.ts:94) — this is a dev default. Verify this is acceptable for production or if it should come from getEnvOptions() / a config value instead.
  • SQL interpolation in plugin.ts:264-268 — bucket schema/table names are interpolated into a query string via "${storageModule.buckets_schema}"."${storageModule.buckets_table}". Values come from the trusted storage_module table, but verify this is acceptable vs. parameterized queries.
  • resolveConnection() mutates the passed-in options object (plugin.ts:82-86) — it replaces options.connection (the lazy getter function) with the resolved value for caching. This is a side effect on the caller's object. Confirm this is intentional.
  • Tests are entirely mock-basedgrafast, graphile-utils, bucket-provisioner, and logger are all mocked. No integration tests against a real PostGraphile instance. Consider whether this gives sufficient confidence for the plugin's hook-based behavior.
  • Verify the schema snapshot diff looks correct — the updated snapshot adds provisionBucket mutation, ProvisionBucketInput, and ProvisionBucketPayload. Spot-check that no existing types were accidentally removed or altered.

Recommended test plan: Deploy with a local PostGraphile + MinIO setup, run a createBucket mutation on a @storageBuckets-tagged table, and verify both the DB row and S3 bucket are created. Then test the failure case (e.g., bad S3 credentials) to confirm the mutation still succeeds and the error is logged.

Notes

  • Lock file changes are AWS SDK dependency deduplication from merging the bucket-provisioner branch — not new dependency additions.
  • The provisionBucketForRow helper queries STORAGE_MODULE_QUERY for endpoint/provider overrides, but in the explicit mutation path this same query is also run earlier to find the bucket table. Minor redundancy, not a bug.
  • bucket-provisioner-resolver.ts follows the exact same pattern as presigned-url-resolver.ts (module-level cache, lazy init on first call via getEnvOptions()).
  • The CDNOptions.provider type ('s3' | 'minio' | 'gcs') is a subset of StorageConnectionConfig.provider ('s3' | 'minio' | 'r2' | 'gcs' | 'spaces'), so the cast in the resolver is safe.
  • Schema snapshot changes are purely additive — existing types are unchanged, only new bucket provisioner types were appended.

Link to Devin session: https://app.devin.ai/sessions/4c882ba2dfbf4045adf85fb83cde6f77
Requested by: @pyramation


Open with Devin

…kets on bucket table mutations

- PostGraphile v5 plugin with two provisioning pathways:
  1. Auto-provisioning hook on create mutations tagged with @storagebuckets
  2. Explicit provisionBucket GraphQL mutation for manual/retry provisioning
- Reads per-database endpoint/provider/publicUrlPrefix overrides from storage_module table
- Lazy S3 config resolution (function-based, cached after first call)
- Graceful error handling (provisioning failures logged, never fail the mutation)
- Custom bucket naming via prefix or resolveBucketName function
- 46 passing tests covering plugin structure, mutation callback, auto-provisioning hook,
  connection config resolution, error handling, and bucket name resolution
- Added to CI test matrix
@devin-ai-integration
Copy link
Copy Markdown
Contributor

🤖 Devin AI Engineer

I'll be helping with this pull request! Here's what you should know:

✅ I will automatically:

  • Address comments on this PR. Add '(aside)' to your comment to have me ignore it.
  • Look at CI failures and help fix them

Note: I can only respond to comments from users who have write access to this repository.

⚙️ Control Options:

  • Disable automatic comment and CI monitoring

@socket-security
Copy link
Copy Markdown

socket-security bot commented Apr 3, 2026

All alerts resolved. Learn more about Socket for GitHub.

This PR previously contained dependency changes with security issues that have been resolved, removed, or ignored.

View full report

Copy link
Copy Markdown
Contributor

@devin-ai-integration devin-ai-integration bot left a comment

Choose a reason for hiding this comment

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

✅ Devin Review: No Issues Found

Devin Review analyzed this PR and found no potential bugs to report.

View in Devin Review to see 6 additional findings.

Open in Devin Review

…Options

- Add bucket-provisioner-resolver.ts in graphile-settings (lazy init via getEnvOptions, same pattern as presigned-url-resolver.ts)
- Wire BucketProvisionerPreset into constructive-preset.ts with lazy connection getter
- Update JSDoc examples in bucket-provisioner-plugin to show getEnvOptions pattern instead of raw process.env
- Export getBucketProvisionerConnection from graphile-settings index
@devin-ai-integration devin-ai-integration bot changed the title feat: add graphile-bucket-provisioner-plugin — auto-provisions S3 buckets on bucket table mutations feat: add graphile-bucket-provisioner-plugin + wire into ConstructivePreset Apr 4, 2026
@pyramation pyramation merged commit e95d201 into main Apr 4, 2026
49 checks passed
@pyramation pyramation deleted the devin/1775215835-bucket-provisioner-plugin branch April 4, 2026 02:37
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant