diff --git a/.gitignore b/.gitignore index 82a4de1..f432a1f 100644 --- a/.gitignore +++ b/.gitignore @@ -61,4 +61,7 @@ pids # Test coverage coverage.txt -coverage.out \ No newline at end of file +coverage.out + +# Go workspace sum file (generated, varies by environment) +go.work.sum \ No newline at end of file diff --git a/Makefile b/Makefile index 880d24e..093aec8 100644 --- a/Makefile +++ b/Makefile @@ -50,11 +50,9 @@ clean: rm -f get-next-semver/get-next-semver rm -f tag-and-create-semver-release/tag-and-create-semver-release -# Run tests for all actions and go-kit +# Run tests for all actions test: @echo "Running tests..." - @echo "Testing go-kit..." - @cd internal/go-kit && go test -v ./... @echo "Testing create-issue..." @cd create-issue && go test -v ./... @echo "Testing find-issue..." diff --git a/close-issue/go.mod b/close-issue/go.mod index 6a63100..1971617 100644 --- a/close-issue/go.mod +++ b/close-issue/go.mod @@ -1,3 +1,5 @@ module github.com/half-ogre-games/hog-actions/close-issue -go 1.24 \ No newline at end of file +go 1.24.3 + +require github.com/half-ogre/go-kit v0.2.0 diff --git a/close-issue/go.sum b/close-issue/go.sum new file mode 100644 index 0000000..913e76d --- /dev/null +++ b/close-issue/go.sum @@ -0,0 +1,2 @@ +github.com/half-ogre/go-kit v0.2.0 h1:qRQKapcB0qVen28VPn1V9ucxD+csDwaVIev7YK1qAhU= +github.com/half-ogre/go-kit v0.2.0/go.mod h1:MSPRSJ1vN0ljh/UvDYmSIvLBONyL5nIPMHu+QtJ/ra8= diff --git a/comment-issue/go.mod b/comment-issue/go.mod index f3cb71b..366a9a7 100644 --- a/comment-issue/go.mod +++ b/comment-issue/go.mod @@ -1,3 +1,5 @@ module github.com/half-ogre-games/hog-actions/comment-issue -go 1.24 \ No newline at end of file +go 1.24.3 + +require github.com/half-ogre/go-kit v0.2.0 diff --git a/comment-issue/go.sum b/comment-issue/go.sum new file mode 100644 index 0000000..913e76d --- /dev/null +++ b/comment-issue/go.sum @@ -0,0 +1,2 @@ +github.com/half-ogre/go-kit v0.2.0 h1:qRQKapcB0qVen28VPn1V9ucxD+csDwaVIev7YK1qAhU= +github.com/half-ogre/go-kit v0.2.0/go.mod h1:MSPRSJ1vN0ljh/UvDYmSIvLBONyL5nIPMHu+QtJ/ra8= diff --git a/create-issue/go.mod b/create-issue/go.mod index 8dfecce..a47f056 100644 --- a/create-issue/go.mod +++ b/create-issue/go.mod @@ -1,3 +1,5 @@ module github.com/half-ogre-games/hog-actions/create-issue -go 1.24 \ No newline at end of file +go 1.24.3 + +require github.com/half-ogre/go-kit v0.2.0 diff --git a/create-issue/go.sum b/create-issue/go.sum new file mode 100644 index 0000000..913e76d --- /dev/null +++ b/create-issue/go.sum @@ -0,0 +1,2 @@ +github.com/half-ogre/go-kit v0.2.0 h1:qRQKapcB0qVen28VPn1V9ucxD+csDwaVIev7YK1qAhU= +github.com/half-ogre/go-kit v0.2.0/go.mod h1:MSPRSJ1vN0ljh/UvDYmSIvLBONyL5nIPMHu+QtJ/ra8= diff --git a/find-issue/go.mod b/find-issue/go.mod index a5ff9db..d4db505 100644 --- a/find-issue/go.mod +++ b/find-issue/go.mod @@ -1,3 +1,5 @@ module github.com/half-ogre-games/hog-actions/find-issue -go 1.24 \ No newline at end of file +go 1.24.3 + +require github.com/half-ogre/go-kit v0.2.0 diff --git a/find-issue/go.sum b/find-issue/go.sum new file mode 100644 index 0000000..913e76d --- /dev/null +++ b/find-issue/go.sum @@ -0,0 +1,2 @@ +github.com/half-ogre/go-kit v0.2.0 h1:qRQKapcB0qVen28VPn1V9ucxD+csDwaVIev7YK1qAhU= +github.com/half-ogre/go-kit v0.2.0/go.mod h1:MSPRSJ1vN0ljh/UvDYmSIvLBONyL5nIPMHu+QtJ/ra8= diff --git a/get-latest-semver-tag/go.mod b/get-latest-semver-tag/go.mod index ee91494..55918ca 100644 --- a/get-latest-semver-tag/go.mod +++ b/get-latest-semver-tag/go.mod @@ -1,3 +1,5 @@ module github.com/half-ogre-games/hog-actions/get-latest-semver-tag -go 1.24 \ No newline at end of file +go 1.24.3 + +require github.com/half-ogre/go-kit v0.2.0 diff --git a/get-latest-semver-tag/go.sum b/get-latest-semver-tag/go.sum new file mode 100644 index 0000000..913e76d --- /dev/null +++ b/get-latest-semver-tag/go.sum @@ -0,0 +1,2 @@ +github.com/half-ogre/go-kit v0.2.0 h1:qRQKapcB0qVen28VPn1V9ucxD+csDwaVIev7YK1qAhU= +github.com/half-ogre/go-kit v0.2.0/go.mod h1:MSPRSJ1vN0ljh/UvDYmSIvLBONyL5nIPMHu+QtJ/ra8= diff --git a/get-next-semver/go.mod b/get-next-semver/go.mod index 3b51ee1..66ff295 100644 --- a/get-next-semver/go.mod +++ b/get-next-semver/go.mod @@ -1,3 +1,5 @@ module github.com/half-ogre-games/hog-actions/get-next-semver -go 1.24 \ No newline at end of file +go 1.24.3 + +require github.com/half-ogre/go-kit v0.2.0 diff --git a/get-next-semver/go.sum b/get-next-semver/go.sum new file mode 100644 index 0000000..913e76d --- /dev/null +++ b/get-next-semver/go.sum @@ -0,0 +1,2 @@ +github.com/half-ogre/go-kit v0.2.0 h1:qRQKapcB0qVen28VPn1V9ucxD+csDwaVIev7YK1qAhU= +github.com/half-ogre/go-kit v0.2.0/go.mod h1:MSPRSJ1vN0ljh/UvDYmSIvLBONyL5nIPMHu+QtJ/ra8= diff --git a/go.mod b/go.mod deleted file mode 100644 index 262f15c..0000000 --- a/go.mod +++ /dev/null @@ -1,3 +0,0 @@ -module github.com/half-ogre-games/hog-actions - -go 1.24 \ No newline at end of file diff --git a/go.work b/go.work index 5becf7f..246dacd 100644 --- a/go.work +++ b/go.work @@ -1,13 +1,12 @@ -go 1.24 +go 1.24.3 use ( - ./internal/go-kit - ./internal/semveractions - ./create-issue - ./find-issue ./close-issue ./comment-issue + ./create-issue + ./find-issue ./get-latest-semver-tag ./get-next-semver + ./internal/semveractions ./tag-and-create-semver-release -) \ No newline at end of file +) diff --git a/internal/go-kit/actionskit/actionskit.go b/internal/go-kit/actionskit/actionskit.go deleted file mode 100644 index 2ca55f0..0000000 --- a/internal/go-kit/actionskit/actionskit.go +++ /dev/null @@ -1,83 +0,0 @@ -package actionskit - -import ( - "fmt" - "os" - "strings" -) - -// GetInput retrieves the value of an input by name from the environment. -// GitHub Actions sets input values as environment variables with the prefix INPUT_ -// and converts the input name to uppercase with dashes replaced by underscores. -// -// For example, an input named "github-token" would be available as environment -// variable "INPUT_GITHUB_TOKEN". -// -// Returns the input value or an empty string if the input is not set. -func GetInput(name string) string { - // Convert input name to environment variable format - envName := "INPUT_" + strings.ToUpper(strings.ReplaceAll(name, "-", "_")) - return os.Getenv(envName) -} - -// GetInputRequired retrieves the value of a required input by name from the environment. -// If the input is not set or is empty, it returns an error. -func GetInputRequired(name string) (string, error) { - value := GetInput(name) - if value == "" { - return "", fmt.Errorf("input required and not supplied: %s", name) - } - return value, nil -} - -// SetOutput sets an output parameter for the action. -// GitHub Actions reads outputs from the GITHUB_OUTPUT environment file. -func SetOutput(name, value string) error { - outputFile := os.Getenv("GITHUB_OUTPUT") - if outputFile == "" { - // For local testing, output to stdout - fmt.Printf("::set-output name=%s::%s\n", name, value) - return nil - } - - // Write to GitHub Actions output file - f, err := os.OpenFile(outputFile, os.O_APPEND|os.O_WRONLY, 0644) - if err != nil { - return fmt.Errorf("error opening output file: %v", err) - } - defer f.Close() - - _, err = fmt.Fprintf(f, "%s=%s\n", name, value) - if err != nil { - return fmt.Errorf("error writing to output file: %v", err) - } - - return nil -} - -// IsDebug returns true if the runner debug mode is enabled. -func IsDebug() bool { - return os.Getenv("RUNNER_DEBUG") == "1" -} - -// Info writes an info message to the log. -func Info(message string) { - fmt.Println(message) -} - -// Debug writes a debug message to the log if debug mode is enabled. -func Debug(message string) { - if IsDebug() { - fmt.Printf("::debug::%s\n", message) - } -} - -// Warning writes a warning message to the log. -func Warning(message string) { - fmt.Printf("::warning::%s\n", message) -} - -// Error writes an error message to the log. -func Error(message string) { - fmt.Fprintf(os.Stderr, "::error::%s\n", message) -} \ No newline at end of file diff --git a/internal/go-kit/actionskit/actionskit_test.go b/internal/go-kit/actionskit/actionskit_test.go deleted file mode 100644 index 6174558..0000000 --- a/internal/go-kit/actionskit/actionskit_test.go +++ /dev/null @@ -1,368 +0,0 @@ -package actionskit - -import ( - "os" - "path/filepath" - "strings" - "testing" -) - -func TestGetInput(t *testing.T) { - tests := []struct { - name string - inputName string - envValue string - expected string - }{ - { - name: "simple input name", - inputName: "token", - envValue: "test-token-value", - expected: "test-token-value", - }, - { - name: "input name with dashes", - inputName: "github-token", - envValue: "ghp_test123", - expected: "ghp_test123", - }, - { - name: "input name with multiple dashes", - inputName: "my-long-input-name", - envValue: "some-value", - expected: "some-value", - }, - { - name: "empty input value", - inputName: "empty-input", - envValue: "", - expected: "", - }, - { - name: "input not set", - inputName: "nonexistent-input", - envValue: "", // Will not be set - expected: "", - }, - { - name: "input with special characters", - inputName: "special-chars", - envValue: "value with spaces & symbols!", - expected: "value with spaces & symbols!", - }, - } - - for _, tt := range tests { - t.Run(tt.name, func(t *testing.T) { - // Set up environment variable - envName := "INPUT_" + strings.ToUpper(strings.ReplaceAll(tt.inputName, "-", "_")) - if tt.name != "input not set" { - os.Setenv(envName, tt.envValue) - defer os.Unsetenv(envName) - } - - // Test GetInput - result := GetInput(tt.inputName) - if result != tt.expected { - t.Errorf("GetInput(%q) = %q, want %q", tt.inputName, result, tt.expected) - } - }) - } -} - -func TestGetInputRequired(t *testing.T) { - tests := []struct { - name string - inputName string - envValue string - shouldError bool - expected string - }{ - { - name: "valid required input", - inputName: "required-token", - envValue: "valid-token", - shouldError: false, - expected: "valid-token", - }, - { - name: "empty required input", - inputName: "empty-required", - envValue: "", - shouldError: true, - expected: "", - }, - { - name: "missing required input", - inputName: "missing-required", - envValue: "", // Will not be set - shouldError: true, - expected: "", - }, - } - - for _, tt := range tests { - t.Run(tt.name, func(t *testing.T) { - // Set up environment variable - envName := "INPUT_" + strings.ToUpper(strings.ReplaceAll(tt.inputName, "-", "_")) - if tt.name != "missing required input" { - os.Setenv(envName, tt.envValue) - defer os.Unsetenv(envName) - } - - // Test GetInputRequired - result, err := GetInputRequired(tt.inputName) - - // Check error expectation - if tt.shouldError && err == nil { - t.Error("Expected error but got none") - } - if !tt.shouldError && err != nil { - t.Errorf("Unexpected error: %v", err) - } - - // Check result - if result != tt.expected { - t.Errorf("GetInputRequired(%q) = %q, want %q", tt.inputName, result, tt.expected) - } - - // Check error message format - if tt.shouldError && err != nil { - expectedErrorMsg := "input required and not supplied: " + tt.inputName - if err.Error() != expectedErrorMsg { - t.Errorf("Error message = %q, want %q", err.Error(), expectedErrorMsg) - } - } - }) - } -} - -func TestSetOutput(t *testing.T) { - tests := []struct { - name string - outputName string - outputValue string - useOutputFile bool - expectedInFile string - }{ - { - name: "simple output", - outputName: "result", - outputValue: "success", - useOutputFile: true, - expectedInFile: "result=success\n", - }, - { - name: "output with spaces", - outputName: "message", - outputValue: "hello world", - useOutputFile: true, - expectedInFile: "message=hello world\n", - }, - { - name: "output with special characters", - outputName: "data", - outputValue: "value=with&special!chars", - useOutputFile: true, - expectedInFile: "data=value=with&special!chars\n", - }, - { - name: "empty output value", - outputName: "empty", - outputValue: "", - useOutputFile: true, - expectedInFile: "empty=\n", - }, - { - name: "no output file set", - outputName: "test", - outputValue: "value", - useOutputFile: false, - expectedInFile: "", // No file to check - }, - } - - for _, tt := range tests { - t.Run(tt.name, func(t *testing.T) { - if tt.useOutputFile { - // Create temporary file for GitHub Actions output - tempDir := t.TempDir() - outputFile := filepath.Join(tempDir, "output") - - // Create the file with proper permissions - file, err := os.OpenFile(outputFile, os.O_CREATE|os.O_WRONLY, 0644) - if err != nil { - t.Fatalf("Failed to create output file: %v", err) - } - file.Close() - - os.Setenv("GITHUB_OUTPUT", outputFile) - defer os.Unsetenv("GITHUB_OUTPUT") - - // Test SetOutput - err = SetOutput(tt.outputName, tt.outputValue) - if err != nil { - t.Errorf("SetOutput(%q, %q) returned error: %v", tt.outputName, tt.outputValue, err) - } - - // Verify file contents - content, err := os.ReadFile(outputFile) - if err != nil { - t.Fatalf("Failed to read output file: %v", err) - } - - if string(content) != tt.expectedInFile { - t.Errorf("Output file content = %q, want %q", string(content), tt.expectedInFile) - } - } else { - // Test without GITHUB_OUTPUT set (should not error) - os.Unsetenv("GITHUB_OUTPUT") - - err := SetOutput(tt.outputName, tt.outputValue) - if err != nil { - t.Errorf("SetOutput(%q, %q) returned error: %v", tt.outputName, tt.outputValue, err) - } - } - }) - } -} - -func TestSetOutputAppend(t *testing.T) { - // Test that multiple SetOutput calls append to the file - tempDir := t.TempDir() - outputFile := filepath.Join(tempDir, "output") - - // Create the file - file, err := os.OpenFile(outputFile, os.O_CREATE|os.O_WRONLY, 0644) - if err != nil { - t.Fatalf("Failed to create output file: %v", err) - } - file.Close() - - os.Setenv("GITHUB_OUTPUT", outputFile) - defer os.Unsetenv("GITHUB_OUTPUT") - - // Make multiple SetOutput calls - err = SetOutput("first", "value1") - if err != nil { - t.Errorf("First SetOutput failed: %v", err) - } - - err = SetOutput("second", "value2") - if err != nil { - t.Errorf("Second SetOutput failed: %v", err) - } - - // Verify both outputs are in the file - content, err := os.ReadFile(outputFile) - if err != nil { - t.Fatalf("Failed to read output file: %v", err) - } - - expected := "first=value1\nsecond=value2\n" - if string(content) != expected { - t.Errorf("Output file content = %q, want %q", string(content), expected) - } -} - -func TestIsDebug(t *testing.T) { - tests := []struct { - name string - envValue string - expected bool - }{ - { - name: "debug enabled", - envValue: "1", - expected: true, - }, - { - name: "debug disabled with 0", - envValue: "0", - expected: false, - }, - { - name: "debug disabled with false", - envValue: "false", - expected: false, - }, - { - name: "debug disabled when not set", - envValue: "", // Will not be set - expected: false, - }, - { - name: "debug disabled with other value", - envValue: "true", - expected: false, - }, - } - - for _, tt := range tests { - t.Run(tt.name, func(t *testing.T) { - if tt.name != "debug disabled when not set" { - os.Setenv("RUNNER_DEBUG", tt.envValue) - defer os.Unsetenv("RUNNER_DEBUG") - } else { - os.Unsetenv("RUNNER_DEBUG") - } - - result := IsDebug() - if result != tt.expected { - t.Errorf("IsDebug() = %v, want %v", result, tt.expected) - } - }) - } -} - -// Note: Testing Info, Debug, Warning, and Error functions would require -// capturing stdout/stderr, which is more complex. In a real-world scenario, -// you might want to make these functions accept io.Writer parameters for easier testing. -// For now, we'll test that they don't panic. - -func TestLoggingFunctions(t *testing.T) { - // Test that logging functions don't panic - t.Run("Info doesn't panic", func(t *testing.T) { - defer func() { - if r := recover(); r != nil { - t.Errorf("Info() panicked: %v", r) - } - }() - Info("test info message") - }) - - t.Run("Warning doesn't panic", func(t *testing.T) { - defer func() { - if r := recover(); r != nil { - t.Errorf("Warning() panicked: %v", r) - } - }() - Warning("test warning message") - }) - - t.Run("Error doesn't panic", func(t *testing.T) { - defer func() { - if r := recover(); r != nil { - t.Errorf("Error() panicked: %v", r) - } - }() - Error("test error message") - }) - - t.Run("Debug doesn't panic", func(t *testing.T) { - defer func() { - if r := recover(); r != nil { - t.Errorf("Debug() panicked: %v", r) - } - }() - - // Test with debug disabled - os.Unsetenv("RUNNER_DEBUG") - Debug("test debug message when disabled") - - // Test with debug enabled - os.Setenv("RUNNER_DEBUG", "1") - Debug("test debug message when enabled") - os.Unsetenv("RUNNER_DEBUG") - }) -} \ No newline at end of file diff --git a/internal/go-kit/go.mod b/internal/go-kit/go.mod deleted file mode 100644 index dca2772..0000000 --- a/internal/go-kit/go.mod +++ /dev/null @@ -1,3 +0,0 @@ -module github.com/half-ogre/go-kit - -go 1.24 \ No newline at end of file diff --git a/internal/go-kit/versionkit/versionkit.go b/internal/go-kit/versionkit/versionkit.go deleted file mode 100644 index da7f03d..0000000 --- a/internal/go-kit/versionkit/versionkit.go +++ /dev/null @@ -1,204 +0,0 @@ -package versionkit - -import ( - "errors" - "fmt" - "strconv" - "strings" -) - -type SemanticVersion struct { - MajorVersion uint - MinorVersion uint - PatchVersion uint // Fixed typo: was PathVersion - PreReleaseVersion string - BuildMetadata string -} - -func ParseSemanticVersion(v string) (*SemanticVersion, error) { - if len(v) == 0 { - return nil, errors.New("value is empty") - } - - // First handle build metadata (everything after +) - buildMetadataRaw := "" - if strings.Contains(v, "+") { - buildParts := strings.Split(v, "+") - if len(buildParts) > 2 { - return nil, fmt.Errorf("value %s has more than one + sign", v) - } - buildMetadataRaw = buildParts[1] - v = buildParts[0] // Remove build metadata for further processing - } - - // Then handle pre-release (everything after - but before +) - preReleaseVersionRaw := "" - if strings.Contains(v, "-") { - preParts := strings.SplitN(v, "-", 2) - preReleaseVersionRaw = preParts[1] - v = preParts[0] // Remove pre-release for further processing - } - - // Now split the core version (should be exactly 3 parts) - parts := strings.Split(v, ".") - if len(parts) != 3 { - return nil, fmt.Errorf("value %s did not contain major, minor, and patch versions", v) - } - - majorVersionRaw := parts[0] - minorVersionRaw := parts[1] - patchVersionRaw := parts[2] - - sv := &SemanticVersion{} - - // TODO: handle leading 0 in version numbers - - majorVersion, err := strconv.ParseUint(majorVersionRaw, 10, 32) - if err == nil { - sv.MajorVersion = uint(majorVersion) - } else { - return nil, fmt.Errorf("value %s major version is not numeric", v) - } - - minorVersion, err := strconv.ParseUint(minorVersionRaw, 10, 32) - if err == nil { - sv.MinorVersion = uint(minorVersion) - } else { - return nil, fmt.Errorf("value %s minor version is not numeric", v) - } - - patchVersion, err := strconv.ParseUint(patchVersionRaw, 10, 32) - if err == nil { - sv.PatchVersion = uint(patchVersion) - } else { - return nil, fmt.Errorf("value %s patch version is not numeric", v) - } - - // TODO: Validate pre-release and build metadata characters - sv.PreReleaseVersion = preReleaseVersionRaw - sv.BuildMetadata = buildMetadataRaw - - return sv, nil -} - -func (sv SemanticVersion) String() string { - core := fmt.Sprintf("%d.%d.%d", sv.MajorVersion, sv.MinorVersion, sv.PatchVersion) - - if sv.PreReleaseVersion != "" { - core = fmt.Sprintf("%s-%s", core, sv.PreReleaseVersion) - } - - if sv.BuildMetadata != "" { - core = fmt.Sprintf("%s+%s", core, sv.BuildMetadata) - } - - return core -} - -// Compare returns -1 if sv < other, 0 if sv == other, 1 if sv > other -// according to semantic versioning precedence rules -func (sv SemanticVersion) Compare(other SemanticVersion) int { - // Compare major version - if sv.MajorVersion < other.MajorVersion { - return -1 - } - if sv.MajorVersion > other.MajorVersion { - return 1 - } - - // Compare minor version - if sv.MinorVersion < other.MinorVersion { - return -1 - } - if sv.MinorVersion > other.MinorVersion { - return 1 - } - - // Compare patch version - if sv.PatchVersion < other.PatchVersion { - return -1 - } - if sv.PatchVersion > other.PatchVersion { - return 1 - } - - // Compare pre-release versions - // A pre-release version has lower precedence than a normal version - if sv.PreReleaseVersion == "" && other.PreReleaseVersion != "" { - return 1 - } - if sv.PreReleaseVersion != "" && other.PreReleaseVersion == "" { - return -1 - } - if sv.PreReleaseVersion != "" && other.PreReleaseVersion != "" { - return comparePrerelease(sv.PreReleaseVersion, other.PreReleaseVersion) - } - - // Build metadata does not affect version precedence - return 0 -} - -// comparePrerelease compares two pre-release version strings -func comparePrerelease(a, b string) int { - aParts := strings.Split(a, ".") - bParts := strings.Split(b, ".") - - maxLen := len(aParts) - if len(bParts) > maxLen { - maxLen = len(bParts) - } - - for i := 0; i < maxLen; i++ { - var aPart, bPart string - if i < len(aParts) { - aPart = aParts[i] - } - if i < len(bParts) { - bPart = bParts[i] - } - - // If one side is missing, it has lower precedence - if aPart == "" && bPart != "" { - return -1 - } - if aPart != "" && bPart == "" { - return 1 - } - - // Try to parse as numbers - aNum, aIsNum := parseUintOrZero(aPart) - bNum, bIsNum := parseUintOrZero(bPart) - - if aIsNum && bIsNum { - if aNum < bNum { - return -1 - } - if aNum > bNum { - return 1 - } - } else if aIsNum && !bIsNum { - // Numeric identifiers always have lower precedence than non-numeric - return -1 - } else if !aIsNum && bIsNum { - // Non-numeric identifiers always have higher precedence than numeric - return 1 - } else { - // Both are non-numeric, compare lexically - if aPart < bPart { - return -1 - } - if aPart > bPart { - return 1 - } - } - } - - return 0 -} - -func parseUintOrZero(s string) (uint64, bool) { - if num, err := strconv.ParseUint(s, 10, 64); err == nil { - return num, true - } - return 0, false -} \ No newline at end of file diff --git a/internal/go-kit/versionkit/versionkit_test.go b/internal/go-kit/versionkit/versionkit_test.go deleted file mode 100644 index 67f6c29..0000000 --- a/internal/go-kit/versionkit/versionkit_test.go +++ /dev/null @@ -1,240 +0,0 @@ -package versionkit - -import ( - "testing" -) - -func TestParseSemanticVersion(t *testing.T) { - tests := []struct { - name string - input string - expected *SemanticVersion - expectError bool - }{ - { - name: "basic version", - input: "1.2.3", - expected: &SemanticVersion{ - MajorVersion: 1, - MinorVersion: 2, - PatchVersion: 3, - }, - }, - { - name: "version with prerelease", - input: "1.2.3-alpha.1", - expected: &SemanticVersion{ - MajorVersion: 1, - MinorVersion: 2, - PatchVersion: 3, - PreReleaseVersion: "alpha.1", - }, - }, - { - name: "version with build metadata", - input: "1.2.3+build.456", - expected: &SemanticVersion{ - MajorVersion: 1, - MinorVersion: 2, - PatchVersion: 3, - BuildMetadata: "build.456", - }, - }, - { - name: "version with prerelease and build", - input: "1.2.3-beta.2+build.789", - expected: &SemanticVersion{ - MajorVersion: 1, - MinorVersion: 2, - PatchVersion: 3, - PreReleaseVersion: "beta.2", - BuildMetadata: "build.789", - }, - }, - { - name: "zero version", - input: "0.0.0", - expected: &SemanticVersion{ - MajorVersion: 0, - MinorVersion: 0, - PatchVersion: 0, - }, - }, - { - name: "empty string", - input: "", - expectError: true, - }, - { - name: "invalid format - too few parts", - input: "1.2", - expectError: true, - }, - { - name: "invalid format - too many parts", - input: "1.2.3.4", - expectError: true, - }, - { - name: "non-numeric major", - input: "a.2.3", - expectError: true, - }, - { - name: "non-numeric minor", - input: "1.b.3", - expectError: true, - }, - { - name: "non-numeric patch", - input: "1.2.c", - expectError: true, - }, - { - name: "multiple + signs", - input: "1.2.3+build1+build2", - expectError: true, - }, - } - - for _, tt := range tests { - t.Run(tt.name, func(t *testing.T) { - result, err := ParseSemanticVersion(tt.input) - - if tt.expectError { - if err == nil { - t.Errorf("Expected error but got none") - } - return - } - - if err != nil { - t.Errorf("Unexpected error: %v", err) - return - } - - if result.MajorVersion != tt.expected.MajorVersion { - t.Errorf("MajorVersion = %d, want %d", result.MajorVersion, tt.expected.MajorVersion) - } - if result.MinorVersion != tt.expected.MinorVersion { - t.Errorf("MinorVersion = %d, want %d", result.MinorVersion, tt.expected.MinorVersion) - } - if result.PatchVersion != tt.expected.PatchVersion { - t.Errorf("PatchVersion = %d, want %d", result.PatchVersion, tt.expected.PatchVersion) - } - if result.PreReleaseVersion != tt.expected.PreReleaseVersion { - t.Errorf("PreReleaseVersion = %q, want %q", result.PreReleaseVersion, tt.expected.PreReleaseVersion) - } - if result.BuildMetadata != tt.expected.BuildMetadata { - t.Errorf("BuildMetadata = %q, want %q", result.BuildMetadata, tt.expected.BuildMetadata) - } - }) - } -} - -func TestSemanticVersionString(t *testing.T) { - tests := []struct { - name string - version SemanticVersion - expected string - }{ - { - name: "basic version", - version: SemanticVersion{ - MajorVersion: 1, - MinorVersion: 2, - PatchVersion: 3, - }, - expected: "1.2.3", - }, - { - name: "version with prerelease", - version: SemanticVersion{ - MajorVersion: 1, - MinorVersion: 2, - PatchVersion: 3, - PreReleaseVersion: "alpha.1", - }, - expected: "1.2.3-alpha.1", - }, - { - name: "version with build metadata", - version: SemanticVersion{ - MajorVersion: 1, - MinorVersion: 2, - PatchVersion: 3, - BuildMetadata: "build.456", - }, - expected: "1.2.3+build.456", - }, - { - name: "version with prerelease and build", - version: SemanticVersion{ - MajorVersion: 1, - MinorVersion: 2, - PatchVersion: 3, - PreReleaseVersion: "beta.2", - BuildMetadata: "build.789", - }, - expected: "1.2.3-beta.2+build.789", - }, - } - - for _, tt := range tests { - t.Run(tt.name, func(t *testing.T) { - result := tt.version.String() - if result != tt.expected { - t.Errorf("String() = %q, want %q", result, tt.expected) - } - }) - } -} - -func TestSemanticVersionCompare(t *testing.T) { - tests := []struct { - name string - a string - b string - expected int - }{ - // Basic version comparisons - {"1.0.0 < 2.0.0", "1.0.0", "2.0.0", -1}, - {"2.0.0 > 1.0.0", "2.0.0", "1.0.0", 1}, - {"1.0.0 == 1.0.0", "1.0.0", "1.0.0", 0}, - {"1.1.0 > 1.0.0", "1.1.0", "1.0.0", 1}, - {"1.0.1 > 1.0.0", "1.0.1", "1.0.0", 1}, - - // Pre-release comparisons - {"1.0.0-alpha < 1.0.0", "1.0.0-alpha", "1.0.0", -1}, - {"1.0.0 > 1.0.0-alpha", "1.0.0", "1.0.0-alpha", 1}, - {"1.0.0-alpha < 1.0.0-beta", "1.0.0-alpha", "1.0.0-beta", -1}, - {"1.0.0-beta > 1.0.0-alpha", "1.0.0-beta", "1.0.0-alpha", 1}, - {"1.0.0-alpha.1 < 1.0.0-alpha.2", "1.0.0-alpha.1", "1.0.0-alpha.2", -1}, - {"1.0.0-alpha.1 < 1.0.0-alpha.beta", "1.0.0-alpha.1", "1.0.0-alpha.beta", -1}, - {"1.0.0-alpha.beta > 1.0.0-alpha.1", "1.0.0-alpha.beta", "1.0.0-alpha.1", 1}, - {"1.0.0-rc.1 > 1.0.0-beta.11", "1.0.0-rc.1", "1.0.0-beta.11", 1}, - - // Build metadata should not affect comparison - {"1.0.0+build1 == 1.0.0+build2", "1.0.0+build1", "1.0.0+build2", 0}, - {"1.0.0+build == 1.0.0", "1.0.0+build", "1.0.0", 0}, - } - - for _, tt := range tests { - t.Run(tt.name, func(t *testing.T) { - aVer, err := ParseSemanticVersion(tt.a) - if err != nil { - t.Fatalf("Failed to parse version A: %v", err) - } - - bVer, err := ParseSemanticVersion(tt.b) - if err != nil { - t.Fatalf("Failed to parse version B: %v", err) - } - - result := aVer.Compare(*bVer) - if result != tt.expected { - t.Errorf("Compare(%s, %s) = %d, want %d", tt.a, tt.b, result, tt.expected) - } - }) - } -} \ No newline at end of file diff --git a/internal/semveractions/go.mod b/internal/semveractions/go.mod index 91d3812..fdeb0ef 100644 --- a/internal/semveractions/go.mod +++ b/internal/semveractions/go.mod @@ -1,3 +1,5 @@ module github.com/half-ogre-games/hog-actions/internal/semveractions -go 1.24 \ No newline at end of file +go 1.24.3 + +require github.com/half-ogre/go-kit v0.2.0 diff --git a/internal/semveractions/go.sum b/internal/semveractions/go.sum new file mode 100644 index 0000000..913e76d --- /dev/null +++ b/internal/semveractions/go.sum @@ -0,0 +1,2 @@ +github.com/half-ogre/go-kit v0.2.0 h1:qRQKapcB0qVen28VPn1V9ucxD+csDwaVIev7YK1qAhU= +github.com/half-ogre/go-kit v0.2.0/go.mod h1:MSPRSJ1vN0ljh/UvDYmSIvLBONyL5nIPMHu+QtJ/ra8= diff --git a/tag-and-create-semver-release/go.mod b/tag-and-create-semver-release/go.mod index 54b88f6..d8f960c 100644 --- a/tag-and-create-semver-release/go.mod +++ b/tag-and-create-semver-release/go.mod @@ -1,3 +1,8 @@ module github.com/half-ogre-games/hog-actions/tag-and-create-semver-release -go 1.24 \ No newline at end of file +go 1.24.3 + +require ( + github.com/half-ogre-games/hog-actions/internal/semveractions v0.0.0-20250721173534-824962fd61a1 + github.com/half-ogre/go-kit v0.2.0 +) diff --git a/tag-and-create-semver-release/go.sum b/tag-and-create-semver-release/go.sum new file mode 100644 index 0000000..60ec3f9 --- /dev/null +++ b/tag-and-create-semver-release/go.sum @@ -0,0 +1,4 @@ +github.com/half-ogre-games/hog-actions/internal/semveractions v0.0.0-20250721173534-824962fd61a1 h1:p5niZVON236lGmUNS7EO28S2oQuSa90u6ZgDGGSsygM= +github.com/half-ogre-games/hog-actions/internal/semveractions v0.0.0-20250721173534-824962fd61a1/go.mod h1:CSmBiRB8454ugIabbsCV/TWT2vwSSZjnKwCytlrLm2M= +github.com/half-ogre/go-kit v0.2.0 h1:qRQKapcB0qVen28VPn1V9ucxD+csDwaVIev7YK1qAhU= +github.com/half-ogre/go-kit v0.2.0/go.mod h1:MSPRSJ1vN0ljh/UvDYmSIvLBONyL5nIPMHu+QtJ/ra8=