-
Notifications
You must be signed in to change notification settings - Fork 16
Handle commented config fields across migrations #188
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
Conversation
|
Note Other AI code review bot(s) detectedCodeRabbit has detected other AI code review bot(s) in this pull request and will avoid duplicating their findings in the review comments. This may lead to a less comprehensive review. WalkthroughUpdated multiple v3 migration utilities to robustly remove config fields that may include trailing inline comments or appear inline; refactored field-removal logic to parse nested structures and iteratively strip inline occurrences. Added tests covering comment-handling for several migrations. No public APIs changed. Changes
Sequence Diagram(s)sequenceDiagram
autonumber
participant CLI as migrate cmd
participant File as source file
participant Basicauth as MigrateBasicauthConfig
participant RegexLine as reCtxKeyLine
participant RegexInline as reCtxKeyInline
CLI->>Basicauth: run migration on dir
Basicauth->>File: read file content
Basicauth->>RegexLine: apply once -> remove full lines with trailing comments
Note right of RegexLine #E6F1FF: single pass removes standalone lines
Basicauth->>RegexInline: loop: apply repeatedly until no change
Note right of RegexInline #F1F1E6: iterative removal of inline occurrences before '}'
RegexInline-->>Basicauth: modified content
Basicauth->>File: write updated content
Basicauth-->>CLI: log "Migrating basicauth configs"
sequenceDiagram
autonumber
participant Caller as removeConfigField
participant Parser as nesting parser
participant Content as source string
Caller->>Parser: locate field start (include preceding comma/space)
Parser->>Content: traverse chars tracking depth ((), {}, [])
Note right of Parser #E8F8E6: skip quoted strings and comments
Parser-->>Caller: determine end index (comma/newline/top-level '}')
Caller->>Content: remove slice [start:end], return updated content
Estimated code review effort🎯 4 (Complex) | ⏱️ ~45 minutes Possibly related PRs
Suggested labels
Poem
✨ Finishing Touches
🧪 Generate unit tests
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. 🪧 TipsChatThere are 3 ways to chat with CodeRabbit:
SupportNeed help? Create a ticket on our support page for assistance with any issues or questions. CodeRabbit Commands (Invoked using PR/Issue comments)Type Other keywords and placeholders
CodeRabbit Configuration 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.
Summary of Changes
Hello @ReneWerner87, I'm Gemini Code Assist1! I'm currently reviewing this pull request and will post my feedback shortly. In the meantime, here's a summary to help you and other reviewers quickly get up to speed!
This pull request addresses an issue where migration scripts failed to correctly process configuration fields that had inline comments. The changes involve updating the regular expressions used in the migration logic for basicauth, CSRF, middleware locals, and healthcheck configurations to properly account for and ignore these comments. This ensures that the migration process can reliably remove or modify the intended fields, improving the robustness of the migration tools. Additionally, new test cases have been introduced to validate these fixes and prevent future regressions.
Highlights
- Enhanced Regex for Comment Handling: The regular expressions used in various migration scripts (basicauth, CSRF, middleware locals, healthcheck) have been updated to correctly identify and process configuration fields even when they are followed by inline comments. This ensures that the migration logic can reliably remove or transform these fields without being hindered by comments.
- Comprehensive Test Coverage for Commented Fields: New dedicated test cases have been added for each affected migration (basicauth, config listener fields, CSRF, healthcheck, and middleware locals). These tests specifically target scenarios where configuration fields include inline comments, validating that the updated regex patterns correctly handle these cases and prevent regressions.
Using Gemini Code Assist
The full guide for Gemini Code Assist can be found on our documentation page, here are some quick tips.
Invoking Gemini
You can request assistance from Gemini at any point in your pull request via creating an issue comment (i.e. comment on the pull request page) using either /gemini <command> or @gemini-code-assist <command>. Below is a summary of the supported commands.
| Feature | Command | Description |
|---|---|---|
| Code Review | /gemini review |
Performs a code review for the current pull request in its current state. |
| Pull Request Summary | /gemini summary |
Provides a summary of the current pull request in its current state. |
| Comment | @gemini-code-assist | Responds in comments when explicitly tagged, both in issue comments and review comments. |
| Help | /gemini help |
Displays a list of available commands. |
Customization
To customize Gemini Code Assist for GitHub experience, repository maintainers can create a configuration file and/or provide a custom code review style guide (such as PEP-8 for Python) by creating and adding files to a .gemini/ folder in the base of the repository. Detailed instructions can be found here.
Limitations & Feedback
Gemini Code Assist may make mistakes. Please leave feedback on any instances where its feedback is incorrect or counter productive. You can react with 👍 and 👎 on @gemini-code-assist comments. If you're interested in giving your feedback about your experience with Gemini Code Assist for Github and other Google products, sign up here.
You can also get AI-powered code generation, chat, as well as code reviews directly in the IDE at no cost with the Gemini Code Assist IDE Extension.
Footnotes
-
Review the Privacy Notices, Generative AI Prohibited Use Policy, Terms of Service, and learn how to configure Gemini Code Assist in GitHub here. Gemini can make mistakes, so double check it and use code with caution. ↩
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.
Code Review
This pull request enhances several migration scripts to correctly handle configuration fields that have inline comments. The changes primarily involve updating regular expressions to optionally match and consume comments, preventing migration failures for commented code. New tests have been added to cover these scenarios, which is great for preventing future regressions. The approach is consistent across the different migration scripts. I've found one place where the regex could be made more robust to avoid matching across newlines, which I've commented on.
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
Caution
Some comments are outside the diff and can’t be posted inline due to platform limitations.
⚠️ Outside diff range comments (1)
cmd/internal/migrations/v3/middleware_locals_test.go (1)
45-72: CI failures stem from inline single-line configs not being strippedThe failures in Test_MigrateMiddlewareLocals_ContextKey (Line 71) and Test_MigrateMiddlewareLocals_CustomContextKey (Line 127) suggest ContextKey is not removed when it appears inline like csrf.New(csrf.Config{ContextKey: "token"}) (no newline before “})”). The updated line-based regex in the migrator requires a newline and misses this shape. See code fix suggestion in middleware_locals.go review.
Also applies to: 100-129
🧹 Nitpick comments (12)
cmd/internal/migrations/v3/csrfconfig.go (1)
16-16: Handle CRLF and end-of-file: make the trailing newline optional and robustYour regex requires a trailing newline to match. This misses cases where SessionKey is the last item before a closing brace on the same line, or files with CRLF endings. Anchor to line start and accept either CRLF, LF, or EOF.
Apply this diff:
- reSession := regexp.MustCompile(`(?m)\s*SessionKey:\s*[^,\n]+,?\s*(//[^\n]*)?\n`) + reSession := regexp.MustCompile(`(?m)^\s*SessionKey:\s*[^,\n]+,?\s*(//[^\n]*)?\s*(?:\r?\n|$)`)cmd/internal/migrations/v3/basicauth_config.go (2)
17-18: Unify newline handling across platforms and EOFSame concern as CSRF: both patterns require a trailing newline. Anchor to start-of-line and accept CRLF/LF/EOF to catch “last field on the same line as }” and Windows line endings. Functionality is unchanged otherwise.
- reCtxUser := regexp.MustCompile(`(?m)\s*ContextUsername:\s*[^,\n]+,?\s*(//[^\n]*)?\n`) - reCtxPass := regexp.MustCompile(`(?m)\s*ContextPassword:\s*[^,\n]+,?\s*(//[^\n]*)?\n`) + reCtxUser := regexp.MustCompile(`(?m)^\s*ContextUsername:\s*[^,\n]+,?\s*(//[^\n]*)?\s*(?:\r?\n|$)`) + reCtxPass := regexp.MustCompile(`(?m)^\s*ContextPassword:\s*[^,\n]+,?\s*(//[^\n]*)?\s*(?:\r?\n|$)`)
22-25: Scope removal to basicauth.Config blocks (optional hardening)Right now, user/pass lines are removed anywhere in the file. To reduce accidental matches inside comments or string literals unrelated to basicauth, consider restricting the replacements to the content inside basicauth.Config blocks (similar to CSRF).
I can draft a scoped variant that finds basicauth.Config{...} blocks first and applies the removals only inside them—say the word, and I’ll propose a patch.
cmd/internal/migrations/v3/csrfconfig_test.go (1)
42-65: Add edge cases: same-line closing brace and CRLF endingsConsider adding tests to prevent regressions where:
- SessionKey is followed immediately by the closing brace on the same line (no trailing newline).
- File uses Windows CRLF line endings.
Example additional tests (new functions to append to this file):
func Test_MigrateCSRFConfig_SessionKey_SameLineBrace(t *testing.T) { t.Parallel() dir, err := os.MkdirTemp("", "mcsrfslb") require.NoError(t, err) defer func() { require.NoError(t, os.RemoveAll(dir)) }() file := writeTempFile(t, dir, `package main import "github.com/gofiber/fiber/v2/middleware/csrf" var _ = csrf.New(csrf.Config{ SessionKey: "csrf"})`) // note: no newline before } var buf bytes.Buffer cmd := newCmd(&buf) require.NoError(t, v3.MigrateCSRFConfig(cmd, dir, nil, nil)) content := readFile(t, file) assert.NotContains(t, content, "SessionKey") } func Test_MigrateCSRFConfig_SessionKey_CRLF(t *testing.T) { t.Parallel() dir, err := os.MkdirTemp("", "mcsrfcrlf") require.NoError(t, err) defer func() { require.NoError(t, os.RemoveAll(dir)) }() src := "package main\r\n" + "import \"github.com/gofiber/fiber/v2/middleware/csrf\"\r\n" + "var _ = csrf.New(csrf.Config{\r\n" + " SessionKey: \"csrf\", // comment\r\n" + "})\r\n" file := writeTempFile(t, dir, src) var buf bytes.Buffer cmd := newCmd(&buf) require.NoError(t, v3.MigrateCSRFConfig(cmd, dir, nil, nil)) content := readFile(t, file) assert.NotContains(t, content, "SessionKey") assert.NotContains(t, content, "comment") }cmd/internal/migrations/v3/healthcheck_config.go (2)
37-47: Normalize endpoint regexes: anchor to line start and support CRLF/EOFGreat that you already made the trailing newline optional. For consistency and Windows support, also anchor to start-of-line and accept CRLF/EOF.
- reLE := regexp.MustCompile(`(?m)\s*LivenessEndpoint:\s*([^,\n}]+),?\s*(//[^\n]*)?\n?`) + reLE := regexp.MustCompile(`(?m)^\s*LivenessEndpoint:\s*([^,\n}]+),?\s*(//[^\n]*)?\s*(?:\r?\n|$)`) if m := reLE.FindStringSubmatch(body); len(m) > 1 { lEndpoint = strings.TrimSpace(m[1]) } body = reLE.ReplaceAllString(body, "") - reRE := regexp.MustCompile(`(?m)\s*ReadinessEndpoint:\s*([^,\n}]+),?\s*(//[^\n]*)?\n?`) + reRE := regexp.MustCompile(`(?m)^\s*ReadinessEndpoint:\s*([^,\n}]+),?\s*(//[^\n]*)?\s*(?:\r?\n|$)`) if m := reRE.FindStringSubmatch(body); len(m) > 1 { rEndpoint = strings.TrimSpace(m[1]) } body = reRE.ReplaceAllString(body, "")
17-18: MakereUsenon-greedy to avoid overmatching across blocks
(?s:(.*))is greedy and can jump across multiple “)” matches if formatting is unusual. A non-greedy quantifier keeps the match tight around the healthcheck.New(...) call.- reUse := regexp.MustCompile(`(?m)^(\s*)(\w+)\.Use\(\s*healthcheck\.New\((?s:(.*))\)\s*\)`) + reUse := regexp.MustCompile(`(?m)^(\s*)(\w+)\.Use\(\s*healthcheck\.New\((?s:(.*?))\)\s*\)`)cmd/internal/migrations/v3/config_listener_fields.go (1)
20-20: Anchor to line start and handle CRLF/EOF to remove the whole line including commentsThe current pattern works but isn’t line-anchored and doesn’t explicitly handle CRLF or EOF. Anchoring reduces accidental mid-line matches and normalizes behavior across platforms. Consistent with other migrations.
- reField := regexp.MustCompile(`\s*(Prefork|Network|DisableStartupMessage|EnablePrintRoutes):\s*([^,}]+),?\s*(//[^\n]*)?`) + reField := regexp.MustCompile(`(?m)^\s*(Prefork|Network|DisableStartupMessage|EnablePrintRoutes):\s*([^,}\r\n]+),?\s*(//[^\r\n]*)?\s*(?:\r?\n|$)`)cmd/internal/migrations/v3/healthcheck_config_test.go (1)
185-214: Tighten assertions to catch endpoint fields lingering outside app.UseConsider also asserting that LivenessEndpoint/ReadinessEndpoint are not present anywhere in the migrated file for this comment case too. It keeps parity with the non-comment test and protects against regressions when endpoints are configured elsewhere.
content := readFile(t, file) assert.Contains(t, content, `app.Get("/live"`) assert.Contains(t, content, `app.Get("/ready"`) assert.NotContains(t, content, "live comment") assert.NotContains(t, content, "ready comment") + assert.NotContains(t, content, "LivenessEndpoint") + assert.NotContains(t, content, "ReadinessEndpoint")cmd/internal/migrations/v3/config_listener_fields_test.go (1)
280-284: Add explicit “no Prefork” assertion for clarityWhile fiber.Config{} indirectly implies it, asserting the string “Prefork” is not present makes the intent crystal clear and guards against formatting edge cases.
content := readFile(t, file) assert.Contains(t, content, "fiber.New(fiber.Config{})") assert.NotContains(t, content, "// comment") + assert.NotContains(t, content, "Prefork") assert.Contains(t, content, `app.Listen(":3000", fiber.ListenConfig{EnablePrefork: prod})`) assert.Contains(t, buf.String(), "Migrating listener related config fields")cmd/internal/migrations/v3/basicauth_config_test.go (1)
14-38: Optional: add a hashing smoke-check to prevent regressionsTo ensure the Users hashing path remains unaffected by adjacent comment removal, add a minimal Users map and assert the “{SHA256}” prefix appears post-migration (no need to lock the exact digest).
var _ = basicauth.New(basicauth.Config{ ContextUsername: "user", // username comment ContextPassword: "pass", // password comment + Users: map[string]string{"alice": "plaintext"}, }) @@ content := readFile(t, file) assert.NotContains(t, content, "ContextUsername") assert.NotContains(t, content, "ContextPassword") assert.NotContains(t, content, "username comment") assert.NotContains(t, content, "password comment") +assert.Contains(t, content, "{SHA256}") assert.Contains(t, buf.String(), "Migrating basicauth configs")cmd/internal/migrations/v3/middleware_locals_test.go (1)
74-99: Optional: add a CSRF “with comment” variantWe already test keyauth with a trailing comment; adding the same for csrf would catch package-specific gaps.
func Test_MigrateMiddlewareLocals_ContextKeyWithComment(t *testing.T) { @@ - "github.com/gofiber/fiber/v2/middleware/keyauth" + "github.com/gofiber/fiber/v2/middleware/keyauth" + "github.com/gofiber/fiber/v2/middleware/csrf" @@ _ = keyauth.New(keyauth.Config{ContextKey: "token", // key comment }) + _ = csrf.New(csrf.Config{ContextKey: "csrf", // csrf comment + }) @@ assert.NotContains(t, content, "ContextKey") assert.NotContains(t, content, "key comment") + assert.NotContains(t, content, "csrf comment")cmd/internal/migrations/v3/middleware_locals.go (1)
45-61: Optional: reuse the shared removeConfigField helper for consistencyTo avoid regex drift across migrators, consider delegating to removeConfigField for "ContextKey", "ContextUsername", and "ContextPassword". It already handles field cleanup and comma normalization elsewhere.
Example:
- // (regex removal here) - reCtxKeyLine := ... - ... - content = reCtxKeyInline.ReplaceAllString(content, "$1") + for _, fld := range []string{"ContextKey", "ContextUsername", "ContextPassword"} { + content = removeConfigField(content, fld) + }If removeConfigField currently isn’t comment-aware in all shapes, extending it once would harmonize all migrations.
📜 Review details
Configuration used: CodeRabbit UI
Review profile: CHILL
Plan: Pro
💡 Knowledge Base configuration:
- MCP integration is disabled by default for public repositories
- Jira integration is disabled by default for public repositories
- Linear integration is disabled by default for public repositories
You can enable these sources in your CodeRabbit configuration.
📒 Files selected for processing (10)
cmd/internal/migrations/v3/basicauth_config.go(1 hunks)cmd/internal/migrations/v3/basicauth_config_test.go(1 hunks)cmd/internal/migrations/v3/config_listener_fields.go(1 hunks)cmd/internal/migrations/v3/config_listener_fields_test.go(1 hunks)cmd/internal/migrations/v3/csrfconfig.go(1 hunks)cmd/internal/migrations/v3/csrfconfig_test.go(1 hunks)cmd/internal/migrations/v3/healthcheck_config.go(1 hunks)cmd/internal/migrations/v3/healthcheck_config_test.go(1 hunks)cmd/internal/migrations/v3/middleware_locals.go(1 hunks)cmd/internal/migrations/v3/middleware_locals_test.go(1 hunks)
🧰 Additional context used
🧠 Learnings (1)
📚 Learning: 2024-06-30T00:38:06.580Z
Learnt from: sixcolors
PR: gofiber/fiber#3051
File: middleware/session/session.go:215-216
Timestamp: 2024-06-30T00:38:06.580Z
Learning: Parallel tests for `Session.Save` already exist in the `middleware/session/session_test.go` file, specifically in the `Test_Session_Save` and `Test_Session_Save_Expiration` functions.
Applied to files:
cmd/internal/migrations/v3/csrfconfig_test.go
🧬 Code graph analysis (6)
cmd/internal/migrations/v3/middleware_locals_test.go (1)
cmd/internal/migrations/v3/middleware_locals.go (1)
MigrateMiddlewareLocals(13-76)
cmd/internal/migrations/v3/basicauth_config_test.go (1)
cmd/internal/migrations/v3/basicauth_config.go (1)
MigrateBasicauthConfig(16-58)
cmd/internal/migrations/v3/config_listener_fields_test.go (1)
cmd/internal/migrations/v3/config_listener_fields.go (1)
MigrateConfigListenerFields(14-141)
cmd/internal/migrations/v3/csrfconfig_test.go (1)
cmd/internal/migrations/v3/csrfconfig.go (1)
MigrateCSRFConfig(14-76)
cmd/internal/migrations/v3/healthcheck_config_test.go (1)
cmd/internal/migrations/v3/healthcheck_config.go (1)
MigrateHealthcheckConfig(14-95)
cmd/internal/migrations/v3/config_listener_fields.go (1)
cmd/internal/helpers.go (1)
ChangeFileContent(38-79)
🪛 GitHub Actions: Test
cmd/internal/migrations/v3/middleware_locals_test.go
[error] 71-71: Test_MigrateMiddlewareLocals_ContextKey failed: ContextKey usage in CSRF middleware locals migration test.
[error] 127-127: Test_MigrateMiddlewareLocals_CustomContextKey failed: ContextKey usage in CSRF middleware locals migration test.
cmd/internal/migrations/v3/healthcheck_config_test.go
[error] 45-47: MigrateHealthcheckConfig test failure: ReadinessProbe is present in healthcheck config; remove ReadinessProbe usage.
🔇 Additional comments (7)
cmd/internal/migrations/v3/csrfconfig_test.go (1)
42-65: LGTM: solid coverage for inline comment removal on SessionKeyTest clearly asserts removal of both the field and the trailing comment and checks the log output. Parallel-safe and uses tempdir correctly.
cmd/internal/migrations/v3/config_listener_fields.go (1)
27-28: Guard update is correctAdjusting the length check to account for the added optional comment capture is right and keeps parsing safe.
cmd/internal/migrations/v3/healthcheck_config_test.go (2)
185-214: Great addition: comment-tolerant endpoints are coveredGood end-to-end assertion set: verifies both endpoints get migrated to app.Get and that inline comments are removed. This guards the new regex tolerance.
41-49: Pipeline failure indicates ReadinessProbe remains in output; re-check probe strippingCI reports “ReadinessProbe is present” failing the assertions in Test_MigrateHealthcheckConfig (Lines 45–47). Please verify the probe-stripping paths in MigrateHealthcheckConfig for both:
- The in-place .Use(healthcheck.New(healthcheck.Config{...})) transformation
- The follow-up global cleanup using removeConfigField
A quick hypothesis: removeConfigField may miss some shapes (e.g., trailing commas or inline closers) and leave ReadinessProbe behind in specific layouts. If needed, I can propose a resilient removeConfigField regex or add a focused test reproducing the exact surviving layout.
Also applies to: 176-183
cmd/internal/migrations/v3/config_listener_fields_test.go (1)
259-285: Nice coverage: inline comment on Prefork handled end-to-endGood assertions: Config is normalized to fiber.Config{}, comment is gone, and ListenConfig picks up EnablePrefork: prod.
cmd/internal/migrations/v3/basicauth_config_test.go (1)
14-38: Solid: inline comments on ContextUsername/ContextPassword are removedThis test precisely targets the updated removal regex and confirms the migrator log. Looks good.
cmd/internal/migrations/v3/middleware_locals_test.go (1)
74-99: Good: validates comment-tolerant removal for ContextKeyThis complements the base ContextKey test by covering the trailing comment scenario. Nice.
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: 4
🧹 Nitpick comments (1)
cmd/internal/migrations/v3/basicauth_config_test.go (1)
14-38: Add cases for block comments and mid-list fields to prevent regressions.Current tests cover “tail field” and
//comments. Add:
/* block */comment after value- field not last (e.g.,
Foo, ContextUsername, Bar)Extend with:
+func Test_MigrateBasicauthConfig_Inline_NotLast_AndBlockComment(t *testing.T) { + t.Parallel() + dir, err := os.MkdirTemp("", "mbasiccfg_notlast") + require.NoError(t, err) + t.Cleanup(func() { require.NoError(t, os.RemoveAll(dir)) }) + + file := writeTempFile(t, dir, `package main +import "github.com/gofiber/fiber/v2/middleware/basicauth" +var _ = basicauth.New(basicauth.Config{ + Foo: 1, + ContextUsername: "user", /* user block comment */ + Bar: 2, + ContextPassword: "pass", /* pass block comment */ +})`) + + var buf bytes.Buffer + cmd := newCmd(&buf) + require.NoError(t, v3.MigrateBasicauthConfig(cmd, dir, nil, nil)) + + content := readFile(t, file) + assert.NotContains(t, content, "ContextUsername") + assert.NotContains(t, content, "ContextPassword") + assert.NotContains(t, content, "block comment") + assert.Contains(t, content, "basicauth.Config{") + assert.Contains(t, buf.String(), "Migrating basicauth configs") +}
📜 Review details
Configuration used: CodeRabbit UI
Review profile: CHILL
Plan: Pro
💡 Knowledge Base configuration:
- MCP integration is disabled by default for public repositories
- Jira integration is disabled by default for public repositories
- Linear integration is disabled by default for public repositories
You can enable these sources in your CodeRabbit configuration.
📒 Files selected for processing (4)
cmd/internal/migrations/v3/basicauth_config.go(1 hunks)cmd/internal/migrations/v3/basicauth_config_test.go(1 hunks)cmd/internal/migrations/v3/common.go(3 hunks)cmd/internal/migrations/v3/middleware_locals.go(1 hunks)
🧰 Additional context used
🧬 Code graph analysis (1)
cmd/internal/migrations/v3/basicauth_config.go (1)
cmd/internal/helpers.go (1)
ChangeFileContent(38-79)
⏰ Context from checks skipped due to timeout of 90000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (1)
- GitHub Check: Build (1.25.x, windows-latest)
🔇 Additional comments (2)
cmd/internal/migrations/v3/middleware_locals.go (1)
62-64: Action Required: Manually VerifyremoveConfigFieldDoes Not Alter Comments or String LiteralsI attempted to run the provided verification script, but it failed due to missing module context and a telemetry sidecar error. As a result, I could not automatically confirm that commented-out occurrences of
ContextKey,ContextUsername, andContextPasswordremain intact while real fields are removed.Please perform a manual check using one of the following approaches:
- Initalize a Go module at the repo root and rerun the specific test:
cd <repo-root> go mod init your/module/path go test -v ./cmd/internal/migrations/v3 \ -run Test_MigrateMiddlewareLocals_ContextKeyWithComment \ -count=1- Alternatively, add or locate a source file containing commented-out or string-literal uses of the target fields, run your migration, and inspect that only the actual (non-commented) field assignments are removed.
Once you’ve confirmed that
removeConfigFieldskips over comments and string literals as intended, please update or resolve accordingly.cmd/internal/migrations/v3/common.go (1)
16-47: Good enhancement: comma skipper now handles inline comments.The updated
skipCommaSuffixcorrectly advances past//and/* */—this materially reduces dangling commas and formatting glitches in migrated code.
| func Test_MigrateBasicauthConfig_Inline(t *testing.T) { | ||
| t.Parallel() | ||
|
|
||
| dir, err := os.MkdirTemp("", "mbasiccfg_inline") | ||
| require.NoError(t, err) | ||
| defer func() { require.NoError(t, os.RemoveAll(dir)) }() | ||
|
|
||
| file := writeTempFile(t, dir, `package main | ||
| import "github.com/gofiber/fiber/v2/middleware/basicauth" | ||
| var _ = basicauth.New(basicauth.Config{ContextUsername: "user", ContextPassword: "pass"})`) | ||
|
|
||
| var buf bytes.Buffer | ||
| cmd := newCmd(&buf) | ||
| require.NoError(t, v3.MigrateBasicauthConfig(cmd, dir, nil, nil)) | ||
|
|
||
| content := readFile(t, file) | ||
| assert.NotContains(t, content, "ContextUsername") | ||
| assert.NotContains(t, content, "ContextPassword") | ||
| assert.Contains(t, content, "basicauth.Config{}") | ||
| assert.Contains(t, buf.String(), "Migrating basicauth configs") | ||
| } |
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
Guard against cross-migration effects: ensure basicauth migration does not touch ContextKey in other configs.
Given the prior inclusion of ContextKey in removal, add a safety test to ensure basicauth migration leaves other middlewares intact.
Add:
+func Test_MigrateBasicauthConfig_DoesNotTouch_OtherContextKey(t *testing.T) {
+ t.Parallel()
+ dir, err := os.MkdirTemp("", "mbasiccfg_scope")
+ require.NoError(t, err)
+ t.Cleanup(func() { require.NoError(t, os.RemoveAll(dir)) })
+
+ file := writeTempFile(t, dir, `package main
+import (
+ "github.com/gofiber/fiber/v2/middleware/basicauth"
+ "github.com/gofiber/fiber/v2/middleware/csrf"
+)
+var _ = basicauth.New(basicauth.Config{ContextUsername: "user", ContextPassword: "pass"})
+var _ = csrf.New(csrf.Config{ContextKey: "token"})
+`)
+ var buf bytes.Buffer
+ cmd := newCmd(&buf)
+ require.NoError(t, v3.MigrateBasicauthConfig(cmd, dir, nil, nil))
+ content := readFile(t, file)
+ assert.NotContains(t, content, "ContextUsername")
+ assert.NotContains(t, content, "ContextPassword")
+ assert.Contains(t, content, `csrf.Config{ContextKey: "token"}`)
+}📝 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.
| func Test_MigrateBasicauthConfig_Inline(t *testing.T) { | |
| t.Parallel() | |
| dir, err := os.MkdirTemp("", "mbasiccfg_inline") | |
| require.NoError(t, err) | |
| defer func() { require.NoError(t, os.RemoveAll(dir)) }() | |
| file := writeTempFile(t, dir, `package main | |
| import "github.com/gofiber/fiber/v2/middleware/basicauth" | |
| var _ = basicauth.New(basicauth.Config{ContextUsername: "user", ContextPassword: "pass"})`) | |
| var buf bytes.Buffer | |
| cmd := newCmd(&buf) | |
| require.NoError(t, v3.MigrateBasicauthConfig(cmd, dir, nil, nil)) | |
| content := readFile(t, file) | |
| assert.NotContains(t, content, "ContextUsername") | |
| assert.NotContains(t, content, "ContextPassword") | |
| assert.Contains(t, content, "basicauth.Config{}") | |
| assert.Contains(t, buf.String(), "Migrating basicauth configs") | |
| } | |
| // Add this new test to cmd/internal/migrations/v3/basicauth_config_test.go | |
| func Test_MigrateBasicauthConfig_DoesNotTouch_OtherContextKey(t *testing.T) { | |
| t.Parallel() | |
| dir, err := os.MkdirTemp("", "mbasiccfg_scope") | |
| require.NoError(t, err) | |
| t.Cleanup(func() { require.NoError(t, os.RemoveAll(dir)) }) | |
| file := writeTempFile(t, dir, `package main | |
| import ( | |
| "github.com/gofiber/fiber/v2/middleware/basicauth" | |
| "github.com/gofiber/fiber/v2/middleware/csrf" | |
| ) | |
| var _ = basicauth.New(basicauth.Config{ContextUsername: "user", ContextPassword: "pass"}) | |
| var _ = csrf.New(csrf.Config{ContextKey: "token"}) | |
| `) | |
| var buf bytes.Buffer | |
| cmd := newCmd(&buf) | |
| require.NoError(t, v3.MigrateBasicauthConfig(cmd, dir, nil, nil)) | |
| content := readFile(t, file) | |
| assert.NotContains(t, content, "ContextUsername") | |
| assert.NotContains(t, content, "ContextPassword") | |
| assert.Contains(t, content, `csrf.Config{ContextKey: "token"}`) | |
| } |
🤖 Prompt for AI Agents
In cmd/internal/migrations/v3/basicauth_config_test.go around lines 40 to 60,
add a safety subtest that creates a separate temp source file containing a
different middleware config that uses ContextKey (e.g., another middleware
package), run v3.MigrateBasicauthConfig against the directory, then read that
file and assert it still contains "ContextKey" (and other original identifiers)
to ensure the basicauth migration doesn't remove or alter ContextKey in
non-basicauth configs; implement using the same temp dir helpers, run migration
once, and add asserts that the unrelated file remains unchanged.
| // Remove ContextKey/Username/Password when they are on their own line (with optional trailing comment). | ||
| reCtxKeyLine := regexp.MustCompile(`(?m)^\s*Context(?:Username|Password|Key):\s*[^,\n}]+,?\s*(//[^\n]*)?\n`) | ||
|
|
||
| // Also remove inline occurrences immediately before a closing '}' (with optional comma/comment), | ||
| // e.g. basicauth.Config{ContextUsername: "user"}) or {..., ContextPassword: "pass"}) | ||
| // Keep the closing brace via a capture group. | ||
| reCtxKeyInline := regexp.MustCompile(`(?m)\s*Context(?:Username|Password|Key):\s*[^,\n}]+(?:,\s*)?(?://[^\n]*)?(\s*})`) | ||
|
|
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.
Scope leak: basicauth migration must not remove ContextKey (belongs to other middlewares).
Including ContextKey here risks deleting fields in unrelated configs (e.g., csrf/keyauth/session) when only running the basicauth migration. Keep basicauth focused on ContextUsername and ContextPassword only.
Apply this minimal fix:
- // Remove ContextKey/Username/Password when they are on their own line (with optional trailing comment).
- reCtxKeyLine := regexp.MustCompile(`(?m)^\s*Context(?:Username|Password|Key):\s*[^,\n}]+,?\s*(//[^\n]*)?\n`)
+ // Remove ContextUsername/ContextPassword when they are on their own line (with optional trailing comment).
+ reCtxKeyLine := regexp.MustCompile(`(?m)^\s*Context(?:Username|Password):\s*[^,\n}]+,?\s*(//[^\n]*)?\n`)- reCtxKeyInline := regexp.MustCompile(`(?m)\s*Context(?:Username|Password|Key):\s*[^,\n}]+(?:,\s*)?(?://[^\n]*)?(\s*})`)
+ reCtxKeyInline := regexp.MustCompile(`(?m)\s*Context(?:Username|Password):\s*[^,\n}]+(?:,\s*)?(?://[^\n]*)?(\s*})`)📝 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.
| // Remove ContextKey/Username/Password when they are on their own line (with optional trailing comment). | |
| reCtxKeyLine := regexp.MustCompile(`(?m)^\s*Context(?:Username|Password|Key):\s*[^,\n}]+,?\s*(//[^\n]*)?\n`) | |
| // Also remove inline occurrences immediately before a closing '}' (with optional comma/comment), | |
| // e.g. basicauth.Config{ContextUsername: "user"}) or {..., ContextPassword: "pass"}) | |
| // Keep the closing brace via a capture group. | |
| reCtxKeyInline := regexp.MustCompile(`(?m)\s*Context(?:Username|Password|Key):\s*[^,\n}]+(?:,\s*)?(?://[^\n]*)?(\s*})`) | |
| // Remove ContextUsername/ContextPassword when they are on their own line (with optional trailing comment). | |
| reCtxKeyLine := regexp.MustCompile(`(?m)^\s*Context(?:Username|Password):\s*[^,\n}]+,?\s*(//[^\n]*)?\n`) | |
| // Also remove inline occurrences immediately before a closing '}' (with optional comma/comment), | |
| // e.g. basicauth.Config{ContextUsername: "user"}) or {..., ContextPassword: "pass"}) | |
| // Keep the closing brace via a capture group. | |
| reCtxKeyInline := regexp.MustCompile(`(?m)\s*Context(?:Username|Password):\s*[^,\n}]+(?:,\s*)?(?://[^\n]*)?(\s*})`) |
🤖 Prompt for AI Agents
In cmd/internal/migrations/v3/basicauth_config.go around lines 17 to 24, the
current regexes also match ContextKey which can remove unrelated config fields;
update both patterns to only target ContextUsername and ContextPassword so the
basicauth migration does not delete ContextKey from other middlewares.
Specifically, remove `Key` from the alternation in both reCtxKeyLine and
reCtxKeyInline so they only use `(?:Username|Password)`, and keep the rest of
the regex behavior (optional trailing comma/comment and capture of the closing
brace) unchanged.
| content = reCtxKeyLine.ReplaceAllString(content, "") | ||
| for { | ||
| newContent := reCtxKeyInline.ReplaceAllString(content, "$1") | ||
| if newContent == content { | ||
| break | ||
| } | ||
| content = newContent | ||
| } |
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
Regex-only removal still misses non-tail inline fields and can affect non-basicauth structs; make removal struct-aware.
The iterative “remove if immediately before '}'” works for “last field” cases, but fails when the target field appears mid-list (e.g., Config{Foo:1, ContextUsername:"u", Bar:2}) unless another pass happens to move it to tail. Also, patterns aren’t scoped to basicauth.Config{...} blocks, so similar field names in other structs could be touched.
Refactor to operate only within basicauth.Config{...} literals and remove fields using the common parser (removeConfigField) which already handles comments and nested values.
Proposed change:
- content = reCtxKeyLine.ReplaceAllString(content, "")
- for {
- newContent := reCtxKeyInline.ReplaceAllString(content, "$1")
- if newContent == content {
- break
- }
- content = newContent
- }
+ // Limit removals strictly to basicauth.Config blocks and handle any position (head/mid/tail).
+ reCfgOpen := regexp.MustCompile(`basicauth\.Config\s*\{`)
+ for {
+ m := reCfgOpen.FindStringIndex(content)
+ if m == nil {
+ break
+ }
+ // m[1] points just after '{'
+ end := extractBlock(content, m[1], '{', '}')
+ if end <= m[1] {
+ // malformed, bail out of this occurrence
+ // continue searching after '{' to avoid infinite loop
+ content = content[:m[1]] + content[m[1]:]
+ continue
+ }
+ inner := content[m[1] : end-1]
+ inner = removeConfigField(inner, "ContextUsername")
+ inner = removeConfigField(inner, "ContextPassword")
+ content = content[:m[0]] + "basicauth.Config{" + inner + "}" + content[end:]
+ }📝 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.
| content = reCtxKeyLine.ReplaceAllString(content, "") | |
| for { | |
| newContent := reCtxKeyInline.ReplaceAllString(content, "$1") | |
| if newContent == content { | |
| break | |
| } | |
| content = newContent | |
| } | |
| // Limit removals strictly to basicauth.Config blocks and handle any position (head/mid/tail). | |
| reCfgOpen := regexp.MustCompile(`basicauth\.Config\s*\{`) | |
| for { | |
| m := reCfgOpen.FindStringIndex(content) | |
| if m == nil { | |
| break | |
| } | |
| // m[1] points just after '{' | |
| end := extractBlock(content, m[1], '{', '}') | |
| if end <= m[1] { | |
| // malformed, bail out of this occurrence | |
| // continue searching after '{' to avoid infinite loop | |
| content = content[:m[1]] + content[m[1]:] | |
| continue | |
| } | |
| inner := content[m[1] : end-1] | |
| inner = removeConfigField(inner, "ContextUsername") | |
| inner = removeConfigField(inner, "ContextPassword") | |
| content = content[:m[0]] + "basicauth.Config{" + inner + "}" + content[end:] | |
| } |
🤖 Prompt for AI Agents
In cmd/internal/migrations/v3/basicauth_config.go around lines 29 to 36, the
current regex-only loop that strips inline ContextKey/ContextUsername fields can
miss mid-list fields and accidentally touch non-basicauth structs; change the
logic to find only basicauth.Config{...} composite literals and within each
literal call the existing removeConfigField parser helper for the ContextKey and
ContextUsername fields so removals respect comments, nested values and ordering;
ensure you iterate each matched basicauth.Config block and replace its content
with the removeConfigField result rather than using global regex replacements.
| re := regexp.MustCompile(field + `:\s*`) | ||
| for { | ||
| loc := re.FindStringIndex(src) | ||
| if loc == nil { | ||
| break | ||
| } | ||
|
|
||
| start := loc[0] | ||
| // include any leading whitespace and comma | ||
| for start > 0 { |
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.
Bug: removeConfigField can match inside comments/strings and corrupt code.
Because the regex isn’t constrained to code context, field: inside strings or comments can be “removed,” slicing arbitrary text. This is high-risk for false positives across the repo.
Adopt a context-aware finder that ignores strings and comments and returns the index right after field:\s* (mirrors old loc[1]), then reuse the existing removal logic.
Patch:
- func removeConfigField(src, field string) string {
- re := regexp.MustCompile(field + `:\s*`)
- for {
- loc := re.FindStringIndex(src)
- if loc == nil {
- break
- }
-
- start := loc[0]
+ func removeConfigField(src, field string) string {
+ for {
+ start, i := findFieldIndexOutsideLiterals(src, field, 0)
+ if start < 0 {
+ break
+ }
- i := loc[1]Add the scanner (outside the selected range; same file):
// findFieldIndexOutsideLiterals scans src starting at from and returns the
// start index of 'field' and the index just after 'field:\s*' while ignoring
// occurrences inside comments and string literals. If not found, returns -1,-1.
func findFieldIndexOutsideLiterals(src, field string, from int) (int, int) {
inStr := false
var quote byte
inLine, inBlock := false, false
for i := from; i+len(field)+1 <= len(src); i++ {
ch := src[i]
if inLine {
if ch == '\n' {
inLine = false
}
continue
}
if inBlock {
if ch == '*' && i+1 < len(src) && src[i+1] == '/' {
inBlock = false
i++
}
continue
}
if inStr {
if ch == '\\' {
i++
continue
}
if ch == quote {
inStr = false
}
continue
}
// enter literal/comment
if ch == '"' || ch == '\'' || ch == '`' {
inStr = true
quote = ch
continue
}
if ch == '/' && i+1 < len(src) {
if src[i+1] == '/' {
inLine = true
i++
continue
}
if src[i+1] == '*' {
inBlock = true
i++
continue
}
}
// candidate: field name followed by ':'
if strings.HasPrefix(src[i:], field) && i+len(field) < len(src) && src[i+len(field)] == ':' {
// ensure reasonable left boundary: start, comma, '{', or newline/space
j := i - 1
for j >= 0 && (src[j] == ' ' || src[j] == '\t') {
j--
}
if j >= 0 && src[j] != '{' && src[j] != ',' && src[j] != '\n' && src[j] != '\r' {
continue
}
// skip 'field:' and any following spaces/tabs
k := i + len(field) + 1
for k < len(src) && (src[k] == ' ' || src[k] == '\t') {
k++
}
return i, k
}
}
return -1, -1
}This preserves your depth-based removal and makes matches safe and precise.
Also applies to: 93-147
🤖 Prompt for AI Agents
In cmd/internal/migrations/v3/common.go around lines 62-71 (and similarly for
93-147), remove the current regex-based loop because it can match inside
strings/comments and corrupt code; add the provided
findFieldIndexOutsideLiterals(src, field, from) function to this file (outside
the current range) which scans while ignoring string literals and both
line/block comments and returns the start index of the field and the index
immediately after the trailing colon+whitespace; then replace the regex
FindStringIndex usage with calls to findFieldIndexOutsideLiterals to get start
and k (end) and reuse the existing depth-based removal logic exactly as before,
using the returned indices to perform the slice removals.
Summary
Testing
make lint(fails: interrupt)go vet ./cmd/internal/migrations/v3/...make test(fails: interrupt)go test -v ./cmd/internal/migrations/v3 -run Test_MigrateBasicauthConfig_WithComments -count=1go test -v ./cmd/internal/migrations/v3 -run Test_Migrate(CSRFConfig_SessionKeyWithComment|MiddlewareLocals_ContextKeyWithComment|HealthcheckConfig_WithComments) -count=1https://chatgpt.com/codex/tasks/task_e_68ab00f8a9008326b9ca000e7f410bb4
Summary by CodeRabbit
Bug Fixes
Refactor
Tests