Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
25 changes: 25 additions & 0 deletions cmd/internal/migrations/common_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -49,3 +49,28 @@ require github.com/gofiber/fiber/v2 v2.0.0`
assert.Contains(t, mod, "github.com/gofiber/fiber/v3 v3.0.0")
assert.Contains(t, buf.String(), "Migrating Go packages")
}

func Test_MigrateGoPkgs_WithHash(t *testing.T) {
dir, err := os.MkdirTemp("", "mgpkgs_hash")
require.NoError(t, err)
defer func() { require.NoError(t, os.RemoveAll(dir)) }()

file := filepath.Join(dir, "main.go")
require.NoError(t, os.WriteFile(file, []byte("package main"), 0o600))

modContent := `module example

go 1.22

require github.com/gofiber/fiber/v2 v2.0.0`
require.NoError(t, os.WriteFile(filepath.Join(dir, "go.mod"), []byte(modContent), 0o600))

var buf bytes.Buffer
cmd := newCmd(&buf)
target := semver.MustParse("3.0.1-0.20200102030405-abcdef123456")
require.NoError(t, migrations.MigrateGoPkgs(cmd, dir, nil, target))

mod := readFile(t, filepath.Join(dir, "go.mod"))
assert.Contains(t, mod, "github.com/gofiber/fiber/v3 v3.0.1-0.20200102030405-abcdef123456")
assert.Contains(t, buf.String(), "Migrating Go packages")
}
64 changes: 63 additions & 1 deletion cmd/migrate.go
Original file line number Diff line number Diff line change
@@ -1,19 +1,26 @@
package cmd

import (
"context"
"encoding/json"
"fmt"
"net/http"
"os"
"strconv"
"strings"
"time"

"github.com/Masterminds/semver/v3"
"github.com/muesli/termenv"
"github.com/spf13/cobra"
"golang.org/x/mod/module"

"github.com/gofiber/cli/cmd/internal/migrations"
)

func newMigrateCmd() *cobra.Command {
var targetVersionS string
var targetHash string
var force bool
var skipGoMod bool
var verbose bool
Expand All @@ -27,11 +34,13 @@ func newMigrateCmd() *cobra.Command {
cmd.Flags().BoolVarP(&force, "force", "f", false, "Force migration even if already on version")
cmd.Flags().BoolVarP(&skipGoMod, "skip_go_mod", "s", false, "Skip running go mod tidy, download and vendor")
cmd.Flags().BoolVarP(&verbose, "verbose", "v", false, "Enable verbose output")
cmd.Flags().StringVar(&targetHash, "hash", "", "Commit hash for Fiber version")

cmd.RunE = func(cmd *cobra.Command, _ []string) error {
return migrateRunE(cmd, MigrateOptions{
CurrentVersionFile: currentVersionFile,
TargetVersionS: targetVersionS,
TargetHash: targetHash,
Force: force,
SkipGoMod: skipGoMod,
Verbose: verbose,
Expand All @@ -46,6 +55,7 @@ var migrateCmd = newMigrateCmd()
type MigrateOptions struct {
CurrentVersionFile string
TargetVersionS string
TargetHash string
Force bool
SkipGoMod bool
Verbose bool
Expand All @@ -66,11 +76,24 @@ func migrateRunE(cmd *cobra.Command, opts MigrateOptions) error {
}
}
opts.TargetVersionS = strings.TrimPrefix(opts.TargetVersionS, "v")
targetVersion, err := semver.NewVersion(opts.TargetVersionS)
baseVersion, err := semver.NewVersion(opts.TargetVersionS)
if err != nil {
return fmt.Errorf("invalid version for \"%s\": %w", opts.TargetVersionS, err)
}

targetVersion := baseVersion
if opts.TargetHash != "" {
pv, err := pseudoVersionFromHash(baseVersion, opts.TargetHash)
if err != nil {
return fmt.Errorf("pseudo version: %w", err)
}
opts.TargetVersionS = pv
targetVersion, err = semver.NewVersion(pv)
if err != nil {
return fmt.Errorf("invalid pseudo version for \"%s\": %w", pv, err)
}
}

if !targetVersion.GreaterThan(currentVersion) && !(opts.Force && targetVersion.Equal(currentVersion)) {
return fmt.Errorf("target version v%s is not greater than current version v%s", opts.TargetVersionS, currentVersionS)
}
Expand Down Expand Up @@ -102,3 +125,42 @@ func migrateRunE(cmd *cobra.Command, opts MigrateOptions) error {

return nil
}

func pseudoVersionFromHash(base *semver.Version, hash string) (string, error) {
url := "https://api.github.com/repos/gofiber/fiber/commits/" + hash
ctx, cancel := context.WithTimeout(context.Background(), 5*time.Second)
defer cancel()

req, err := http.NewRequestWithContext(ctx, http.MethodGet, url, nil)
if err != nil {
return "", fmt.Errorf("create http request: %w", err)
}
client := http.Client{}
res, err := client.Do(req)
if err != nil {
return "", fmt.Errorf("http request failed: %w", err)
}
defer func() {
if err := res.Body.Close(); err != nil {
fmt.Fprintf(os.Stderr, "failed to close response body: %v\n", err)
}
}()

var data struct {
Commit struct {
Committer struct {
Date time.Time `json:"date"`
} `json:"committer"`
} `json:"commit"`
}
if err := json.NewDecoder(res.Body).Decode(&data); err != nil {
return "", fmt.Errorf("decode response: %w", err)
}

short := hash
if len(short) > 12 {
short = short[:12]
}
pv := module.PseudoVersion("v"+strconv.FormatUint(base.Major(), 10), "v"+base.String(), data.Commit.Committer.Date, short)
return strings.TrimPrefix(pv, "v"), nil
}
52 changes: 38 additions & 14 deletions cmd/migrate_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -21,18 +21,19 @@ func readFileTB(tb testing.TB, path string) string {
return string(b)
}

func Test_Migrate_V2_to_V3(t *testing.T) {
dir, err := os.MkdirTemp("", "migrate_v2_v3")
require.NoError(t, err)
defer func() { require.NoError(t, os.RemoveAll(dir)) }()

gomod := `module example.com/demo
const goModV2 = `module example.com/demo

go 1.20

require github.com/gofiber/fiber/v2 v2.0.6
`
require.NoError(t, os.WriteFile(filepath.Join(dir, "go.mod"), []byte(gomod), 0o600))

func Test_Migrate_V2_to_V3(t *testing.T) {
dir, err := os.MkdirTemp("", "migrate_v2_v3")
require.NoError(t, err)
defer func() { require.NoError(t, os.RemoveAll(dir)) }()

require.NoError(t, os.WriteFile(filepath.Join(dir, "go.mod"), []byte(goModV2), 0o600))

main := `package main
import (
Expand Down Expand Up @@ -118,13 +119,7 @@ func Test_Migrate_DefaultTarget(t *testing.T) {
require.NoError(t, err)
defer func() { require.NoError(t, os.RemoveAll(dir)) }()

gomod := `module example.com/demo

go 1.20

require github.com/gofiber/fiber/v2 v2.0.6
`
require.NoError(t, os.WriteFile(filepath.Join(dir, "go.mod"), []byte(gomod), 0o600))
require.NoError(t, os.WriteFile(filepath.Join(dir, "go.mod"), []byte(goModV2), 0o600))

main := `package main
import "github.com/gofiber/fiber/v2"
Expand Down Expand Up @@ -303,3 +298,32 @@ func main() {}`
content := readFileTB(t, filepath.Join(dir, "main.go"))
assert.NotContains(t, content, "github.com/gofiber/fiber/v2")
}

func Test_Migrate_WithHash(t *testing.T) {
dir, err := os.MkdirTemp("", "migrate_hash")
require.NoError(t, err)
defer func() { require.NoError(t, os.RemoveAll(dir)) }()

require.NoError(t, os.WriteFile(filepath.Join(dir, "go.mod"), []byte(goModV2), 0o600))
require.NoError(t, os.WriteFile(filepath.Join(dir, "main.go"), []byte("package main"), 0o600))

cwd, err := os.Getwd()
require.NoError(t, err)
require.NoError(t, os.Chdir(dir))
defer func() { require.NoError(t, os.Chdir(cwd)) }()

hash := "abcdef1234567890abcdef1234567890abcdef12"
httpmock.Activate()
defer httpmock.DeactivateAndReset()
commitURL := "https://api.github.com/repos/gofiber/fiber/commits/" + hash
httpmock.RegisterResponder(http.MethodGet, commitURL, httpmock.NewBytesResponder(200, []byte(`{"commit":{"committer":{"date":"2020-01-02T03:04:05Z"}}}`)))

cmd := newMigrateCmd()
setupCmd()
defer teardownCmd()
_, err = runCobraCmd(cmd, "-t=3.0.0", "--hash="+hash)
require.NoError(t, err)

gm := readFileTB(t, filepath.Join(dir, "go.mod"))
assert.Contains(t, gm, "github.com/gofiber/fiber/v3 v3.0.1-0.20200102030405-abcdef123456")
}
Loading