From d83b96666338e5473369397f0c0a9d5be29ab0a8 Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Thu, 2 Jul 2026 13:29:23 +0000 Subject: [PATCH 1/2] Initial plan From 76aa4ae2cd8e9da5a56cbda4ac7f92f2b17de10c Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Thu, 2 Jul 2026 13:35:14 +0000 Subject: [PATCH 2/2] feat(kubectl): install fzf from GitHub binaries instead of apt --- .../src/kubectl/devcontainer-feature.json | 15 ++++++ features/src/kubectl/installer.go | 48 ++++++++++++++++++- features/test/kubectl/full.sh | 1 + features/test/kubectl/scenarios.json | 6 ++- override-all.env | 1 + 5 files changed, 67 insertions(+), 4 deletions(-) diff --git a/features/src/kubectl/devcontainer-feature.json b/features/src/kubectl/devcontainer-feature.json index 049e96f..a39c78e 100644 --- a/features/src/kubectl/devcontainer-feature.json +++ b/features/src/kubectl/devcontainer-feature.json @@ -129,6 +129,21 @@ "type": "string", "default": "", "description": "The download URL to use for kube-score binaries." + }, + "fzfVersion": { + "type": "string", + "proposals": [ + "latest", + "none", + "0.60.0" + ], + "default": "latest", + "description": "The version of fzf to install." + }, + "fzfDownloadUrl": { + "type": "string", + "default": "", + "description": "The download URL to use for fzf binaries." } } } \ No newline at end of file diff --git a/features/src/kubectl/installer.go b/features/src/kubectl/installer.go index 5f59cb0..3af7578 100644 --- a/features/src/kubectl/installer.go +++ b/features/src/kubectl/installer.go @@ -50,6 +50,8 @@ func runMain() error { kustomizeDownloadUrl := flag.String("kustomizeDownloadUrl", "", "") kubeconformDownloadUrl := flag.String("kubeconformDownloadUrl", "", "") kubescoreDownloadUrl := flag.String("kubescoreDownloadUrl", "", "") + fzfVersion := flag.String("fzfVersion", "latest", "") + fzfDownloadUrl := flag.String("fzfDownloadUrl", "", "") flag.Parse() // Load settings from an external file @@ -66,6 +68,7 @@ func runMain() error { installer.HandleGitHubOverride(kustomizeDownloadUrl, "kubernetes-sigs/kustomize", "kubectl-kustomize-download-url") installer.HandleGitHubOverride(kubeconformDownloadUrl, "yannh/kubeconform", "kubectl-kubeconform-download-url") installer.HandleGitHubOverride(kubescoreDownloadUrl, "zegl/kube-score", "kubectl-kubescore-download-url") + installer.HandleGitHubOverride(fzfDownloadUrl, "junegunn/fzf", "kubectl-fzf-download-url") // Create and process the feature feature := installer.NewFeature("kubectl", true, @@ -102,7 +105,8 @@ func runMain() error { DownloadUrl: *kubescoreDownloadUrl, }, &fzfComponent{ - ComponentBase: installer.NewComponentBase("fzf", installer.VERSION_SYSTEM_DEFAULT), + ComponentBase: installer.NewComponentBase("fzf", *fzfVersion), + DownloadUrl: *fzfDownloadUrl, }, ) return feature.Process() @@ -528,8 +532,48 @@ func (c *kubescoreComponent) InstallVersion(version *gover.Version) error { type fzfComponent struct { *installer.ComponentBase + DownloadUrl string +} + +func (c *fzfComponent) GetAllVersions() ([]*gover.Version, error) { + tags, err := installer.Tools.GitHub.GetTags("junegunn", "fzf") + if err != nil { + return nil, err + } + return installer.Tools.Versioning.ParseVersionsFromList(tags, threeDigitRegex, true) } func (c *fzfComponent) InstallVersion(version *gover.Version) error { - return installer.Tools.System.InstallPackages("fzf") + // Download + archPart, err := installer.Tools.System.MapArchitecture(map[string]string{ + installer.AMD64: "amd64", + installer.ARM64: "arm64", + }) + if err != nil { + return err + } + fileName := fmt.Sprintf("fzf-%s-linux_%s.tar.gz", version.Raw, archPart) + downloadUrl, err := installer.Tools.Http.BuildUrl(c.DownloadUrl, "v"+version.Raw, fileName) + if err != nil { + return err + } + if err := installer.Tools.Download.ToFile(downloadUrl, fileName, "fzf"); err != nil { + return err + } + // Extract + if err := installer.Tools.Compression.ExtractTarGz(fileName, "fzf", false); err != nil { + return err + } + // Install + if err := installer.Tools.System.InstallBinaryToUsrLocalBin("fzf/fzf", "fzf"); err != nil { + return err + } + // Cleanup + if err := os.Remove(fileName); err != nil { + return err + } + if err := os.RemoveAll("fzf"); err != nil { + return err + } + return nil } diff --git a/features/test/kubectl/full.sh b/features/test/kubectl/full.sh index 8307954..2dbe7f8 100755 --- a/features/test/kubectl/full.sh +++ b/features/test/kubectl/full.sh @@ -12,3 +12,4 @@ check_version "$(helm version --short)" "v3.16.2+g13654a5" check_version "$(kustomize version)" "v5.4.2" check_version "$(kubeconform -v)" "v0.6.6" check_version "$(kube-score version)" "kube-score version: 1.18.0, commit: 0fb5f668e153c22696aa75ec769b080c41b5dd3d, built: 2024-02-05T14:13:15Z" +check_version "$(fzf --version)" "0.60.0" diff --git a/features/test/kubectl/scenarios.json b/features/test/kubectl/scenarios.json index b1bc702..b242a22 100644 --- a/features/test/kubectl/scenarios.json +++ b/features/test/kubectl/scenarios.json @@ -15,7 +15,8 @@ "helmVersion": "none", "kustomizeVersion": "none", "kubeconformVersion": "none", - "kubescoreVersion": "none" + "kubescoreVersion": "none", + "fzfVersion": "none" } } }, @@ -35,7 +36,8 @@ "helmVersion": "3.16.2", "kustomizeVersion": "5.4.2", "kubeconformVersion": "0.6.6", - "kubescoreVersion": "1.18.0" + "kubescoreVersion": "1.18.0", + "fzfVersion": "0.60.0" } } } diff --git a/override-all.env b/override-all.env index 78e5f07..6d0e4a7 100644 --- a/override-all.env +++ b/override-all.env @@ -68,6 +68,7 @@ KUBECTL_HELM_DOWNLOAD_URL="" KUBECTL_KUSTOMIZE_DOWNLOAD_URL="" KUBECTL_KUBECONFORM_DOWNLOAD_URL="" KUBECTL_KUBESCORE_DOWNLOAD_URL="" +KUBECTL_FZF_DOWNLOAD_URL="" # nginx NGINX_DOWNLOAD_URL=""