Files
artifactapi/internal/testsupport/deb.go
T
unkin-agent a35f260b74
ci/woodpecker/pr/build Pipeline was successful
ci/woodpecker/pr/pre-commit Pipeline was successful
ci/woodpecker/pr/test Pipeline was successful
feat: deb (Debian/apt) local and remote repository support
Adds a deb provider with feature parity to rpm for local and remote repos,
so .deb packages can be hosted (flat apt repo generated on upload) and a
Debian/Ubuntu mirror can be cached through the proxy.

- add PackageDeb to the package-type enum
- new internal/provider/deb: Classify (.deb immutable, Packages/Release/dists
  mutable), ValidateUpload to pool/<file>, pure-Go .deb parse (ar -> control.tar
  gz/xz/zst -> ./control), and a flat-repo LocalIndexer serving Packages,
  Packages.gz and an unsigned Release ([trusted=yes], mirroring rpm gpgcheck=0)
- remote proxy path: UpstreamURL/ContentType/AuthHeaders via BasicHeaders
- DebMetadata struct + store interfaces on provider; deb_metadata table in
  migrate() and Insert/Delete/List DB methods
- blank-import the deb provider in the server
- testsupport.MinimalDeb pure-Go fixture builder
- unit tests (classify, control parse across gz/xz/zst, Packages/Release
  generation, validate) and a dockere2e TestLocalDebRepo
2026-08-11 22:00:49 +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()
}