From 3e0a7239c473b9640aa319567766ebd4289307d1 Mon Sep 17 00:00:00 2001 From: Lukasz Raczylo Date: Mon, 15 Dec 2025 13:37:07 +0000 Subject: [PATCH] Fix ignoring strict.force and strict.commit. --- cmd/github.go | 16 -------- cmd/github_test.go | 52 ------------------------- cmd/root_test.go | 6 +-- cmd/utils/config_test.go | 2 +- cmd/utils/git.go | 11 +++++- cmd/utils/git_test.go | 26 ++++++------- cmd/utils/github.go | 78 -------------------------------------- cmd/utils/github_test.go | 80 --------------------------------------- cmd/utils/logging.go | 2 +- cmd/utils/logging_test.go | 17 +++++---- cmd/utils/semver.go | 37 ++++++++++++------ main_test.go | 2 +- 12 files changed, 63 insertions(+), 266 deletions(-) delete mode 100644 cmd/github.go delete mode 100644 cmd/github_test.go diff --git a/cmd/github.go b/cmd/github.go deleted file mode 100644 index a0c00fa..0000000 --- a/cmd/github.go +++ /dev/null @@ -1,16 +0,0 @@ -package cmd - -import ( - "github.com/lukaszraczylo/semver-generator/cmd/utils" -) - -// These functions are now in the utils package -// They are kept here as stubs for backward compatibility - -func updatePackage() bool { - return utils.UpdatePackage() -} - -func checkLatestRelease() (string, bool) { - return utils.CheckLatestRelease() -} diff --git a/cmd/github_test.go b/cmd/github_test.go deleted file mode 100644 index 324d3aa..0000000 --- a/cmd/github_test.go +++ /dev/null @@ -1,52 +0,0 @@ -package cmd - -import ( - "testing" - - "github.com/lukaszraczylo/semver-generator/cmd/utils" -) - -func Test_checkLatestRelease(t *testing.T) { - utils.InitLogger(true) - tests := []struct { - name string - want string - want1 bool - }{ - { - name: "Check latest release", - want1: true, - }, - } - for _, tt := range tests { - t.Run(tt.name, func(t *testing.T) { - _, got1 := checkLatestRelease() - if got1 != tt.want1 { - t.Errorf("checkLatestRelease() got1 = %v, want %v", got1, tt.want1) - } - }) - } -} - -func Test_updatePackage(t *testing.T) { - utils.InitLogger(true) - if testing.Short() { - t.Skip("Skipping test in short / CI mode") - } - tests := []struct { - name string - want bool - }{ - { - name: "Run autoupdater", - want: true, - }, - } - for _, tt := range tests { - t.Run(tt.name, func(t *testing.T) { - if got := updatePackage(); got != tt.want { - t.Errorf("updatePackage() = %v, want %v", got, tt.want) - } - }) - } -} diff --git a/cmd/root_test.go b/cmd/root_test.go index cabdac7..acb34df 100644 --- a/cmd/root_test.go +++ b/cmd/root_test.go @@ -30,13 +30,13 @@ func TestExecute(t *testing.T) { Short: "Test command", Run: func(cmd *cobra.Command, args []string) {}, } - + // Add all the required flags to the test command testCmd.Flags().Bool("version", false, "Print version information") testCmd.Flags().String("repository", "test-repo", "Repository URL") testCmd.Flags().String("branch", "test-branch", "Repository branch") testCmd.Flags().String("config", "test-config", "Config file path") - + rootCmd = testCmd // Execute should not panic @@ -82,4 +82,4 @@ func TestSetupCobra(t *testing.T) { assertions.Equal(t, "test-branch", testRepo.RepositoryBranch, "Repository branch should be set") assertions.Equal(t, "test-config", testRepo.LocalConfigFile, "Config file should be set") assertions.True(t, testRepo.UseLocal, "UseLocal should be set to true") -} \ No newline at end of file +} diff --git a/cmd/utils/config_test.go b/cmd/utils/config_test.go index e2d5336..a5fde8c 100644 --- a/cmd/utils/config_test.go +++ b/cmd/utils/config_test.go @@ -198,4 +198,4 @@ wording: // Test reading a non-existent config _, err = ReadConfig("non-existent-file.yaml") assert.Error(t, err) -} \ No newline at end of file +} diff --git a/cmd/utils/git.go b/cmd/utils/git.go index db29f83..807019c 100644 --- a/cmd/utils/git.go +++ b/cmd/utils/git.go @@ -135,18 +135,25 @@ func ListCommits(repo *GitRepository) ([]CommitDetails, error) { Debug("Listing commits", map[string]interface{}{"commits": tmpResults}) - // Filter commits starting from the specified commit if provided + // Filter commits starting after the specified commit if provided if repo.StartCommit != "" { + found := false for commitId, cmt := range tmpResults { if cmt.Hash == repo.StartCommit { Debug("Found commit match", map[string]interface{}{ "commit": cmt.Hash, "index": commitId, }) - repo.Commits = tmpResults[commitId:] + // Start from the commit AFTER the specified one + repo.Commits = tmpResults[commitId+1:] + found = true break } } + if !found { + // If specified commit not found, use all commits + repo.Commits = tmpResults + } } else { repo.Commits = tmpResults } diff --git a/cmd/utils/git_test.go b/cmd/utils/git_test.go index f711d1c..15f1dbd 100644 --- a/cmd/utils/git_test.go +++ b/cmd/utils/git_test.go @@ -64,7 +64,7 @@ func TestListCommits(t *testing.T) { t.Run("Test commit filtering logic", func(t *testing.T) { // Create a test repository with predefined commits repo := &GitRepository{} - + // Manually populate the commits for testing repo.Commits = []CommitDetails{ { @@ -83,7 +83,7 @@ func TestListCommits(t *testing.T) { // Test with StartCommit specified repo.StartCommit = "def456" - + // Instead of calling ListCommits which would try to use the nil Handler, // we'll just test the filtering logic directly if repo.StartCommit != "" { @@ -94,19 +94,19 @@ func TestListCommits(t *testing.T) { } } } - + // Verify the filtering worked correctly assert.Len(t, repo.Commits, 1, "Should filter commits starting from specified hash") assert.Equal(t, "def456", repo.Commits[0].Hash, "Commit hash should match") }) - + t.Run("Test with nil Handler", func(t *testing.T) { // Create a test repository with nil Handler repo := &GitRepository{} - + // Now we can safely call ListCommits since we've added a nil check commits, err := ListCommits(repo) - + // Verify the function returns without error assert.NoError(t, err, "Should not error with nil Handler") assert.Empty(t, commits, "Should return empty commits with nil Handler") @@ -120,10 +120,10 @@ func TestListExistingTags(t *testing.T) { t.Run("Test tag processing", func(t *testing.T) { // Create a test repository repo := &GitRepository{} - + // Since we can't test the actual git operations, we'll test the function's behavior // by manually setting up the repository state - + // Manually add tags to verify they're processed correctly repo.Tags = []TagDetails{ { @@ -131,20 +131,20 @@ func TestListExistingTags(t *testing.T) { Hash: "abc123", }, } - + assert.Len(t, repo.Tags, 1, "Should have 1 tag") assert.Equal(t, "v1.0.0", repo.Tags[0].Name, "Tag name should match") assert.Equal(t, "abc123", repo.Tags[0].Hash, "Tag hash should match") }) - + t.Run("Test with nil Handler", func(t *testing.T) { // Create a test repository with nil Handler repo := &GitRepository{} - + // Now we can safely call ListExistingTags since we've added a nil check ListExistingTags(repo) - + // Verify no tags were added assert.Empty(t, repo.Tags, "Should have no tags after calling with nil Handler") }) -} \ No newline at end of file +} diff --git a/cmd/utils/github.go b/cmd/utils/github.go index 2e9742c..903ceac 100644 --- a/cmd/utils/github.go +++ b/cmd/utils/github.go @@ -34,14 +34,6 @@ type ReleaseAsset struct { BrowserDownloadURL string `json:"browser_download_url"` } -// UpdateInfo contains information about an available update -type UpdateInfo struct { - CurrentVersion string - LatestVersion string - ReleaseURL string - DownloadURL string -} - // httpClient is the HTTP client used for requests (allows mocking in tests) var httpClient = &http.Client{ Timeout: requestTimeout, @@ -60,30 +52,6 @@ func CheckLatestRelease() (string, bool) { return version, true } -// CheckForUpdate checks if a newer version is available -// Returns UpdateInfo if an update is available, nil otherwise -func CheckForUpdate(currentVersion string) *UpdateInfo { - release, err := fetchLatestRelease(context.Background()) - if err != nil { - return nil - } - - latestVersion := normalizeVersion(release.TagName) - current := normalizeVersion(currentVersion) - - if isNewerVersion(latestVersion, current) { - downloadURL := findBinaryAsset(release.Assets) - return &UpdateInfo{ - CurrentVersion: current, - LatestVersion: latestVersion, - ReleaseURL: release.HTMLURL, - DownloadURL: downloadURL, - } - } - - return nil -} - // UpdatePackage downloads and installs the latest version func UpdatePackage() bool { Info("Checking for updates", nil) @@ -389,49 +357,3 @@ func normalizeVersion(v string) string { v = strings.TrimPrefix(v, "V") return v } - -// isNewerVersion compares two semver-like versions -// Returns true if latest is newer than current -func isNewerVersion(latest, current string) bool { - latestParts := parseVersionParts(latest) - currentParts := parseVersionParts(current) - - for i := 0; i < len(latestParts) && i < len(currentParts); i++ { - if latestParts[i] > currentParts[i] { - return true - } - if latestParts[i] < currentParts[i] { - return false - } - } - - return len(latestParts) > len(currentParts) -} - -// parseVersionParts splits a version string into numeric parts -func parseVersionParts(v string) []int { - // Remove any suffix like -beta, -rc1, etc. - if idx := strings.IndexAny(v, "-+"); idx != -1 { - v = v[:idx] - } - - parts := strings.Split(v, ".") - result := make([]int, 0, len(parts)) - - for _, p := range parts { - var num int - if _, err := fmt.Sscanf(p, "%d", &num); err != nil { - // If parsing fails, use 0 for this part - num = 0 - } - result = append(result, num) - } - - return result -} - -// FormatUpdateMessage formats a user-friendly update notification -func (u *UpdateInfo) FormatUpdateMessage() string { - return fmt.Sprintf("New version available: %s (current: %s) - %s", - u.LatestVersion, u.CurrentVersion, u.ReleaseURL) -} diff --git a/cmd/utils/github_test.go b/cmd/utils/github_test.go index 9c3ebae..4d46ce4 100644 --- a/cmd/utils/github_test.go +++ b/cmd/utils/github_test.go @@ -30,57 +30,6 @@ func TestNormalizeVersion(t *testing.T) { } } -func TestParseVersionParts(t *testing.T) { - tests := []struct { - input string - expected []int - }{ - {"1.0.0", []int{1, 0, 0}}, - {"2.1.3", []int{2, 1, 3}}, - {"1.0", []int{1, 0}}, - {"10.20.30", []int{10, 20, 30}}, - {"1.0.0-beta", []int{1, 0, 0}}, - {"1.0.0-rc1", []int{1, 0, 0}}, - {"1.0.0+build123", []int{1, 0, 0}}, - } - - for _, tt := range tests { - t.Run(tt.input, func(t *testing.T) { - result := parseVersionParts(tt.input) - assert.Equal(t, tt.expected, result) - }) - } -} - -func TestIsNewerVersion(t *testing.T) { - tests := []struct { - name string - latest string - current string - expected bool - }{ - {"major version bump", "2.0.0", "1.0.0", true}, - {"minor version bump", "1.1.0", "1.0.0", true}, - {"patch version bump", "1.0.1", "1.0.0", true}, - {"same version", "1.0.0", "1.0.0", false}, - {"current is newer major", "1.0.0", "2.0.0", false}, - {"current is newer minor", "1.0.0", "1.1.0", false}, - {"current is newer patch", "1.0.0", "1.0.1", false}, - {"multi-digit versions", "1.10.0", "1.9.0", true}, - {"longer version is newer", "1.0.1", "1.0", true}, - {"shorter version is older", "1.0", "1.0.1", false}, - {"complex comparison", "2.1.3", "2.1.2", true}, - {"real world example", "0.2.0", "0.1.0", true}, - } - - for _, tt := range tests { - t.Run(tt.name, func(t *testing.T) { - result := isNewerVersion(tt.latest, tt.current) - assert.Equal(t, tt.expected, result) - }) - } -} - func TestFindBinaryAsset(t *testing.T) { assets := []ReleaseAsset{ {Name: "semver-gen-1.0.0-linux-amd64.tar.gz", BrowserDownloadURL: "https://example.com/linux-amd64.tar.gz"}, @@ -102,19 +51,6 @@ func TestFindBinaryAssetEmpty(t *testing.T) { assert.Empty(t, url, "Should return empty string when no assets") } -func TestUpdateInfo_FormatUpdateMessage(t *testing.T) { - info := &UpdateInfo{ - CurrentVersion: "1.0.0", - LatestVersion: "2.0.0", - ReleaseURL: "https://github.com/lukaszraczylo/semver-generator/releases/tag/v2.0.0", - } - - msg := info.FormatUpdateMessage() - assert.Contains(t, msg, "2.0.0") - assert.Contains(t, msg, "1.0.0") - assert.Contains(t, msg, "https://github.com/lukaszraczylo/semver-generator/releases/tag/v2.0.0") -} - func TestCheckLatestRelease(t *testing.T) { // Initialize logger InitLogger(false) @@ -141,22 +77,6 @@ func TestCheckLatestRelease(t *testing.T) { } } -func TestCheckForUpdate(t *testing.T) { - InitLogger(false) - - // Test with a very old version - should show update available if network works - info := CheckForUpdate("0.0.1") - // This will either return update info or nil depending on network - if info != nil { - assert.NotEmpty(t, info.LatestVersion) - assert.Equal(t, "0.0.1", info.CurrentVersion) - } - - // Test with a very new version - should not show update - info = CheckForUpdate("999.999.999") - assert.Nil(t, info, "Should not show update for future version") -} - func TestFetchLatestReleaseError(t *testing.T) { InitLogger(false) diff --git a/cmd/utils/logging.go b/cmd/utils/logging.go index c489cbf..dffba55 100644 --- a/cmd/utils/logging.go +++ b/cmd/utils/logging.go @@ -56,4 +56,4 @@ func Critical(message string, pairs map[string]interface{}) { Pairs: pairs, }) } -} \ No newline at end of file +} diff --git a/cmd/utils/logging_test.go b/cmd/utils/logging_test.go index febb96c..a5af45a 100644 --- a/cmd/utils/logging_test.go +++ b/cmd/utils/logging_test.go @@ -5,6 +5,7 @@ import ( "github.com/stretchr/testify/assert" ) + func TestInitLogger(t *testing.T) { // Test with debug mode enabled logger := InitLogger(true) @@ -25,10 +26,10 @@ func TestLoggingFunctions(t *testing.T) { Debug("Debug message", map[string]interface{}{"key": "value"}) Info("Info message", map[string]interface{}{"key": "value"}) Error("Error message", map[string]interface{}{"key": "value"}) - + // Skip testing Critical as it might call os.Exit // Critical("Critical message", map[string]interface{}{"key": "value"}) - + // Test passes if we get here without panicking assert.True(t, true) } @@ -43,10 +44,10 @@ func TestLoggingWithNilLogger(t *testing.T) { Debug("Debug message", map[string]interface{}{"key": "value"}) Info("Info message", map[string]interface{}{"key": "value"}) Error("Error message", map[string]interface{}{"key": "value"}) - + // Skip testing Critical as it might call os.Exit // Critical("Critical message", map[string]interface{}{"key": "value"}) - + // Test passes if we get here without panicking assert.True(t, true) } @@ -56,15 +57,15 @@ func TestCriticalNilLogger(t *testing.T) { // Save original logger and restore after test originalLogger := Logger defer func() { Logger = originalLogger }() - + // Set logger to nil Logger = nil - + // This should not panic Critical("Critical message", map[string]interface{}{"key": "value"}) - + // Test passes if we get here without panicking assert.True(t, true) } -// Note: We don't test Critical with an actual logger because it calls os.Exit \ No newline at end of file +// Note: We don't test Critical with an actual logger because it calls os.Exit diff --git a/cmd/utils/semver.go b/cmd/utils/semver.go index 275e8f4..77e648d 100644 --- a/cmd/utils/semver.go +++ b/cmd/utils/semver.go @@ -16,22 +16,37 @@ func CalculateSemver( tagPrefixes []string, ) SemVer { semver := initialSemver + startIndex := 0 - for _, commit := range commits { - // Check for existing tags if enabled - if respectExisting { - for _, tagHash := range tags { - if commit.Hash == tagHash.Hash { - Debug("Found existing tag", map[string]interface{}{ - "tag": tagHash.Name, - "commit": strings.TrimSuffix(commit.Message, "\n"), - }) - semver = ParseExistingSemver(tagHash.Name, semver, tagPrefixes) - continue + // If respecting existing tags, find the latest tagged commit and start from there + if respectExisting && len(tags) > 0 { + latestTagIndex := -1 + var latestTagName string + + // Find the latest tagged commit (highest index since commits are oldest-first) + for i, commit := range commits { + for _, tag := range tags { + if commit.Hash == tag.Hash { + if i > latestTagIndex { + latestTagIndex = i + latestTagName = tag.Name + } } } } + // If we found a tagged commit, use its version and start processing after it + if latestTagIndex >= 0 { + Debug("Found latest existing tag", map[string]interface{}{ + "tag": latestTagName, + "commit": strings.TrimSuffix(commits[latestTagIndex].Message, "\n"), + }) + semver = ParseExistingSemver(latestTagName, semver, tagPrefixes) + startIndex = latestTagIndex + 1 + } + } + + for _, commit := range commits[startIndex:] { // In non-strict mode, increment patch by default if !strictMode { semver.Patch++ diff --git a/main_test.go b/main_test.go index f787f92..ca567d6 100644 --- a/main_test.go +++ b/main_test.go @@ -30,4 +30,4 @@ func TestMain(t *testing.T) { // Verify that the version was set correctly assert.Equal(t, "test-version", cmd.PKG_VERSION, "PKG_VERSION should be set correctly") -} \ No newline at end of file +}