Files
artifactapi/internal/testsupport/deb.go
T
unkin-agent 60f008debc Add deb (Debian/apt) local and remote repository support (#111)
Brings Debian/apt to artifactapi with feature parity to the existing rpm support (local + remote), so `.deb` packages can be hosted as a flat apt repo and a Debian/Ubuntu mirror can be cached through the proxy.

- Adds `deb` to the package-type enum and registers a new `internal/provider/deb` provider.
- Classifies `.deb` blobs immutable and the apt index surface (`Packages`, `Release`, `InRelease`, `dists/`, by-hash) mutable so the caching engine revalidates it.
- Parses the `.deb` in pure Go (ar archive to `control.tar.{gz,xz,zst}` to `./control`), storing the raw control stanza plus computed size/md5/sha256 as `deb_metadata`.
- Serves a flat apt repo (`deb [trusted=yes] .../ ./`): generates `Packages`, `Packages.gz` and an unsigned `Release` (returns 404 for `InRelease`/`Release.gpg`), mirroring rpm unsigned repodata / gpgcheck=0 trust model.
- Proxies a remote mirror via `UpstreamURL`/`ContentType`/`AuthHeaders` (HTTP Basic).
- Adds the `deb_metadata` table to `migrate()`, DB access methods, a `MinimalDeb` pure-Go fixture, unit tests, and a `dockere2e` `TestLocalDebRepo`.

---------

Co-authored-by: unkin-agent <unkin-agent@git.unkin.net>
Reviewed-on: #111
Co-authored-by: Unkin Agent <unkin-agent@unkin.net>
Co-committed-by: Unkin Agent <unkin-agent@unkin.net>
2026-08-11 23:21:08 +10:00

62 lines
1.6 KiB
Go

package testsupport
import (
"archive/tar"
"bytes"
"compress/gzip"
"fmt"
)
// MinimalDeb builds a valid-enough Debian package in pure Go (no committed
// binary fixture, no dpkg-deb): an ar archive of debian-binary, a gzip
// control.tar.gz carrying ./control, and an (empty) gzip data.tar.gz. It is the
// deb analog of MinimalRPM and is parseable by the deb provider.
func MinimalDeb(name, version, arch string) []byte {
control := fmt.Sprintf(
"Package: %s\nVersion: %s\nArchitecture: %s\nMaintainer: e2e <e2e@example.com>\n"+
"Section: utils\nPriority: optional\nDescription: minimal test package\n",
name, version, arch)
controlTarGz := gzipBytes(tarSingle("./control", []byte(control)))
dataTarGz := gzipBytes(tarEmpty())
var buf bytes.Buffer
buf.WriteString("!<arch>\n")
arWrite(&buf, "debian-binary", []byte("2.0\n"))
arWrite(&buf, "control.tar.gz", controlTarGz)
arWrite(&buf, "data.tar.gz", dataTarGz)
return buf.Bytes()
}
func arWrite(buf *bytes.Buffer, name string, data []byte) {
fmt.Fprintf(buf, "%-16s%-12s%-6s%-6s%-8s%-10d`\n", name, "0", "0", "0", "100644", len(data))
buf.Write(data)
if len(data)%2 == 1 {
buf.WriteByte('\n')
}
}
func tarSingle(name string, data []byte) []byte {
var buf bytes.Buffer
tw := tar.NewWriter(&buf)
tw.WriteHeader(&tar.Header{Name: name, Mode: 0o644, Size: int64(len(data)), Typeflag: tar.TypeReg})
tw.Write(data)
tw.Close()
return buf.Bytes()
}
func tarEmpty() []byte {
var buf bytes.Buffer
tw := tar.NewWriter(&buf)
tw.Close()
return buf.Bytes()
}
func gzipBytes(data []byte) []byte {
var buf bytes.Buffer
gz := gzip.NewWriter(&buf)
gz.Write(data)
gz.Close()
return buf.Bytes()
}