Is it possible to make an NPM package that allows users to determine what dependency they need? - npm-package

I'm going to make my first NPM package and I have two versions of it. One that needs MUI4 as a dependency and another that needs MUI5. I would like to just have one package that can support them both, but obviously don't want to (and couldn't even if I did want to) have both MUI versions as a dependency.
Can I add a flag that allows the user to pick which version they want?
Would that be a bad practice?

Related

Need to use multiple Go versions along with Makefiles

If I am working on multiple projects where different Go versions are required to build them, how would I elegantly set up my development environment to deal with this?
Each project has its own Makefile which at some point or the other would invoke Go commands. The issue is that some projects require different versions of Go, but the Makefiles simply use go build. My solution so far has been to simply add whichever Go version I needed to the PATH variable, e.g. project 1 requires go1.12.10, so I just run
export PATH=<path_to_go1.12.10_>/bin>:$PATH
And when I want to build project 2 which requires go1.13.6
export PATH=<path_to_go1.13.6>/bin:$PATH
This works, but is there a more elegant solution? Modifying the projects' build systems is not something I can do, at least not in the short term.
Go build has no native way to set the version to build with, so you are stuck either setting the path like you are now, or executing explicitly using /<path_to_go1.13.6>/bin/go.
For the versions that you implied you are working with, there really should be no incompatibilities between them and the latest version of go. On of Go's tenants is to preserve backwards compatibility under basically all circumstances. You would most likely be better off using go's latest version, and, if something is preventing you from upgrading the compiler, fixing that instead.

Preventing NuGet package update in team environment

We have a large solution with many projects, and many developers working together.
We need a way to validate Nuget package versions to insure no developer accidentally breaks the build with a package update.
Ideally, is there a way to validate and interupt/stop during Nuget package installation if it is a known incompatible package? We know we can do a validation at build time, but Ideally I'd like to actually be able to stop/inform the developer the newer version is not supported in the build to prevent them from going off and building with the newer package, only at build time to discover they've wasted time on a new package that might have differing calls etc.
If this is not possible, what would be the easiest way to do this at build time? I'm thinking a pre-build script but interested in other ideas. Effectively, the script would look across other project package versions to compare and inform if an incorrect version (and stop a publish to a shared location during build).

Go dep keep package even if not currently used

Go dep's dep ensure command will remove packages not currently in use. There's one particular package we use for debugging github.com/sanity-io/litter. The challenge we're facing is if we run dep ensure outside of a debugging session, dep will remove that package.
One solution could be to call that package in some backstage spot in the code that won't bother anyone, thereby showing dep that we are, in fact, using this package. But that sounds ugly, hacky, and could get removed by a future developer on the team.
So, the question is, how to tell dep to keep a package, even if it's not currently in use?
Add to the beginning of Gopkg.toml:
required = ["github.com/sanity-io/litter"]
The Gopkg.toml docs state about required:
Use this for: linters, generators, and other development tools that
Are needed by your project
Aren't imported by your project, directly or transitively
You don't want to put them in your GOPATH, and/or you want to lock the version
Please note that this only pulls in the sources of these dependencies.
It does not install or compile them.
You should use required for your dependency, take a look at documentation
about it. And maybe more useful link about required section.

Go binaries for concourse ci tasks

What are some good patterns for using go in concourse-ci tasks. For example, should I build files locally with all dependencies and check-in cross-compiled binaries to the repo? Should I build on concourse prior to running the task?
Examples of what people do here would be great. Public repos of pipelines/tasks even better.
The way I see it there are currently 3 options for handling go builds:
Use vendoring
Explicitly declare the dependencies as concourse resources
Maintain a docker image with the required dependencies already included
All options have pros and cons. The first option is currently my favorite since the responsibility for handling dependencies is up to the project maintainers and there is a very clear way to see which versions/revisions of the dependencies are being used - i.e. just check the vendoring tool config - but it does force you to have all dependency code in the project's repo.
The second option follows the go "philosophy" of always tracking master, but it may lead to slower builds (concourse will need to check every single resource regularly) and may lead to sudden breakage because of changes in dependencies.
The third option allows you to implicitly fix the revision of the dependencies in the docker image, in that respect it's similar to the first, however it requires maintaining docker images (doesn't necessarily mean 1 per project, but it might mean more than one depending on the number of projects that use this option and if there are conflicting dependency versions between them)

Package version management in Go 1.5

I'm getting my hands dirty with Go, and while I understand and appreciate the principle of simplicity that Go was built upon, I'd like to grasp the rationale behind forgoing a built-in package versioning method in their dependency-fetching tool go get and the import statement.
If I understand correctly, go get and import fetch the package from HEAD and they are unable to refer to a branch or a tag. While there are tools like gopkg.in that circumvent this limitation, the official toolchain:
Forces developers to create separate repos for major (breaking) versions of their products.
It doesn't allow consumers to downgrade between minor or micro versions in case bugs are found in newer ones.
Truth be told, things are not so easy because package versioning would require a strategy to deal with conflicting transitive dependencies, e.g. X depends on A and B, each of which depend on different versions of C.
Coming from a Java background, it does appear that this limitation poses some risks and problems, amongst others:
Product/package evolution and breakage of public APIs of 3rd party deps is unavoidable, therefore versioning must be a first-class citizen in the toolchain IMHO.
The Git-repo-per-version policy is highly inefficient:
The overall Git history of the package is lost or scattered across repos (merges between versions, backports, etc.)
Conflicts with transitive dependencies may still occur, and will go about undetected because the language nor the toolchain impose any semantics to allow detection in the first place.
Enterprise adoption may be hindered and development teams may shy away from the language, given that:
Always dragging in HEAD means that they can't control or freeze their 3rd party deps, leading to a potentially unpredictable end product.
May lack the manpower to keep their product constantly updated and tested with upstream's HEAD (not every company in the world is Google :)).
While I do understand that the latter risk can be – and must be – mitigated with Continuous Integration, it does not solve the underlying root of the problem.
What information am I missing? How do you deal with package upstream changes when deploying Go in an enterprise with limited manpower?
It is being addressed by vendoring which is part of Go 1.5 as an experimental feature, it can be enabled if the go command is run with GO15VENDOREXPERIMENT=1 in its environment, and will be a "full" feature in Go 1.6. Also see Vendor Directories.
The original discussion that led to the Go 1.5 Vedor Experiment can be found here.
The essence of vendoring is that you create a folder named vendor, and you put the exact version of the packages that your code relies on. Code inside the vendor folder is only importable by the code in the directory tree rooted at the parent of vendor, and you can import packages from vendor with an import path as if vendor would be the workspace/src folder (that is, with an import path that omits the prefix up to and including the vendor element).
Example:
/home/user/goworkspace/
src/
mymath/
mymath.go
vendor/
github.com/somebob/math
math.go
In this example github.com/somebob/math is an external package used by mymath package (from mymath.go). It can be used from mymath.go if it is imported like:
import "github.com/somebob/math"
(And not as import mymath/vendor/github.com/somebob/math which would be bad.)
While Go doesn't come with the standard package manager there are enough options to make builds reproducible (even in an enterprise with limited manpower).
Vendoring, which is described in another answer by #icza. This is almost complete equivalent of checking in versioned jar files in Java. This was very common approach with ant build tool before maven became popular. Actually vendoring is much better because you cannot lose source code.
This is slight variation of the first option. Instead of checking in vendored source code you can populate vendor folder during build by checking out predefined versions of the dependencies. There tools (e.g. glide) that automate this process.
Finally you can maintain predefined versions of all 3-rd party libraries in the internal repository and add it to GOPATH. This approach is described in detail in https://blog.gopheracademy.com/advent-2015/go-in-a-monorepo/
Note that incompatible transitive dependencies are not specific to Go. They exist in Java (and most other languages) too, though Java has a mechanism to partially solve this problem by making programs more complex - class loaders. Note that Go will report all incompatibilities at compile time while in Java some of the incompatibilities are triggered only at run time (because of late linking).
Java toolchain doesn't have concept of versions. It is provided by the external tool - maven. I believe by the time Go becomes more mature and popular a similar standard dependency management tool will emerge.

Resources