Can composer use local variables for specifying repositories version? - composer-php

I'm using composer to manage my PHP project dependencies and it uses some personal projects as dependency.
Let's say we've got this structure:
- Main project
---- Dep 1: dev-3.2
---- Dep 2: dev-3.2
---- Dep 3: dev-3.2
It needs the same version for all dependencies. Is there any way to set some kind of local variable and use it instead of defining "dev-3.2" for every subproject? For example:
- Main project
---- $dependencyVersion: dev-3.2
---- Dep 1: $dependencyVersion
---- Dep 2: $dependencyVersion
---- Dep 3: $dependencyVersion
I've tried using COMPOSER_ROOT_VERSION but it seems it's not used for this purpose. I know there is an "extra" section in composer where I can set all my custom variables, but I haven't found any way to refer to theses variables to achieve my goal.
Any idea if this can be achieved in composer?

After some searching, I could achieve this by creating the tag 3.2 in Main project and in each one of the dependencies, and then using:
"require": {
"Dep 1": "self.version",
"Dep 2": "self.version",
"Dep 3": "self.version"
}
This way all subprojects would download the version that Main project is currently on.

Related

Is there a way to use one Vendor for multiple projects with different seeder

i was having issues on how vendor take too much place. Since my host has a limit on number of files and folders (INODES). So i found a solution to use one Vendor for multiple project in laravel through the following link : Using one Vendor Folder for Multiple Projects in Laravel 5.2.
In the following lines I put the vendor in projectA, then link the others projects to it.
In projectA everything works well when i do php artisan migrate:fresh --seed
When i try the same thing to projectB for example, the above command works till it arrives where the seeders should be executed. There, some error occur due to the fact that the command is trying to launch a seeder of projectA in the projectB as shown in the following screenshot.
Seeder Error Screenshot
So i want to know if there's a way to make the seeder separately.
I tried to create a symlink on the composer.json file as it was done for the vendor folder, but it doesn't work.
I'm using Laravel 8
I thínk this is a terrible idea, except in the case that both projects share exact same codebase.
Composer use composer.json as you know. How does your B project composer file determines how to resolve PSR4 autoload entries in Laravel, If it is symlinked to A project? That is probably the reason why your seed command is trying to locate Classes in A project.
Composer is clever enough to cache downloaded packages and reuse them, but I think that every project has its own dependencies and state, which is maintained by composer.json in the first case and composer.lock on the state case.
What happen if you update composer in A but not in B, will B work?
And last, composer autoload file reference all satisfied dependencies in your project, and in this case that (unique) autoload file will be loaded in both projects but what happen if your required packages are not exactly the same? ie You have Laravel Debug Bar in one project but not in the other. The autoload generated file will reference that package that will not exist on your other project.
Is not this the way composer work? Am I wrong?
In Composer the Vendor Directory (vendor in the project tree by default) is per project.
You ask about how to use one vendor folder for different projects.
Now first of all, this is absolutely not what Composer expects nor how it works. See Manuel Glez answer. In short a terrible idea.
When it comes to Composer, the place to share the actual PHP code across projects is not in the vendor directory but in repositories.
And as long as the dependencies are compatible, you could make one project depend on another and use its vendor/<vendor>/<name> folders as repositories. The remarks in Manuel Glez answer are still the same, this need to be same compatible versions across the board.
But to give the example, see Composer Path Repository which has this layout:
...
├── apps
│ └── my-app
│ └── composer.json
├── packages
│ └── my-package
│ └── composer.json
...
{
"repositories": [
{
"type": "path",
"url": "../../packages/my-package"
}
]
}
It can be adopted for each ../../project/A/vendor/<pkg-vendor>/<pkg-name> in ../../project/B/composer.json so that the vendor folder in project/A can act as a path repository for project/B.
As dependencies composer.json files normally do not contain the version, the documented remarks about repositories.options.versions apply:
When the version cannot be inferred from the local VCS repository, or when you want to override the version, you can use the versions option when declaring the repository:
{
"repositories": [
{
"type": "path",
"url": "../../packages/my-package",
"options": {
"versions": {
"my/package": "4.2-dev"
}
}
}
]
}
To prevent the duplication of the files the default strategy for Composer is to symlink the package directories. Ensure it works, then you only have one symbolic link per dependency in project B.
Okay how cool is that? Well IMHO while you still give up much of what Composer can do for you for dependency management, this at least makes use of local Composer repositories which I'd recommend for sharing instead of completely symlinking the overall vendor folder. Each project still have its own vendor/composer setup and overall what is done is much more well defined and in line with Composer itself.
Whether this works or not depends on the individual case. Key point here is as these local repositories only provide a single version per each package, you can only have that one. So these versions must all be version compatible on API level.
The system where it runs needs to support (relative) symbolic links, this should be commonly available for the situation described.
You could then automate the production of the repositories configuration and adopt it to the file-system layout. You could even generate the repositories and update them in the global configuration file so that each project would automatically prefer those packages from local.
$ echo "$(composer config --global home)/config.json"
/home/user/.config/composer/config.json
(compare: COMPOSER_HOME/config.json (Composer docs))
Take care all projects and their dependencies have a portable path-profile and then I'd say this should be quite straight forward shell processing.
To obtain the actual versions of the dependencies installed check per each vendor folder inside vendor/composer/*installed* files.
$ (echo "PACKAGE VERSION"; find .. -type f -path '*/vendor/composer/installed.json' -exec jq -r '.packages[] | .name + " " + .version_normalized ' {} \; | sort -u | sort -k 1b,2V) | cols
PACKAGE VERSION
composer/ca-bundle 1.3.2.0
composer/composer 2.3.7.0
composer/metadata-minifier 1.0.0.0
composer/pcre 3.0.0.0
composer/semver 3.3.2.0
composer/spdx-licenses 1.5.7.0
composer/xdebug-handler 3.0.3.0
...
phar-io/manifest 1.0.1.0
phar-io/manifest 1.0.3.0
phar-io/manifest 2.0.1.0
phar-io/manifest 2.0.3.0
...
(very old installations don't have the packages keyword, you'll likely want to filter)
Finally you may want to have something to smoke-test the setup easily so that you can have guards against the dependency incompatibility problems when you take notice of them.

Yarn packages hoisted despite entire package adding to nohoist

I'm on version 1.22.X
I have a workspace like this:
/application
/common-package
/project-a
/project-b
Project A and B has similar dependencies but on different versions, this causes a bunch of issues so I want to add Project B to the workspace but I don't want Project B to hoist any dependency in the Application workspace.
I just want Project B to be able to import things from Common-Package.
I have tried:
/application/package.json:
"nohoist": [
"**/application/project-b",
"**/application/project-b/**",
]
But this isn't working and still sends some dependencies to application/node_modules.
I've also tried:
/application/project-b/package.json:
"nohoist": ["**"]
But again some packages still get hoisted. Then VS Code complains it cannot find them

How do I import generated SDKs in golang?

I've used openapi-generator to generate multiple SDK separately and put it in the same parent dir:
sdks
--- bar-api
------ go.mod
--- foo-api
------ go.mod
I'd like to be able to import bar-api in my client code. Initially there's bar-api's go.mod was generated as:
module github.com/coolrepo/bar-api
go 1.13
but I couldn't fix the imports in my client code:
bar "github.com/cool-repo/bar-api"
so what I did was:
sdks
--- bar-api
------ go.mod
---go.mod
i.e., created sdks/go.mod:
module github.com/coolrepo
go 1.13
and manually edited bar-api's go.mod to:
module github.com/coolrepo/bar-api
require (
...
)
replace github.com/coolrepo => ./..
go 1.15
Is there a better way to fix it? This one seems to work but looks kinda hacky with this replace.
The “better way to fix it” is to put all of the generated Go packages inside a single module, instead of splitting up the repo into multiple modules.
rm bar-api/go.mod
go mod tidy
You only really need to split a repo into separate modules if you need to be able to tag a release for one set of packages independently from another set of packages in the same repo. For generated service APIs, that probably isn't worth the development overhead of juggling versions for multiple modules.

How to update a go dependency with different module name than src path?

The location: github.com/elastic/beats
The mod file: github.com/elastic/beats/go.mod
The module name: github.com/elastic/beats/v7
The tag: v7.10.2
What LoTR incantation of go get to I have to run to get a little dependency update action?
This will update to latest minor.patch version of v7:
go get github.com/elastic/beats/v7
or if you want a specific version to update/downgrade to:
go get github.com/elastic/beats/v7#v7.10.2
Adding the -u flag will additionally update the dependencies of github.com/elastic/beats/v7:
go get -u github.com/elastic/beats/v7
The argument list passed to go get should generally be a list of package paths or patterns, not just a module path.
For example, you might invoke:
go get -d github.com/elastic/beats/v7/libbeat/beat#latest
in order to obtain the latest version of package …/libbeat/beat and also download any transitive dependencies needed for that package.
(You can pass just a module path, and that should also update the version of the dependency module overall, but it will not download source code or module checksums for transitive dependencies that may be needed in order to build the updated package. go get does not in general know which transitive dependencies will be relevant to the commands that you plan to invoke after it, and it does not do extra work to speculatively identify relevant dependencies.)

Within a yarn workspace, how can I force a resolution for a child project's dependency?

I'm using a library that has supports another library with a wide range of versions as a peer dependency. Unfortunately, one of the child projects of the workspace pulls in a version different from the child project that uses the library. As a result, they end up requiring different versions.
I'm trying to use selective resolutions to handle this and force it to use the correct version (https://yarnpkg.com/lang/en/docs/selective-version-resolutions/) but I'm not having any luck.
It's possible I'm misunderstanding how to utilize these.
My current setup is I have a root workspace with these children inside:
Project A package.json (which is the source of the issue):
dependencies: {
backbone.marionette: '2.4.1'
}
Project B package.json (which is the application having issues):
dependencies: {
backbone.marionette: '1.8.8',
#organization/UILibrary: '0.0.22'
}
The #organization/UILibrary (which is outside the workspace) package.json looks like so:
peerDependencies: {
backbone.marionette: ">= 1 < 3"
}
Unfortunately, even though Project B has no dependency on Project A, when #organization/UILibrary is pulled into Project B it gets backbone.marionette version 2.4.1 for it's requires (whereas the requires local to Project B get 1.8.8).
My attempt to use resolutions is updating Project B package.json to this:
dependencies: {
backbone.marionette: '1.8.8',
#organization/UILibrary: '0.0.22'
},
{
"resolutions": {
"#organization/**/backbone.marionette": "1.8.8",
"#organization/backbone.marionette": "1.8.8",
"#organization/UILibrary/backbone.marionette: "1.8.8",
"#organization/UILibrary/**/backbone.marionette: '1.8.8"
}
Any ideas? Based on some digging in yarn's issues and some of their selective dependency PRs (see https://github.com/yarnpkg/yarn/issues/4874) I believe it may be due to the fact that the UILibrary is scoped (has a slash).
I ran into something similar recently; what I found is that resolutions only works in the root package.json. Try moving the resolutions there instead of in Package B's.

Resources