feat: refresh third-party modules#197
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. 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 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. 📒 Files selected for processing (1)
WalkthroughAdds 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
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
Estimated code review effort🎯 4 (Complex) | ⏱️ ~60 minutes Possibly related PRs
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.
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
-
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.
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.
There was a problem hiding this comment.
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 downstreampseudoVersionFromHash 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 rewritesSome 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 resolverYou 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 compatibilitylatestContribVersion 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 feedbackUnknown 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 majorCurrent 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_keepsSingleModuleMajorif you confirm desired behavior.
85-118: Cover hash mode (pseudo-version) to catch the “v”-prefix bugAdd 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.
📒 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)
There was a problem hiding this comment.
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 cleanlyThe 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
findContribModulesonly 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 causeslatestContribVersionto query the wrong path.Two options (preferred first):
- Remove this function and call
findThirdPartyModules(cwd, "contrib")fromrefreshContrib.- 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, nilNote: If you take this path, adjust
refreshContribloops 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-partyConsider 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 explicitlyTo 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 caseCurrent 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
/v2import and ensure it upgrades to latest v2 (imports and go.mod).- Add a test passing a
hashtorefreshContriband 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.
📒 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 majorsPattern 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
majorFromVersionandmajorPathcorrectly 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 robustGood 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-boundedUsing 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 neededI ran a workspace-wide search and confirmed:
- There are no
github.com/gofiber/contrib/.../vNimports in the CLI’s codebase.- There are no hyphenated contrib/storage/template modules.
- There is no
go.modfile in this repository (it’s a standalone CLI, not a Go module).Since the refactoring scripts operate on external target modules (where a
go.moddoes exist), there’s nothing here to adjust. Merging as-is.cmd/third_party_test.go (1)
50-118: Storage/template tests look good and realisticThey validate import path rewriting to the correct module-level major and the go.mod require line. Solid coverage.
| old := latestContribVersionFn | ||
| latestContribVersionFn = func(string) string { return "v1.2.3" } | ||
| defer func() { latestContribVersionFn = old }() |
There was a problem hiding this comment.
🛠️ 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.
| 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.
| 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 | ||
| } | ||
|
|
There was a problem hiding this comment.
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
latestContribVersionaccept(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
latestContribVersionFnsignature.
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.
Summary
--third-partyflag entries with optional commit hashTesting
GOFLAGS=-mod=mod make lintGOFLAGS=-mod=mod make testhttps://chatgpt.com/codex/tasks/task_e_68ab3adf8d488326a21c7145171273ae
Summary by CodeRabbit
New Features
Tests
Documentation