-1

What I essentially have is a mono-repo, which doesn't have a go.mod at the root level. There are multiple directories inside this mono-repo, with each of them having their own go.mod files. I'll refer to them as sub-modules.

Now, I've figured out a way to be able to access the sub-modules independently (versioned) in a completely different codebase. The issue I'm facing now is, to dis-allow the import of the entire mono-repo, using:

go get link.to/mono-repo@commit_id ------> A

and only allow import using :

go get link.to/mono-repo/sub_mod1@v0.x.y

go get link.to/mono-repo/sub_mod2@v0.y.z

The command A is able to fetch the entire repo, and then can be used to access the inner modules. Is there any way to stop this from being allowed?

I tried a few things, like:

  • Added non-compilable code in a file noCompile.go at the root level. On go get..., the compilation error is printed, but use of the inner modules still works fine.
  • Added an init() function in the same noCompile.go file, which just calls panic(). This init function is not being executed, as the root directory is never directly accessed, only the inner modules are.

Is there ANY way to achieve what I'm intending to?

Jonathan Hall
  • 75,165
  • 16
  • 143
  • 189
  • 1
    You could create a `go.mod` file at the top level, that is broken (i.e. it refers to an impossible import path such as `dont.import/this/module`). But this will be very surprising, and is probably a bad idea. Why do you want this? – Jonathan Hall Feb 16 '21 at 08:54
  • 1
    I'm not sure I understand the problem you think you have. You cannot _use_ modules; all you can do is import packages. A module is a set of packages "with the same version and lifecycle"). You say "The command A is able to fetch the entire repo" which might or might not be true (I doubt it, as it is not a module) but that is of no interest as you code must import _packages_ and these _do_ live in what you call submodules and to import them you will have to add their module to you go.mod. – Volker Feb 16 '21 at 09:09
  • 1
    Can you really do a `import "link.to/mono-repo/sub_mod2/some/package/here"` with you go.mod **not** containing `require link.to/mono-repo/sub_mod2` but **only** a `require link.to/mono-repo` when that doesn't contain a go.mod? I think you try to work around a non-problem. – Volker Feb 16 '21 at 09:13
  • @Flimzy we want to keep a single repo for storing many common packages, say for eg. logger, db, Kafka, etc. We want all our micro services to access the individual packages, as that allows the services to use different versions of the packages. Now, we also want to enforce the services to not access the mono-repo directly, just to basically set a development process, and use versioned packages. – rahulkhairwar Feb 16 '21 at 09:59
  • @Volker sorry for the confusion, I meant that we want to store multiple packages in a single repo, and allow all our micro services to access the packages directly, to be able to use the versions for the individual packages. We want to restrict access to the mono-repo as a whole, basically just to set a standard practice. – rahulkhairwar Feb 16 '21 at 10:04
  • @Volker answering your question "Can you really do a ...", yes, it's possible to do that. – rahulkhairwar Feb 16 '21 at 10:06
  • 2
    Sorry, but this makes even less sense, you simply _cannot_ access _packages_ on a version level: Packages with the same version are groupes into a module. the module carries the version of all grouped packages. Import is done on a package level. Version selection is done on the module level. – Volker Feb 16 '21 at 10:07
  • "yes, it's possible to do that." This is astonishing. (And I do not believe it unless you show code and the resulting go.mod). Does this work also with versions >= 2.0.0 ? – Volker Feb 16 '21 at 10:09
  • I'm not sure about restraining the access to the mono-repo, but to access the packages in the submodule only you can create specific git tags prefixed for each sub-module ```go get xxx.com/mon-repo@kafka/v1.0.1``` ```go get xxx.com/mon-repo@logger/v1.1.0``` and it will bring only the packages in that submodule – hmoragrega Feb 16 '21 at 12:30
  • I second the notion that this is trying to solve something which is not a problem. There is always a way users can try and subvert the system, but there is no reason here for anyone to do that. The best you could do is use a broken module which exists on a commit without any of the packages, but if users are trying to breaks things already, that is no more of an impediment than doing it correctly in the first place. – JimB Feb 16 '21 at 15:13
  • A extension of the "broken module" idea, is that all the packages start on version > 1, so that they can only be imported from the correct module in the first place. – JimB Feb 16 '21 at 15:14

1 Answers1

2

Any directory that contains its own go.mod file is excluded from the module in the parent directory. So if you go get link.to/mono-repo@commit_id, that should not contain the packages link.to/mono-repo/sub_mod1 or link.to/mono-repo/sub_mod2 (assuming that they exist and have their own go.mod files).

I suspect that you were observing imports like import "link.to/mono-repo/sub_mod2/some/package/here" to resolve not because of that initial go get, but rather because the go command was resolving the missing imports (and adding the missing dependencies) automatically; see https://golang.org/ref/mod#go-mod-file-updates.

As of Go 1.16 (released today!), most go commands no longer implicitly modify the go.mod file, so the fact that the module at the repo root does not include the contents of nested modules should hopefully be clearer.

bcmills
  • 4,391
  • 24
  • 34
  • I realised I was able to access sub-packages without a `go.mod` file, and assumed I can access the others as well. This comment makes things clearer, thanks a lot! – rahulkhairwar Feb 17 '21 at 03:21