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
11 changes: 5 additions & 6 deletions .codacy/codacy.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -3,14 +3,13 @@ runtimes:
- java@17.0.10
- node@22.2.0
- python@3.11.11
- dart@3.7.2
- flutter@3.7.2
tools:
- codacy-enigma-cli@0.0.1-main.8.49310c3
- dartanalyzer@3.7.2
- eslint@8.57.0
- eslint@9.38.0
- lizard@1.17.31
- pmd@6.55.0
- pylint@3.3.7
- revive@1.11.0
- pylint@3.3.9
- revive@1.12.0
- semgrep@1.78.0
- trivy@0.66.0
- dartanalyzer@3.7.2
3 changes: 2 additions & 1 deletion config/runtimes-installer.go
Original file line number Diff line number Diff line change
Expand Up @@ -128,10 +128,11 @@ func downloadAndExtractRuntime(runtimeInfo *plugins.RuntimeInfo) error {

if strings.HasSuffix(fileName, ".zip") {
err = utils.ExtractZip(file.Name(), runtimesDir)
} else if strings.HasSuffix(fileName, ".tar.xz") || strings.HasSuffix(fileName, ".txz") {
err = utils.ExtractTarXz(file, runtimesDir)
} else {
err = utils.ExtractTarGz(file, runtimesDir)
}

if err != nil {
return fmt.Errorf("failed to extract runtime: %w", err)
}
Expand Down
4 changes: 4 additions & 0 deletions config/tools-installer_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,10 @@ func TestAddTools(t *testing.T) {
Name: "eslint",
Version: "8.38.0",
},
{
Name: "dartanalyzer",
Version: "3.7.2",
},
}

// Add tools to the config
Expand Down
8 changes: 7 additions & 1 deletion plugins/runtime-utils.go
Original file line number Diff line number Diff line change
Expand Up @@ -46,8 +46,14 @@ func processRuntime(config RuntimeConfig, runtimesDir string) (*RuntimeInfo, err
// Get the filename using the template
fileName := GetFileName(pluginConfig.Download.FileNameTemplate, config.Version, mappedArch, runtime.GOOS)

customURLConfig, hasCustomURL := getCustomDownloadURL(pluginConfig.Download.CustomURLConfig, runtime.GOOS)
// Get the download URL using the template
downloadURL := GetDownloadURL(pluginConfig.Download.URLTemplate, fileName, config.Version, mappedArch, mappedOS, extension, pluginConfig.Download.ReleaseVersion)
downloadURL := ""
if hasCustomURL {
downloadURL = GetDownloadURL(customURLConfig, fileName, config.Version, mappedArch, mappedOS, extension, pluginConfig.Download.ReleaseVersion)
} else {
downloadURL = GetDownloadURL(pluginConfig.Download.URLTemplate, fileName, config.Version, mappedArch, mappedOS, extension, pluginConfig.Download.ReleaseVersion)
}

// For Python, we want to use a simpler directory structure
var installDir string
Expand Down
85 changes: 81 additions & 4 deletions plugins/runtime-utils_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,10 @@ func TestProcessRuntimes(t *testing.T) {
Name: "node",
Version: "18.17.1",
},
{
Name: "flutter",
Version: "3.35.7",
},
}

// Define a test runtime directory
Expand All @@ -27,9 +31,15 @@ func TestProcessRuntimes(t *testing.T) {

// Assert we have the expected runtime in the results
assert.Contains(t, runtimeInfos, "node")
assert.Contains(t, runtimeInfos, "flutter")

// Get the node runtime info
nodeInfo := runtimeInfos["node"]
flutterInfo := runtimeInfos["flutter"]

// Basic assertions for flutter
assert.Equal(t, "flutter", flutterInfo.Name)
assert.Equal(t, "3.35.7", flutterInfo.Version)
Comment on lines +40 to +42
Copy link

Copilot AI Jan 14, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The test coverage for Flutter is minimal compared to the Node test. Consider adding assertions to verify the download URL is correctly formatted, the extension is properly set based on the OS (tar.xz for Linux, zip for others), and the install directory is correct. This would help ensure the Flutter-specific configuration changes (linux extension support and removed architecture from URL) work as expected.

Copilot uses AI. Check for mistakes.

// Assert the basic runtime info is correct
assert.Equal(t, "node", nodeInfo.Name)
Expand All @@ -56,6 +66,73 @@ func TestProcessRuntimes(t *testing.T) {
expectedExtension = "zip"
}

flutterExpectedExtension := "zip"
if runtime.GOOS == "linux" {
flutterExpectedExtension = "tar.xz"
}

// Assert flutter extension
assert.Equal(t, flutterExpectedExtension, flutterInfo.Extension)

// Additional flutter assertions
// Assert the filename is correctly set to a constant "flutter"
assert.Equal(t, "flutter", flutterInfo.FileName)

// Assert the install directory is correct for flutter
assert.Equal(t, runtimesDir+"/"+flutterInfo.FileName, flutterInfo.InstallDir)

// Compute expected OS mapping for flutter download URL
var expectedFlutterOS string
switch runtime.GOOS {
case "darwin":
expectedFlutterOS = "macos"
case "linux":
expectedFlutterOS = "linux"
case "windows":
expectedFlutterOS = "windows"
default:
expectedFlutterOS = runtime.GOOS
}

// Compute expected arch for flutter (only used on macOS/default template)
var expectedFlutterArch string
switch runtime.GOARCH {
case "386":
expectedFlutterArch = "ia32"
case "amd64":
expectedFlutterArch = "x64"
case "arm":
expectedFlutterArch = "arm"
case "arm64":
expectedFlutterArch = "arm64"
default:
expectedFlutterArch = runtime.GOARCH
}

// Build expected flutter download URL
var expectedFlutterURL string
if runtime.GOOS == "linux" {
expectedFlutterURL = "https://storage.googleapis.com/flutter_infra_release/releases/stable/linux/flutter_linux_" + flutterInfo.Version + "-stable." + flutterExpectedExtension
} else if runtime.GOOS == "windows" {
expectedFlutterURL = "https://storage.googleapis.com/flutter_infra_release/releases/stable/windows/flutter_windows_" + flutterInfo.Version + "-stable." + flutterExpectedExtension
} else {
// Default template includes arch and mapped OS (e.g., macos)
expectedFlutterURL = "https://storage.googleapis.com/flutter_infra_release/releases/stable/" + expectedFlutterOS + "/flutter_" + expectedFlutterOS + "_" + expectedFlutterArch + "_" + flutterInfo.Version + "-stable." + flutterExpectedExtension
}

assert.Equal(t, expectedFlutterURL, flutterInfo.DownloadURL)

// Assert flutter binaries map has expected entries
assert.NotNil(t, flutterInfo.Binaries)
assert.Greater(t, len(flutterInfo.Binaries), 0)

// Check if dart binary is present and correctly mapped
flutterDartBinary := flutterInfo.InstallDir + "/bin/dart"
if runtime.GOOS == "windows" {
flutterDartBinary += ".exe"
}
assert.Equal(t, flutterDartBinary, flutterInfo.Binaries["dart"])

// Assert the filename is correctly formatted
expectedFileName := "node-v18.17.1-" + runtime.GOOS + "-" + expectedArch
assert.Equal(t, expectedFileName, nodeInfo.FileName)
Expand All @@ -69,21 +146,21 @@ func TestProcessRuntimes(t *testing.T) {
// Assert the download URL is correctly formatted
expectedDownloadURL := "https://nodejs.org/dist/v18.17.1/" + expectedFileName + "." + expectedExtension
assert.Equal(t, expectedDownloadURL, nodeInfo.DownloadURL)

// Assert binary paths are correctly set
assert.NotNil(t, nodeInfo.Binaries)
assert.Greater(t, len(nodeInfo.Binaries), 0)

// Check if node and npm binaries are present
nodeBinary := nodeInfo.InstallDir + "/bin/node"
npmBinary := nodeInfo.InstallDir + "/bin/npm"

// Add .exe extension for Windows
if runtime.GOOS == "windows" {
nodeBinary += ".exe"
npmBinary += ".exe"
}

assert.Equal(t, nodeBinary, nodeInfo.Binaries["node"])
assert.Equal(t, npmBinary, nodeInfo.Binaries["npm"])
}
5 changes: 4 additions & 1 deletion plugins/runtimes/flutter/plugin.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -3,10 +3,13 @@ description: Dart Flutterruntime
default_version: "3.7.2"
download:
url_template: "https://storage.googleapis.com/flutter_infra_release/releases/stable/{{.OS}}/flutter_{{.OS}}_{{.Arch}}_{{.Version}}-stable.{{.Extension}}"
custom_url_config:
linux: "https://storage.googleapis.com/flutter_infra_release/releases/stable/linux/flutter_{{.OS}}_{{.Version}}-stable.{{.Extension}}"
Copy link

Copilot AI Jan 14, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The custom URL template for Linux still contains {{.OS}} placeholder which will be substituted with 'linux', resulting in 'flutter_linux_' in the URL. Based on the URL structure and the fact that tar.xz files don't include architecture, this should likely be just flutter_{{.Version}}-stable.{{.Extension}} without the OS placeholder.

Copilot uses AI. Check for mistakes.
windows: "https://storage.googleapis.com/flutter_infra_release/releases/stable/windows/flutter_{{.OS}}_{{.Version}}-stable.{{.Extension}}"
Copy link

Copilot AI Jan 14, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The custom URL template for Windows contains {{.OS}} placeholder which will be substituted with 'windows', resulting in 'flutter_windows_' in the URL. This is inconsistent with the original url_template which included architecture ({{.Arch}}). If this custom URL is intended to match the actual Flutter download URLs, verify whether Windows downloads should include the {{.Arch}} placeholder or just the OS.

Copilot uses AI. Check for mistakes.
file_name_template: "flutter"
extension:
default: "zip"
linux: "tar.xz"
default: "zip"
arch_mapping:
"386": "ia32"
"amd64": "x64"
Expand Down
33 changes: 33 additions & 0 deletions plugins/shared.go
Original file line number Diff line number Diff line change
Expand Up @@ -8,13 +8,22 @@

// ExtensionConfig defines the file extension based on OS
type ExtensionConfig struct {
Linux string `yaml:"linux"`
Windows string `yaml:"windows"`
Default string `yaml:"default"`
}

type CustomURLConfig struct {

Check notice on line 16 in plugins/shared.go

View check run for this annotation

Codacy Production / Codacy Static Code Analysis

plugins/shared.go#L16

exported type CustomURLConfig should have comment or be unexported

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Linux string `yaml:"linux"`
Windows string `yaml:"windows"`
MacOS string `yaml:"macos"`
Default string `yaml:"default"`
}

// DownloadConfig holds the download configuration from the plugin.yaml
type DownloadConfig struct {
URLTemplate string `yaml:"url_template"`
CustomURLConfig CustomURLConfig `yaml:"custom_url_config,omitempty"`
FileNameTemplate string `yaml:"file_name_template"`
Extension ExtensionConfig `yaml:"extension"`
ArchMapping map[string]string `yaml:"arch_mapping"`
Expand Down Expand Up @@ -80,9 +89,33 @@
if goos == "windows" {
return extension.Windows
}
if goos == "linux" && extension.Linux != "" {
return extension.Linux
}
return extension.Default
}

func getCustomDownloadURL(customURLConfig CustomURLConfig, goos string) (string, bool) {
switch goos {
case "linux":
if customURLConfig.Linux != "" {
return customURLConfig.Linux, true
}
case "windows":
if customURLConfig.Windows != "" {
return customURLConfig.Windows, true
}
case "darwin":
if customURLConfig.MacOS != "" {
return customURLConfig.MacOS, true
}
}
if customURLConfig.Default != "" {
return customURLConfig.Default, true
}
return "", false
}

// GetMajorVersion extracts the major version from a version string (e.g. "17.0.10" -> "17")
func GetMajorVersion(version string) string {
if idx := strings.Index(version, "."); idx != -1 {
Expand Down
10 changes: 9 additions & 1 deletion utils/extract.go
Original file line number Diff line number Diff line change
Expand Up @@ -14,8 +14,16 @@
)

func ExtractTarGz(archive *os.File, targetDir string) error {
return ExtractTar(archive, targetDir, archiver.Gz{})
}

func ExtractTarXz(archive *os.File, targetDir string) error {

Check notice on line 20 in utils/extract.go

View check run for this annotation

Codacy Production / Codacy Static Code Analysis

utils/extract.go#L20

exported function ExtractTarXz should have comment or be unexported

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

return ExtractTar(archive, targetDir, archiver.Xz{})
}

func ExtractTar(archive *os.File, targetDir string, compression archiver.Compression) error {

Check notice on line 24 in utils/extract.go

View check run for this annotation

Codacy Production / Codacy Static Code Analysis

utils/extract.go#L24

exported function ExtractTar should have comment or be unexported

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

format := archiver.CompressedArchive{
Compression: archiver.Gz{},
Compression: compression,
Archival: archiver.Tar{},
}

Expand Down