go_modules: how to create go vendor tarballs from subdirectories
The go_modules OBS service is used to download, verify, and vendor Go module dependency sources.
As described in the source project’s (obs-service-go_modules) README:
Using the
go.modandgo.sumfiles present in a Go application,obs-service-go_moduleswill call Go tools in sequence:
go mod downloadgo mod verifygo mod vendor
obs-service-go_modulesthen creates avendor.tar.gzarchive (or another supported compression format) containing thevendor/directory generated bygo mod vendor.
This archive is produced in the RPM package directory and can be committed to OBS to support offline Go application builds for openSUSE, SUSE, and various other distributions.
The README also provides a few usage examples for packagers.
However, it wasn’t immediately clear how to use the go_modules OBS service to create multiple vendor tarballs from different subdirectories within a single Git source repository.
Below is an example where I create multiple vendor tarballs from a single Git repo— (in this case, the etcd project):
<services>
<!-- Service #1 -->
<service name="obs_scm">
<param name="url">https://github.com/etcd/etcd.git</param>
<param name="scm">git</param>
<param name="package-meta">yes</param>
<param name="versionformat">@PARENT_TAG@</param>
<param name="versionrewrite-pattern">v(.*)</param>
<param name="revision">v3.5.21</param>
<param name="without-version">yes</param>
</service>
<!-- Service #2 -->
<service name="go_modules">
<param name="archive">*etcd.obscpio</param>
</service>
<!-- Service #3 -->
<service name="go_modules">
<param name="archive">*etcd.obscpio</param>
<param name="subdir">server</param>
<param name="vendorname">vendor-server</param>
</service>
<!-- Service #4 -->
<service name="go_modules">
<param name="archive">*etcd.obscpio</param>
<param name="subdir">etcdctl</param>
<param name="vendorname">vendor-etcdctl</param>
</service>
</services>
The above _service file defines four services:
-
Service 1 clones the GitHub repo
github.com/etcd/etcd.gitinto the build root. The resulting output is acpioarchive blob—etcd.cpio. -
Service 2 locates the
etcd.cpioarchive, extracts it, runsgo mod download,go mod verify, andgo mod vendorfrom the repo root, and creates the defaultvendor.tar.gz. -
Service 3 and Service 4 work the same as Service 2, with one difference: they run the Go module commands from subdirectories:
- Service 3 changes into the
server/directory before running the Go commands, producing a tarball namedvendor-server.tar.gz. - Service 4 does the same for the
etcdctl/directory, producingvendor-etcdctl.tar.gz.
- Service 3 changes into the
🔍 Note the
subdirandvendornameparameters. These are the key to generating multiple vendor tarballs from various subdirectories, with custom names.
I found the full list of parameters accepted by the go_modules service defined here1:
...
parser.add_argument("--strategy", default="vendor")
parser.add_argument("--archive")
parser.add_argument("--outdir")
parser.add_argument("--compression", default=DEFAULT_COMPRESSION)
parser.add_argument("--basename")
parser.add_argument("--vendorname", default=DEFAULT_VENDOR_STEM)
parser.add_argument("--subdir")
...
The default values are defined here2:
DEFAULT_COMPRESSION = "gz"
DEFAULT_VENDOR_STEM = "vendor"
Also, while writing this post, I discovered that the final vendor tarball can be compressed in one of the following supported formats3:
.tar.bz2
.tar.gz
.tar.lz
.tar.xz
.tar.zst
And finally, here’s the list of supported source archive formats (the blob from which the vendor tarball is created), powered by the libarchive Python module4:
READ_FORMATS = set((
'7zip', 'all', 'ar', 'cab', 'cpio', 'empty', 'iso9660', 'lha', 'mtree',
'rar', 'raw', 'tar', 'xar', 'zip', 'warc'
))
-
https://github.com/openSUSE/obs-service-go_modules/blob/a9bf055557cf024478744fbd7e8621fd03cb2e87/go_modules#L227-L233 ↩
-
https://github.com/openSUSE/obs-service-go_modules/blob/a9bf055557cf024478744fbd7e8621fd03cb2e87/go_modules#L46C1-L47C31 ↩
-
https://github.com/openSUSE/obs-service-go_modules/blob/a9bf055557cf024478744fbd7e8621fd03cb2e87/go_modules#L119-L124 ↩
-
https://github.com/Changaco/python-libarchive-c/blob/1a5b505ab1818686c488b4904445133bcc86fb4d/libarchive/ffi.py#L243-L246 ↩