Skip to content

Commit

Permalink
fix: correct regex patterns in config.go
Browse files Browse the repository at this point in the history
test: Improve codecov
docs: add doc.go
  • Loading branch information
Nicconike committed Jul 6, 2024
1 parent f3e43a2 commit 28235f5
Show file tree
Hide file tree
Showing 6 changed files with 166 additions and 12 deletions.
1 change: 0 additions & 1 deletion .github/workflows/coverage.yml
Original file line number Diff line number Diff line change
Expand Up @@ -33,4 +33,3 @@ jobs:
flags: unittests
name: codecov-umbrella
fail_ci_if_error: true
verbose: true
2 changes: 2 additions & 0 deletions .github/workflows/release.yml
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,8 @@ name: Release
on:
push:
branches: master
pull_request:
branches: master

jobs:
release:
Expand Down
43 changes: 43 additions & 0 deletions doc.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,43 @@
/*
Package goautomate provides tools for automating Go version checks and downloads.
Do's:
1. Always check for errors returned by functions in this package.
2. Use GetLatestVersion() to fetch the most recent Go version information.
3. Specify the correct target OS and architecture when using DownloadGo().
4. Ensure you have necessary permissions to download and write files.
5. Define Go version in your project files using one of these formats:
- In go.mod: go 1.x
- In Dockerfile:
- - FROM golang:1.x.x
- - ENV GO_VERSION=1.x.x
- In other files:
- - go_version = "1.x.x"
- - GO_VERSION: 1.x.x
- - golang_version: "1.x.x"
6. Use the package to automate version checks in your CI/CD pipelines.
Don'ts:
1. Don't assume the latest version is always compatible with your project.
2. Avoid using this package to modify your system's Go installation directly.
3. Don't use this package in production environments without thorough testing.
4. Don't ignore version constraints specified in your go.mod file.
5. Avoid manually modifying files downloaded by this package.
6. Don't use non-standard formats for specifying Go versions in your project files.
Example usage:
latestVersion, err := goautomate.GetLatestVersion()
if err != nil {
log.Fatal(err)
}
err = goautomate.DownloadGo(latestVersion, "linux", "amd64")
if err != nil {
log.Fatal(err)
}
For more detailed information and advanced usage, refer to the README.md file.
*/
package goautomate
18 changes: 8 additions & 10 deletions pkg/config.go
Original file line number Diff line number Diff line change
Expand Up @@ -36,13 +36,11 @@ func ReadVersionFromFile(filePath string) (string, error) {
func ExtractGoVersion(content string) string {
// Common patterns for Go version
patterns := []string{
`(?i)go\s*version\s*[:=]?\s*["']?(\d+\.\d+(\.\d+)?)["']?`,
`(?i)go_version\s*[:=]?\s*["']?(\d+\.\d+(\.\d+)?)["']?`,
`(?i)golang_version\s*[:=]?\s*["']?(\d+\.\d+(\.\d+)?)["']?`,
`(?i)go(\d+\.\d+(\.\d+)?)`,
`(?i)FROM\s+golang:(\d+\.\d+(\.\d+)?)`,
`(?i)ARG\s+GO_VERSION=(\d+\.\d+(\.\d+)?)`,
`(?i)ENV\s+GO_VERSION=(\d+\.\d+(\.\d+)?)`,
`(?i)(?:go|golang|go_version|golang_version)(?:\s*version)?[:=]?\s*v?(\d+\.\d+(?:\.\d+)?)`,
`(?i)FROM\s+golang:(\d+\.\d+(?:\.\d+)?)`,
`(?i)ARG\s+GO_VERSION=(\d+\.\d+(?:\.\d+)?)`,
`(?i)ENV\s+GO_VERSION=(\d+\.\d+(?:\.\d+)?)`,
`(\d+\.\d+(?:\.\d+)?)`,
}

// Check for JSON format
Expand All @@ -67,9 +65,9 @@ func ExtractGoVersion(content string) string {
// Check for other formats using regex
for _, pattern := range patterns {
re := regexp.MustCompile(pattern)
matches := re.FindAllStringSubmatch(content, -1)
if len(matches) > 0 {
return matches[len(matches)-1][1]
matches := re.FindStringSubmatch(content)
if len(matches) > 1 {
return matches[1]
}
}

Expand Down
45 changes: 45 additions & 0 deletions tests/unit/checker_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -37,3 +37,48 @@ func TestGetLatestVersion(t *testing.T) {
t.Errorf("Expected version go1.17.1, got %s", version)
}
}

func TestGetLatestVersionHTTPError(t *testing.T) {
setTestVersionURL("http://invalid-url")
defer resetTestVersionURL()

_, err := pkg.GetLatestVersion()
if err == nil {
t.Error("Expected an error for invalid URL, got nil")
}
}

func TestGetLatestVersionReadError(t *testing.T) {
server := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
w.Header().Set("Content-Length", "1")
// Don't write anything to body, causing a read error
}))
defer server.Close()

setTestVersionURL(server.URL)
defer resetTestVersionURL()

_, err := pkg.GetLatestVersion()
if err == nil {
t.Error("Expected an error for read failure, got nil")
}
}

func TestGetLatestVersionMalformedResponse(t *testing.T) {
server := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
w.WriteHeader(http.StatusOK)
w.Write([]byte("malformed\nresponse\n"))
}))
defer server.Close()

setTestVersionURL(server.URL)
defer resetTestVersionURL()

version, err := pkg.GetLatestVersion()
if err != nil {
t.Fatalf("Expected no error, got %v", err)
}
if version != "malformed" {
t.Errorf("Expected version 'malformed', got %s", version)
}
}
69 changes: 68 additions & 1 deletion tests/unit/config_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,34 @@ func TestGetCurrentVersion(t *testing.T) {
}
})
}

// Test with valid file path
tmpfile, err := os.CreateTemp("", "version")
if err != nil {
t.Fatal(err)
}
defer os.Remove(tmpfile.Name())
if _, err := tmpfile.Write([]byte("go 1.17")); err != nil {
t.Fatal(err)
}
tmpfile.Close()

result, err := pkg.GetCurrentVersion(tmpfile.Name(), "")
if err != nil {
t.Errorf("GetCurrentVersion() error = %v, expectError false", err)
}
if result != "1.17" {
t.Errorf("GetCurrentVersion() = %v, want %v", result, "1.17")
}

// Test with invalid file path
result, err = pkg.GetCurrentVersion("/non/existent/path", "")
if err == nil {
t.Errorf("GetCurrentVersion() expected error for non-existent file")
}
if result != "" {
t.Errorf("GetCurrentVersion() = %v, want empty string", result)
}
}

func TestExtractGoVersion(t *testing.T) {
Expand All @@ -44,7 +72,6 @@ func TestExtractGoVersion(t *testing.T) {
{"go.mod", "go 1.17", "1.17"},
{"JSON", `{"go_version": "1.18.0"}`, "1.18.0"},
{"No version", "Some random content", ""},
// Add more test cases for different formats
}

for _, tt := range tests {
Expand All @@ -55,6 +82,30 @@ func TestExtractGoVersion(t *testing.T) {
}
})
}

additionalTests := []struct {
name string
content string
expected string
}{
{"Version with equals", "go_version = 1.17.1", "1.17.1"},
{"Golang version", "golang_version: 1.18.0", "1.18.0"},
{"Version without prefix", "1.19.0", "1.19.0"},
{"Dockerfile ARG", "ARG GO_VERSION=1.20.0", "1.20.0"},
{"Dockerfile ENV", "ENV GO_VERSION=1.21.0", "1.21.0"},
{"JSON with goVersion", `{"goVersion": "1.22.0"}`, "1.22.0"},
{"JSON with golangVersion", `{"golangVersion": "1.23.0"}`, "1.23.0"},
{"JSON with GO_VERSION", `{"GO_VERSION": "1.24.0"}`, "1.24.0"},
}

for _, tt := range additionalTests {
t.Run(tt.name, func(t *testing.T) {
result := pkg.ExtractGoVersion(tt.content)
if result != tt.expected {
t.Errorf("ExtractGoVersion() = %v, want %v", result, tt.expected)
}
})
}
}

func TestReadVersionFromFile(t *testing.T) {
Expand Down Expand Up @@ -87,4 +138,20 @@ func TestReadVersionFromFile(t *testing.T) {
if err == nil {
t.Error("Expected an error for non-existent file, got nil")
}

// Test file with no extractable version
noVersionFile, err := os.CreateTemp("", "noversion")
if err != nil {
t.Fatal(err)
}
defer os.Remove(noVersionFile.Name())
if _, err := noVersionFile.Write([]byte("No version here")); err != nil {
t.Fatal(err)
}
noVersionFile.Close()

_, err = pkg.ReadVersionFromFile(noVersionFile.Name())
if err == nil || err.Error() != "unable to extract Go version from file" {
t.Errorf("Expected 'unable to extract Go version from file' error, got %v", err)
}
}

0 comments on commit 28235f5

Please sign in to comment.