Skip to content
Merged
Show file tree
Hide file tree
Changes from 6 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