From 0ae4d01d7561fb4cdf8b33c1bba55f9eaed06f7f Mon Sep 17 00:00:00 2001 From: AJ ONeal Date: Wed, 11 Mar 2026 11:42:35 -0600 Subject: [PATCH] fix(classifypkg): separate github, githubsource, and gittag strategies Three distinct fetch/classify strategies: - github: binary assets only, no source entries - githubsource: tarball + zipball from GitHub releases API - gittag: git clone + tag enumeration (existing) GitHub binary packages (caddy, jq, shellcheck, etc.) no longer get spurious .git and source tarball entries for old releases that had no binary uploads. Source-installable packages (aliasman, duckdns.sh, serviceman) now use github_source in releases.conf. --- aliasman/releases.conf | 2 +- duckdns.sh/releases.conf | 2 +- internal/classifypkg/classifypkg.go | 116 +++++++++++++++--------- internal/installerconf/installerconf.go | 4 + serviceman/releases.conf | 2 +- 5 files changed, 78 insertions(+), 48 deletions(-) diff --git a/aliasman/releases.conf b/aliasman/releases.conf index e3d113d..1cc8f96 100644 --- a/aliasman/releases.conf +++ b/aliasman/releases.conf @@ -1 +1 @@ -github_repo = BeyondCodeBootcamp/aliasman +github_source = BeyondCodeBootcamp/aliasman diff --git a/duckdns.sh/releases.conf b/duckdns.sh/releases.conf index 89bac7c..a0ed3d4 100644 --- a/duckdns.sh/releases.conf +++ b/duckdns.sh/releases.conf @@ -1 +1 @@ -github_repo = BeyondCodeBootcamp/DuckDNS.sh +github_source = BeyondCodeBootcamp/DuckDNS.sh diff --git a/internal/classifypkg/classifypkg.go b/internal/classifypkg/classifypkg.go index 69d24a1..691572d 100644 --- a/internal/classifypkg/classifypkg.go +++ b/internal/classifypkg/classifypkg.go @@ -88,6 +88,8 @@ func classifySource(pkg string, conf *installerconf.Conf, d *rawcache.Dir) ([]st switch conf.Source { case "github": return classifyGitHub(pkg, conf, d) + case "githubsource": + return classifyGitHubSource(pkg, conf, d) case "nodedist": return classifyNodeDist(pkg, conf, d) case "gittag": @@ -367,55 +369,79 @@ func classifyGitHub(pkg string, conf *installerconf.Conf, d *rawcache.Dir) ([]st }) } - // Source archives for packages with no binary assets. - // These are installable on any POSIX system (shell scripts, etc.). - // - // GitHub has two archive URL formats: - // Releases with no uploaded assets are source-only — use the - // API-provided tarball/zipball URLs. These can also be installed - // via `git clone --branch ` as a fallback. - // - // TODO: HEAD-follow the tarball_url at fetch time to get the - // resolved codeload URL and Content-Disposition filename - // (Owner-Repo-Tag-0-gCommitHash.ext). For now, use the tag - // as the filename since the actual download name comes from - // Content-Disposition anyway. - if len(rel.Assets) == 0 { - owner := conf.Owner - repo := conf.Repo - tag := rel.TagName - if rel.TarballURL != "" { - assets = append(assets, storage.Asset{ - Filename: repo + "-" + tag + ".tar.gz", - Version: version, - Channel: channel, - OS: "posix_2017", - Arch: "*", - Format: ".tar.gz", - Download: rel.TarballURL, - Date: date, - }) + // Releases with no uploaded binary assets are skipped for GitHub + // packages. These are typically old releases from before the + // project started uploading binaries. Source-installable packages + // should use githubsource or gittag source type instead. + } + return assets, nil +} + +// classifyGitHubSource handles packages installed from source via GitHub +// releases. Unlike classifyGitHub (which classifies binary assets), this +// emits source tarball/zipball/git entries for every release. Used for +// shell scripts, vim plugins, and other source-installable packages. +func classifyGitHubSource(pkg string, conf *installerconf.Conf, d *rawcache.Dir) ([]storage.Asset, error) { + tagPrefix := conf.TagPrefix + releases, err := ReadAllRaw(d) + if err != nil { + return nil, err + } + + repo := conf.Repo + + var assets []storage.Asset + for _, data := range releases { + var rel ghRelease + if err := json.Unmarshal(data, &rel); err != nil { + continue + } + if rel.Draft { + continue + } + + version := rel.TagName + if tagPrefix != "" { + if !strings.HasPrefix(version, tagPrefix) { + continue } - if rel.ZipballURL != "" { - assets = append(assets, storage.Asset{ - Filename: repo + "-" + tag + ".zip", - Version: version, - Channel: channel, - OS: "posix_2017", - Arch: "*", - Format: ".zip", - Download: rel.ZipballURL, - Date: date, - }) - } - // Git clone asset — same as gittag source. - gitURL := fmt.Sprintf("https://github.com/%s/%s.git", owner, repo) + version = strings.TrimPrefix(version, tagPrefix) + } + + channel := "stable" + if rel.Prerelease { + channel = "beta" + } else { + channel = channelFromVersion(version) + } + + date := "" + if len(rel.PublishedAt) >= 10 { + date = rel.PublishedAt[:10] + } + + tag := rel.TagName + if rel.TarballURL != "" { assets = append(assets, storage.Asset{ - Filename: repo + "-" + tag, + Filename: repo + "-" + tag + ".tar.gz", Version: version, Channel: channel, - Format: "git", - Download: gitURL, + OS: "posix_2017", + Arch: "*", + Format: ".tar.gz", + Download: rel.TarballURL, + Date: date, + }) + } + if rel.ZipballURL != "" { + assets = append(assets, storage.Asset{ + Filename: repo + "-" + tag + ".zip", + Version: version, + Channel: channel, + OS: "posix_2017", + Arch: "*", + Format: ".zip", + Download: rel.ZipballURL, Date: date, }) } diff --git a/internal/installerconf/installerconf.go b/internal/installerconf/installerconf.go index 8afec77..2167171 100644 --- a/internal/installerconf/installerconf.go +++ b/internal/installerconf/installerconf.go @@ -141,6 +141,9 @@ func Read(path string) (*Conf, error) { case raw["github_repo"] != "": c.Source = "github" c.Owner, c.Repo, _ = strings.Cut(raw["github_repo"], "/") + case raw["github_source"] != "": + c.Source = "githubsource" + c.Owner, c.Repo, _ = strings.Cut(raw["github_source"], "/") case raw["git_url"] != "": c.Source = "gittag" c.BaseURL = raw["git_url"] @@ -183,6 +186,7 @@ func Read(path string) (*Conf, error) { known := map[string]bool{ "source": true, "github_repo": true, + "github_source": true, "git_url": true, "gitea_repo": true, "hashicorp_product": true, diff --git a/serviceman/releases.conf b/serviceman/releases.conf index 61959e7..3f244c3 100644 --- a/serviceman/releases.conf +++ b/serviceman/releases.conf @@ -1 +1 @@ -github_repo = bnnanet/serviceman +github_source = bnnanet/serviceman