Skip to content

Commit 879512a

Browse files
Priyankasaggu11929jfkw
authored andcommitted
Implement go mod edit -require using _service params
Add support for requiring specific Go module versions at vendoring time. User may configure one or more _service param name="require" with values valid for go mod edit -require, e.g.: github.com/go-jose/go-jose/v4@v4.0.5 The source service will then: - Apply the require statements to go.mod - Run go mod tidy to update dependencies and checksums - Set a sentinel flag if go.mod or go.sum changed - Include updated go.mod and go.sum in the vendor archive when modified
1 parent 27262b8 commit 879512a

3 files changed

Lines changed: 67 additions & 1 deletion

File tree

README.md

Lines changed: 34 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -351,7 +351,40 @@ go version -m <BINARYNAME> |grep jose
351351
=> github.com/go-jose/go-jose/v4 v4.0.5
352352
```
353353

354-
As soon as the Go application upstream tags a newer release, remove the replace
354+
## Pin a specific module version with `go mod edit -require`
355+
356+
In some cases, it is useful to explicitly require a module version, without replacing it. The `go mod edit -require` command can be used to ensure a specific version of a module is recorded in `go.mod`, even if it is only indirectly required by other dependencies.
357+
358+
This is especially useful in the following scenarios:
359+
360+
- Pinning a minimum secure version of a module to address a known vulnerability, as identified by govulncheck
361+
- Ensuring consistent dependency resolution across vendoring and build environments.
362+
- Promoting a fixed version of an indirectly required dependency to a first-class requirement in `go.mod`.
363+
364+
### Example
365+
366+
You can add a require param:
367+
368+
```
369+
<service name="go_modules" mode="manual">
370+
<param name="require">github.com/go-jose/go-jose/v4@v4.0.5</param>
371+
</service>
372+
```
373+
374+
The `go.mod` will contain:
375+
376+
```
377+
require github.com/go-jose/go-jose/v4 v4.0.5
378+
```
379+
380+
and the binary’s module info will show the pinned version.
381+
382+
```
383+
go version -m <binary> | grep jose
384+
dep github.com/go-jose/go-jose/v4 v4.0.5
385+
```
386+
387+
As soon as the Go application upstream tags a newer release, remove the replace and require
355388
parameters from `_service` to return to pristine upstream sources and receive
356389
further updates to the dependency.
357390

go_modules

Lines changed: 30 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -232,6 +232,25 @@ def replace_modules(replace, go_mod_dir):
232232
return True
233233

234234

235+
def require_modules(require, go_mod_dir):
236+
"""Add require directives to go.mod for one or more modules
237+
Parameter require is a list of strings: 'module@version'
238+
Returns boolean indicating go.mod and go.sum are modified
239+
"""
240+
log.info(f"Setting required versions for {len(require)} modules")
241+
for r in require:
242+
cp = cmd_go_mod(["edit", "-require", r], go_mod_dir)
243+
if cp.returncode:
244+
log.error(f"go mod edit -require={r} failed")
245+
exit(1)
246+
# run go mod tidy to update go.mod and go.sum
247+
cp = cmd_go_mod(["tidy"], go_mod_dir)
248+
if cp.returncode:
249+
log.error("go mod tidy failed")
250+
exit(1)
251+
return True
252+
253+
235254
def sanitize_subdir(basedir, subdir):
236255
ret = os.path.normpath(subdir)
237256
if basedir == os.path.commonpath([basedir, ret]):
@@ -258,12 +277,18 @@ def main():
258277
action="append",
259278
help="go mod edit replace argument: 'module=replacement'. Can be used multiple times.",
260279
)
280+
parser.add_argument(
281+
"--require",
282+
action="append",
283+
help="go mod edit require argument: 'module@version'. Can be used multiple times.",
284+
)
261285
args = parser.parse_args()
262286

263287
outdir = args.outdir
264288
subdir = args.subdir
265289

266290
replace = args.replace
291+
require = args.require
267292

268293
archive_args = get_archive_parameters(args)
269294
vendor_tarname = f"{archive_args['vendorname']}.{archive_args['ext']}"
@@ -313,6 +338,11 @@ def main():
313338
# go.mod and go.sum will be modified and should be included in vendor archive
314339
modified = replace_modules(replace, go_mod_dir)
315340

341+
if args.require:
342+
# add require directives to go.mod for one or more modules
343+
# go.mod and go.sum will be modified and should be included in vendor archive
344+
modified = require_modules(require, go_mod_dir)
345+
316346
if args.strategy == "vendor":
317347
# go subcommand sequence:
318348
# - go mod download

go_modules.service

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -22,4 +22,7 @@
2222
<parameter name="replace">
2323
<description>Specify a module name and its replacement to be updated at vendoring time. Syntax must be a valid expression input to go mod edit -replace, e.g. github.com/go-jose/go-jose/v4=github.com/go-jose/go-jose/v4@v4.0.5. Can be used multiple times. Default: None.</description>
2424
</parameter>
25+
<parameter name="require">
26+
<description>Specify a module and version to be explicitly required in go.mod. Syntax must be a valid input to go mod edit -require, e.g. github.com/go-jose/go-jose/v4@v4.0.5. Can be used multiple times. Default: None.</description>
27+
</parameter>
2528
</service>

0 commit comments

Comments
 (0)