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
1 change: 1 addition & 0 deletions .cursor/rules/cursor.mdc
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@ alwaysApply: true
## Key Rules
- use full names like e.g. feature, instead of feat
- run go build after each code modification to see if app compiles
- remove dead unused code

## Code Style Guidelines
- **Imports**: Standard lib first, external packages second, internal last
Expand Down
23 changes: 10 additions & 13 deletions .github/workflows/go.yml
Original file line number Diff line number Diff line change
Expand Up @@ -54,7 +54,7 @@ jobs:
runs-on: ${{ matrix.os }}
strategy:
matrix:
os: [ubuntu-latest, macos-latest]
os: [ubuntu-latest, macos-latest, windows-latest]
steps:
- name: Checkout
uses: actions/checkout@v4
Expand All @@ -81,18 +81,15 @@ jobs:
if: matrix.os != 'windows-latest'
run: |
./cli-v2 install
# Disable windows it test for now.
# - name: Install dependencies from .codacy/codacy.yaml (Windows)
# if: matrix.os == 'windows-latest'
# shell: pwsh
# run: |
# Get-ChildItem
# Write-Host "Current directory contents:"
# dir
# Write-Host "Node.js version:"
# node --version
# Write-Host "Attempting to run CLI..."
# .\cli-v2.exe install
- name: Install dependencies from .codacy/codacy.yaml (Windows)
if: matrix.os == 'windows-latest'
shell: pwsh
run: |
Get-ChildItem
Write-Host "Current directory contents:"
dir
Write-Host "Attempting to run CLI..."
.\cli-v2.exe install

# For now we are not releasing the CLI, as we are making some quicker iterations
release:
Expand Down
6 changes: 4 additions & 2 deletions cli-v2.go
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ import (
"codacy/cli-v2/utils/logger"
"fmt"
"os"
"path/filepath"

"github.com/sirupsen/logrus"
)
Expand All @@ -15,8 +16,9 @@ func main() {
// Initialize config global object
config.Init()

// Initialize logger
if err := logger.Initialize(&config.Config); err != nil {
// Initialize logger with the logs directory
logsDir := filepath.Join(config.Config.LocalCodacyDirectory(), "logs")
if err := logger.Initialize(logsDir); err != nil {
fmt.Printf("Failed to initialize logger: %v\n", err)
}

Expand Down
51 changes: 25 additions & 26 deletions cmd/install.go
Original file line number Diff line number Diff line change
Expand Up @@ -166,7 +166,10 @@ var installCmd = &cobra.Command{
"version": runtime.Version,
"error": err.Error(),
})
log.Fatal(err)
fmt.Printf("\n⚠️ Warning: Failed to install runtime %s v%s: %v\n", name, runtime.Version, err)
// Continue with next runtime instead of fatal
progressBar.Add(1)
continue
}
logger.Info("Successfully installed runtime", logrus.Fields{
"runtime": name,
Expand All @@ -191,7 +194,10 @@ var installCmd = &cobra.Command{
"version": tool.Version,
"error": err.Error(),
})
log.Fatal(err)
fmt.Printf("\n⚠️ Warning: Failed to install tool %s v%s: %v\n", name, tool.Version, err)
// Continue with next tool instead of fatal
progressBar.Add(1)
continue
}
logger.Info("Successfully installed tool", logrus.Fields{
"tool": name,
Expand All @@ -206,41 +212,34 @@ var installCmd = &cobra.Command{
devNull.Close()
log.SetOutput(os.Stderr)

// Print completion status
// Print completion status with warnings for failed installations
fmt.Println()
var hasFailures bool
for name, runtime := range cfg.Config.Runtimes() {
if !cfg.Config.IsRuntimeInstalled(name, runtime) {
color.Yellow(" ⚠️ Runtime: %s v%s (installation failed)", name, runtime.Version)
hasFailures = true
} else {
green.Printf(" ✓ Runtime: %s v%s\n", name, runtime.Version)
}
}
for name, tool := range cfg.Config.Tools() {
if !cfg.Config.IsToolInstalled(name, tool) {
color.Yellow(" ⚠️ Tool: %s v%s (installation failed)", name, tool.Version)
hasFailures = true
} else {
green.Printf(" ✓ Tool: %s v%s\n", name, tool.Version)
}
}
fmt.Println()
logger.Info("Installation completed successfully", nil)
bold.Println("✅ Installation completed successfully!")
if hasFailures {
logger.Warn("Installation completed with some failures", nil)
bold.Println("⚠️ Installation completed with some failures!")
fmt.Println("Some components failed to install. You can try installing them again with:")
fmt.Println(" codacy-cli install")
} else {
logger.Info("Installation completed successfully", nil)
bold.Println("✅ Installation completed successfully!")
}
},
}

func installRuntimes(config *cfg.ConfigType) {
err := cfg.InstallRuntimes(config)
if err != nil {
logger.Error("Failed to install runtimes", logrus.Fields{
"error": err.Error(),
})
log.Fatal(err)
}
}

func installTools(config *cfg.ConfigType, registry string) {
// Use the new tools-installer instead of manual installation
err := cfg.InstallTools(config, registry)
if err != nil {
logger.Error("Failed to install tools", logrus.Fields{
"error": err.Error(),
})
log.Fatal(err)
}
}
3 changes: 2 additions & 1 deletion cmd/root.go
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,8 @@ var rootCmd = &cobra.Command{
Example: getExampleText(),
PersistentPreRun: func(cmd *cobra.Command, args []string) {
// Initialize logger before any command runs
if err := logger.Initialize(&config.Config); err != nil {
logsDir := filepath.Join(config.Config.LocalCodacyDirectory(), "logs")
if err := logger.Initialize(logsDir); err != nil {
fmt.Printf("Warning: Failed to initialize file logger: %v\n", err)
}
},
Expand Down
11 changes: 11 additions & 0 deletions config/config.go
Original file line number Diff line number Diff line change
Expand Up @@ -209,10 +209,21 @@ func (c *ConfigType) IsToolInstalled(name string, tool *plugins.ToolInfo) bool {

// Check if at least one binary exists
for _, binaryPath := range tool.Binaries {
// If the path is relative, join it with the installation directory
if !filepath.IsAbs(binaryPath) {
binaryPath = filepath.Join(tool.InstallDir, binaryPath)
}

// Try both with and without .exe
_, err := os.Stat(binaryPath)
if err == nil {
return true
}

_, err = os.Stat(binaryPath + ".exe")
if err == nil {
return true
}
}

return false
Expand Down
58 changes: 52 additions & 6 deletions config/runtimes-installer.go
Original file line number Diff line number Diff line change
Expand Up @@ -3,20 +3,44 @@ package config
import (
"codacy/cli-v2/plugins"
"codacy/cli-v2/utils"
"codacy/cli-v2/utils/logger"
"fmt"
"log"
"os"
"path/filepath"
"strings"

"github.com/sirupsen/logrus"
)

// InstallRuntimes installs all runtimes defined in the configuration
func InstallRuntimes(config *ConfigType) error {
var failedRuntimes []string

for name, runtimeInfo := range config.Runtimes() {
logger.Info("Starting runtime installation", logrus.Fields{
"runtime": name,
"version": runtimeInfo.Version,
})

err := InstallRuntime(name, runtimeInfo)
if err != nil {
return fmt.Errorf("failed to install runtime %s: %w", name, err)
logger.Error("Failed to install runtime", logrus.Fields{
"runtime": name,
"version": runtimeInfo.Version,
"error": err.Error(),
})
failedRuntimes = append(failedRuntimes, name)
continue
}

logger.Info("Successfully installed runtime", logrus.Fields{
"runtime": name,
"version": runtimeInfo.Version,
})
}

if len(failedRuntimes) > 0 {
return fmt.Errorf("failed to install the following runtimes: %v", failedRuntimes)
}
return nil
}
Expand All @@ -25,6 +49,10 @@ func InstallRuntimes(config *ConfigType) error {
func InstallRuntime(name string, runtimeInfo *plugins.RuntimeInfo) error {
// Check if the runtime is already installed
if isRuntimeInstalled(runtimeInfo) {
logger.Info("Runtime already installed", logrus.Fields{
"runtime": name,
"version": runtimeInfo.Version,
})
fmt.Printf("Runtime %s v%s is already installed\n", name, runtimeInfo.Version)
return nil
}
Expand Down Expand Up @@ -67,15 +95,24 @@ func downloadAndExtractRuntime(runtimeInfo *plugins.RuntimeInfo) error {
_, err := os.Stat(downloadPath)
if os.IsNotExist(err) {
// Download the file
// log.Printf("Downloading %s v%s...\n", runtimeInfo.Name, runtimeInfo.Version)
logger.Debug("Downloading runtime", logrus.Fields{
"runtime": runtimeInfo.Name,
"version": runtimeInfo.Version,
"downloadURL": runtimeInfo.DownloadURL,
"downloadPath": downloadPath,
})
downloadPath, err = utils.DownloadFile(runtimeInfo.DownloadURL, Config.RuntimesDirectory())
if err != nil {
return fmt.Errorf("failed to download runtime: %w", err)
}
} else if err != nil {
return fmt.Errorf("error checking for existing download: %w", err)
} else {
log.Printf("Using existing download for %s v%s\n", runtimeInfo.Name, runtimeInfo.Version)
logger.Debug("Using existing runtime download", logrus.Fields{
"runtime": runtimeInfo.Name,
"version": runtimeInfo.Version,
"downloadPath": downloadPath,
})
}

// Open the downloaded file
Expand All @@ -86,7 +123,13 @@ func downloadAndExtractRuntime(runtimeInfo *plugins.RuntimeInfo) error {
defer file.Close()

// Extract based on file extension
// log.Printf("Extracting %s v%s...\n", runtimeInfo.Name, runtimeInfo.Version)
logger.Debug("Extracting runtime", logrus.Fields{
"runtime": runtimeInfo.Name,
"version": runtimeInfo.Version,
"fileName": fileName,
"extractDirectory": Config.RuntimesDirectory(),
})

if strings.HasSuffix(fileName, ".zip") {
err = utils.ExtractZip(file.Name(), Config.RuntimesDirectory())
} else {
Expand All @@ -97,6 +140,9 @@ func downloadAndExtractRuntime(runtimeInfo *plugins.RuntimeInfo) error {
return fmt.Errorf("failed to extract runtime: %w", err)
}

log.Printf("Successfully installed %s v%s\n", runtimeInfo.Name, runtimeInfo.Version)
logger.Debug("Runtime extraction completed", logrus.Fields{
"runtime": runtimeInfo.Name,
"version": runtimeInfo.Version,
})
return nil
}
Loading