ref(classify): separate core classifier from legacy backport

Move legacy-specific field translations out of the core classifier into
LegacyBackport(), called by webicached before writing the JSON cache.

Core classifier now outputs canonical values:
- Go dist arm → armv6 (correct per GOARM default)
- ffmpeg Windows .gz → .gz (correct file extension)

LegacyBackport remaps for Node.js compat:
- Go dist armv6 → arm (production keeps raw API value)
- ffmpeg Windows .gz → exe (production releases.js override)

sass armv6→armv7 stays in classifier (Dart Sass genuinely targets ARMv7).
This commit is contained in:
AJ ONeal
2026-03-11 13:58:59 -06:00
parent de1de7fccd
commit 31dc1f114b
3 changed files with 51 additions and 35 deletions

View File

@@ -316,6 +316,8 @@ func (wc *WebiCache) refreshPackage(ctx context.Context, pkg pkgConf) error {
if err != nil {
return fmt.Errorf("classify: %w", err)
}
// Legacy backport: translate canonical values to what Node.js expects.
classifypkg.LegacyBackport(name, assets)
classifyDur := time.Since(classifyStart)
// Step 3: Write to fsstore.

View File

@@ -22,7 +22,6 @@ import (
"github.com/webinstall/webi-installers/internal/rawcache"
"github.com/webinstall/webi-installers/internal/releases/bun"
"github.com/webinstall/webi-installers/internal/releases/chromedist"
"github.com/webinstall/webi-installers/internal/releases/ffmpeg"
"github.com/webinstall/webi-installers/internal/releases/fish"
"github.com/webinstall/webi-installers/internal/releases/gitea"
"github.com/webinstall/webi-installers/internal/releases/flutterdist"
@@ -151,8 +150,6 @@ func TagVariants(pkg string, assets []storage.Asset) {
switch pkg {
case "bun":
bun.TagVariants(assets)
case "ffmpeg":
ffmpeg.TagVariants(assets)
case "fish":
fish.TagVariants(assets)
case "git":
@@ -271,6 +268,54 @@ func ApplyConfig(assets []storage.Asset, conf *installerconf.Conf) []storage.Ass
return out
}
// LegacyBackport translates canonical classifier output into field values
// the Node.js legacy cache expects. The core classifier uses correct,
// canonical values (armv6, .gz, etc.); this function remaps them for
// backward compatibility with the production resolver.
//
// Call this after Package() when writing to the legacy JSON cache.
// The new Go resolver will use canonical values directly.
func LegacyBackport(pkg string, assets []storage.Asset) {
switch pkg {
case "go":
legacyBackportGo(assets)
case "ffmpeg":
legacyBackportFFmpeg(assets)
}
}
// legacyBackportGo remaps Go dist's arm classification.
//
// The Go dist API uses bare "arm" (GOARM default = 6). The classifier
// canonicalizes this to "armv6". Production keeps the raw "arm" value
// because normalize.js doesn't run on Go dist assets. The legacy resolver
// expects "arm" for these assets.
func legacyBackportGo(assets []storage.Asset) {
for i := range assets {
if assets[i].Arch == "armv6" {
assets[i].Arch = "arm"
}
}
}
// legacyBackportFFmpeg remaps Windows gzipped executables.
//
// ffmpeg-static publishes bare executables for Windows. The .gz files
// are gzip-compressed bare executables (not tar archives). Production's
// ffmpeg/releases.js hardcodes rel.ext = 'exe' for Windows assets.
// The legacy resolver needs "exe" to serve these correctly.
func legacyBackportFFmpeg(assets []storage.Asset) {
for i := range assets {
if assets[i].OS != "windows" {
continue
}
switch assets[i].Format {
case ".gz", "":
assets[i].Format = ".exe"
}
}
}
// ReadAllRaw reads all non-directory, non-underscore-prefixed files from
// the active generation of a rawcache directory.
func ReadAllRaw(d *rawcache.Dir) (map[string][]byte, error) {
@@ -883,9 +928,7 @@ func normalizeGoArch(goarch string) string {
case "386":
return "x86"
case "arm":
// Go API uses bare "arm" — keep as-is to match production.
// The resolver handles arm compatibility (armv7→armv6 fallback).
return "arm"
return "armv6"
case "ppc64le":
return "ppc64le"
case "ppc64":

View File

@@ -1,29 +0,0 @@
// Package ffmpeg provides variant tagging for ffmpeg-static releases.
//
// ffmpeg-static publishes bare executables for Windows. The .gz files
// are gzip-compressed bare executables (not archives). Production
// classifies these as ext "exe".
package ffmpeg
import (
"github.com/webinstall/webi-installers/internal/storage"
)
// TagVariants fixes Windows asset extensions for ffmpeg.
//
// Windows .gz files contain a gzipped bare executable, not a tar archive.
// Production treats these as ext "exe". Bare Windows files (no extension)
// are also executables.
func TagVariants(assets []storage.Asset) {
for i := range assets {
if assets[i].OS != "windows" {
continue
}
switch assets[i].Format {
case ".gz":
assets[i].Format = ".exe"
case "":
assets[i].Format = ".exe"
}
}
}