-
Notifications
You must be signed in to change notification settings - Fork 3
fix: Error creating openai_vector_store_file resources #37
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: main
Are you sure you want to change the base?
Conversation
WalkthroughThe PR introduces retry logic with exponential backoff to the Changes
Sequence DiagramsequenceDiagram
participant TF as Terraform
participant Provider as Provider
participant API as OpenAI API
rect rgb(200, 220, 255)
Note over TF,API: Create Vector Store File
TF->>Provider: openai_vector_store_file create
Provider->>API: POST /vector_stores/{id}/files
API-->>Provider: file_id (queued)
end
rect rgb(220, 240, 200)
Note over Provider,API: Retry-Enabled Read Flow (NEW)
Provider->>Provider: readWithRetry(maxRetries=5)
loop Exponential Backoff: 1s, 2s, 4s, 8s, 16s
Provider->>API: GET /vector_stores/{id}/files/{file_id}
alt Success
API-->>Provider: file status=completed
Provider-->>Provider: return success
else Retriable Error (not found)
API-->>Provider: 404 "not found"
Provider->>Provider: wait & retry
else Non-Retriable Error
API-->>Provider: other error
Provider-->>Provider: return error (no retry)
end
end
end
rect rgb(255, 240, 200)
Note over Provider,TF: Resource State Updated
Provider-->>TF: resource complete
TF->>TF: state committed
end
Estimated code review effort🎯 4 (Complex) | ⏱️ ~75 minutes Attention areas:
Poem
Pre-merge checks and finishing touches❌ Failed checks (1 warning, 1 inconclusive)
✅ Passed checks (3 passed)
Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out. Comment |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Actionable comments posted: 1
🧹 Nitpick comments (1)
internal/provider/resource_openai_vector_store_file_test.go (1)
215-224: Mirror the retry predicate’s case-insensitive check in testsOnce the production code normalizes error text, this test should do the same (and ideally add a
"404 Not Found"sample) so the unit test continues to reflect the real retry gate. Suggested tweak:- // Check if error message contains retry-able patterns - shouldRetry := strings.Contains(tc.errorMsg, "No file found") || - strings.Contains(tc.errorMsg, "not found") + msg := strings.ToLower(tc.errorMsg) + shouldRetry := strings.Contains(msg, "no file found") || + strings.Contains(msg, "not found")You can then add a new case with
"404 Not Found"to lock in the regression test.
📜 Review details
Configuration used: CodeRabbit UI
Review profile: CHILL
Plan: Pro
📒 Files selected for processing (2)
internal/provider/resource_openai_vector_store_file.go(4 hunks)internal/provider/resource_openai_vector_store_file_test.go(1 hunks)
🧰 Additional context used
🧬 Code graph analysis (1)
internal/provider/resource_openai_vector_store_file_test.go (1)
internal/client/client.go (1)
Error(206-210)
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Actionable comments posted: 1
📜 Review details
Configuration used: CodeRabbit UI
Review profile: CHILL
Plan: Pro
📒 Files selected for processing (3)
.github/workflows/acceptance-tests.yml(1 hunks)internal/provider/provider_test.go(1 hunks)internal/provider/resource_openai_vector_store_file_retry_test.go(1 hunks)
🧰 Additional context used
🪛 GitHub Actions: CI
internal/provider/resource_openai_vector_store_file_retry_test.go
[error] 240-240: Test 'ZeroMaxRetries' in TestRetryLogicEdgeCases failed: Expected error when maxRetries=0.
🔇 Additional comments (2)
internal/provider/provider_test.go (1)
32-37: Optional org handling aligns with real-world setups.
Allowing acceptance tests to proceed withoutOPENAI_ORGANIZATION_IDmatches the fact that many keys are tied to personal accounts, and the logging is helpful for debugging..github/workflows/acceptance-tests.yml (1)
31-60: CI guardrails look solid.
Thanks for wiring the dispatch/label gates, the API key checks, and the explicit warning whenOPENAI_ORGANIZATION_IDis absent — that mirrors the provider’s new optional handling and keeps the job output clear. Pinning Terraform to the 1.12 line is reasonable today, though we should plan to validate against the current 1.13.x releases soon. (developer.hashicorp.com)
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Actionable comments posted: 1
♻️ Duplicate comments (1)
internal/provider/resource_openai_vector_store_file_retry_test.go (1)
170-205: [Still unresolved] Past review comment not addressed: zero maxRetries silently succeeds.The issue from the previous review remains unresolved. When
maxRetriesis 0, the for-loop (line 175) never executes,lastErrstaysnil, and the function returns success instead of an error. This causes test misconfiguration to pass silently.Apply the guard suggested in the past review:
func simulateRetryLogic(readFunc mockReadFunc, maxRetries int) diag.Diagnostics { + if maxRetries <= 0 { + return diag.Errorf("maxRetries must be at least 1 for vector store file read retries") + } + ctx := context.Background() d := &schema.ResourceData{} var lastErr diag.Diagnostics
🧹 Nitpick comments (1)
internal/provider/resource_openai_vector_store_file_retry_test.go (1)
127-165: Consider increasing timing tolerance for CI stability.The 200ms tolerance (line 154) and sub-second thresholds (lines 43, 122) may cause flakiness in resource-constrained CI environments. Consider increasing the tolerance to 500ms or using relative thresholds.
Apply this diff to increase tolerance:
- tolerance := 200 * time.Millisecond + tolerance := 500 * time.MillisecondAnd for quick-completion checks:
// Should complete almost immediately (no retries) - if elapsed > 500*time.Millisecond { + if elapsed > 1*time.Second { t.Errorf("Expected to complete quickly, took %v", elapsed) }
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Actionable comments posted: 1
🧹 Nitpick comments (3)
internal/provider/resource_openai_vector_store_file_test.go (3)
62-75: Consider verifying the resource exists via API.The helper currently only validates that the resource ID exists in Terraform state without confirming the resource exists in the OpenAI API. While this is acceptable for basic scaffolding, consider making an actual API call to verify the resource exists when the tests are enabled, similar to the destroy check pattern used in
testAccCheckOpenAIVectorStoreFileDestroy.Example enhancement:
func testAccCheckOpenAIVectorStoreFileExists(n string) resource.TestCheckFunc { return func(s *terraform.State) error { rs, ok := s.RootModule().Resources[n] if !ok { return fmt.Errorf("Not found: %s", n) } if rs.Primary.ID == "" { return fmt.Errorf("No vector store file ID is set") } + + // Verify the resource exists in the API + client := testClient() + vectorStoreID := rs.Primary.Attributes["vector_store_id"] + fileID := rs.Primary.ID + _, err := client.DoRequest("GET", fmt.Sprintf("/v1/vector_stores/%s/files/%s", vectorStoreID, fileID), nil) + if err != nil { + return fmt.Errorf("Vector store file %s does not exist: %s", fileID, err) + } return nil } }
162-191: Test name could be more descriptive.The test function is named
TestVectorStoreFileReadRetryLogic, but it primarily validates the resource schema rather than testing retry behavior. The comment on line 179 acknowledges this. Consider renaming toTestVectorStoreFileResourceSchemafor clarity.-func TestVectorStoreFileReadRetryLogic(t *testing.T) { +func TestVectorStoreFileResourceSchema(t *testing.T) { // Mock resource data d := schema.TestResourceDataRaw(t, resourceOpenAIVectorStoreFile().Schema, map[string]interface{}{
195-240: Consider testing the actual retry detection function.The test reimplements the retry detection logic inline (lines 231-232) rather than calling the actual implementation. This creates a risk: if the real retry logic in
resourceOpenAIVectorStoreFileReadWithRetrychanges, this test won't detect the discrepancy.Consider extracting the retry detection logic into a testable helper function and calling it from both the production code and the test:
// In resource_openai_vector_store_file.go func isRetriableError(err error) bool { if err == nil { return false } errMsg := err.Error() return strings.Contains(errMsg, "No file found") || strings.Contains(errMsg, "not found") } // In test func TestRetryLogicErrorDetection(t *testing.T) { // ... for _, tc := range testCases { t.Run(tc.name, func(t *testing.T) { err := errors.New(tc.errorMsg) shouldRetry := isRetriableError(err) if shouldRetry != tc.shouldRetry { t.Errorf("Expected shouldRetry=%v for error '%s', got %v", tc.shouldRetry, tc.errorMsg, shouldRetry) } }) } }Verify if such a function already exists:
#!/bin/bash # Search for retry-related functions in the resource implementation rg -n "func.*[Rr]etry|shouldRetry|isRetriable" --type=go internal/provider/resource_openai_vector_store_file.go
📜 Review details
Configuration used: CodeRabbit UI
Review profile: CHILL
Plan: Pro
📒 Files selected for processing (2)
.github/workflows/acceptance-tests.yml(1 hunks)internal/provider/resource_openai_vector_store_file_test.go(1 hunks)
🧰 Additional context used
🧬 Code graph analysis (1)
internal/provider/resource_openai_vector_store_file_test.go (1)
internal/client/client.go (1)
Error(206-210)
🔇 Additional comments (5)
.github/workflows/acceptance-tests.yml (4)
1-15: Well-designed workflow triggers.The combination of manual dispatch with optional test filtering and automatic label-based triggering provides good flexibility for both ad-hoc and automated testing scenarios.
44-62: Excellent test execution configuration.The test execution step includes:
- Proper environment variable configuration for OpenAI credentials
- Clear warnings about real resource creation and costs
- Appropriate validation that fails fast on missing required credentials
- Flexible test filtering via the TEST_FILTER variable
The implementation correctly handles both required (API key) and optional (Organization ID) credentials.
64-86: LGTM: PR feedback implementation.The PR commenting logic correctly posts feedback only for pull request events (not manual dispatches) and uses clear, concise messaging with visual indicators.
36-39: The original review comment contains an incorrect premise.Terraform 1.12 does exist, and as of November 3, 2025, the latest stable release is 1.13.4. The version
1.12.*specified in the workflow is a valid, released version and is available for use. The original concern that "this version may not exist yet" is unfounded.While the workflow could optionally be updated to use the latest stable version (1.13.4) for access to newer features and bug fixes, the current specification is not incorrect or broken. Any decision to update should be based on project requirements and compatibility testing, not on the version being unavailable.
Likely an incorrect or invalid review comment.
internal/provider/resource_openai_vector_store_file_test.go (1)
77-101: No action required—testClient() is properly defined.The
testClient()function is defined ininternal/provider/provider_test.goat line 41, making it available for use in the test file. The code is correct.
…ixes #35) Implements retry mechanism with exponential backoff to handle eventual consistency issues when the OpenAI API returns 'No file found' errors immediately after file creation in vector stores. Changes: - Add resourceOpenAIVectorStoreFileReadWithRetry wrapper with exponential backoff - Retry up to 5 times with delays: 1s, 2s, 4s, 8s, 16s (total ~31s max) - Case-insensitive error detection for 'not found' and 'no file found' errors - Guard against invalid maxRetries configuration (must be >= 1) - Enhanced logging with tflog for debugging retry attempts Testing: - Comprehensive unit tests for retry behavior and edge cases - Acceptance test infrastructure with secure GitHub Actions workflow - Test data files for file upload validation - Made OPENAI_ORGANIZATION_ID optional (supports personal accounts) All tests pass with proper timing validation.
641b57d to
a55f871
Compare
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Actionable comments posted: 0
♻️ Duplicate comments (2)
internal/provider/resource_openai_vector_store_file_test.go (2)
103-119: Missing test data file: testdata/sample.txtLine 110 references
testdata/sample.txtwhich is not included in this PR. While the test is currently skipped, this file will be required when enabling the acceptance tests.Please add the missing test data file before removing the skip annotation.
121-157: Missing test data file: testdata/sample2.txtLine 133 references
testdata/sample2.txtwhich is not included in this PR. This PR includes sample1.txt and sample3.txt but is missing sample2.txt. While the test is currently skipped, this file will be required when enabling the acceptance tests.Please add the missing test data file to complete the test fixture set.
🧹 Nitpick comments (1)
internal/provider/resource_openai_vector_store_file_test.go (1)
195-240: Consider case-insensitive matching in error detection test.The test uses case-sensitive string matching (lines 231-232), while the actual implementation in
resource_openai_vector_store_file.go(lines 292-297) uses case-insensitive matching withstrings.ToLower. This creates a discrepancy between test expectations and actual behavior.Consider updating the test to match the actual implementation:
t.Run(tc.name, func(t *testing.T) { // Check if error message contains retry-able patterns - shouldRetry := strings.Contains(tc.errorMsg, "No file found") || - strings.Contains(tc.errorMsg, "not found") + lowerMsg := strings.ToLower(tc.errorMsg) + shouldRetry := strings.Contains(lowerMsg, "no file found") || + strings.Contains(lowerMsg, "not found") if shouldRetry != tc.shouldRetry {This would ensure the test validates the actual behavior and would correctly handle test cases like "FILE NOT FOUND" and "404 Not Found".
📜 Review details
Configuration used: CodeRabbit UI
Review profile: CHILL
Plan: Pro
📒 Files selected for processing (9)
.github/workflows/acceptance-tests.yml(1 hunks)internal/provider/provider_test.go(1 hunks)internal/provider/resource_openai_vector_store_file.go(4 hunks)internal/provider/resource_openai_vector_store_file_retry_test.go(1 hunks)internal/provider/resource_openai_vector_store_file_test.go(1 hunks)testdata/sample.txt(1 hunks)testdata/sample1.txt(1 hunks)testdata/sample2.txt(1 hunks)testdata/sample3.txt(1 hunks)
✅ Files skipped from review due to trivial changes (2)
- testdata/sample.txt
- testdata/sample2.txt
🚧 Files skipped from review as they are similar to previous changes (2)
- .github/workflows/acceptance-tests.yml
- internal/provider/provider_test.go
🧰 Additional context used
🧬 Code graph analysis (1)
internal/provider/resource_openai_vector_store_file_test.go (1)
internal/client/client.go (1)
Error(206-210)
🔇 Additional comments (14)
testdata/sample1.txt (1)
1-7: LGTM! Test data file is well-documented.The file content clearly describes the test scenario and aligns with the PR's retry logic objectives.
testdata/sample3.txt (1)
1-10: LGTM! Test data file clearly documents expected behavior.The retry timing documentation (1s, 2s, 4s, 8s, 16s) accurately reflects the exponential backoff implementation.
internal/provider/resource_openai_vector_store_file.go (5)
8-10: LGTM! Necessary imports for retry logic.The
timeandtflogimports are properly used for exponential backoff delays and debug logging throughout the retry implementation.
237-243: LGTM! Helpful logging for debugging.The debug and info logs provide good visibility into the file creation process and ID assignment, which will be valuable for troubleshooting eventual consistency issues.
266-268: LGTM! Retry logic correctly applied after creation.Using
resourceOpenAIVectorStoreFileReadWithRetrywith 5 retries addresses the eventual consistency issue described in the PR objectives. The approach maintains Terraform lifecycle semantics while handling transient API failures.
270-315: LGTM! Robust retry implementation with proper error handling.The retry function correctly implements:
- Exponential backoff with appropriate delays (1s, 2s, 4s, 8s, 16s)
- Case-insensitive error detection (addresses past review concern about "404 Not Found" variants)
- Fast-fail for non-retryable errors (auth, rate limits, etc.)
- Comprehensive logging at each retry stage
The implementation aligns well with the PR objectives and handles the OpenAI API's eventual consistency behavior.
324-332: LGTM! Read function properly uses resource ID.The modifications correctly use
d.Id()for the file ID and add helpful debug/error logging. This aligns with Terraform resource patterns and improves troubleshooting capabilities.internal/provider/resource_openai_vector_store_file_test.go (2)
13-60: LGTM! Well-structured acceptance tests.Both test cases follow Terraform provider testing best practices:
- Proper use of
PreCheckandProviderFactories- Appropriate existence and destruction checks
- Comprehensive attribute validation
The skip guards are sensible until API credentials are configured for CI.
62-101: LGTM! Helper functions properly validate resource lifecycle.The existence and destroy check functions correctly:
- Validate resource state presence
- Make API calls to verify actual deletion
- Use case-insensitive error matching for 404/not found responses
- Distinguish between expected (404) and unexpected errors
internal/provider/resource_openai_vector_store_file_retry_test.go (5)
18-166: LGTM! Comprehensive retry behavior testing.The test scenarios thoroughly validate:
- Immediate success without unnecessary retries
- Correct retry count after transient failures
- Exhaustion of all retries for persistent failures
- Fast-fail for non-retriable errors
- Accurate exponential backoff timing
Timing assertions use appropriate tolerances to account for test execution overhead while still catching timing regressions.
170-209: LGTM! Retry simulation properly guards against invalid configuration.The function now includes the guard clause for
maxRetries <= 0(lines 171-173), addressing the past review concern. The simulation accurately mirrors the actual retry logic inresource_openai_vector_store_file.go, including:
- Exponential backoff calculation
- Retriable error detection
- Early exit for non-retriable errors
213-216: LGTM! Error detection properly handles case variations.The case-insensitive matching correctly identifies retriable errors across different formats ("No file found", "404 Not Found", "FILE NOT FOUND", etc.), matching the actual implementation.
230-304: LGTM! Comprehensive edge case coverage.The edge case tests now include all scenarios requested in past reviews:
- Zero and negative
maxRetriesvalidation (lines 232-259)- Single retry behavior (lines 261-277)
- Case-insensitive error message matching with extensive test cases (lines 279-303)
The test cases cover both retriable and non-retriable error patterns, ensuring robust error handling.
219-228: LGTM! Useful performance baseline.The benchmark provides a baseline for the retry logic's happy path (immediate success), which helps identify performance regressions in future changes.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Actionable comments posted: 0
🧹 Nitpick comments (2)
internal/provider/resource_openai_vector_store_file.go (2)
266-270: LGTM! Consider making retry count configurable.The retry logic correctly addresses issue #35. The hardcoded
maxRetries=5provides a reasonable default (~31s max wait), but consider making this configurable via provider configuration or environment variable in a future enhancement for users with different latency requirements.
272-310: LGTM! Add parameter validation.The retry loop and exponential backoff logic are correctly implemented. However, add validation for the
maxRetriesparameter.Apply this diff to add validation:
func resourceOpenAIVectorStoreFileReadWithRetry(ctx context.Context, d *schema.ResourceData, m interface{}, maxRetries int) diag.Diagnostics { + if maxRetries < 1 { + return diag.Errorf("maxRetries must be at least 1, got: %d", maxRetries) + } + var lastErr diag.Diagnostics
📜 Review details
Configuration used: CodeRabbit UI
Review profile: CHILL
Plan: Pro
📒 Files selected for processing (2)
.gitignore(1 hunks)internal/provider/resource_openai_vector_store_file.go(4 hunks)
🔇 Additional comments (7)
.gitignore (1)
168-169: Verify that ignoring the entireexamples/directory aligns with project intent.The change adds a blanket ignore for
examples/, but line 46 already has a specific entry:terraform-provider-openai/examples/basic/terraform.tfvars. Before merging, clarify:
- Should the entire
examples/directory be ignored, or only specific test artifacts within it?- Are there example files that should remain committed to the repository (e.g., documentation or reference examples)?
- Does the new entry at line 169 make the line 46 entry redundant, or do they serve different purposes?
This is particularly important if the
examples/directory contains reference or documentation files that should be part of the repository.internal/provider/resource_openai_vector_store_file.go (6)
8-10: LGTM!The import additions are appropriate for the retry logic and structured logging being introduced.
237-243: LGTM!The structured logging adds valuable observability for debugging file creation and ID assignment.
311-324: LGTM! Case-insensitive matching correctly implemented.The case-insensitive error detection correctly addresses the previous review feedback and will catch both "No file found" and "404 Not Found" error variants.
325-338: LGTM!The retry exit logic correctly distinguishes between retriable and non-retriable errors, returning immediately for non-transient failures while logging retry attempts for eventual consistency issues.
352-355: LGTM!The error logging provides helpful debugging context when read operations fail.
347-349: I need to examine the codebase to understand what ID is actually being stored in the resource.Based on the web search results, I can now provide a comprehensive assessment.
The OpenAI API returns a file object with an "id" field (e.g., "file-Z80edd3ZDAkbrm43V...."), and the API expects you to pass the file_id parameter when attaching files to a vector store.
The change from
d.Get("file_id")tod.Id()is correct and important:
- The resource's ID should be the file ID returned by the API ("file-" format), which is what
d.Id()providesd.Get("file_id")retrieves the user-provided input field, which may diverge from the authoritative ID managed by the API- Using
d.Id()ensures you're using the canonical resource identifier for all subsequent API calls, including the read/retrieve operationThe logging additions are also appropriate for debugging resource state. The code change is correct.
| t.Logf("Using organization ID: %s", v) | ||
| } else { | ||
| t.Log("No organization ID set - using personal account") | ||
| } |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Is changing this test file really required in this PR?
|
PR title doesn't reflect what PR is doing |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Actionable comments posted: 0
🧹 Nitpick comments (1)
internal/provider/resource_openai_vector_store_file_retry_test.go (1)
74-74: Consider increasing timing tolerances for CI stability.The timing assertions at lines 74 (2-4 second range for ~3s backoff) and 154 (200ms tolerance) might be too tight for CI environments where systems can be under heavy load, potentially causing flaky test failures.
Consider widening the tolerances:
- if elapsed < 2*time.Second || elapsed > 4*time.Second { + if elapsed < 2*time.Second || elapsed > 5*time.Second {- tolerance := 200 * time.Millisecond + tolerance := 500 * time.MillisecondAlso applies to: 154-154
📜 Review details
Configuration used: CodeRabbit UI
Review profile: CHILL
Plan: Pro
📒 Files selected for processing (2)
internal/provider/resource_openai_vector_store_file.go(4 hunks)internal/provider/resource_openai_vector_store_file_retry_test.go(1 hunks)
🚧 Files skipped from review as they are similar to previous changes (1)
- internal/provider/resource_openai_vector_store_file.go
🔇 Additional comments (3)
internal/provider/resource_openai_vector_store_file_retry_test.go (3)
17-166: Comprehensive test coverage for retry behavior.The test suite covers all critical scenarios: immediate success, success after retries, max retries exhausted, non-retriable errors, and exponential backoff timing. The structure with clear subtests and call count tracking is excellent.
223-297: Excellent edge case coverage.The edge cases test thoroughly validates invalid configurations (zero/negative maxRetries), boundary conditions (single retry), and case-insensitive error matching. The test cases in ErrorMessageCaseInsensitivity appropriately distinguish between retriable and non-retriable errors.
194-194: No issues found - verification confirms containsRetriableError is properly accessible.The function
containsRetriableErroris defined at line 274 ininternal/provider/resource_openai_vector_store_file.go. Since both the test file and production file are in the sameinternal/provider/package, the test can access this function without any issues.
|
@pabloinigo could you please adjust the PR title? |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Actionable comments posted: 28
Caution
Some comments are outside the diff and can’t be posted inline due to platform limitations.
⚠️ Outside diff range comments (1)
examples/invite/README.md (1)
230-250: Fix markdown style issues in the data sources section.Line 234 uses emphasis (
**...Important**) instead of a proper heading. Consider using a proper Markdown heading syntax. Additionally, line 341 has a fenced code block without a language identifier.Apply this diff to improve the markdown structure:
-### Data Source: openai_project_users - -This data source retrieves information about all users within a specific project. - -**Important: Never output the entire data source directly** +### Data Source: openai_project_users + +This data source retrieves information about all users within a specific project. + +#### Important: Never output the entire data source directlyAnd for line 341:
- ``` + ```json { "role": "member" } - ``` + ```
🧹 Nitpick comments (23)
examples/moderation_direct/main.tf (1)
80-80: Remove trailing whitespace.Line 80 has a trailing space after the closing brace that should be removed for formatting consistency.
-} +}examples/rate_limit/README.md (1)
44-65: Refine repeated use of "right" for better readability.The permissions section uses "right" twice in nearby sentences (lines 46 and 60). Consider rephrasing one occurrence for better writing clarity.
Apply this diff to improve word variety:
- If you don't have the right permissions, the data sources will fail with a permissions error, but the example will still work for setting rate limits through the resources. + If you lack the required permissions, the data sources will fail with a permissions error, but the example will still work for setting rate limits through the resources.examples/fine_tuning/training_data/sample_validation.jsonl (1)
4-4: Remove trailing whitespace.Line 4 has trailing whitespace after the closing brace. For consistency with lines 1-3, please remove it.
examples/project_api/import_project_key.sh (1)
207-211: Auto-approve is reasonable for this workflow but consider adding confirmation.The script provides clear messaging before auto-applying, which is appropriate for an import workflow. However, consider adding an optional confirmation prompt to let users review the generated main.tf before applying, in case they notice issues.
examples/invite/README.md (1)
100-125: Helpful provider code fix example.The provider code fix section (lines 102-122) demonstrates good error handling for the "already accepted" deletion error case. Consider adding a note that this pattern should be reviewed against the actual provider implementation to ensure synchronization.
Consider adding a disclaimer:
## Provider Code Fix The provider's client code has been updated to handle "already accepted" errors during deletion: + +**Note: Verify this implementation against the current provider codebase to ensure it's up to date.**examples/organization_users/main.tf (2)
48-53: Replace hardcoded user ID with a variable for example reusability.The user ID is hardcoded, making this example harder for users to adapt. Consider extracting it to a variable with a comment explaining how to obtain a real user ID.
variable "organization_user_id" { description = "ID of the user to retrieve. Replace with a real user ID from your organization." type = string default = "user-udjrDA1SqpU8CnkH28BGq5JY" # Replace this with a real user ID } data "openai_organization_user" "specific" { count = var.enable_organization_users ? 1 : 0 user_id = var.organization_user_id }
61-66: Remove unreachable hardcoded user ID fallback.Line 64 contains a hardcoded fallback
"user-abc123xyz"that is unreachable because the resource only creates whenvar.enable_organization_usersis true, which also guards the data source. Simplify to remove the dead code path.resource "openai_project_user" "specific_user" { count = var.enable_organization_users ? 1 : 0 project_id = openai_project.example.id - user_id = var.enable_organization_users ? data.openai_organization_user.specific[0].id : "user-abc123xyz" + user_id = data.openai_organization_user.specific[0].id role = "owner" }examples/invite/data_sources.tf (2)
11-22: Extract hardcoded email to a variable for example reusability.The email address is hardcoded, making it difficult for users to adapt this example. Extract it to a variable with a descriptive name and default.
+# Email to use for the example invitation +variable "example_invite_email" { + description = "Email address for the example invitation" + type = string + default = "someone-new-example-a@example.com" +} + resource "openai_invite" "example_invite_data" { count = var.create_example_invite ? 1 : 0 - email = "someone-new-example-a@example.com" + email = var.example_invite_email role = "reader" # Can be "owner" or "reader"
49-78: Consider usingnullinstead of "example_invite_disabled" string fallback.The fallback string "example_invite_disabled" is not idiomatic Terraform. When the feature is disabled, consider using
nullor returning the data conditionally to avoid confusion about what the output actually represents.output "invite_id" { description = "ID of the invitation" - value = var.create_example_invite ? data.openai_invite.invitation_details[0].id : "example_invite_disabled" + value = try(data.openai_invite.invitation_details[0].id, null) }This way, Terraform users understand that a
nulloutput means the feature was disabled, and they won't accidentally use the sentinel string value.examples/project_user/data_sources.tf (2)
10-17: Extract hardcoded user ID to a variable for example reusability.The user ID is hardcoded, making this example less adaptable. Extract it to a variable so users can easily customize it with their own organization user IDs.
+# User ID from your organization to demonstrate project user operations +variable "example_user_id" { + description = "Real user ID from your organization" + type = string + default = "user-yatSd6LuWvgeoqZbd89xzPlJ" # Replace with a real user ID +} + resource "openai_project_user" "data_source_user" { project_id = openai_project.data_source_example.id - user_id = "user-yatSd6LuWvgeoqZbd89xzPlJ" # Real user ID from your organization + user_id = var.example_user_id role = "owner"
19-22: Use the same variable for organization user lookup (consistency with refactor).Line 21 also contains the hardcoded user ID. When refactoring line 13 to use a variable, update this data source to use the same variable for consistency.
data "openai_organization_user" "user_info" { - user_id = "user-yatSd6LuWvgeoqZbd89xzPlJ" # Real user ID from your organization + user_id = var.example_user_id }examples/embeddings/README.md (1)
68-102: Clarify import limitations and workaround approach.The "Import Limitations" section (lines 72-86) describes a workaround using "simulated embeddings" and "fault-tolerant structure," but these terms are vague. Additionally, line 93 states that applying after import will replace the resource, which seems to contradict the purpose of importing.
Consider:
- Clarifying what "simulated embeddings" means in concrete terms
- Explaining whether import is recommended or if it has significant caveats
- Documenting the exact behavior users should expect after import + apply
examples/upload/main.tf (1)
28-31: Remove unused local variable.The
training_file_pathlocal variable is defined but never used. Line 40 hardcodes the path instead of referencing this variable.Apply this diff to either remove the unused variable or use it:
-# Local variables for file properties -locals { - # Path to the training data file - training_file_path = "${path.module}/training_data.jsonl" -} - # Use the upload module to manage the file # This module works with both new uploads and imports module "fine_tune_upload" { source = "../../modules/upload" # Required attributes purpose = "fine-tune" - file_path = "./training_data.jsonl" + file_path = "${path.module}/training_data.jsonl"Or simply remove the unused locals block if the hardcoded path is preferred.
examples/upload/README.md (2)
103-119: Add language specifiers to code blocks.Multiple shell code blocks are missing language specifiers, which reduces readability and prevents proper syntax highlighting.
Apply these diffs to add bash language specifiers:
``` + ```bash export OPENAI_API_KEY=your_api_key_here ``` ``` + ```bash terraform init ``` ``` + ```bash terraform apply ``` ``` + ```bash terraform output file_id ```
153-161: Add language specifiers to cleanup code blocks.The cleanup section code blocks are missing language specifiers.
Apply this diff:
To destroy the resources created by Terraform:+```bash
terraform destroyNote that this will not delete the file from OpenAI. To delete the file, you need to call the OpenAI API:+```bash
curl -X DELETE https://api.openai.com/v1/files/$(terraform output -raw file_id)
-H "Authorization: Bearer $OPENAI_API_KEY"examples/model_response/README.md (1)
227-227: Consider tightening the phrasing around resource preservation.Line 227 could be more concise: change "If you want to make changes to your configuration file after importing, the provider will detect drift but won't recreate the resource, preserving your original output." to something like "After importing, configuration changes won't recreate the resource, preserving the original output."
examples/service_account/run.sh (1)
1-17: Add error handling and prefer environment variables for sensitive inputs.The script uses
-auto-approvewithout error handling, so failures go undetected. Additionally, passing the API key as a command-line argument makes it visible in process listings; use environment variables instead (e.g.,TF_VAR_openai_admin_key).#!/bin/bash +set -e # Exit on any error + # Check if admin key is provided if [ -z "$1" ]; then echo "Usage: ./run.sh YOUR_OPENAI_ADMIN_KEY" echo "Example: ./run.sh sk-your-openai-admin-key" exit 1 fi -# Store the admin key in a variable -OPENAI_ADMIN_KEY="$1" +# For better security, use environment variable instead: +# export TF_VAR_openai_admin_key="sk-admin-..." +# Then call: ./run.sh +if [ -z "$TF_VAR_openai_admin_key" ]; then + export TF_VAR_openai_admin_key="$1" +fi # Run terraform apply with the admin key terraform apply \ -var="try_create_service_account=true" \ -var="try_data_sources=false" \ - -var="openai_admin_key=$OPENAI_ADMIN_KEY" \ - -auto-approve + -auto-approveexamples/service_account/README.md (2)
105-114: Remove redundant "explicitly" adverbs in the list.Line 110 repeats the word "explicitly" in consecutive bullet points, which is redundant.
This design allows you to run the examples even without all permissions and see what would happen if you had the right permissions. - -1. Resources are only created when explicitly enabled -2. Data sources are only queried when explicitly enabled -3. Fallback values are used for all outputs when permissions are missing -4. Dependencies are carefully managed to ensure data sources are only accessed after resources are created + +1. Resources are only created when explicitly enabled +2. Data sources are only queried when needed +3. Fallback values are used for all outputs when permissions are missing +4. Dependencies are carefully managed to ensure data sources are only accessed after resources are created
91-103: Clarify that the curl example is a template.Add a note that the curl command is a template and that users should replace placeholder values with actual credentials.
## Verifying Your Admin Key You can verify that your admin key has the correct permissions by using curl: ```bash +# NOTE: This is a template. Replace placeholders with actual values. # Check if you can access a service account curl https://api.openai.com/v1/organization/projects/YOUR_PROJECT_ID/service_accounts/YOUR_SERVICE_ACCOUNT_ID \ -H "Authorization: Bearer YOUR_ADMIN_KEY" \examples/projects/data_sources.tf (1)
12-12: Consider whether explicitdepends_onis necessary.The configuration explicitly includes
depends_on = [openai_project.example]for both data sources (lines 12, 17). Terraform's implicit dependency tracking viaopenai_project.example.idin theopenai_projectdata source should be sufficient. Thedepends_onon theopenai_projectsdata source may be intentional for timing reasons, but verify if it's needed or if it could be removed for clarity.Also applies to: 17-17
examples/projects/README.md (1)
1-44: README setup and documentation structure is clear and professional.The documentation provides appropriate context, prerequisites, setup instructions, and usage workflows. The
terraform.tfvarsapproach for credential management is documented (lines 26-30), though the examples in main.tf rely on environment variables instead. Consider clarifying the relationship between these two approaches.Clarify the credential setup documentation by noting that the examples use environment variables (
OPENAI_API_KEY,OPENAI_ADMIN_KEY) rather thanterraform.tfvars. You could add a note about both approaches:## Setup Options ### Option 1: Environment Variables (Recommended) ```bash export OPENAI_API_KEY="sk-xxxx" export OPENAI_ADMIN_KEY="sk-xxxx" terraform applyOption 2: terraform.tfvars
Create a
terraform.tfvarsfile with your credentials (do not commit to VCS).</blockquote></details> <details> <summary>examples/run/cleanup_active_runs.sh (1)</summary><blockquote> `46-46`: **Simplify jq command to avoid useless use of cat.** The pattern `cat file | jq` is inefficient. `jq` can read files directly. Apply this diff: ```diff - thread_ids=$(cat terraform.tfstate | jq -r '.resources[]? | select(.type == "openai_thread") | .instances[].attributes.id' 2>/dev/null) + thread_ids=$(jq -r '.resources[]? | select(.type == "openai_thread") | .instances[].attributes.id' terraform.tfstate 2>/dev/null)examples/run/main.tf.example (1)
1-149: Clarify the purpose of .example files.Files with
.exampleextensions typically indicate template files that users should copy and customize. However, this file is much more complex thanmain.tfand includes features (custom functions, multiple tool types, module usage) that may overwhelm users looking for a basic example.Consider one of these approaches:
- If this is meant to be a comprehensive reference: Rename to something like
advanced.tforcomprehensive.tf- If it's meant to be a template: Add comments explaining what users should customize
- If it's redundant: Remove it in favor of the simpler
main.tfAlso add a README in
examples/run/explaining which example file serves which purpose.
📜 Review details
Configuration used: CodeRabbit UI
Review profile: CHILL
Plan: Pro
⛔ Files ignored due to path filters (6)
examples/audio/output/prueba_directorio_original.mp3is excluded by!**/*.mp3examples/audio/output/speech.mp3is excluded by!**/*.mp3examples/audio/output/test_speech.mp3is excluded by!**/*.mp3examples/audio/samples/speech.mp3is excluded by!**/*.mp3examples/image/output/edited_image_18043.pngis excluded by!**/*.pngexamples/messages/data/sample_data.csvis excluded by!**/*.csv
📒 Files selected for processing (73)
.gitignore(1 hunks)examples/embeddings/README.md(1 hunks)examples/embeddings/main.tf(1 hunks)examples/files/data/chat_requests_fixed.jsonl(1 hunks)examples/files/data/chat_requests_fixed2.jsonl(1 hunks)examples/files/data/embeddings_fixed.jsonl(1 hunks)examples/fine_tuning/data/fine_tune_data_v4.jsonl(1 hunks)examples/fine_tuning/training_data/sample_training.jsonl(1 hunks)examples/fine_tuning/training_data/sample_validation.jsonl(1 hunks)examples/image/output/simulated_image.txt(1 hunks)examples/invite/README.md(1 hunks)examples/invite/data_sources.tf(1 hunks)examples/invite/main.tf(1 hunks)examples/messages/README.md(1 hunks)examples/messages/data/sample_config.json(1 hunks)examples/messages/data/sample_document.txt(1 hunks)examples/messages/main.tf(1 hunks)examples/messages/retrieve_messages.tf(1 hunks)examples/model_response/README.md(1 hunks)examples/model_response/data_sources.tf(1 hunks)examples/model_response/input_items.tf(1 hunks)examples/model_response/main.tf(1 hunks)examples/model_response/model_response_data_source.tf(1 hunks)examples/model_response/model_response_input_items_data_source.tf(1 hunks)examples/model_response/model_responses_data_source.tf(1 hunks)examples/moderation/README.md(1 hunks)examples/moderation/main.tf(1 hunks)examples/moderation_direct/README.md(1 hunks)examples/moderation_direct/main.tf(1 hunks)examples/organization_users/README.md(1 hunks)examples/organization_users/email_lookup.tf(1 hunks)examples/organization_users/main.tf(1 hunks)examples/project_api/README.md(1 hunks)examples/project_api/import_project_key.sh(1 hunks)examples/project_api/main.tf(1 hunks)examples/project_user/README.md(1 hunks)examples/project_user/data_sources.tf(1 hunks)examples/project_user/email_lookup.tf(1 hunks)examples/project_user/main.tf(1 hunks)examples/projects/README.md(1 hunks)examples/projects/data_sources.tf(1 hunks)examples/projects/main.tf(1 hunks)examples/projects/test.tf(1 hunks)examples/rate_limit/README.md(1 hunks)examples/rate_limit/data_sources.tf(1 hunks)examples/rate_limit/main.tf(1 hunks)examples/run/README.md(1 hunks)examples/run/backup/main_fixed.tf(1 hunks)examples/run/backup/main_original.tf(1 hunks)examples/run/backup/runs_example.tf(1 hunks)examples/run/backup/test_simple.tf(1 hunks)examples/run/cleanup_active_runs.sh(1 hunks)examples/run/main.tf(1 hunks)examples/run/main.tf.example(1 hunks)examples/service_account/README.md(1 hunks)examples/service_account/data_sources.tf(1 hunks)examples/service_account/main.tf(1 hunks)examples/service_account/run.sh(1 hunks)examples/upload/README.md(1 hunks)examples/upload/fine_tuning_response.json(1 hunks)examples/upload/main.tf(1 hunks)examples/upload/training_data.jsonl(1 hunks)examples/vector_store/README.md(1 hunks)examples/vector_store/batch.tf(1 hunks)examples/vector_store/data_sources.tf(1 hunks)examples/vector_store/file.tf(1 hunks)examples/vector_store/files/api_documentation.md(1 hunks)examples/vector_store/files/product_guide.md(1 hunks)examples/vector_store/files/support_faq.md(1 hunks)examples/vector_store/main.tf(1 hunks)examples/vector_store/outputs.tf(1 hunks)examples/vector_store/provider.tf(1 hunks)examples/vector_store/test_file.txt(1 hunks)
✅ Files skipped from review due to trivial changes (15)
- examples/messages/README.md
- examples/files/data/chat_requests_fixed.jsonl
- examples/files/data/embeddings_fixed.jsonl
- examples/fine_tuning/training_data/sample_training.jsonl
- examples/run/README.md
- examples/vector_store/test_file.txt
- examples/model_response/model_responses_data_source.tf
- examples/moderation_direct/README.md
- examples/upload/fine_tuning_response.json
- examples/vector_store/provider.tf
- .gitignore
- examples/messages/retrieve_messages.tf
- examples/model_response/input_items.tf
- examples/messages/data/sample_document.txt
- examples/model_response/data_sources.tf
🧰 Additional context used
🪛 Gitleaks (8.29.0)
examples/service_account/README.md
[high] 93-98: Discovered a potential authorization token provided in a curl command header, which could compromise the curl accessed resource.
(curl-auth-header)
examples/vector_store/files/product_guide.md
[high] 76-77: Discovered a potential authorization token provided in a curl command header, which could compromise the curl accessed resource.
(curl-auth-header)
🪛 LanguageTool
examples/vector_store/files/support_faq.md
[grammar] ~17-~17: Use a hyphen to join words.
Context: ...ited to 60 requests per minute. Standard tier accounts are limited to 600 request...
(QB_NEW_EN_HYPHEN)
examples/service_account/README.md
[grammar] ~45-~45: Ensure spelling is correct
Context: ...e both creation and reading in the same apply: bash terraform apply -var="try_create_service_account=true" -var="try_data_sources=true" -var="openai_admin_key=sk-admin-..." ### Helper Script A convenient run.sh scr...
(QB_NEW_EN_ORTHOGRAPHY_ERROR_IDS_1)
[style] ~110-~110: This adverb was used twice in the sentence. Consider removing one of them or replacing them with a synonym.
Context: ... explicitly enabled 2. Data sources are only queried when explicitly enabled 3. Fall...
(ADVERB_REPETITION_PREMIUM)
examples/invite/README.md
[style] ~147-~147: The noun “invitation” is usually used instead of ‘invite’ in formal writing.
Context: ...er" } ### Custom API Key Invite An invite using a custom API key:hcl resource...
(AN_INVITE)
examples/model_response/README.md
[style] ~227-~227: Consider shortening or rephrasing this to strengthen your wording.
Context: ...ponse.resource_name ``` If you want to make changes to your configuration file after importing...
(MAKE_CHANGES)
examples/rate_limit/README.md
[style] ~60-~60: You have already used ‘right’ in nearby sentences. Consider using an alternative word to let your writing stand out and sound more polished.
Context: ...k-admin-..." ``` If you don't have the right permissions, the data sources will fail...
(REP_RIGHT)
🪛 markdownlint-cli2 (0.18.1)
examples/moderation/README.md
107-107: Fenced code blocks should have a language specified
(MD040, fenced-code-language)
128-128: Fenced code blocks should have a language specified
(MD040, fenced-code-language)
135-135: Fenced code blocks should have a language specified
(MD040, fenced-code-language)
146-146: Fenced code blocks should have a language specified
(MD040, fenced-code-language)
180-180: Fenced code blocks should have a language specified
(MD040, fenced-code-language)
examples/project_user/README.md
234-234: Emphasis used instead of a heading
(MD036, no-emphasis-as-heading)
341-341: Fenced code blocks should have a language specified
(MD040, fenced-code-language)
examples/vector_store/files/api_documentation.md
11-11: Fenced code blocks should have a language specified
(MD040, fenced-code-language)
examples/upload/README.md
100-100: Multiple headings with the same content
(MD024, no-duplicate-heading)
103-103: Fenced code blocks should have a language specified
(MD040, fenced-code-language)
108-108: Fenced code blocks should have a language specified
(MD040, fenced-code-language)
113-113: Fenced code blocks should have a language specified
(MD040, fenced-code-language)
118-118: Fenced code blocks should have a language specified
(MD040, fenced-code-language)
153-153: Fenced code blocks should have a language specified
(MD040, fenced-code-language)
159-159: Fenced code blocks should have a language specified
(MD040, fenced-code-language)
examples/model_response/README.md
155-155: Fenced code blocks should have a language specified
(MD040, fenced-code-language)
160-160: Fenced code blocks should have a language specified
(MD040, fenced-code-language)
165-165: Fenced code blocks should have a language specified
(MD040, fenced-code-language)
179-179: Fenced code blocks should have a language specified
(MD040, fenced-code-language)
examples/organization_users/README.md
75-75: Fenced code blocks should have a language specified
(MD040, fenced-code-language)
85-85: Fenced code blocks should have a language specified
(MD040, fenced-code-language)
examples/project_api/README.md
75-75: Fenced code blocks should have a language specified
(MD040, fenced-code-language)
115-115: Bare URL used
(MD034, no-bare-urls)
🔇 Additional comments (61)
examples/messages/data/sample_config.json (1)
1-15: Example configuration file looks good.The JSON structure is valid and well-formed. This serves as a useful reference configuration for the messaging example workflow. No issues with the content or structure.
examples/files/data/chat_requests_fixed2.jsonl (1)
1-3: JSONL examples look consistent and validAll three lines are valid JSON objects, follow a consistent chat request shape (model/custom_id/method/messages), and are appropriate as example data alongside the existing
chat_requests_fixed.jsonl. No issues from a schema or usability perspective.examples/image/output/simulated_image.txt (1)
1-10: Scope concern: This file appears tangential to the stated PR objectives.The PR objectives focus on vector store file retry logic (Go code changes), while this file is example documentation for image generation. Although the AI summary mentions "extensive Terraform example documentation," the explicit PR objectives don't reference image examples.
Please clarify whether this file is intentional and in scope, or if it was included unintentionally.
examples/moderation/README.md (1)
1-250: Content quality is excellent.The documentation is comprehensive, well-structured, and provides clear guidance on moderation usage patterns, import workflows, and API limitations. The dual approach to model version handling (provider-level and resource-level lifecycle blocks) is well-explained and defensively coded. Examples are concrete and directly applicable.
examples/moderation/main.tf (1)
1-90: Configuration is well-structured and follows best practices.The Terraform configuration consistently applies per-resource lifecycle blocks to handle model version differences. Resource declarations are clear with appropriate input examples. Output definitions properly map to both individual and batch moderation results with descriptive labels.
examples/moderation_direct/main.tf (1)
1-80: Configuration is well-structured and consistent with the moderation example.The direct moderation example follows the same established patterns: per-resource lifecycle blocks, consistent output naming with the
direct_prefix, and descriptive labels. The three examples demonstrate a straightforward usage pattern without modules.examples/rate_limit/data_sources.tf (1)
1-72: Well-structured data sources with appropriate conditional logic.The data sources are correctly configured with count conditions to make them optional, and the outputs properly reference the conditional data source instances. The error handling documentation accurately reflects the PR's improvements for graceful authentication failure handling.
examples/rate_limit/main.tf (2)
17-21: Verify hardcoded project_id is clearly documented as a placeholder.The default project_id value appears to be a real OpenAI project ID format. If this is an actual project, consider removing it as a default or clearly marking it as an example/test-only value. Alternatively, make it required so users must provide their own project ID explicitly.
37-54: Resource definitions are well-structured with appropriate documentation.Both rate limit resources are correctly configured with model-appropriate attributes, and the ignore_rate_limit_warning flag is properly set. The comments effectively document the deletion behavior and how it's handled by the provider.
examples/rate_limit/README.md (4)
73-90: Clarify environment variable naming inconsistency.The usage instructions reference
OPENAI_ADMIN_API(line 79), but the provider configuration in main.tf comments mentionOPENAI_ADMIN_KEY(line 14). This naming discrepancy could confuse users about which environment variable to set. Ensure consistency or clarify the relationship between these variables.
92-131: Example components are clear and demonstrate practical usage patterns.The resource creation and data source examples are well-structured and show key concepts like conditional usage with count. Code blocks are syntactically correct and align with the actual configurations in main.tf and data_sources.tf.
175-208: Import instructions are comprehensive and well-documented.The import section clearly explains the composite ID format, prerequisites, and provides practical examples with verification steps. The use cases are relevant, and the instructions would help users bring existing rate limits under Terraform management.
210-217: Clean up section appropriately documents final state.The documentation clearly explains what happens during
terraform destroy(archival and reset, not deletion), which aligns with the provider improvements mentioned in the PR objectives.examples/fine_tuning/data/fine_tune_data_v4.jsonl (1)
1-12: JSONL training examples are well-formed and factually correctEach line is valid JSON (one object per line), follows the expected
messagesschema for chat fine‑tuning (system/user/assistant roles), and the listed capitals for all countries are correct. This dataset looks ready to use as fine‑tuning input, assuming the file is stored as UTF‑8 to preserve the accented characters (e.g., “Brasília”).examples/project_api/import_project_key.sh (1)
31-53: Input validation is clear and well-structured.The argument and environment checks provide helpful error messages and graceful exits. Good defensive programming.
examples/project_api/main.tf (1)
1-113: Well-structured Terraform example with clear patterns.The configuration demonstrates good practices:
- Proper use of conditional data sources with count
- Environment-based provider authentication
- Clear output expressions with fallback messages for missing inputs
- Good inline documentation
examples/vector_store/batch.tf (1)
1-23: LGTM!The batch upload example correctly demonstrates the multi-file creation scenario described in the PR objectives. This pattern, combined with the retry logic in the provider, should handle eventual-consistency issues when creating multiple vector store files concurrently.
examples/vector_store/README.md (1)
1-144: Comprehensive and well-structured documentation.The README clearly guides users through the vector store examples with prerequisites, configuration requirements, troubleshooting, and both module and direct resource approaches. The documentation correctly captures API constraints and error handling scenarios.
examples/vector_store/file.tf (1)
1-24: LGTM!The file correctly demonstrates the vector store file creation pattern that benefits from the PR's retry logic. The openai_vector_store_file resource creation and immediate read is precisely the scenario the fix addresses (eventual-consistency handling when OpenAI API returns "file not found" temporarily).
examples/vector_store/outputs.tf (1)
1-35: LGTM!The outputs are well-organized, providing both simple ID outputs and richer composite details. The aggregated
all_vector_store_idsoutput offers a useful summary for users of these examples.examples/vector_store/data_sources.tf (1)
1-97: Example file structure is well-organized.The file provides comprehensive examples of querying vector store data sources with pagination, filtering, and nested resource relationships. The outputs effectively expose the key attributes users would need. The file complements the PR's fix for vector store file creation by demonstrating the subsequent data query operations users can perform after successful resource creation.
examples/messages/main.tf (4)
1-86: Solid setup for sample data generation.The provider configuration, data directory creation, and sample file generation follow good Terraform practices with proper dependencies and path handling.
88-116: File uploads and thread creation are well-configured.Proper sequencing with explicit dependencies and meaningful metadata usage.
158-179: Verify the module path reference.The module reference at line 160 (
source = "../../modules/messages") should be verified to ensure the module exists in the repository and exports the expected outputs (message_id,content,created_at,attachments).
182-244: Comprehensive and well-structured outputs.The outputs provide useful information about created resources with clear descriptions and proper references to resource attributes.
examples/project_user/email_lookup.tf (1)
1-30: Well-structured email lookup pattern for project users.The data source configuration and outputs clearly demonstrate how to retrieve project user information by email address, with proper dependencies and descriptive output names.
examples/organization_users/email_lookup.tf (1)
1-45: Clear demonstration of email-based organization user lookup.The data sources and outputs effectively demonstrate how to retrieve organization user information by email address, with a practical commented example showing how to use the retrieved user ID in downstream resources.
examples/project_user/README.md (1)
334-366: Excellent guidance on role management and API integration.The section on "Role Management and API Integration" (lines 334-366) provides valuable context about how Terraform handles configuration drift and role updates. This is particularly useful for users unfamiliar with how the provider handles the source-of-truth pattern.
examples/invite/main.tf (3)
50-62: Clarify lifecycle configuration intent.Line 54 sets
prevent_destroy = false, which disables protection against destruction. Given the comment above about preventing deletion of accepted invitations, verify this is intentional. Typically, you would either omit this line (defaulting to false) or set it to true to prevent accidental deletion.The current configuration allows Terraform to destroy the invitation resource, which could be problematic for accepted invitations. Consider whether this is the intended behavior or if you meant to enable a different lifecycle rule.
1-96: Well-designed 3-step invitation workflow with good conditional logic.The use of variables (
countblocks at lines 39 and 85) to control workflow steps and the lifecycleignore_changesto handle non-updatable fields demonstrates good Terraform patterns for multi-step processes. The workflow instructions output is particularly helpful.
146-192: Comprehensive workflow instructions with practical error handling.The
workflow_instructionsoutput and the locals block for email-to-ID mapping provide clear guidance for users on executing the multi-step invitation workflow, including handling edge cases like deletion of accepted invitations.examples/project_user/main.tf (2)
1-56: Solid project setup and user data source configuration.The project creation, organization user retrieval, and locals for determining org owner status follow good patterns. The setup clearly demonstrates prerequisites and context.
88-132: Well-structured outputs with proper aggregation functions.The outputs use appropriate functions to extract user IDs, owner IDs, and member IDs from the project users data source, providing useful verification information without exposing sensitive internal fields.
examples/organization_users/main.tf (1)
87-132: Output definitions are well-structured and properly conditional.The outputs correctly guard access to data sources and provide sensible disabled placeholders when the feature is off. Good use of descriptions and conditional ternary operators.
examples/invite/data_sources.tf (2)
24-47: Data source definitions are correct and well-commented.The conditional data sources properly use
countanddepends_onfor clarity. The warning comment on line 34 about potential timeouts with large invite lists is helpful for users.
80-103: All-invitations outputs are well-structured with appropriate empty defaults.The use of empty collections
[]and{}as fallbacks is idiomatic and safe. Outputs correctly filter and map invite data.examples/project_user/data_sources.tf (1)
56-122: Output definitions are clear and comprehensive.All outputs correctly reference data sources and module attributes with appropriate descriptions. The filtering logic (e.g., selecting owners or members) is clear and maintainable.
examples/embeddings/main.tf (1)
76-76: Module outputs are correctly defined.Both referenced outputs exist in the embeddings module:
embedding_idoutput is defined (line 145 in modules/embeddings/main.tf)model_usedoutput is defined (line 135 in modules/embeddings/main.tf)The references on lines 76 and 81 of examples/embeddings/main.tf are valid and match the actual module outputs.
examples/embeddings/README.md (1)
87-93: The review comment is incorrect and should be disregarded.The import command on line 90 correctly references
openai_chat_completion.embedding_simulationbecause that is the actual resource type and name defined inmodules/embeddings/main.tf:66. The embeddings module intentionally usesopenai_chat_completionas a simulation resource, not the separateopenai_embeddingresource type. This is a deliberate design choice explained in the README's context about "simulated embeddings." The import example is accurate as written.Likely an incorrect or invalid review comment.
examples/upload/training_data.jsonl (1)
1-5: LGTM!The training data file is correctly formatted as JSONL with appropriate prompt-completion pairs for OpenAI fine-tuning examples.
examples/upload/README.md (1)
144-147: Both resource types are valid and registered in the provider.Verification confirms that both
openai_fine_tuned_modelandopenai_fine_tuning_jobare valid, registered Terraform resources in the provider (lines 280-281 ofinternal/provider/provider.go). The README's use ofopenai_fine_tuned_modelis not incorrect—it's a legitimate resource type with full CRUD support. The presence ofopenai_fine_tuning_jobin main.tf does not make the README example wrong; these appear to be two distinct resources that may serve different purposes in the fine-tuning workflow. No changes required.Likely an incorrect or invalid review comment.
examples/model_response/model_response_input_items_data_source.tf (1)
1-41: Intentionally commented example file serves its purpose.The examples are well-structured and demonstrate idiomatic usage of the
openai_model_response_input_itemsdata source with clear output patterns. Using comments to show alternative usage patterns is appropriate for documentation files.examples/model_response/model_response_data_source.tf (1)
1-44: Example file is well-structured and demonstrates correct data source usage.Both examples correctly show how to retrieve model responses and extract usage information. The mix of active and commented examples provides helpful guidance for different use cases.
examples/model_response/main.tf (2)
26-34: Use oflookup()for output safety is good practice.The outputs correctly use
lookup()with a fallback value to safely access nested attributes:lookup(openai_model_response.bedtime_story.output, "text", "No output available")This prevents errors if the
outputattribute structure changes. This approach is appropriate.Also applies to: 45-48, 59-62, 92-105
16-24: I'll help verify the attribute compatibility. Sinceterraformisn't available in the sandbox, let me search for information about the OpenAI Terraform provider schema and also check the repository for provider configuration.Now let me search more specifically for the mkdev-me provider documentation for theopenai_model_responseresource:Let me search the repository to find the provider schema and resource definitions:
Based on my investigation, I cannot fully verify the attribute compatibility for the
openai_model_responseresource because:
The
openai_model_responseresource exists in the mkdev-me/openai provider, but the Terraform Registry documentation requires JavaScript and is not accessible in this environment.The provider's GitHub repository is available, but the specific resource schema definitions are not accessible through web search.
The
terraformCLI is not available in the sandbox environment, so I cannot execute the validation command suggested in the review comment.The original review comment's recommendation to run
terraform validateis the correct approach. However, since this cannot be done in the current environment, the validation must be performed locally.
Verify attribute compatibility by running terraform validate locally.
The resource uses attributes including
model,input,temperature,max_output_tokens,instructions,preserve_on_change,imported, anduser. Executeterraform validatein your development environment to confirm these attribute names match the mkdev-me/openai provider's schema for theopenai_model_responseresource version in use.examples/service_account/main.tf (1)
38-57: LGTM: Good use of defensive coding patterns.The outputs properly use
try()with fallback strings to handle permission errors gracefully. Thesensitive = trueflag on the API key output is good security practice, and thecountconditional on the resource creation is a clean pattern.examples/service_account/data_sources.tf (2)
36-50: LGTM: Data sources properly handle conditionals.The data sources use appropriate
countconditions and thedepends_onsequencing ensures resources are created before data retrieval. The fallback local value pattern at lines 30-33 is clean and defensive.
65-88: LGTM: Outputs properly handle permission errors.The outputs use
try()with descriptive fallback values when permissions are insufficient, providing a good user experience when operations fail due to scope limitations.examples/projects/main.tf (3)
18-53: Resource definitions are well-structured and demonstrate useful patterns.The resources properly showcase basic creation (
test), production scenario (production), and optional resources usingcount = 0. No structural issues identified.
1-15: Verify fjcorp/openai provider availability and credentials support.The web search could not locate the "fjcorp/openai" provider in the Terraform registry or public GitHub repositories. While the environment variable names
OPENAI_API_KEYandOPENAI_ADMIN_KEYare standard patterns used by other OpenAI providers, the specific provider you've referenced cannot be verified.Confirm that:
- The provider source "fjcorp/openai" v1.0.0 exists and is accessible in your environment
- It actually supports the
OPENAI_API_KEYandOPENAI_ADMIN_KEYenvironment variables as documentedIf this is a private provider, ensure its documentation confirms these specific environment variable names are recognized.
23-28: Attributes verified as valid in fjcorp/openai provider.All referenced attributes on
openai_projectare documented in the provider schema:
id(read-only)name(required)created_at(read-only)status(read-only)The outputs in lines 23–28 and 56–63 correctly access these exposed attributes.
examples/projects/data_sources.tf (2)
21-56: Well-structured outputs demonstrating good Terraform patterns.The outputs effectively showcase various query patterns: accessing single resource attributes, counting collections, and extracting specific fields via for-loops. Good example-quality documentation through code.
5-7: I need to search for more specific information about the fjcorp/openai Terraform provider schema. Let me try a targeted search:Provider namespace "fjcorp/openai" does not appear to exist in the Terraform Registry.
Extensive searches for the fjcorp/openai provider yielded no results. The Terraform Registry contains multiple OpenAI providers (mkdev-me/openai, jianyuan/openai, nventive/openai, antonbabenko/openai, vravind1/openai, skyscrapr/openai), but "fjcorp/openai" is not among them. Verify the correct provider source before referencing its data sources or fields.
examples/projects/README.md (2)
167-191: Technical details and troubleshooting sections provide useful guidance.The sections covering technical implementation details and common troubleshooting scenarios are well-written and address likely user issues.
58-120: All documented attributes are correctly exposed by the openai_project and openai_projects data sources.Verification confirms that all attributes documented in the README (project_id, name, status, created_at, usage_limits, max_monthly_dollars, max_parallel_requests, max_tokens) match the actual schema definitions in data_source_openai_project.go and data_source_openai_projects.go. The examples are accurate and complete.
examples/projects/test.tf (1)
1-14: Test file correctly references valid data source attributes.The
openai_projectsdata source schema confirms both theprojectsattribute (TypeList, computed) and thenamefield (TypeString, computed) exist within each project object. The test configuration properly accesses these attributes to retrieve project count and names via outputs.examples/run/main.tf (2)
1-120: Good example structure.This file demonstrates the correct pattern for avoiding "thread already has an active run" errors by using separate threads. The approach is cleaner than forcing sequential execution with
depends_on. The code is well-commented and includes diverse examples (basic run, custom parameters, combined thread_run, and data sources).
22-22: The model namegpt-4-turbo-previewis valid and actively maintained by OpenAI as an alias that automatically points to the latest GPT-4 Turbo preview version. The example code is correct as written.examples/run/backup/main_original.tf (1)
133-149: Module path is valid—concern does not apply.The verification confirms that the
modules/rundirectory exists at the repository root with the required Terraform files (main.tf, variables.tf, outputs.tf). The relative path../../modules/runfromexamples/run/backup/main_original.tfcorrectly resolves to this module. The example will not fail due to a missing module.Likely an incorrect or invalid review comment.
examples/run/main.tf.example (1)
97-113: Module path is valid—no action required.The
modules/runmodule exists in the repository and is correctly referenced via the relative path../../modules/runfrom the example location. The example will resolve properly.examples/run/cleanup_active_runs.sh (1)
26-28: No changes needed—API version is current.The current OpenAI Assistants API version is v2, which matches the header value in the script. The code is correct as written.
| {"messages": [{"role": "system", "content": "You are a weather assistant that provides accurate forecasts."}, {"role": "user", "content": "What's the weather forecast for Chicago?"}, {"role": "assistant", "content": "I don't have access to current weather forecasts, but I can tell you about typical weather patterns in Chicago based on historical data for this time of year."}]} | ||
| {"messages": [{"role": "system", "content": "You are a weather assistant that provides accurate forecasts."}, {"role": "user", "content": "Is it going to be sunny in San Francisco tomorrow?"}, {"role": "assistant", "content": "I don't have access to real-time weather predictions, but I can discuss typical weather patterns in San Francisco during this season."}]} | ||
| {"messages": [{"role": "system", "content": "You are a weather assistant that provides accurate forecasts."}, {"role": "user", "content": "What should I wear in Boston today?"}, {"role": "assistant", "content": "I don't have access to current weather data, but I can provide suggestions based on typical Boston weather patterns for this time of year."}]} | ||
| {"messages": [{"role": "system", "content": "You are a weather assistant that provides accurate forecasts."}, {"role": "user", "content": "Will there be a storm in Florida this week?"}, {"role": "assistant", "content": "I don't have access to current forecast data, but I can provide information about typical storm patterns in Florida during this season."}]} No newline at end of file |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
🛠️ Refactor suggestion | 🟠 Major
Fix inconsistent system message across all training examples.
The system message claims the assistant "provides accurate forecasts," but every assistant response explicitly declines to provide forecasts (e.g., "I don't have access to current weather forecasts"). This inconsistency creates a contradictory training signal that could confuse the fine-tuned model about its capabilities.
Consider updating the system message to align with the assistant's actual behavior:
-{"messages": [{"role": "system", "content": "You are a weather assistant that provides accurate forecasts."}, {"role": "user", "content": "What's the weather forecast for Chicago?"}, {"role": "assistant", "content": "I don't have access to current weather forecasts, but I can tell you about typical weather patterns in Chicago based on historical data for this time of year."}]}
+{"messages": [{"role": "system", "content": "You are a weather assistant that provides information about typical weather patterns based on historical data."}, {"role": "user", "content": "What's the weather forecast for Chicago?"}, {"role": "assistant", "content": "I don't have access to current weather forecasts, but I can tell you about typical weather patterns in Chicago based on historical data for this time of year."}]}
-{"messages": [{"role": "system", "content": "You are a weather assistant that provides accurate forecasts."}, {"role": "user", "content": "Is it going to be sunny in San Francisco tomorrow?"}, {"role": "assistant", "content": "I don't have access to real-time weather predictions, but I can discuss typical weather patterns in San Francisco during this season."}]}
+{"messages": [{"role": "system", "content": "You are a weather assistant that provides information about typical weather patterns based on historical data."}, {"role": "user", "content": "Is it going to be sunny in San Francisco tomorrow?"}, {"role": "assistant", "content": "I don't have access to real-time weather predictions, but I can discuss typical weather patterns in San Francisco during this season."}]}
-{"messages": [{"role": "system", "content": "You are a weather assistant that provides accurate forecasts."}, {"role": "user", "content": "What should I wear in Boston today?"}, {"role": "assistant", "content": "I don't have access to current weather data, but I can provide suggestions based on typical Boston weather patterns for this time of year."}]}
+{"messages": [{"role": "system", "content": "You are a weather assistant that provides information about typical weather patterns based on historical data."}, {"role": "user", "content": "What should I wear in Boston today?"}, {"role": "assistant", "content": "I don't have access to current weather data, but I can provide suggestions based on typical Boston weather patterns for this time of year."}]}
-{"messages": [{"role": "system", "content": "You are a weather assistant that provides accurate forecasts."}, {"role": "user", "content": "Will there be a storm in Florida this week?"}, {"role": "assistant", "content": "I don't have access to current forecast data, but I can provide information about typical storm patterns in Florida during this season."}]}
+{"messages": [{"role": "system", "content": "You are a weather assistant that provides information about typical weather patterns based on historical data."}, {"role": "user", "content": "Will there be a storm in Florida this week?"}, {"role": "assistant", "content": "I don't have access to current forecast data, but I can provide information about typical storm patterns in Florida during this season."}]}📝 Committable suggestion
‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.
| {"messages": [{"role": "system", "content": "You are a weather assistant that provides accurate forecasts."}, {"role": "user", "content": "What's the weather forecast for Chicago?"}, {"role": "assistant", "content": "I don't have access to current weather forecasts, but I can tell you about typical weather patterns in Chicago based on historical data for this time of year."}]} | |
| {"messages": [{"role": "system", "content": "You are a weather assistant that provides accurate forecasts."}, {"role": "user", "content": "Is it going to be sunny in San Francisco tomorrow?"}, {"role": "assistant", "content": "I don't have access to real-time weather predictions, but I can discuss typical weather patterns in San Francisco during this season."}]} | |
| {"messages": [{"role": "system", "content": "You are a weather assistant that provides accurate forecasts."}, {"role": "user", "content": "What should I wear in Boston today?"}, {"role": "assistant", "content": "I don't have access to current weather data, but I can provide suggestions based on typical Boston weather patterns for this time of year."}]} | |
| {"messages": [{"role": "system", "content": "You are a weather assistant that provides accurate forecasts."}, {"role": "user", "content": "Will there be a storm in Florida this week?"}, {"role": "assistant", "content": "I don't have access to current forecast data, but I can provide information about typical storm patterns in Florida during this season."}]} | |
| {"messages": [{"role": "system", "content": "You are a weather assistant that provides information about typical weather patterns based on historical data."}, {"role": "user", "content": "What's the weather forecast for Chicago?"}, {"role": "assistant", "content": "I don't have access to current weather forecasts, but I can tell you about typical weather patterns in Chicago based on historical data for this time of year."}]} | |
| {"messages": [{"role": "system", "content": "You are a weather assistant that provides information about typical weather patterns based on historical data."}, {"role": "user", "content": "Is it going to be sunny in San Francisco tomorrow?"}, {"role": "assistant", "content": "I don't have access to real-time weather predictions, but I can discuss typical weather patterns in San Francisco during this season."}]} | |
| {"messages": [{"role": "system", "content": "You are a weather assistant that provides information about typical weather patterns based on historical data."}, {"role": "user", "content": "What should I wear in Boston today?"}, {"role": "assistant", "content": "I don't have access to current weather data, but I can provide suggestions based on typical Boston weather patterns for this time of year."}]} | |
| {"messages": [{"role": "system", "content": "You are a weather assistant that provides information about typical weather patterns based on historical data."}, {"role": "user", "content": "Will there be a storm in Florida this week?"}, {"role": "assistant", "content": "I don't have access to current forecast data, but I can provide information about typical storm patterns in Florida during this season."}]} |
🤖 Prompt for AI Agents
In examples/fine_tuning/training_data/sample_validation.jsonl around lines 1 to
4, the system message ("You are a weather assistant that provides accurate
forecasts.") contradicts the assistant responses that explicitly say it cannot
access current forecasts; update the system message across all examples to
reflect the assistant's actual behavior (e.g., "You are a weather assistant that
provides information about typical or historical weather patterns and cannot
access real-time forecasts") so the instruction and assistant outputs are
consistent; ensure every JSONL entry uses the revised system message exactly and
re-run validation to confirm no remaining contradictions.
examples/model_response/main.tf
Outdated
| terraform { | ||
| required_providers { | ||
| openai = { | ||
| source = "fjcorp/openai" | ||
| } | ||
| } | ||
| } |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
🧩 Analysis chain
Verify provider source and version constraints.
The provider source is specified as fjcorp/openai without version constraints. Consider adding explicit version constraints to ensure reproducible configurations across environments.
Apply this diff to add version constraints:
terraform {
required_providers {
openai = {
source = "fjcorp/openai"
+ version = ">= 1.0, < 2.0" # Adjust based on provider releases
}
}
}Alternatively, verify the intended version strategy for this provider.
🏁 Script executed:
#!/bin/bash
# Verify provider exists and check available versions
curl -s https://registry.terraform.io/v1/providers/fjcorp/openai | jq '.provider'Length of output: 4
🏁 Script executed:
#!/bin/bash
# Check the actual file content
cat examples/model_response/main.tf | head -20Length of output: 540
🏁 Script executed:
#!/bin/bash
# Search for known OpenAI provider sources in Terraform registry
# Check common variations
curl -s https://registry.terraform.io/v1/providers/opentofu/openai 2>/dev/null | jq '.provider.namespace' 2>/dev/null || echo "Not found"
curl -s https://registry.terraform.io/v1/providers/hashicorp/random 2>/dev/null | jq '.provider.namespace' 2>/dev/null || echo "Checking structure"Length of output: 9
🏁 Script executed:
#!/bin/bash
# Search the codebase for all provider references
rg -n "source\s*=" examples/ --type hcl || rg -n "source\s*=" examples/ --type tfLength of output: 7010
🏁 Script executed:
#!/bin/bash
# Verify the correct provider source exists
curl -s https://registry.terraform.io/v1/providers/mkdev-me/openai | jq '.provider.namespace'Length of output: 4
Update provider source to match codebase standard.
The provider source fjcorp/openai is outdated and inconsistent with the rest of the codebase. Replace it with mkdev-me/openai, which is used consistently across all other example files.
terraform {
required_providers {
openai = {
- source = "fjcorp/openai"
+ source = "mkdev-me/openai"
}
}
}📝 Committable suggestion
‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.
| terraform { | |
| required_providers { | |
| openai = { | |
| source = "fjcorp/openai" | |
| } | |
| } | |
| } | |
| terraform { | |
| required_providers { | |
| openai = { | |
| source = "mkdev-me/openai" | |
| } | |
| } | |
| } |
🤖 Prompt for AI Agents
In examples/model_response/main.tf around lines 1 to 7, the Terraform provider
source is set to "fjcorp/openai" which is inconsistent with the codebase
standard; update the provider block to use "mkdev-me/openai" instead, ensuring
the required_providers entry's source value is replaced and the file matches
other example files.
examples/model_response/README.md
Outdated
| To run these examples: | ||
|
|
||
| 1. Set your OpenAI API key as an environment variable: | ||
| ``` |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Add language specifiers to fenced code blocks per MD040 rule.
The terraform validate command checks configuration syntax, and documentation should follow consistent markdown standards. Markdownlint requires language identifiers on code blocks for proper rendering and syntax highlighting.
Apply these diffs to add language specifiers:
- ```
+ ```bash
export OPENAI_API_KEY="your-api-key"
```- ```
+ ```bash
terraform init
```- ```
+ ```bash
terraform apply
```-```
+```bash
POST https://api.openai.com/v1/responses # Create a model responseAlso applies to: 160-160, 165-165, 179-179
🧰 Tools
🪛 markdownlint-cli2 (0.18.1)
155-155: Fenced code blocks should have a language specified
(MD040, fenced-code-language)
🤖 Prompt for AI Agents
In examples/model_response/README.md around lines 155, 160, 165, and 179,
several fenced code blocks are missing language specifiers; update each fenced
block to include the appropriate language tag (e.g., ```bash) before the code
and keep the closing ``` after it so markdownlint MD040 is satisfied —
specifically add ```bash for the export/openai key block (line ~155), the
terraform init block (~160), terraform apply block (~165), and the POST request
block (~179).
examples/moderation/README.md
Outdated
| Below is an example workflow showing what happens when importing a moderation resource: | ||
|
|
||
| 1. Original state before removal: | ||
| ``` |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Add language specifiers to fenced code blocks.
Several code blocks are missing language identifiers, which will cause linting failures. The static analysis tool (markdownlint) flags these violations:
- Line 107:
terraform state showoutput → use```bashor```shell - Line 128:
terraform state rmcommand → use```bashor```shell - Line 135:
terraform importcommand → use```bashor```shell - Line 146: Import confirmation output → use
```bashor```shell - Line 180: Output structure → use
```textor```plaintext
- ```
+ ```bash
$ terraform state show openai_moderation.harmful_textApply similar fixes to lines 128, 135, 146 (use bash or shell), and line 180 (use text or plaintext).
Also applies to: 128-128, 135-135, 146-146, 180-180
🧰 Tools
🪛 markdownlint-cli2 (0.18.1)
107-107: Fenced code blocks should have a language specified
(MD040, fenced-code-language)
🤖 Prompt for AI Agents
In examples/moderation/README.md around lines 107, 128, 135, 146, and 180,
several fenced code blocks are missing language specifiers which triggers
markdownlint failures; update each opening triple-backtick to include the
appropriate language tag: use ```bash or ```shell for the command/CLI outputs on
lines 107, 128, 135, and 146, and use ```text or ```plaintext for the plain
output/example on line 180, ensuring each fenced block begins with the chosen
specifier and no other content is changed.
examples/organization_users/main.tf
Outdated
| # Only use organization data if enabled, otherwise skip | ||
| locals { | ||
| owners = var.enable_organization_users ? [ | ||
| for user in data.openai_organization_users.all[0].users : | ||
| user if user.role == "owner" && user.id != data.openai_organization_user.specific[0].id | ||
| ] : [] | ||
| } |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Fix null reference in locals block when enable_organization_users is false.
Line 72 references data.openai_organization_user.specific[0].id inside the list comprehension, but when enable_organization_users is false, this data source does not exist. Terraform will fail at plan/apply time with "resource not found" error.
Apply this fix to guard the data source access:
locals {
- owners = var.enable_organization_users ? [
+ owners = (var.enable_organization_users && length(data.openai_organization_user.specific) > 0) ? [
for user in data.openai_organization_users.all[0].users :
- user if user.role == "owner" && user.id != data.openai_organization_user.specific[0].id
+ user if user.role == "owner" && user.id != try(data.openai_organization_user.specific[0].id, "")
] : []
}Alternatively, simplify by moving the filter logic inside a try() or using concat() to safely reference only when enabled.
Committable suggestion skipped: line range outside the PR's diff.
🤖 Prompt for AI Agents
In examples/organization_users/main.tf around lines 68 to 74, the locals block
always evaluates references to data.openai_organization_user.specific[0].id even
when var.enable_organization_users is false, causing a "resource not found"
error; fix it by guarding the data source access (e.g., replace the direct
reference with a safe call using try(...) or a conditional expression so that
when enable_organization_users is false you return an empty list and when true
you compare user.id against try(data.openai_organization_user.specific[0].id,
null)); ensure the locals block never dereferences the data source when disabled
and keep the original owner filtering logic intact.
| # Show all vector stores in your account | ||
| output "vector_stores_list" { | ||
| value = data.openai_vector_stores.all.vector_stores | ||
| } | ||
|
|
||
| # Show detailed information about a specific vector store | ||
| output "vector_store_details" { | ||
| value = { | ||
| id = data.openai_vector_store.existing.id | ||
| name = data.openai_vector_store.existing.name | ||
| file_count = data.openai_vector_store.existing.file_count | ||
| status = data.openai_vector_store.existing.status | ||
| created_at = data.openai_vector_store.existing.created_at | ||
| file_ids = data.openai_vector_store.existing.file_ids | ||
| } | ||
| } | ||
|
|
||
| # Show list of files in a vector store | ||
| output "vector_store_files_list" { | ||
| value = data.openai_vector_store_files.store_files.files | ||
| } | ||
|
|
||
| # Show detailed information about a specific file in a vector store | ||
| output "vector_store_file_details" { | ||
| value = { | ||
| id = data.openai_vector_store_file.specific_file.id | ||
| created_at = data.openai_vector_store_file.specific_file.created_at | ||
| status = data.openai_vector_store_file.specific_file.status | ||
| attributes = data.openai_vector_store_file.specific_file.attributes | ||
| } | ||
| } | ||
|
|
||
| # Show file content from a vector store | ||
| output "vector_store_file_content" { | ||
| value = substr(data.openai_vector_store_file_content.file_content.content, 0, 100) | ||
| } | ||
|
|
||
| # Show detailed information about a file batch in a vector store | ||
| output "vector_store_file_batch_details" { | ||
| value = { | ||
| id = data.openai_vector_store_file_batch.specific_batch.id | ||
| created_at = data.openai_vector_store_file_batch.specific_batch.created_at | ||
| status = data.openai_vector_store_file_batch.specific_batch.status | ||
| file_ids = data.openai_vector_store_file_batch.specific_batch.file_ids | ||
| batch_type = data.openai_vector_store_file_batch.specific_batch.batch_type | ||
| purpose = data.openai_vector_store_file_batch.specific_batch.purpose | ||
| } | ||
| } | ||
|
|
||
| # Show list of files in a batch | ||
| output "vector_store_file_batch_files_list" { | ||
| value = data.openai_vector_store_file_batch_files.batch_files.files | ||
| } No newline at end of file |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Remove trailing whitespace on line 97.
Line 97 has trailing whitespace after the closing brace.
-}
+}🤖 Prompt for AI Agents
In examples/vector_store/data_sources.tf around lines 45 to 97, there is
trailing whitespace at the end of line 97 (after the closing brace); remove the
trailing spaces on that line (or run the repo formatter) so the line ends
exactly with the '}' and no extra whitespace.
| ``` | ||
| Authorization: Bearer YOUR_API_KEY | ||
| ``` |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Add language identifier to fenced code block.
Line 11 uses a fenced code block without specifying a language. Add a language identifier (yaml, bash, etc.) for syntax highlighting and linting compliance.
-```
+```yaml
Authorization: Bearer YOUR_API_KEY
-```
+```🧰 Tools
🪛 markdownlint-cli2 (0.18.1)
11-11: Fenced code blocks should have a language specified
(MD040, fenced-code-language)
🤖 Prompt for AI Agents
In examples/vector_store/files/api_documentation.md around lines 11 to 13, the
fenced code block lacks a language identifier; update the opening fence to
include an appropriate language (e.g., "yaml" or "bash") so it reads as ```yaml
(or ```bash) followed by the existing content and the closing ``` to enable
syntax highlighting and satisfy linting.
| ``` | ||
| curl -X POST https://api.example.com/v1/workflows/trigger \ | ||
| -H "Authorization: Bearer YOUR_API_KEY" \ | ||
| -H "Content-Type: application/json" \ | ||
| -d '{"workflow_id": "wf_123", "data": {"key": "value"}}' | ||
| ``` |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Sanitize example curl command to avoid security concerns.
Line 76-77 includes a curl example with an Authorization header containing a placeholder API key. While YOUR_API_KEY is a placeholder, Gitleaks flags this pattern as a potential security risk. Consider one of these approaches:
-
Replace the placeholder with a comment:
curl -X POST https://api.example.com/v1/workflows/trigger \ - -H "Authorization: Bearer YOUR_API_KEY" \ + -H "Authorization: Bearer <your-api-key-here>" \ -H "Content-Type: application/json" \ -d '{"workflow_id": "wf_123", "data": {"key": "value"}}'
-
Or add an explicit security note:
+**⚠️ Security note:** Never commit real API keys. Use environment variables or secret management tools.
🧰 Tools
🪛 Gitleaks (8.29.0)
[high] 76-77: Discovered a potential authorization token provided in a curl command header, which could compromise the curl accessed resource.
(curl-auth-header)
🤖 Prompt for AI Agents
In examples/vector_store/files/product_guide.md around lines 75 to 80, the curl
example includes an Authorization header with a literal placeholder API key
which Gitleaks flags; update the example to avoid exposing credential-like
patterns by either removing the header and showing a comment (e.g. replace the
header line with a comment like "# set Authorization header from environment"),
or replace the literal placeholder with a clearly non-secret token or
environment variable usage (e.g. show -H "Authorization: Bearer $API_KEY"), and
add a one-line security note stating readers must not paste real keys and should
use environment variables or secret management when running examples.
| ## API Questions | ||
|
|
||
| ### What is the rate limit for API calls? | ||
| Free tier accounts are limited to 60 requests per minute. Standard tier accounts are limited to 600 requests per minute. Enterprise accounts have customizable rate limits based on their specific needs. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Fix compound modifier hyphenation.
Line 17 uses "tier accounts" where a hyphen is needed for the compound modifier.
-Free tier accounts are limited to 60 requests per minute. Standard tier accounts are limited to 600 requests per minute.
+Free tier-accounts are limited to 60 requests per minute. Standard tier-accounts are limited to 600 requests per minute.Or consider rephrasing for clarity:
-Free tier accounts are limited to 60 requests per minute. Standard tier accounts are limited to 600 requests per minute.
+Accounts on the free tier are limited to 60 requests per minute. Standard tier accounts are limited to 600 requests per minute.📝 Committable suggestion
‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.
| Free tier accounts are limited to 60 requests per minute. Standard tier accounts are limited to 600 requests per minute. Enterprise accounts have customizable rate limits based on their specific needs. | |
| Free-tier accounts are limited to 60 requests per minute. Standard-tier accounts are limited to 600 requests per minute. Enterprise accounts have customizable rate limits based on their specific needs. |
🧰 Tools
🪛 LanguageTool
[grammar] ~17-~17: Use a hyphen to join words.
Context: ...ited to 60 requests per minute. Standard tier accounts are limited to 600 request...
(QB_NEW_EN_HYPHEN)
🤖 Prompt for AI Agents
In examples/vector_store/files/support_faq.md around line 17, the phrase "tier
accounts" is being used as a compound modifier and should be hyphenated; change
to "Free-tier accounts", "Standard-tier accounts", and "Enterprise-tier
accounts" (or alternatively rephrase to "Free accounts", "Standard accounts",
and "Enterprise accounts are limited to...") so the compound modifier is
correctly formed.
examples/vector_store/main.tf
Outdated
| terraform { | ||
| required_providers { | ||
| openai = { | ||
| source = "fjcorp/openai" | ||
| version = "1.0.0" | ||
| } | ||
| } | ||
| } | ||
|
|
||
| provider "openai" {} | ||
|
|
||
| # Example 1: Simple Vector Store without files | ||
| module "basic_vector_store" { | ||
| source = "../../modules/vector_store" | ||
|
|
||
| name = "Basic Knowledge Base" | ||
|
|
||
| # Add some metadata for organization | ||
| metadata = { | ||
| "category" = "general", | ||
| "purpose" = "demonstration", | ||
| "version" = "1.0" | ||
| } | ||
|
|
||
| } | ||
|
|
||
| # Example 2: Vector Store with individually added files | ||
| module "support_vector_store" { | ||
| source = "../../modules/vector_store" | ||
|
|
||
| name = "Support Knowledge Base" | ||
| file_ids = [] | ||
|
|
||
| use_file_batches = true | ||
|
|
||
| file_attributes = { | ||
| "department" = "support", | ||
| "language" = "english" | ||
| } | ||
|
|
||
| } | ||
|
|
||
| # Example 3: Vector Store with file batches | ||
| module "api_vector_store" { | ||
| source = "../../modules/vector_store" | ||
|
|
||
| name = "API Documentation Store" | ||
| file_ids = [] | ||
|
|
||
| use_file_batches = true | ||
|
|
||
| } | ||
|
|
||
| # Example 4: Create a resource directly (not through the module) | ||
| resource "openai_vector_store" "custom_store" { | ||
| name = "Custom Vector Store" | ||
|
|
||
| # Start without files, add them later | ||
| file_ids = [] | ||
|
|
||
| metadata = { | ||
| "project" = "terraform-demo", | ||
| "owner" = "infrastructure-team" | ||
| } | ||
|
|
||
| } |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
🧩 Analysis chain
Verify provider version availability.
The Terraform configuration specifies openai provider version 1.0.0. Ensure this version is available from the fjcorp/openai namespace in the Terraform Registry.
🌐 Web query:
Is Terraform provider fjcorp/openai version 1.0.0 available in the Terraform Registry?
💡 Result:
Short answer: No — there is no fjcorp/openai provider (v1.0.0) listed on the Terraform Registry. I found no registry entry for fjcorp/openai; the only third‑party OpenAI Terraform provider I could find listed publicly is e.g. jianyuan/openai. [1][2]
Sources:
[1] Search results showing Terraform OpenAI provider projects. (reddit.com)
[2] General web search results (no registry entry for fjcorp/openai). (gist.github.com)
Citations:
- 1: https://www.reddit.com/r/Terraform/comments/1d1rf3m?utm_source=openai
- 2: https://gist.github.com/Zetaphor/ad6a8669414f6a8637815ef187bdb373?utm_source=openai
Replace the non-existent provider with a valid Terraform OpenAI provider.
The provider fjcorp/openai version 1.0.0 does not exist in the Terraform Registry. The only third-party OpenAI Terraform provider available is jianyuan/openai. Update lines 2-5 to use a valid provider, or implement a custom provider if required.
🤖 Prompt for AI Agents
In examples/vector_store/main.tf lines 1-66, the terraform required_providers
block references a non-existent provider "fjcorp/openai" version "1.0.0";
replace that with the valid third-party provider "jianyuan/openai" and set an
appropriate released version (for example a stable version constraint like ">=
0.5.0" or a specific released tag), update any provider configuration if the
jianyuan provider uses different argument names, then run terraform init to
fetch the correct provider and verify there are no schema mismatches.
9bf8f9c to
e100e7f
Compare
e100e7f to
d28b7ec
Compare
Description
Summary
Fixes #35: Adds retry logic with exponential backoff to handle eventual consistency issues when reading vector store
files immediately after creation.
Problem
The OpenAI API experiences eventual consistency issues when reading a vector store file immediately after creation.
This causes Terraform to fail with errors like:
Error: Error reading vector store file: API error: No file found with id 'file-XXX' in vector store 'vs_XXX'.This is particularly problematic when creating multiple vector store files simultaneously, as reported in issue #35.
The issue started occurring approximately 5 days before the bug report, suggesting a change in OpenAI's API behavior.
Solution
This PR implements an exponential backoff retry mechanism specifically for "file not found" errors during the read
operation after file creation:
Changes
Code Changes
Tests Added
configured)
configured)
Testing
Unit Tests
All unit tests pass:
go test -v ./internal/provider -run TestRetryLogicErrorDetection
go test -v ./internal/provider -run TestVectorStoreFileReadRetryLogic
Manual Testing
The fix can be manually tested by creating multiple vector store files simultaneously:
resource "openai_vector_store_file" "kb" {
for_each = openai_file.kb
vector_store_id = openai_vector_store.app_kb.id
file_id = each.value.id
}
Impact
Checklist
Type of change
Please delete options that are not relevant.
How Has This Been Tested?
Please describe the tests that you ran to verify your changes. Provide instructions so we can reproduce.
Checklist:
Summary by CodeRabbit
Release Notes
New Features
Documentation