Solved Poudriere go:modules and GHT_TUPLE issues with custom build script

I'm creating a port for Publisher, a Go application, that uses a custom build script instead of GO_TARGET. The script calls go build -mod=vendor directly.

I'm doing it with the help of an LLM that is using USES=go:modules with GH_TUPLE. The framework extracts all dependencies into the vendor directory correctly, but the generated vendor/modules.txt is missing ## explicit markers. This causes "Go 1.25" to fail with:

Code:
go: inconsistent vendoring    github.com/Masterminds/semver@v1.5.0: is explicitly required in go.mod,    but not marked as explicit in vendor/modules.txt    To sync the vendor directory, run: go mod vendor

The LLM states that: running go mod vendor in a pre-build target would fix this, but inside Poudriere it fails because GOPATH points to /portdistfiles/go/ which is not writable by the nobody user.

The LLM is stuck, it doesn't find a solution, and my presence is practically useless, what would be the correct way to handle this situation?

Additional info:
  • go.mod is not in the repository root, so it is used WRKSRC_SUBDIR=src/go
  • FreeBSD 15.0, Poudriere 3.4.4, Go 1.25
Makefile
Code:
cat /usr/local/poudriere/ports/latest/print/publisher/Makefile
PORTNAME=    publisher
DISTVERSION=    5.4.0
CATEGORIES=    print
DIST_SUBDIR=    publisher

MAINTAINER=    misterd@renderdata.pro
COMMENT=    Non-interactive Layout Engine Typesetting
WWW=        https://www.speedata.de/

LICENSE=    AGPLv3
LICENSE_FILE=    ${PUBLISHER_WRKSRC}/COPYING

BUILD_DEPENDS=    git:devel/git \
        lua53:lang/lua53
RUN_DEPENDS=    lua53:lang/lua53 \
        luahbtex:print/tex-luatex

USES=        go:modules
USE_GITHUB=    yes
GH_ACCOUNT=    speedata
GH_PROJECT=    publisher
GH_TAGNAME=    v${DISTVERSION}
WRKSRC_SUBDIR=    src/go
PUBLISHER_WRKSRC=    ${WRKDIR}/${GH_PROJECT}-${DISTVERSION}

GH_TUPLE=    \
        Masterminds:semver:v1.5.0:masterminds_semver/vendor/github.com/Masterminds/semver \
        PuerkitoBio:goquery:v1.9.1:puerkitobio_goquery/vendor/github.com/PuerkitoBio/goquery \
        alecthomas:chroma:v0.10.0:alecthomas_chroma/vendor/github.com/alecthomas/chroma \
        alecthomas:chroma:v2.13.0:alecthomas_chroma_v2/vendor/github.com/alecthomas/chroma/v2 \
        andybalholm:cascadia:v1.3.2:andybalholm_cascadia/vendor/github.com/andybalholm/cascadia \
        cjoudrey:gluahttp:25003d9adfa9:cjoudrey_gluahttp/vendor/github.com/cjoudrey/gluahttp \
        dlclark:regexp2:v1.11.0:dlclark_regexp2/vendor/github.com/dlclark/regexp2 \
        fsnotify:fsnotify:v1.7.0:fsnotify_fsnotify/vendor/github.com/fsnotify/fsnotify \
        gammazero:deque:v0.2.1:gammazero_deque/vendor/github.com/gammazero/deque \
        gammazero:workerpool:v1.1.3:gammazero_workerpool/vendor/github.com/gammazero/workerpool \
        go-yaml:yaml:v3.0.1:go_yaml_yaml/vendor/gopkg.in/yaml.v3 \
        gofrs:uuid:v4.4.0:gofrs_uuid/vendor/github.com/gofrs/uuid \
        golang:image:v0.18.0:golang_image/vendor/golang.org/x/image \
        golang:net:v0.35.0:golang_net/vendor/golang.org/x/net \
        golang:sys:v0.30.0:golang_sys/vendor/golang.org/x/sys \
        golang:text:v0.22.0:golang_text/vendor/golang.org/x/text \
        google:btree:v1.1.2:google_btree/vendor/github.com/google/btree \
        gorilla:mux:v1.8.1:gorilla_mux/vendor/github.com/gorilla/mux \
        gregjones:httpcache:901d90724c79:gregjones_httpcache/vendor/github.com/gregjones/httpcache \
        inconshreveable:mousetrap:v1.1.0:inconshreveable_mousetrap/vendor/github.com/inconshreveable/mousetrap \
        peterbourgon:diskv:v2.0.1:peterbourgon_diskv/vendor/github.com/peterbourgon/diskv \
        russross:blackfriday:v1.6.0:russross_blackfriday/vendor/github.com/russross/blackfriday \
        speedata:bild:dd063a632b14:speedata_bild/vendor/github.com/speedata/bild \
        speedata:config:3a3f44982ec4:speedata_config/vendor/github.com/speedata/config \
        speedata:css:68d469dc62c4:speedata_css_scanner/vendor/github.com/speedata/css \
        speedata:go-epub:v0.5.5:speedata_go_epub/vendor/github.com/speedata/go-epub \
        speedata:goxlsx:v1.0.2:speedata_goxlsx/vendor/github.com/speedata/goxlsx \
        speedata:hotfolder:5f743a840a92:speedata_hotfolder/vendor/github.com/speedata/hotfolder \
        speedata:optionparser:v1.1.1:speedata_optionparser/vendor/github.com/speedata/optionparser \
        yuin:goldmark-highlighting:37449abec8cc:yuin_goldmark_highlighting_v2/vendor/github.com/yuin/goldmark-highlighting/v2 \
        yuin:goldmark:v1.7.1:yuin_goldmark/vendor/github.com/yuin/goldmark \
        yuin:gopher-lua:v1.1.1:yuin_gopher_lua/vendor/github.com/yuin/gopher-lua

CONFLICTS_INSTALL=    publisher-devel

OPTIONS_DEFINE=    PRO
PRO_DESC=    Build the Pro version
PRO_MAKE_ENV=    SDPRO=yes

pre-build:
    ${INSTALL_SCRIPT} ${FILESDIR}/sphelper.sh ${PUBLISHER_WRKSRC}/sphelper.sh

do-build:
    cd ${PUBLISHER_WRKSRC} && ${SETENV} ${MAKE_ENV} ${SH} sphelper.sh buildlib
    cd ${PUBLISHER_WRKSRC} && ${SETENV} ${MAKE_ENV} ${SH} sphelper.sh build

do-install:
    cd ${PUBLISHER_WRKSRC} && ${SETENV} ${MAKE_ENV} PREFIX=${STAGEDIR}${PREFIX} ${SH} sphelper.sh install

.include <bsd.port.mk>

BUILD SECTION LOG:
Code:
=======================<phase: build          >============================
===== env: NO_DEPENDS=yes USER=nobody UID=65534 GID=65534
===>  Building for publisher-5.4.0
install  -m 555 /usr/ports/print/publisher/files/sphelper.sh /wrkdirs/usr/ports/print/publisher/work/publisher-5.4.0/sphelper.sh
cd /wrkdirs/usr/ports/print/publisher/work/publisher-5.4.0 && /usr/bin/env XDG_DATA_HOME=/wrkdirs/usr/ports/print/publisher/work  XDG_CONFIG_HOME=/wrkdirs/usr/ports/print/publisher/work  XDG_CACHE_HOME=/wrkdirs/usr/ports/print/publisher/work/.cache  HOME=/wrkdirs/usr/ports/print/publisher/work TMPDIR="/tmp" PATH=/wrkdirs/usr/ports/print/publisher/work/.bin:/sbin:/bin:/usr/sbin:/usr/bin:/usr/local/sbin:/usr/local/bin:/nonexistent/bin PKG_CONFIG_LIBDIR=/wrkdirs/usr/ports/print/publisher/work/.pkgconfig:/usr/local/libdata/pkgconfig:/usr/local/share/pkgconfig:/usr/libdata/pkgconfig MK_DEBUG_FILES=no MK_KERNEL_SYMBOLS=no SHELL=/bin/sh NO_LINT=YES PREFIX=/usr/local  LOCALBASE=/usr/local  CC="cc" CFLAGS="-O2 -pipe  -fstack-protector-strong -fno-strict-aliasing "  CPP="cpp" CPPFLAGS=""  LDFLAGS=" " LIBS=""  CXX="c++" CXXFLAGS="-O2 -pipe -fstack-protector-strong -fno-strict-aliasing   " BSD_INSTALL_PROGRAM="install  -s -m 555"  BSD_INSTALL_LIB="install  -s -m 0644"  BSD_INSTALL_SCRIPT="install  -m 555"  BSD_INSTALL_DATA="install  -m 0644"  BSD_INSTALL_MAN="install  -m 444" /bin/sh sphelper.sh buildlib
Building dynamic library for freebsd amd64
go: inconsistent vendoring in /wrkdirs/usr/ports/print/publisher/work/publisher-5.4.0/src/go:
    github.com/Masterminds/semver@v1.5.0: is explicitly required in go.mod, but not marked as explicit in vendor/modules.txt
    github.com/PuerkitoBio/goquery@v1.9.1: is explicitly required in go.mod, but not marked as explicit in vendor/modules.txt
    github.com/alecthomas/chroma@v0.10.0: is explicitly required in go.mod, but not marked as explicit in vendor/modules.txt
    github.com/alecthomas/chroma/v2@v2.13.0: is explicitly required in go.mod, but not marked as explicit in vendor/modules.txt
    github.com/andybalholm/cascadia@v1.3.2: is explicitly required in go.mod, but not marked as explicit in vendor/modules.txt
    github.com/cjoudrey/gluahttp@v0.0.0-20201111170219-25003d9adfa9: is explicitly required in go.mod, but not marked as explicit in vendor/modules.txt
    github.com/fsnotify/fsnotify@v1.7.0: is explicitly required in go.mod, but not marked as explicit in vendor/modules.txt
    github.com/gammazero/workerpool@v1.1.3: is explicitly required in go.mod, but not marked as explicit in vendor/modules.txt
    github.com/gorilla/mux@v1.8.1: is explicitly required in go.mod, but not marked as explicit in vendor/modules.txt
    github.com/gregjones/httpcache@v0.0.0-20190611155906-901d90724c79: is explicitly required in go.mod, but not marked as explicit in vendor/modules.txt
    github.com/inconshreveable/mousetrap@v1.1.0: is explicitly required in go.mod, but not marked as explicit in vendor/modules.txt
    github.com/russross/blackfriday@v1.6.0: is explicitly required in go.mod, but not marked as explicit in vendor/modules.txt
    github.com/speedata/bild@v0.0.0-20240628091728-dd063a632b14: is explicitly required in go.mod, but not marked as explicit in vendor/modules.txt
    github.com/speedata/config@v0.0.0-20181203093101-3a3f44982ec4: is explicitly required in go.mod, but not marked as explicit in vendor/modules.txt
    github.com/speedata/css/scanner@v0.0.0-20250825095519-68d469dc62c4: is explicitly required in go.mod, but not marked as explicit in vendor/modules.txt
    github.com/speedata/go-epub@v0.5.5: is explicitly required in go.mod, but not marked as explicit in vendor/modules.txt
    github.com/speedata/goxlsx@v1.0.2: is explicitly required in go.mod, but not marked as explicit in vendor/modules.txt
    github.com/speedata/hotfolder@v0.0.0-20181204121114-5f743a840a92: is explicitly required in go.mod, but not marked as explicit in vendor/modules.txt
    github.com/speedata/optionparser@v1.1.1: is explicitly required in go.mod, but not marked as explicit in vendor/modules.txt
    github.com/yuin/goldmark@v1.7.1: is explicitly required in go.mod, but not marked as explicit in vendor/modules.txt
    github.com/yuin/goldmark-highlighting/v2@v2.0.0-20230729083705-37449abec8cc: is explicitly required in go.mod, but not marked as explicit in vendor/modules.txt
    github.com/yuin/gopher-lua@v1.1.1: is explicitly required in go.mod, but not marked as explicit in vendor/modules.txt
    golang.org/x/net@v0.35.0: is explicitly required in go.mod, but not marked as explicit in vendor/modules.txt
    golang.org/x/sys@v0.30.0: is explicitly required in go.mod, but not marked as explicit in vendor/modules.txt
    golang.org/x/text@v0.22.0: is explicitly required in go.mod, but not marked as explicit in vendor/modules.txt
    github.com/dlclark/regexp2@v1.11.0: is explicitly required in go.mod, but not marked as explicit in vendor/modules.txt
    github.com/gammazero/deque@v0.2.1: is explicitly required in go.mod, but not marked as explicit in vendor/modules.txt
    github.com/gofrs/uuid@v4.4.0+incompatible: is explicitly required in go.mod, but not marked as explicit in vendor/modules.txt
    github.com/google/btree@v1.1.2: is explicitly required in go.mod, but not marked as explicit in vendor/modules.txt
    github.com/peterbourgon/diskv@v2.0.1+incompatible: is explicitly required in go.mod, but not marked as explicit in vendor/modules.txt
    golang.org/x/image@v0.18.0: is explicitly required in go.mod, but not marked as explicit in vendor/modules.txt
    gopkg.in/yaml.v3@v3.0.1: is explicitly required in go.mod, but not marked as explicit in vendor/modules.txt

    To ignore the vendor directory, use -mod=readonly or -mod=mod.
    To sync the vendor directory, run:
        go mod vendor
*** Error code 1

Stop.
make: stopped making "build" in /usr/ports/print/publisher
=>> Cleaning up wrkdir
===>  Cleaning for publisher-5.4.0
build of print/publisher | publisher-5.4.0 ended at Sat Feb 28 01:36:03 EST 2026
build time: 00:00:23
!!! build failure encountered !!!

Thanks... 🙏🙏🙏
 
I was able to build it with Poudriere:

Code:
[00:06:31] [01] [00:06:24] Finished print/publisher | publisher-5.4.0: Success
[00:06:32] Stopping 1 builders
15amd64-latest-job-01: removed
15amd64-latest-job-01-n: removed
[00:06:33] Creating pkg repository
Creating repository in /tmp/packages: 100%
Packing files for repository: 100%
[00:06:47] Committing packages to repository: /usr/local/poudriere/data/packages/15amd64-latest/.real_1772289575 via .latest symlink
[00:06:47] Removing old packages
[00:06:47] Built ports: print/publisher
[15amd64-latest] [2026-02-28_09h32m48s] [committing] Queued: 1  Built: 1  Failed: 0  Skipped: 0  Ignored: 0  Fetched: 0  Tobuild: 0   Time: 00:06:44
[00:06:47] Logs: /usr/local/poudriere/data/logs/bulk/15amd64-latest/2026-02-28_09h32m48s
[00:06:47] Cleaning up
15amd64-latest: removed
15amd64-latest-n: removed
[00:06:47] Unmounting file systems

The solution was a combination of three things:
  1. USES=go:modules with GH_TUPLE — the proper FreeBSD way to declare Go dependencies, replacing the rerolled tarball approach
  2. GO_MODULE=speedatapublisher — adding this triggered the framework's go-post-extract to run go mod vendor, which created the vendor directory structure
  3. files/modules.txt copied in post-extract — since the framework's go mod vendor generates a vendor/modules.txt without ## explicit markers, we pre-generate a correct one on the host using go125 mod vendor and copy it into place after extraction, overwriting the incomplete one
The root cause was that Go 1.25 is strict about ## explicit markers in vendor/modules.txt, and the framework wasn't generating them correctly for a non-standard module name like speedatapublisher.
 
Back
Top