Building RPM for acme-dns 0.8 (with go)

Acme-dns 0.8 was released yesterday:


It represents a significant change in functionality from 0.7.2, and also in how the source is designed. And it seems to be breaking my build process.

Here’s what I was doing to build the RPM successfully with 0.7.2:

mock -r nethserver-7-x86_64 --init
mock -r nethserver-7-x86_64 --install go
mock -r nethserver-7-x86_64 --buildsrpm --spec <specfile> --sources . --resultdir .
mock -r nethserver-7-x86_64 --rebuild <.src.rpm> --resultdir .

…and what I think would be the relevant portion of the .spec file:

%prep
%setup -c -q -n "acme-dns-%{pkg_version}"
mv %{_builddir}/acme-dns-%{pkg_version}/acme-dns-%{pkg_version}/* %{_builddir}/acme-dns-%{pkg_version}/

%build
GOPATH=%{_builddir}/acme-dns-%{pkg_version}/ go build -v -o acme-dns

…and the end of the build process:

Executing(%build): /bin/sh -e /var/tmp/rpm-tmp.yvCviK
+ umask 022
+ cd /builddir/build/BUILD
+ cd acme-dns-0.8
+ GOPATH=/builddir/build/BUILD/acme-dns-0.8/
+ go build -v -o acme-dns
$GOPATH/go.mod exists but should not


RPM build errors:
error: Bad exit status from /var/tmp/rpm-tmp.yvCviK (%build)
    Bad exit status from /var/tmp/rpm-tmp.yvCviK (%build)
ERROR: Exception(acme-dns-0.8-1ns7.src.rpm) Config(nethserver-7-x86_64) 1 minutes 27 seconds
INFO: Results and/or logs in: .
INFO: Cleaning up build root ('cleanup_on_failure=True')
Start: clean chroot
Finish: clean chroot
ERROR: state finish mismatch: current: rpmbuild acme-dns-0.8-1ns7.src.rpm, state: build phase for acme-dns-0.8-1ns7.src.rpm

The error is kind of confusing to me–a web search indicates that the go.mod file shouldn’t be there, but I can download the source tarball, extract it, cd to the directory, and run go build -v -o acme-dns, and it completes successfully. Obviously there’s some difference between doing it this way and via trying to build the RPM, but I’m at a loss to figure it out right now. Any thoughts what I’m missing here?

1 Like

You may try it without defining the GOPATH explicitly, ie omit this in the spec file:

2 Likes

Well, it’s changed the output, but still doesn’t build:

Executing(%build): /bin/sh -e /var/tmp/rpm-tmp.pWolNO
+ umask 022
+ cd /builddir/build/BUILD
+ cd acme-dns-0.8
+ go build -v -o acme-dns
go: github.com/BurntSushi/toml@v0.3.1: reading github.com/BurntSushi/toml/go.mod at revision v0.3.1: unknown revision v0.3.1

That project (BurntSushi/toml) does have a release tagged v0.3.1, but the RPM build process doesn’t seem to be seeing it.

From what I can see (which isn’t much, so feel free to disregard if this sounds silly), the problem relates to how the libraries/modules are being handled. Under 0.7 and prior, those were packaged in the source tree for acme-dns in the vendor/ subdirectory (which I had to move to a src/ subdirectory in order to get those to build). Now, the maintainer has migrated to Go 1.13 (which is the version that mock will install in its environment), and stopped bundling those dependencies, rather having them download at build time. It makes the source tarball much smaller (< 50 KB vs. 16 MB), but apparently needs a somewhat different build process in ways I haven’t yet figured out.

Yes that’s true and I’m also struggling with figuring this out… It seems Go V1.13 is more to blame in this situation, With newer Go versions they changed the logic for vendoring, forcing dependency modules out-of the builld-tree (or path, whatever they call it) .
I read some posts of the like " After feedback of the community we …bla… …bla… …bla… legacy vendoring" cannot find it now but I read this more like “After a lot of complains we reverted this, sorry…” .
Meanwhile a lot of developers adopted this new logic and stopped publishing “vendored” sources. IIUC with Go 1.13 it is possible to honner the vendor directory again with the flag mod=vendor. However this won’t help if the developer does not include the dependency modules in the source, which makes maintaining such a packages for a distro an nightmare.

Will try to look into the acme-dns package in more detail soon.

Meanwhile you can try to build in a mock chroot with network enabled and go get modules first, but you won’t end up with a source-rpm which can be rebuild…

I never found a way to easily build a go application inside an RPM environment.
As workaround, I usually build the go binary in a prep-sources script like this one: https://github.com/nethesis/dante/blob/master/dist/prep-sources#L28

That’s a possibility. Or I could go back to what I was doing before 0.7.2-2, and just build the developer’s Linux binary release into an RPM. Neither is really consistent with the intent of RPMs, but certainly the latter works.

I opened an issue against acme-dns because I thought the tarball was incomplete (it’s 0.3% the size of the previous version, so I don’t think that was an unreasonable assumption), and it sounds like he might be open to including the vendor/ directory again–so that may be another possibility.

What’s confusing to me is that if I just do cd /wherever; go build -v -o acme-dns, it works just fine. But, as near as I can tell, I’m doing the same thing in the RPM build process–and it doesn’t work there. Obviously something’s different, but it isn’t apparent to me what it is.

Edit: Even more confusing, though it presents a straightforward workaround: If I just install golang on my development VM (yum install golang), copy the .spec and source files into an RPM build tree, and run rpmbuild -ba acme-dns.spec, it builds just fine. So it’s something specific to the mock environment, so it’s an easy workaround–just don’t use mock to build the RPM. This leaves the question of what mock is doing to break things, but until that’s resolved, it’s another way to get the RPM built.

1 Like