diff --git a/internal/container/build.go b/internal/container/build.go index d6eb8dd..a8cb5bb 100644 --- a/internal/container/build.go +++ b/internal/container/build.go @@ -229,18 +229,27 @@ func miseInstallBlock(langs []DetectedLang) string { func pluralDownloadBlock(version, arch string) string { var b strings.Builder + var url string if version == "" || version == "dev" { // Use latest release URL pattern (no API call needed) - fmt.Fprintf(&b, "RUN curl -sfL \"https://github.com/zhubert/plural/releases/latest/download/plural_Linux_%s.tar.gz\" | tar -xz -C /tmp plural && \\\n", arch) - b.WriteString(" mv /tmp/plural /usr/local/bin/plural && \\\n") - b.WriteString(" chmod +x /usr/local/bin/plural\n\n") + url = fmt.Sprintf("https://github.com/zhubert/plural/releases/latest/download/plural_Linux_%s.tar.gz", arch) } else { - // Exact version download - fmt.Fprintf(&b, "RUN curl -sfL \"https://github.com/zhubert/plural/releases/download/%s/plural_Linux_%s.tar.gz\" | tar -xz -C /tmp plural && \\\n", version, arch) - b.WriteString(" mv /tmp/plural /usr/local/bin/plural && \\\n") - b.WriteString(" chmod +x /usr/local/bin/plural\n\n") + // Exact version download — ensure "v" prefix for GitHub release tag + tag := version + if !strings.HasPrefix(tag, "v") { + tag = "v" + tag + } + url = fmt.Sprintf("https://github.com/zhubert/plural/releases/download/%s/plural_Linux_%s.tar.gz", tag, arch) } + // Download to file first so curl failures surface clearly instead of + // producing misleading tar errors (e.g. "invalid magic" on a 404). + fmt.Fprintf(&b, "RUN curl -sfL -o /tmp/plural.tar.gz \"%s\" && \\\n", url) + b.WriteString(" tar -xz -C /tmp plural -f /tmp/plural.tar.gz && \\\n") + b.WriteString(" rm /tmp/plural.tar.gz && \\\n") + b.WriteString(" mv /tmp/plural /usr/local/bin/plural && \\\n") + b.WriteString(" chmod +x /usr/local/bin/plural\n\n") + return b.String() } diff --git a/internal/container/build_test.go b/internal/container/build_test.go index a84710d..e3910fb 100644 --- a/internal/container/build_test.go +++ b/internal/container/build_test.go @@ -416,6 +416,23 @@ func TestPluralDownloadBlock(t *testing.T) { t.Error("release version should not use /latest/download/") } }) + + t.Run("version without v prefix gets v added", func(t *testing.T) { + block := pluralDownloadBlock("1.2.0", "arm64") + if !strings.Contains(block, "/download/v1.2.0/") { + t.Errorf("version without v prefix should get v added, got: %s", block) + } + }) + + t.Run("downloads to file before extracting", func(t *testing.T) { + block := pluralDownloadBlock("v1.0.0", "arm64") + if !strings.Contains(block, "-o /tmp/plural.tar.gz") { + t.Error("should download to file first") + } + if !strings.Contains(block, "-f /tmp/plural.tar.gz") { + t.Error("should extract from downloaded file") + } + }) } func TestMiseInstallBlock_RubyAndPython(t *testing.T) {