@@ -1801,52 +1801,99 @@ func extractPluginIDFromRepo(repo string) string {
18011801// Pre-built Binary Installation
18021802// =============================================================================
18031803
1804- // getPlatformString returns the platform identifier for the current system
1805- func getPlatformString () string {
1806- goos := runtime .GOOS
1807- goarch := runtime .GOARCH
1804+ // PluginAvailability represents the available installation options for a plugin
1805+ type PluginAvailability struct {
1806+ PluginID string `json:"pluginId"`
1807+ Repository string `json:"repository"`
1808+ Platform string `json:"platform"`
1809+ HasStable bool `json:"hasStable"`
1810+ StableVersion string `json:"stableVersion,omitempty"`
1811+ StableSize int64 `json:"stableSize,omitempty"`
1812+ HasBeta bool `json:"hasBeta"`
1813+ BetaVersion string `json:"betaVersion,omitempty"`
1814+ BetaSize int64 `json:"betaSize,omitempty"`
1815+ CanBuildSource bool `json:"canBuildSource"`
1816+ Error string `json:"error,omitempty"`
1817+ }
18081818
1809- if goos != "linux" {
1810- return "" // Only Linux pre-built binaries are available
1819+ // CheckPluginAvailability checks what installation options are available for a plugin
1820+ func (pi * PluginInstaller ) CheckPluginAvailability (org , repo string ) PluginAvailability {
1821+ pluginID := repo
1822+ if strings .HasPrefix (repo , "Plugin_" ) {
1823+ pluginID = strings .TrimPrefix (repo , "Plugin_" )
18111824 }
18121825
1813- switch goarch {
1814- case "amd64" :
1815- return "linux-amd64"
1816- case "386" :
1817- return "linux-386"
1818- case "arm64" :
1819- return "linux-arm64"
1820- case "arm" :
1821- // Detect ARM version - default to ARM6 for compatibility
1822- return "linux-arm6"
1823- default :
1824- return ""
1826+ platform := getPlatformString ()
1827+ result := PluginAvailability {
1828+ PluginID : pluginID ,
1829+ Repository : fmt .Sprintf ("https://github.com/%s/%s" , org , repo ),
1830+ Platform : platform ,
1831+ CanBuildSource : true , // Always available as fallback
18251832 }
1826- }
18271833
1828- // GitHubRelease represents a GitHub release from the API
1829- type GitHubRelease struct {
1830- TagName string `json:"tag_name"`
1831- Name string `json:"name"`
1832- Prerelease bool `json:"prerelease"`
1833- Assets []GitHubReleaseAsset `json:"assets"`
1834- }
1834+ if platform == "" {
1835+ result .Error = fmt .Sprintf ("No pre-built binaries for %s/%s, source install only" , runtime .GOOS , runtime .GOARCH )
1836+ return result
1837+ }
18351838
1836- // GitHubReleaseAsset represents an asset in a GitHub release
1837- type GitHubReleaseAsset struct {
1838- Name string `json:"name"`
1839- BrowserDownloadURL string `json:"browser_download_url"`
1840- Size int64 `json:"size"`
1839+ // Check stable release
1840+ stableRelease , stableAsset , err := pi .findReleaseAsset (org , repo , pluginID , platform , false )
1841+ if err == nil && stableAsset != nil {
1842+ result .HasStable = true
1843+ result .StableVersion = stableRelease .TagName
1844+ result .StableSize = stableAsset .Size
1845+ }
1846+
1847+ // Check beta release
1848+ betaRelease , betaAsset , err := pi .findReleaseAsset (org , repo , pluginID , platform , true )
1849+ if err == nil && betaAsset != nil {
1850+ result .HasBeta = true
1851+ result .BetaVersion = betaRelease .TagName
1852+ result .BetaSize = betaAsset .Size
1853+ }
1854+
1855+ return result
18411856}
18421857
1843- // downloadPrebuiltBinary downloads and installs a pre-built plugin binary from GitHub releases
1844- func (pi * PluginInstaller ) downloadPrebuiltBinary (org , repo , pluginID string , useBeta bool ) error {
1845- platform := getPlatformString ()
1846- if platform == "" {
1847- return fmt .Errorf ("no pre-built binary available for this platform: %s/%s" , runtime .GOOS , runtime .GOARCH )
1858+ // CheckMultiplePluginsAvailability checks availability for multiple plugins
1859+ func (pi * PluginInstaller ) CheckMultiplePluginsAvailability (repositories []string ) []PluginAvailability {
1860+ results := make ([]PluginAvailability , 0 , len (repositories ))
1861+
1862+ for _ , repo := range repositories {
1863+ // Extract org and repo name from the URL
1864+ parts := strings .Split (repo , "/" )
1865+ var org , repoName string
1866+ for i , part := range parts {
1867+ if part == "github.com" && i + 2 < len (parts ) {
1868+ org = parts [i + 1 ]
1869+ repoName = parts [i + 2 ]
1870+ break
1871+ }
1872+ }
1873+
1874+ if org == "" || repoName == "" {
1875+ // Fallback: use last two parts
1876+ if len (parts ) >= 2 {
1877+ org = parts [len (parts )- 2 ]
1878+ repoName = parts [len (parts )- 1 ]
1879+ }
1880+ }
1881+
1882+ // Remove .git suffix if present
1883+ if strings .HasSuffix (repoName , ".git" ) {
1884+ repoName = repoName [:len (repoName )- 4 ]
1885+ }
1886+
1887+ if org != "" && repoName != "" {
1888+ results = append (results , pi .CheckPluginAvailability (org , repoName ))
1889+ }
18481890 }
18491891
1892+ return results
1893+ }
1894+
1895+ // findReleaseAsset finds the appropriate asset for the platform in a release
1896+ func (pi * PluginInstaller ) findReleaseAsset (org , repo , pluginID , platform string , useBeta bool ) (* GitHubRelease , * GitHubReleaseAsset , error ) {
18501897 // Determine which release to fetch
18511898 var releaseURL string
18521899 if useBeta {
@@ -1858,7 +1905,7 @@ func (pi *PluginInstaller) downloadPrebuiltBinary(org, repo, pluginID string, us
18581905 // Create request
18591906 req , err := http .NewRequest ("GET" , releaseURL , nil )
18601907 if err != nil {
1861- return fmt .Errorf ("failed to create request: %v" , err )
1908+ return nil , nil , fmt .Errorf ("failed to create request: %v" , err )
18621909 }
18631910
18641911 // Add authentication if available
@@ -1873,51 +1920,95 @@ func (pi *PluginInstaller) downloadPrebuiltBinary(org, repo, pluginID string, us
18731920 client := & http.Client {Timeout : 30 * time .Second }
18741921 resp , err := client .Do (req )
18751922 if err != nil {
1876- return fmt .Errorf ("failed to fetch release info: %v" , err )
1923+ return nil , nil , fmt .Errorf ("failed to fetch release info: %v" , err )
18771924 }
18781925 defer resp .Body .Close ()
18791926
18801927 if resp .StatusCode != http .StatusOK {
1881- return fmt .Errorf ("release not found (HTTP %d)" , resp .StatusCode )
1928+ return nil , nil , fmt .Errorf ("release not found (HTTP %d)" , resp .StatusCode )
18821929 }
18831930
18841931 // Parse release
18851932 var release GitHubRelease
18861933 if err := json .NewDecoder (resp .Body ).Decode (& release ); err != nil {
1887- return fmt .Errorf ("failed to parse release info: %v" , err )
1934+ return nil , nil , fmt .Errorf ("failed to parse release info: %v" , err )
18881935 }
18891936
18901937 // Find the appropriate asset for this platform
1891- var assetURL string
1892- var assetName string
1893- versionSuffix := release . TagName
1894- if useBeta {
1895- versionSuffix = "beta"
1938+ for i , asset := range release . Assets {
1939+ // Try various naming patterns
1940+ if strings . Contains ( asset . Name , platform ) && strings . HasSuffix ( asset . Name , ".tar.gz" ) {
1941+ return & release , & release . Assets [ i ], nil
1942+ }
18961943 }
18971944
1898- expectedName := fmt .Sprintf ("%s-%s-%s.tar.gz" , pluginID , platform , versionSuffix )
1945+ return & release , nil , fmt .Errorf ("no asset found for platform %s" , platform )
1946+ }
18991947
1900- for _ , asset := range release .Assets {
1901- if asset .Name == expectedName {
1902- assetURL = asset .BrowserDownloadURL
1903- assetName = asset .Name
1904- break
1905- }
1906- // Also try without version suffix for beta
1907- if useBeta && strings .Contains (asset .Name , platform ) && strings .HasSuffix (asset .Name , ".tar.gz" ) {
1908- assetURL = asset .BrowserDownloadURL
1909- assetName = asset .Name
1910- }
1948+ // GetPlatformString exports the platform string for API use
1949+ func GetPlatformString () string {
1950+ return getPlatformString ()
1951+ }
1952+
1953+ // getPlatformString returns the platform identifier for the current system
1954+ func getPlatformString () string {
1955+ goos := runtime .GOOS
1956+ goarch := runtime .GOARCH
1957+
1958+ if goos != "linux" {
1959+ return "" // Only Linux pre-built binaries are available
19111960 }
19121961
1913- if assetURL == "" {
1962+ switch goarch {
1963+ case "amd64" :
1964+ return "linux-amd64"
1965+ case "386" :
1966+ return "linux-386"
1967+ case "arm64" :
1968+ return "linux-arm64"
1969+ case "arm" :
1970+ // Detect ARM version - default to ARM6 for compatibility
1971+ return "linux-arm6"
1972+ default :
1973+ return ""
1974+ }
1975+ }
1976+
1977+ // GitHubRelease represents a GitHub release from the API
1978+ type GitHubRelease struct {
1979+ TagName string `json:"tag_name"`
1980+ Name string `json:"name"`
1981+ Prerelease bool `json:"prerelease"`
1982+ Assets []GitHubReleaseAsset `json:"assets"`
1983+ }
1984+
1985+ // GitHubReleaseAsset represents an asset in a GitHub release
1986+ type GitHubReleaseAsset struct {
1987+ Name string `json:"name"`
1988+ BrowserDownloadURL string `json:"browser_download_url"`
1989+ Size int64 `json:"size"`
1990+ }
1991+
1992+ // downloadPrebuiltBinary downloads and installs a pre-built plugin binary from GitHub releases
1993+ func (pi * PluginInstaller ) downloadPrebuiltBinary (org , repo , pluginID string , useBeta bool ) error {
1994+ platform := getPlatformString ()
1995+ if platform == "" {
1996+ return fmt .Errorf ("no pre-built binary available for this platform: %s/%s" , runtime .GOOS , runtime .GOARCH )
1997+ }
1998+
1999+ // Use the new findReleaseAsset function
2000+ release , asset , err := pi .findReleaseAsset (org , repo , pluginID , platform , useBeta )
2001+ if err != nil {
2002+ return err
2003+ }
2004+ if asset == nil {
19142005 return fmt .Errorf ("no binary found for platform %s in release %s" , platform , release .TagName )
19152006 }
19162007
1917- log .Printf ("Downloading pre-built binary: %s" , assetName )
2008+ log .Printf ("Downloading pre-built binary: %s" , asset . Name )
19182009
19192010 // Download the asset
1920- assetResp , err := http .Get (assetURL )
2011+ assetResp , err := http .Get (asset . BrowserDownloadURL )
19212012 if err != nil {
19222013 return fmt .Errorf ("failed to download binary: %v" , err )
19232014 }
0 commit comments