mirror of
https://github.com/webinstall/webi-installers.git
synced 2026-04-06 18:36:50 +00:00
feat: whitespace-delimited releases.conf, variant tagging
- Switch installerconf parser from comma to whitespace delimiters - Add asset_exclude as alias for exclude (fixes hugo) - Add variants key (documentation cue, detection in Go code) - Add per-package variant taggers: bun (profile, amd64v3 arch), pwsh (fxdependent), ollama (rocm, jetpack5/6), git (installer), node (msi installer), lsd (deb, msvc), fish (pkg), xcaddy (deb) - Update releases.conf files with variant declarations
This commit is contained in:
@@ -1,3 +1,7 @@
|
||||
source = github
|
||||
owner = oven-sh
|
||||
repo = bun
|
||||
# non-baseline=amd64v3, -baseline=amd64
|
||||
default_x86_64 = x86_64_v3
|
||||
x86_64_v2 = baseline
|
||||
variants = profile
|
||||
|
||||
@@ -199,6 +199,9 @@ func (wc *WebiCache) refreshPackage(ctx context.Context, pkg pkgConf) error {
|
||||
return fmt.Errorf("classify: %w", err)
|
||||
}
|
||||
|
||||
// Step 2.5: Tag build variants.
|
||||
tagVariants(name, conf, assets)
|
||||
|
||||
// Step 3: Apply config transforms.
|
||||
assets = applyConfig(assets, conf)
|
||||
|
||||
@@ -1449,3 +1452,135 @@ func isMetaAsset(name string) bool {
|
||||
return false
|
||||
}
|
||||
|
||||
// tagVariants sets Asset.Variants for known build variants.
|
||||
// Detection logic is per-package; the releases.conf "variants" key
|
||||
// is documentation only — actual pattern matching lives here.
|
||||
func tagVariants(pkg string, conf *installerconf.Conf, assets []storage.Asset) {
|
||||
switch pkg {
|
||||
case "bun":
|
||||
tagVariantsBun(assets)
|
||||
case "pwsh":
|
||||
tagVariantsPwsh(assets)
|
||||
case "ollama":
|
||||
tagVariantsOllama(assets)
|
||||
case "git":
|
||||
tagVariantsGit(assets)
|
||||
case "node":
|
||||
tagVariantsNode(assets)
|
||||
case "lsd":
|
||||
tagVariantsLsd(assets)
|
||||
case "fish":
|
||||
tagVariantsFish(assets)
|
||||
case "xcaddy":
|
||||
tagVariantsXcaddy(assets)
|
||||
}
|
||||
}
|
||||
|
||||
// tagVariantsBun: -profile is a debug build, -baseline is actually amd64
|
||||
// (non-baseline is amd64v3). Arch remapping + variant tagging.
|
||||
func tagVariantsBun(assets []storage.Asset) {
|
||||
for i := range assets {
|
||||
lower := strings.ToLower(assets[i].Filename)
|
||||
if strings.Contains(lower, "-profile") {
|
||||
assets[i].Variants = append(assets[i].Variants, "profile")
|
||||
}
|
||||
// Non-baseline x86_64 is actually amd64v3; baseline is plain amd64.
|
||||
if assets[i].Arch == "amd64" {
|
||||
if strings.Contains(lower, "-baseline") {
|
||||
// baseline stays amd64, no variant needed
|
||||
} else {
|
||||
// non-baseline is the v3 microarchitecture
|
||||
assets[i].Arch = "amd64v3"
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// tagVariantsPwsh: -fxdependent and -fxdependentWinDesktop are
|
||||
// .NET framework-dependent builds (smaller, require .NET runtime).
|
||||
func tagVariantsPwsh(assets []storage.Asset) {
|
||||
for i := range assets {
|
||||
lower := strings.ToLower(assets[i].Filename)
|
||||
if strings.Contains(lower, "-fxdependentwindesktop") {
|
||||
assets[i].Variants = append(assets[i].Variants, "fxdependentWinDesktop")
|
||||
} else if strings.Contains(lower, "-fxdependent") {
|
||||
assets[i].Variants = append(assets[i].Variants, "fxdependent")
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// tagVariantsOllama: GPU accelerator builds (-rocm, -jetpack5, -jetpack6).
|
||||
func tagVariantsOllama(assets []storage.Asset) {
|
||||
for i := range assets {
|
||||
lower := strings.ToLower(assets[i].Filename)
|
||||
for _, v := range []string{"rocm", "jetpack5", "jetpack6"} {
|
||||
if strings.Contains(lower, "-"+v) {
|
||||
assets[i].Variants = append(assets[i].Variants, v)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// tagVariantsGit: GUI installer .exe files (Git-*-bit.exe, PortableGit, etc.)
|
||||
// vs MinGit .zip which is the actual portable binary.
|
||||
func tagVariantsGit(assets []storage.Asset) {
|
||||
for i := range assets {
|
||||
name := assets[i].Filename
|
||||
lower := strings.ToLower(name)
|
||||
// Git-2.48.1-64-bit.exe and similar are GUI installers
|
||||
if assets[i].Format == ".exe" {
|
||||
assets[i].Variants = append(assets[i].Variants, "installer")
|
||||
}
|
||||
// PortableGit is a self-extracting installer
|
||||
if strings.Contains(lower, "portablegit") {
|
||||
assets[i].Variants = append(assets[i].Variants, "installer")
|
||||
}
|
||||
// .pdb archives are debug symbols
|
||||
if strings.Contains(lower, "-pdb") {
|
||||
assets[i].Variants = append(assets[i].Variants, "pdb")
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// tagVariantsNode: .exe files for Windows are the bare binary, but
|
||||
// node-v*-x64.msi and similar are GUI installers.
|
||||
func tagVariantsNode(assets []storage.Asset) {
|
||||
for i := range assets {
|
||||
if assets[i].Format == ".msi" {
|
||||
assets[i].Variants = append(assets[i].Variants, "installer")
|
||||
}
|
||||
// node-v25.8.0-win-x64.exe is a bare binary, not an installer.
|
||||
// Only .msi is the installer for node.
|
||||
}
|
||||
}
|
||||
|
||||
// tagVariantsLsd: .deb packages and windows-msvc builds.
|
||||
func tagVariantsLsd(assets []storage.Asset) {
|
||||
for i := range assets {
|
||||
if assets[i].Format == ".deb" {
|
||||
assets[i].Variants = append(assets[i].Variants, "deb")
|
||||
}
|
||||
if strings.Contains(strings.ToLower(assets[i].Filename), "-msvc") {
|
||||
assets[i].Variants = append(assets[i].Variants, "msvc")
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// tagVariantsFish: .pkg installers and source tarballs.
|
||||
func tagVariantsFish(assets []storage.Asset) {
|
||||
for i := range assets {
|
||||
if assets[i].Format == ".pkg" {
|
||||
assets[i].Variants = append(assets[i].Variants, "installer")
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// tagVariantsXcaddy: .deb packages.
|
||||
func tagVariantsXcaddy(assets []storage.Asset) {
|
||||
for i := range assets {
|
||||
if assets[i].Format == ".deb" {
|
||||
assets[i].Variants = append(assets[i].Variants, "deb")
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -1,3 +1,4 @@
|
||||
source = github
|
||||
owner = git-for-windows
|
||||
repo = git
|
||||
variants = installer
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
source = github
|
||||
owner = gohugoio
|
||||
repo = hugo
|
||||
asset_exclude = extended
|
||||
exclude = extended
|
||||
|
||||
@@ -2,6 +2,7 @@
|
||||
//
|
||||
// The format is simple key=value, one per line. Blank lines and lines
|
||||
// starting with # are ignored. Keys and values are trimmed of whitespace.
|
||||
// Multi-value keys are whitespace-delimited.
|
||||
//
|
||||
// Minimal example (covers ~60% of packages):
|
||||
//
|
||||
@@ -16,12 +17,13 @@
|
||||
// repo = jq
|
||||
// version_prefixes = jq-
|
||||
//
|
||||
// With filename exclusions (hugo publishes _extended_ variants):
|
||||
// With filename exclusions and variant documentation:
|
||||
//
|
||||
// source = github
|
||||
// owner = gohugoio
|
||||
// repo = hugo
|
||||
// exclude = _extended_, Linux-64bit
|
||||
// exclude = _extended_ Linux-64bit
|
||||
// variants = extended extended_withdeploy
|
||||
//
|
||||
// Monorepo with tag prefix:
|
||||
//
|
||||
@@ -43,6 +45,8 @@
|
||||
// Complex packages that need custom logic beyond what the classifier
|
||||
// auto-detects (e.g. ollama's universal binaries, ffmpeg's non-standard
|
||||
// naming) should put that logic in Go code, not in the config.
|
||||
// The variants key documents known build variants for human readers;
|
||||
// actual variant detection logic lives in Go.
|
||||
package installerconf
|
||||
|
||||
import (
|
||||
@@ -74,17 +78,21 @@ type Conf struct {
|
||||
TagPrefix string
|
||||
|
||||
// VersionPrefixes are stripped from version/tag strings.
|
||||
// Comma-separated. Each release tag is checked against these in order;
|
||||
// the first match is stripped. Projects may change tag conventions across
|
||||
// versions (e.g. "jq-1.7.1" in older releases, bare "1.8.0" later).
|
||||
// Example: "jq-, cli-"
|
||||
// Whitespace-delimited. Each release tag is checked against these
|
||||
// in order; the first match is stripped. Projects may change tag
|
||||
// conventions across versions (e.g. "jq-1.7.1" older, "1.8.0" later).
|
||||
VersionPrefixes []string
|
||||
|
||||
// Exclude lists filename substrings to filter out.
|
||||
// Assets whose name contains any of these are skipped.
|
||||
// Example: ["_extended_", "-gogit-", "-docs-"]
|
||||
// Whitespace-delimited. Assets whose name contains any of these
|
||||
// are skipped entirely (not stored).
|
||||
Exclude []string
|
||||
|
||||
// Variants documents known build variant names for this package.
|
||||
// Whitespace-delimited. This is a human-readable cue — actual
|
||||
// variant detection logic lives in Go code per-package.
|
||||
Variants []string
|
||||
|
||||
// Extra holds any unrecognized keys for forward compatibility.
|
||||
Extra map[string]string
|
||||
}
|
||||
@@ -121,15 +129,9 @@ func Read(path string) (*Conf, error) {
|
||||
c.TagPrefix = raw["tag_prefix"]
|
||||
|
||||
if v := raw["version_prefixes"]; v != "" {
|
||||
for _, p := range strings.Split(v, ",") {
|
||||
p = strings.TrimSpace(p)
|
||||
if p != "" {
|
||||
c.VersionPrefixes = append(c.VersionPrefixes, p)
|
||||
}
|
||||
}
|
||||
c.VersionPrefixes = strings.Fields(v)
|
||||
} else if v := raw["version_prefix"]; v != "" {
|
||||
// Back-compat with singular form.
|
||||
c.VersionPrefixes = []string{v}
|
||||
c.VersionPrefixes = strings.Fields(v)
|
||||
}
|
||||
|
||||
if v := raw["base_url"]; v != "" {
|
||||
@@ -138,13 +140,15 @@ func Read(path string) (*Conf, error) {
|
||||
c.BaseURL = raw["url"]
|
||||
}
|
||||
|
||||
// Accept both "exclude" and "asset_exclude" (back-compat).
|
||||
if v := raw["exclude"]; v != "" {
|
||||
for _, p := range strings.Split(v, ",") {
|
||||
p = strings.TrimSpace(p)
|
||||
if p != "" {
|
||||
c.Exclude = append(c.Exclude, p)
|
||||
}
|
||||
}
|
||||
c.Exclude = strings.Fields(v)
|
||||
} else if v := raw["asset_exclude"]; v != "" {
|
||||
c.Exclude = strings.Fields(v)
|
||||
}
|
||||
|
||||
if v := raw["variants"]; v != "" {
|
||||
c.Variants = strings.Fields(v)
|
||||
}
|
||||
|
||||
// Collect unrecognized keys.
|
||||
@@ -152,7 +156,7 @@ func Read(path string) (*Conf, error) {
|
||||
"source": true, "owner": true, "repo": true,
|
||||
"base_url": true, "url": true,
|
||||
"tag_prefix": true, "version_prefix": true, "version_prefixes": true,
|
||||
"exclude": true,
|
||||
"exclude": true, "asset_exclude": true, "variants": true,
|
||||
}
|
||||
for k, v := range raw {
|
||||
if !known[k] {
|
||||
|
||||
@@ -32,7 +32,7 @@ func TestVersionPrefixes(t *testing.T) {
|
||||
source = github
|
||||
owner = jqlang
|
||||
repo = jq
|
||||
version_prefixes = jq-, cli-
|
||||
version_prefixes = jq- cli-
|
||||
`)
|
||||
if len(c.VersionPrefixes) != 2 {
|
||||
t.Fatalf("VersionPrefixes has %d items, want 2: %v", len(c.VersionPrefixes), c.VersionPrefixes)
|
||||
@@ -46,7 +46,7 @@ func TestExclude(t *testing.T) {
|
||||
source = github
|
||||
owner = gohugoio
|
||||
repo = hugo
|
||||
exclude = _extended_, Linux-64bit
|
||||
exclude = _extended_ Linux-64bit
|
||||
`)
|
||||
if len(c.Exclude) != 2 {
|
||||
t.Fatalf("Exclude has %d items, want 2: %v", len(c.Exclude), c.Exclude)
|
||||
@@ -110,6 +110,34 @@ custom_thing = hello
|
||||
}
|
||||
}
|
||||
|
||||
func TestAssetExcludeAlias(t *testing.T) {
|
||||
c := confFromString(t, `
|
||||
source = github
|
||||
owner = gohugoio
|
||||
repo = hugo
|
||||
asset_exclude = extended
|
||||
`)
|
||||
if len(c.Exclude) != 1 {
|
||||
t.Fatalf("Exclude has %d items, want 1: %v", len(c.Exclude), c.Exclude)
|
||||
}
|
||||
assertEqual(t, "Exclude[0]", c.Exclude[0], "extended")
|
||||
}
|
||||
|
||||
func TestVariants(t *testing.T) {
|
||||
c := confFromString(t, `
|
||||
source = github
|
||||
owner = jmorganca
|
||||
repo = ollama
|
||||
variants = rocm jetpack5 jetpack6
|
||||
`)
|
||||
if len(c.Variants) != 3 {
|
||||
t.Fatalf("Variants has %d items, want 3: %v", len(c.Variants), c.Variants)
|
||||
}
|
||||
assertEqual(t, "Variants[0]", c.Variants[0], "rocm")
|
||||
assertEqual(t, "Variants[1]", c.Variants[1], "jetpack5")
|
||||
assertEqual(t, "Variants[2]", c.Variants[2], "jetpack6")
|
||||
}
|
||||
|
||||
func TestEmptyExclude(t *testing.T) {
|
||||
c := confFromString(t, "source = github\n")
|
||||
if c.Exclude != nil {
|
||||
|
||||
@@ -1,3 +1,4 @@
|
||||
source = github
|
||||
owner = jmorganca
|
||||
repo = ollama
|
||||
variants = rocm jetpack5 jetpack6
|
||||
|
||||
@@ -1,3 +1,4 @@
|
||||
source = github
|
||||
owner = powershell
|
||||
repo = powershell
|
||||
variants = fxdependent fxdependentWinDesktop
|
||||
|
||||
Reference in New Issue
Block a user