packaging/linux/rpm/rpmbuild.go (37 lines of code) (raw):
package rpm
import (
"errors"
"fmt"
"github.com/Azure/dalec"
"github.com/moby/buildkit/client/llb"
)
// Builds an RPM and source RPM from a spec
//
// `topDir` is the rpmbuild top directory which should contain the SOURCES and SPECS directories along with any other necessary files
//
// `workerImg` is the image to use for the build
// It is expected to have rpmbuild and any other necessary build dependencies installed
//
// `specPath` is the path to the spec file to build relative to `topDir`
func Build(topDir, workerImg llb.State, specPath string, opts ...llb.ConstraintsOpt) llb.State {
opts = append(opts, dalec.ProgressGroup("Build RPM"))
return workerImg.Run(
// some notes on these args:
// - _topdir is the directory where rpmbuild will look for SOURCES and SPECS
// - _srcrpmdir is the directory where rpmbuild will put the source RPM
// - _rpmdir is the directory where rpmbuild will put the RPM
// - --buildroot is the work directory where rpmbuild will build the RPM
// - -ba tells rpmbuild to build the source and binary RPMs
//
// TODO(cpuguy83): specPath would ideally never change.
// We don't want to have to re-run this step just because the path changed, this should be based on inputs only (ie the content of the rpm spec, sources, etc)
// The path should not be an input.
dalec.ShArgs(`rpmbuild --define "_topdir /build/top" --define "_srcrpmdir /build/out/SRPMS" --define "_rpmdir /build/out/RPMS" --buildroot /build/tmp/work -ba `+specPath),
llb.AddMount("/build/top", topDir),
llb.AddMount("/build/tmp", llb.Scratch(), llb.Tmpfs()),
llb.Dir("/build/top"),
dalec.WithConstraints(opts...),
).
AddMount("/build/out", llb.Scratch())
}
var errMissingRequiredField = errors.New("missing required field")
// ValidateSpec makes sure all the necessary fields are present in the spec to make rpmbuild work
// This validation is specific to rpmbuild.
func ValidateSpec(spec *dalec.Spec) (out error) {
if spec.Name == "" {
out = errors.Join(out, fmt.Errorf("%w: name", errMissingRequiredField))
}
if spec.Version == "" {
out = errors.Join(out, fmt.Errorf("%w: version", errMissingRequiredField))
}
if spec.Revision == "" {
out = errors.Join(out, fmt.Errorf("%w: revision", errMissingRequiredField))
}
if spec.Description == "" {
out = errors.Join(out, fmt.Errorf("%w: description", errMissingRequiredField))
}
if spec.License == "" {
out = errors.Join(out, fmt.Errorf("%w: license", errMissingRequiredField))
}
return out
}