Skip to content

feat: refresh third-party modules#197

Merged
ReneWerner87 merged 5 commits into
masterfrom
codex/2025-08-24-17-02-38
Aug 24, 2025
Merged

feat: refresh third-party modules#197
ReneWerner87 merged 5 commits into
masterfrom
codex/2025-08-24-17-02-38

Conversation

@ReneWerner87
Copy link
Copy Markdown
Member

@ReneWerner87 ReneWerner87 commented Aug 24, 2025

Summary

  • allow --third-party flag entries with optional commit hash
  • refresh Fiber storage and template modules to latest versions or specified commits
  • generalize pseudo version calculation for third-party repositories

Testing

  • GOFLAGS=-mod=mod make lint
  • GOFLAGS=-mod=mod make test

https://chatgpt.com/codex/tasks/task_e_68ab3adf8d488326a21c7145171273ae

Summary by CodeRabbit

  • New Features

    • Added a new --third-party flag to the migrate CLI to refresh contrib, storage, and template modules (supports multiple entries and optional @ pinning).
    • Offers interactive version selection or hash-based pseudo-version resolution.
    • Automatically updates import paths and go.mod entries and runs tidy when changes occur.
  • Tests

    • Added tests confirming import and go.mod updates for contrib, storage, and template modules.
  • Documentation

    • Updated README and migrate guide with flag usage and examples.

@coderabbitai
Copy link
Copy Markdown

coderabbitai Bot commented Aug 24, 2025

Note

Other AI code review bot(s) detected

CodeRabbit 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.

Warning

Rate limit exceeded

@ReneWerner87 has exceeded the limit for the number of commits or files that can be reviewed per hour. Please wait 3 minutes and 16 seconds before requesting another review.

⌛ How to resolve this issue?

After the wait time has elapsed, a review can be triggered using the @coderabbitai review command as a PR comment. Alternatively, push new commits to this PR.

We recommend that you space out your commits to avoid hitting the rate limit.

🚦 How do rate limits work?

CodeRabbit enforces hourly rate limits for each developer per organization.

Our paid plans have higher rate limits than the trial, open-source and free plans. In all cases, we re-allow further reviews after a brief timeout.

Please see our FAQ for further information.

📥 Commits

Reviewing files that changed from the base of the PR and between ce5e321 and c066ed6.

📒 Files selected for processing (1)
  • cmd/third_party.go (1 hunks)

Walkthrough

Adds CLI support to refresh specified third-party modules (contrib, storage, template) during migrate. Parses --third-party inputs (name[@commit]), discovers imports, resolves target versions (latest or hash-derived pseudo-versions), rewrites import paths and go.mod entries, and conditionally runs go mod tidy.

Changes

Cohort / File(s) Summary
Migration CLI updates
cmd/migrate.go
Adds ThirdPartyParam type and ThirdParty []ThirdPartyParam in MigrateOptions. Parses --third-party flag, wires third-party items into migrate flow, updates pseudoVersionFromHash to accept a repo parameter, and conditionally runs internal.RunGoMod when refreshes change state.
Third-party refresh implementation
cmd/third_party.go
New file implementing discovery of contrib/storage/template imports, resolution of target versions (latest or hash-derived pseudo-versions), import-path and go.mod rewriting, and helpers refreshContrib, refreshStorage, and refreshTemplates. Respects vendor dir and uses 5s proxy timeouts.
Tests for third-party refresh
cmd/third_party_test.go
New unit tests creating temporary modules to validate import rewrites and go.mod require-line updates for contrib, storage, and template modules using stubbed latest-version functions.
Docs / CLI help
README.md, docs/guide/migrate.md
Adds --third-party flag documentation and usage examples describing comma-separated module list and optional @<commit> pinning.

Sequence Diagram(s)

sequenceDiagram
  autonumber
  actor Dev as Developer
  participant CLI as migrate (CLI)
  participant Core as Migration Core
  participant TP as Third-Party Refresher
  participant GoMod as go mod tidy

  Dev->>CLI: migrate --third-party=contrib,storage@abcdef
  CLI->>Core: run core migration
  Core-->>CLI: core migration complete
  alt third-party entries present
    loop each entry
      CLI->>TP: refreshX(dir, name, hash)
      TP->>TP: scan imports (skip vendor)
      TP->>TP: resolve version (latest OR pseudoVersionFromHash(repo, base, hash))
      TP->>TP: rewrite imports and go.mod
      TP-->>CLI: changed? (true/false)
    end
    opt any change and not SkipGoMod
      CLI->>GoMod: internal.RunGoMod(dir)
      GoMod-->>CLI: tidy complete
    end
  end
  CLI-->>Dev: migration finished
Loading

Estimated code review effort

🎯 4 (Complex) | ⏱️ ~60 minutes

Possibly related PRs

Poem

I hop through deps with tidy paws,
Nudging imports, fixing laws;
Contrib, storage, templates too—
Versions fresh as morning dew.
With a twitch of whisker and a cheerful sigh,
I run go mod tidy and watch changes fly.

✨ Finishing Touches
  • 📝 Generate Docstrings
🧪 Generate unit tests
  • Create PR with unit tests
  • Post copyable unit tests in a comment
  • Commit unit tests in branch codex/2025-08-24-17-02-38

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.

❤️ Share
🪧 Tips

Chat

There are 3 ways to chat with CodeRabbit:

  • Review comments: Directly reply to a review comment made by CodeRabbit. Example:
    • I pushed a fix in commit <commit_id>, please review it.
    • Open a follow-up GitHub issue for this discussion.
  • Files and specific lines of code (under the "Files changed" tab): Tag @coderabbitai in a new review comment at the desired location with your query.
  • PR comments: Tag @coderabbitai in a new PR comment to ask questions about the PR branch. For the best results, please provide a very specific query, as very limited context is provided in this mode. Examples:
    • @coderabbitai gather interesting stats about this repository and render them as a table. Additionally, render a pie chart showing the language distribution in the codebase.
    • @coderabbitai read the files in the src/scheduler package and generate a class diagram using mermaid and a README in the markdown format.

Support

Need help? Create a ticket on our support page for assistance with any issues or questions.

CodeRabbit Commands (Invoked using PR/Issue comments)

Type @coderabbitai help to get the list of available commands.

Other keywords and placeholders

  • Add @coderabbitai ignore anywhere in the PR description to prevent this PR from being reviewed.
  • Add @coderabbitai summary to generate the high-level summary at a specific location in the PR description.
  • Add @coderabbitai or @coderabbitai title anywhere in the PR title to generate the title automatically.

CodeRabbit Configuration File (.coderabbit.yaml)

  • You can programmatically configure CodeRabbit by adding a .coderabbit.yaml file to the root of your repository.
  • Please see the configuration documentation for more information.
  • If your editor has YAML language server enabled, you can add the path at the top of this file to enable auto-completion and validation: # yaml-language-server: $schema=https://coderabbit.ai/integrations/schema.v2.json

Status, Documentation and Community

  • Visit our Status Page to check the current availability of CodeRabbit.
  • Visit our Documentation for detailed information on how to use CodeRabbit.
  • Join our Discord Community to get help, request features, and share feedback.
  • Follow us on X/Twitter for updates and announcements.

Copy link
Copy Markdown
Contributor

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

Choose a reason for hiding this comment

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

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 introduces a new feature to the migrate command, enabling users to refresh third-party Fiber modules (like contrib, storage, and template) to their latest versions or specific commit hashes. It also generalizes the pseudo version calculation logic for broader applicability across different repositories.

Highlights

  • Enhanced migrate command: A new --third-party flag is added to the migrate command, allowing users to specify which third-party modules to refresh.
  • Flexible versioning: The --third-party flag now supports optional commit hashes (e.g., --third-party=contrib@), providing precise control over module versions.
  • Generalized pseudo version calculation: The internal pseudoVersionFromHash utility has been refactored to accept a repository name, making it reusable for various Fiber-related repositories.
  • Dedicated third-party refresh logic: New Go functions (refreshContrib, refreshStorage, refreshTemplates) are introduced to handle the complex process of updating module import paths in source files and their corresponding entries in go.mod.
  • New files for modularity: The new cmd/third_party.go file centralizes the logic for refreshing third-party modules, while cmd/third_party_test.go provides comprehensive unit tests for this new functionality.
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

  1. 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.

Comment thread cmd/third_party.go Fixed
Comment thread cmd/third_party.go Fixed
Comment thread cmd/third_party.go Fixed
Copy link
Copy Markdown
Contributor

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

Choose a reason for hiding this comment

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

Code Review

This pull request introduces a valuable feature for refreshing third-party modules using a new --third-party flag. The implementation for storage and template modules is well-structured. However, the logic for handling contrib modules appears to be based on an incorrect assumption about the repository's structure, which would result in generating invalid module paths. I've left a critical comment detailing this issue and suggesting a fix. I also noted that the associated test needs updating. Furthermore, there's an opportunity to improve maintainability by refactoring duplicated code, for which I've provided a suggestion.

Comment thread cmd/third_party.go
Comment thread cmd/third_party.go Outdated
Comment thread cmd/third_party_test.go
Copy link
Copy Markdown

@coderabbitai coderabbitai Bot left a comment

Choose a reason for hiding this comment

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

Actionable comments posted: 2

Caution

Some comments are outside the diff and can’t be posted inline due to platform limitations.

⚠️ Outside diff range comments (1)
cmd/migrate.go (1)

109-116: Pseudo-version must retain leading “v”; current trim likely yields invalid go.mod entries downstream

pseudoVersionFromHash currently returns the pseudo-version without the leading “v”. Go module versions (incl. pseudo versions) are “v”-prefixed. Keeping it trimmed can produce lines like “… 1.2.3-0.2025…” which is invalid.

Apply this diff to return the “v”-prefixed pseudo-version, and trim only for semver parsing:

@@
-		pv, err := pseudoVersionFromHash("gofiber/fiber", baseVersion, opts.TargetHash)
+		pv, err := pseudoVersionFromHash("gofiber/fiber", baseVersion, opts.TargetHash)
@@
-		targetVersion, err = semver.NewVersion(pv)
+		targetVersion, err = semver.NewVersion(strings.TrimPrefix(pv, "v"))
 func pseudoVersionFromHash(repo string, base *semver.Version, hash string) (string, error) {
@@
-	pv := module.PseudoVersion("v"+strconv.FormatUint(base.Major(), 10), "v"+base.String(), commitTime, short)
-	return strings.TrimPrefix(pv, "v"), nil
+	pv := module.PseudoVersion("v"+strconv.FormatUint(base.Major(), 10), "v"+base.String(), commitTime, short)
+	return pv, nil
 }

Follow-up: The third-party refreshers use this function too; keeping the “v” fixes their go.mod writes in hash mode.

Also applies to: 180-234

🧹 Nitpick comments (7)
cmd/third_party.go (4)

130-130: Anchor regexes to import strings and allow hyphenated module names (resolves CodeQL “Missing regular expression anchor”)

  • Current patterns may match anywhere in the file and don’t allow hyphens in module names.
  • Anchor to a leading quote and broaden the character class to include “-”.
-	re := regexp.MustCompile(`github\.com/gofiber/contrib/(?:v\d+/)?([a-zA-Z0-9_]+)`) // capture module name
+	re := regexp.MustCompile(`(?m)"github\.com/gofiber/contrib/(?:v\d+/)?([a-zA-Z0-9_\-]+)`) // capture module name anchored to a quote

-	re := regexp.MustCompile(`github\.com/gofiber/storage/([a-zA-Z0-9_]+)(?:/(v\d+))?`)
+	re := regexp.MustCompile(`(?m)"github\.com/gofiber/storage/([a-zA-Z0-9_\-]+)(?:/(v\d+))?`)

-	re := regexp.MustCompile(`github\.com/gofiber/template/([a-zA-Z0-9_]+)(?:/(v\d+))?`)
+	re := regexp.MustCompile(`(?m)"github\.com/gofiber/template/([a-zA-Z0-9_\-]+)(?:/(v\d+))?`)

Note: The anchored patterns still extract the intended capture groups while reducing false positives.

Also applies to: 364-364, 396-396


231-244: Support hyphens in module names for storage/template import rewrites

Some modules may contain hyphens. Broaden the character class in the storage/template import rewrite regex.

-	re := regexp.MustCompile(`"github\.com/gofiber/storage/([a-zA-Z0-9_]+)(?:/v\d+)?([^\"]*)"`)
+	re := regexp.MustCompile(`"github\.com/gofiber/storage/([a-zA-Z0-9_\-]+)(?:/v\d+)?([^\"]*)"`)
-	re := regexp.MustCompile(`"github\.com/gofiber/template/([a-zA-Z0-9_]+)(?:/v\d+)?([^\"]*)"`)
+	re := regexp.MustCompile(`"github\.com/gofiber/template/([a-zA-Z0-9_\-]+)(?:/v\d+)?([^\"]*)"`)

Also applies to: 313-326


198-226: Cross-major upgrades for storage/templates may never occur with default resolver

You pass the current major (e.g., v2) into latestStorageVersionFn/TemplateVersionFn, which queries ...///@latest. That confines updates to the current major. Tests simulate a major bump by overriding the resolver, but the default code won’t upgrade from v2→v3.

If the intent is “latest across majors,” consider:

  • Querying without a major first to get the global latest, and fall back to the current-major query if needed.
  • Example sketch:
latestAny := latestStorageVersionFn(mod, "")
if latestAny == "" {
    latest := latestStorageVersionFn(mod, curMajor)
    // use latest within same major
} else {
    // use latestAny (may change major)
}

Confirm desired behavior (stay on current major vs. upgrade across majors) and I can draft a precise diff.


165-180: Hardcoded contrib aggregator v3 limits future compatibility

latestContribVersion fetches from contrib/v3//@latest. If contrib moves to v4, this will break discovery. Either:

  • Parameterize the contrib aggregator major, or
  • Discover the latest contrib major first.
cmd/migrate.go (1)

152-159: Warn on unknown --third-party names to aid user feedback

Unknown names are silently ignored. Emit a friendly warning listing supported values.

 		switch tp.Name {
 		case "contrib":
 			changed, err = refreshContrib(cmd, wd, tp.Hash)
 		case "storage":
 			changed, err = refreshStorage(cmd, wd, tp.Hash)
 		case "template", "templates":
 			changed, err = refreshTemplates(cmd, wd, tp.Hash)
+		default:
+			cmd.Printf("Unknown third-party %q (supported: contrib, storage, template)\n", tp.Name)
 		}
cmd/third_party_test.go (2)

14-48: Add regression for contrib: avoid double “/vN” when input already contains a module major

Current tests don’t cover the case where the starting import already has “/vN”. Add a case like importing github.com/gofiber/contrib/monitor/v1 and assert the result remains singular (…/monitor/v1), not duplicated.

I can draft a new test function Test_refreshContrib_keepsSingleModuleMajor if you confirm desired behavior.


85-118: Cover hash mode (pseudo-version) to catch the “v”-prefix bug

Add a test that passes a hash to refreshers, stubs pseudoVersionFromHash via a seam (or injects a fixed return), and asserts go.mod contains a “v”-prefixed pseudo-version. This would have flagged the trimming issue.

Shall I provide a concrete test that stubs the hash resolver and validates go.mod writes?

📜 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.

📥 Commits

Reviewing files that changed from the base of the PR and between 23d8879 and 5835adb.

📒 Files selected for processing (3)
  • cmd/migrate.go (6 hunks)
  • cmd/third_party.go (1 hunks)
  • cmd/third_party_test.go (1 hunks)
🧰 Additional context used
🧬 Code graph analysis (2)
cmd/migrate.go (1)
cmd/internal/go_mod.go (1)
  • RunGoMod (20-40)
cmd/third_party.go (1)
cmd/internal/helpers.go (1)
  • ChangeFileContent (38-79)
🪛 GitHub Check: CodeQL
cmd/third_party.go

[failure] 130-130: Missing regular expression anchor
When this is used as a regular expression on a URL, it may match anywhere, and arbitrary hosts may come before or after it.


[failure] 364-364: Missing regular expression anchor
When this is used as a regular expression on a URL, it may match anywhere, and arbitrary hosts may come before or after it.


[failure] 396-396: Missing regular expression anchor
When this is used as a regular expression on a URL, it may match anywhere, and arbitrary hosts may come before or after it.

⏰ 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). (2)
  • GitHub Check: Build (1.25.x, windows-latest)
  • GitHub Check: Build (1.25.x, macos-13)

Comment thread cmd/third_party.go Outdated
Comment thread cmd/third_party.go
@ReneWerner87 ReneWerner87 added the ✏️ Feature New feature or request label Aug 24, 2025
Comment thread cmd/third_party.go Fixed
Copy link
Copy Markdown

@coderabbitai coderabbitai Bot left a comment

Choose a reason for hiding this comment

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

Actionable comments posted: 2

♻️ Duplicate comments (2)
cmd/third_party.go (2)

79-92: Contrib import rewrite regex: allow hyphenated module names and drop captured old module-major cleanly

The current pattern excludes hyphens in module names and doesn’t preserve them. Some contrib modules can be hyphenated; also, explicitly capture-and-drop the old module-level major to avoid accidental duplication.

-	re := regexp.MustCompile(`"github\.com/gofiber/contrib(?:/v\d+)?/([a-zA-Z0-9_]+)(?:/v\d+)?([^\"]*)"`)
+	re := regexp.MustCompile(`"github\.com/gofiber/contrib(?:/v\d+)?/([A-Za-z0-9_\-]+)(?:/(v\d+))?([^\"]*)"`)
@@
-			mod := sub[1]
-			rest := sub[2]
+			mod := sub[1]
+			// sub[2] is any existing module-level major (e.g., v2) – intentionally dropped
+			rest := sub[3]
@@
-			return fmt.Sprintf("\"github.com/gofiber/contrib/%s%s%s\"", mod, majorPath(major), rest)
+			return fmt.Sprintf("\"github.com/gofiber/contrib/%s%s%s\"", mod, majorPath(major), rest)

128-163: Discovery for contrib misses module-level major; prefer reusing generic finder

findContribModules only returns module names and looks for an aggregator major before the module. Contrib’s module major is after the module segment (e.g., contrib/jwt/v4). This mismatch causes latestContribVersion to query the wrong path.

Two options (preferred first):

  • Remove this function and call findThirdPartyModules(cwd, "contrib") from refreshContrib.
  • Or, change this function to return map[string]string (module -> currentMajor) and update callers.

If you prefer to keep it, here’s a minimal signature/impl change:

-func findContribModules(cwd string) ([]string, error) {
-	modules := make(map[string]struct{})
-	re := regexp.MustCompile(`\bgithub\.com/gofiber/contrib/(?:v\d+/)?([a-zA-Z0-9_]+)`) // capture module name
+func findContribModules(cwd string) (map[string]string, error) {
+	modules := make(map[string]string)
+	re := regexp.MustCompile(`\bgithub\.com/gofiber/contrib/([A-Za-z0-9_\-]+)(?:/(v\d+))?`) // capture module and optional module-major
@@
-		matches := re.FindAllStringSubmatch(string(b), -1)
-		for _, m := range matches {
-			modules[m[1]] = struct{}{}
-		}
+		for _, m := range re.FindAllStringSubmatch(string(b), -1) {
+			modules[m[1]] = m[2]
+		}
@@
-	res := make([]string, 0, len(modules))
-	for m := range modules {
-		res = append(res, m)
-	}
-	sort.Strings(res)
-	return res, nil
+	return modules, nil

Note: If you take this path, adjust refreshContrib loops accordingly.

I can push the cohesive refactor (reuse findThirdPartyModules) if you want to avoid duplicate scanners.

🧹 Nitpick comments (3)
README.md (1)

167-167: Clarify allowed values and commit pinning semantics for --third-party

Consider explicitly listing the allowed tokens and per-item commit pinning in the help text to avoid ambiguity.

-      --third-party strings   Refresh third-party modules (contrib,storage,template). Provide a comma-separated list and optionally append @<commit> to pin a commit
+      --third-party strings   Refresh third-party modules. Comma-separated list of {contrib|storage|template}; each entry may append @<commit> to pin a specific commit, e.g. "contrib@abcdef,template"
cmd/third_party.go (1)

231-243: Allow hyphens in storage/template module names and capture existing module-major explicitly

To be consistent and future-proof, permit - in module segment and capture the existing module-level major so it can be dropped cleanly in the replacement.

-	re := regexp.MustCompile(fmt.Sprintf(`"github\.com/gofiber/%s/([a-zA-Z0-9_]+)(?:/v\d+)?([^\"]*)"`, regexp.QuoteMeta(repo)))
+	re := regexp.MustCompile(fmt.Sprintf(`"github\.com/gofiber/%s/([A-Za-z0-9_\-]+)(?:/(v\d+))?([^\"]*)"`, regexp.QuoteMeta(repo)))
@@
-			mod := sub[1]
-			rest := sub[2]
+			mod := sub[1]
+			// sub[2] is any existing module-level major (e.g., v2) – intentionally dropped
+			rest := sub[3]

And update the finder:

-	re := regexp.MustCompile(fmt.Sprintf(`\bgithub\.com/gofiber/%s/([a-zA-Z0-9_]+)(?:/(v\d+))?`, regexp.QuoteMeta(repo)))
+	re := regexp.MustCompile(fmt.Sprintf(`\bgithub\.com/gofiber/%s/([A-Za-z0-9_\-]+)(?:/(v\d+))?`, regexp.QuoteMeta(repo)))

Also applies to: 288-291

cmd/third_party_test.go (1)

14-48: Consider adding a contrib v2+ case and hash-pinning case

Current test covers a v1 contrib module. To guard against the major-handling bug and validate pseudo-version use:

  • Add a test for a contrib module with an existing /v2 import and ensure it upgrades to latest v2 (imports and go.mod).
  • Add a test passing a hash to refreshContrib and assert the resulting pseudo-version format and path.

I can draft these tests with deterministic stubs for version/hash to keep them stable.

📜 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.

📥 Commits

Reviewing files that changed from the base of the PR and between 5835adb and ce5e321.

📒 Files selected for processing (5)
  • README.md (1 hunks)
  • cmd/migrate.go (6 hunks)
  • cmd/third_party.go (1 hunks)
  • cmd/third_party_test.go (1 hunks)
  • docs/guide/migrate.md (2 hunks)
✅ Files skipped from review due to trivial changes (1)
  • docs/guide/migrate.md
🚧 Files skipped from review as they are similar to previous changes (1)
  • cmd/migrate.go
🧰 Additional context used
🧠 Learnings (1)
📚 Learning: 2024-11-26T20:05:15.793Z
Learnt from: ReneWerner87
PR: gofiber/recipes#0
File: :0-0
Timestamp: 2024-11-26T20:05:15.793Z
Learning: For future contributions to the `gofiber/recipes` repository, ensure that the tasks outlined in `.github/CONTRIBUTING.md` are incorporated, including creating a new directory without a "fiber" prefix, adding a `README.md` with Docusaurus metadata, and updating the overview by running `make generate`.

Applied to files:

  • cmd/third_party.go
🧬 Code graph analysis (1)
cmd/third_party.go (1)
cmd/internal/helpers.go (1)
  • ChangeFileContent (38-79)
🪛 GitHub Check: CodeQL
cmd/third_party.go

[failure] 130-130: Missing regular expression anchor
When this is used as a regular expression on a URL, it may match anywhere, and arbitrary hosts may come before or after it.

⏰ 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, macos-13)
🔇 Additional comments (6)
cmd/third_party.go (5)

97-120: Nice: go.mod contrib rewrite now catches existing aggregator and module majors

Pattern accounts for both optional contrib aggregator major and module-level major and preserves inline comments by matching only up to the version. Good improvement and safe replacement with ${1} prefix.


182-196: Major helpers look solid

majorFromVersion and majorPath correctly handle v0/v1 (no path) and higher majors with a leading slash. These are safe for pseudo-versions too.


198-278: Generic refresh flow for storage/template is clean and robust

Good reuse via refreshThirdParty, safe file traversal with vendor skip, bounded network calls, and careful go.mod editing with multiline support. Nicely done.


320-339: Network fetch logic is defensive and time-bounded

Using a 5s context and returning empty on non-200 or JSON errors keeps the flow resilient. Good.


30-92: No contrib imports or go.mod found – no verification needed

I ran a workspace-wide search and confirmed:

  • There are no github.com/gofiber/contrib/.../vN imports in the CLI’s codebase.
  • There are no hyphenated contrib/storage/template modules.
  • There is no go.mod file in this repository (it’s a standalone CLI, not a Go module).

Since the refactoring scripts operate on external target modules (where a go.mod does exist), there’s nothing here to adjust. Merging as-is.

cmd/third_party_test.go (1)

50-118: Storage/template tests look good and realistic

They validate import path rewriting to the correct module-level major and the go.mod require line. Solid coverage.

Comment thread cmd/third_party_test.go
Comment on lines +28 to +30
old := latestContribVersionFn
latestContribVersionFn = func(string) string { return "v1.2.3" }
defer func() { latestContribVersionFn = old }()
Copy link
Copy Markdown

Choose a reason for hiding this comment

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

🛠️ Refactor suggestion

Adjust test stub to new signature if adopting contrib-major fix

If you update latestContribVersionFn to accept (module, major), adapt the test stub accordingly.

-	old := latestContribVersionFn
-	latestContribVersionFn = func(string) string { return "v1.2.3" }
-	defer func() { latestContribVersionFn = old }()
+	old := latestContribVersionFn
+	latestContribVersionFn = func(string, string) string { return "v1.2.3" }
+	defer func() { latestContribVersionFn = old }()
📝 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.

Suggested change
old := latestContribVersionFn
latestContribVersionFn = func(string) string { return "v1.2.3" }
defer func() { latestContribVersionFn = old }()
old := latestContribVersionFn
latestContribVersionFn = func(string, string) string { return "v1.2.3" }
defer func() { latestContribVersionFn = old }()
🤖 Prompt for AI Agents
In cmd/third_party_test.go around lines 28 to 30, the test replaces
latestContribVersionFn with a stub that currently has signature func(string)
string but the implementation under review changed the real function to accept
(module, major), so update the test stub to match the new signature (e.g.,
func(module string, major string) string or appropriate types) and return the
expected version string; keep the defer restoration as-is but ensure the stub
parameter list and any call sites in the test are updated to pass both
arguments.

Comment thread cmd/third_party.go
Comment on lines +30 to +38
func refreshContrib(cmd *cobra.Command, cwd, hash string) (bool, error) {
modules, err := findContribModules(cwd)
if err != nil {
return false, fmt.Errorf("find modules: %w", err)
}
if len(modules) == 0 {
return false, nil
}

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

⚠️ Potential issue

Contrib latest-version resolution ignores module major (v2+ modules break)

refreshContrib gathers only module names and latestContribVersion queries proxy.golang.org without the module-level major (e.g., /jwt/v4). For contrib modules that are v2+, this returns the wrong module (v0/v1) or nothing, producing incorrect versions and paths.

  • Capture the module-level major for contrib (like you do in findThirdPartyModules).
  • Make latestContribVersion accept (module, major) and pass it through when resolving versions.

Apply these focused diffs:

@@
-var (
-	latestContribVersionFn  = latestContribVersion
+var (
+	latestContribVersionFn  = latestContribVersion
 	latestStorageVersionFn  = func(module, major string) string { return latestThirdPartyVersion("storage", module, major) }
 	latestTemplateVersionFn = func(module, major string) string { return latestThirdPartyVersion("template", module, major) }
 )
@@
-func refreshContrib(cmd *cobra.Command, cwd, hash string) (bool, error) {
-	modules, err := findContribModules(cwd)
+func refreshContrib(cmd *cobra.Command, cwd, hash string) (bool, error) {
+	// Reuse generic discovery so we also capture the current module major (e.g., v2, v3)
+	modules, err := findThirdPartyModules(cwd, "contrib")
 	if err != nil {
 		return false, fmt.Errorf("find modules: %w", err)
 	}
 	if len(modules) == 0 {
 		return false, nil
 	}
@@
-	versions := make(map[string]string, len(modules))
-	if hash == "" {
+	versions := make(map[string]string, len(modules))
+	if hash == "" {
 		reader := bufio.NewReader(cmd.InOrStdin())
-		for _, m := range modules {
-			latest := latestContribVersionFn(m)
-			prompt := fmt.Sprintf("Version for github.com/gofiber/contrib/%s (default %s): ", m, latest)
+		for m, curMajor := range modules {
+			latest := latestContribVersionFn(m, curMajor)
+			display := fmt.Sprintf("github.com/gofiber/contrib/%s%s", m, majorPath(curMajor))
+			prompt := fmt.Sprintf("Version for %s (default %s): ", display, latest)
 			cmd.Print(prompt)
 			line, err := reader.ReadString('\n')
 			if err != nil && err != io.EOF {
 				return false, fmt.Errorf("read input: %w", err)
 			}
 			v := strings.TrimSpace(line)
 			if v == "" {
 				v = latest
 			}
 			if v != "" {
 				versions[m] = v
 			}
 		}
 	} else {
-		for _, m := range modules {
-			latest := latestContribVersionFn(m)
+		for m, curMajor := range modules {
+			latest := latestContribVersionFn(m, curMajor)
 			if latest == "" {
 				continue
 			}
 			base, err := semver.NewVersion(strings.TrimPrefix(latest, "v"))
 			if err != nil {
 				return false, fmt.Errorf("parse version: %w", err)
 			}
 			pv, err := pseudoVersionFromHash("gofiber/contrib", base, hash)
 			if err != nil {
 				return false, fmt.Errorf("pseudo version: %w", err)
 			}
 			versions[m] = pv
 		}
 	}
@@
-func latestContribVersion(module string) string {
+func latestContribVersion(module, major string) string {
 	ctx, cancel := context.WithTimeout(context.Background(), 5*time.Second)
 	defer cancel()
-	url := fmt.Sprintf("https://proxy.golang.org/github.com/gofiber/contrib/%s/@latest", module)
+	url := fmt.Sprintf("https://proxy.golang.org/github.com/gofiber/contrib/%s", module)
+	if major != "" {
+		url += "/" + major
+	}
+	url += "/@latest"
 	b, status, err := cachedGET(ctx, url, nil)
 	if err != nil || status != 200 {
 		return ""
 	}
 	var data struct {
 		Version string `json:"Version"` //nolint:tagliatelle // field name defined by proxy
 	}
 	if err := json.Unmarshal(b, &data); err != nil {
 		return ""
 	}
 	return data.Version
 }

Follow-ups:

  • Remove or repurpose findContribModules (now redundant) to avoid drift.
  • Update tests to use the new latestContribVersionFn signature.

Happy to push a targeted PR update if you want me to wire this through and adjust tests.

Also applies to: 165-181

🤖 Prompt for AI Agents
In cmd/third_party.go around lines 30-38 (and similarly 165-181), refreshContrib
currently collects only module paths and calls latestContribVersion without the
module-level major, which breaks v2+ modules; update refreshContrib to capture
the module-level major suffix (e.g., /v4) the same way findThirdPartyModules
does and pass both module and major into latestContribVersion; change
latestContribVersion signature to accept (module, major) and ensure it appends
the major segment when querying proxy.golang.org; update all callers to the new
signature, adjust or remove the now-redundant findContribModules, and update
tests to use the new latestContribVersionFn signature.

@ReneWerner87 ReneWerner87 merged commit c75b11e into master Aug 24, 2025
13 checks passed
@ReneWerner87 ReneWerner87 deleted the codex/2025-08-24-17-02-38 branch August 24, 2025 18:48
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

codex ✏️ Feature New feature or request

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants