Prevent resolving cyclic dependency to local workspace - yarnpkg

I have a package, which offers basic utilities. It has a dev-dependency on a tool, which helps build it. That tool in turn needs features from the package.
The problem is, that during development of the package, the dependency of itself gets resolved to the local workspace, not fetching it from a registry - which obviously won't work, for two reasons:
it isn't built
the version isn't bumped yet, but there may already be breaking changes
Personally, i don't know why this behavior is desirable in the first place, but how do i disable it, forcing a resolution to the registry, fetching the current latest published version?
Using yarn 3.2.0 with pnp (could not see any related changes towards 3.2.1, therefore imho irrelevant)

The behavior can be disabled via enableTransparentWorkspaces: false in yarnrc.yml.
After additional research, i found yarn-2-berry-npm-protocol-switches-to-workspace-resolution, which links to a related github Q&A, where the answer is given. Sadly, it never got accepted on github, nor propagated to the related SO question, so i'll keep this one here.

Related

Remote Swift package incomplete when using versioning

I am in the process of modularising my app using Swift Packages and some of these modules will be useful for future apps so I have created standalone Packages and added them to the main project as dependencies.
As recommended, I am using semantic versioning and have tagged the commit as per the Apple documentation (see here) and pushed to my Github account.
When I attempt to add this package to my app using version rules ("up to next major version") the dependency does not seem to be resolved properly; the code cached locally only contains a bare package without any of the code I subsequently added.
If I remove version rules and use commit rules instead, I get the whole package as expected but that may cause problems with compatibility in the future as the package evolves.
Checking the version control in Xcode and directly on Github shows that the version tag 1.0.0 is present and associated with the last commit which is puzzling. The steps taken in an attempt to resolve the issue are as follows:
force push package (including tag) to GitHub
remove version control from package by deleting .git file and adding version control, committing, tagging then pushing to remote
reset package caches
clear derived data
close and restart XCode
None of the above work and I thought initially that I was not doing things in the correct order. However I'm particularly puzzled that removing version control then setting it back up again (with the code codebase in a complete state at this time) didn't work as the bare-bones template package was never pushed to the remote in the first place. I don't understand how can Xcode be still retrieving it. IMO this suggests there's a cache somewhere it's falling back to (despite being told to clear the cache) but I stand to be corrected.
Screenshots of the remote (showing the correct tag) and states of the Xcode package dependency using branch rules and version rules attached.

Dependabot for updating go dependencies which track commits

I'm trying to use dependabot to auto-update a private Go repository. My current dependabot.yml looks like this:
version: 2
updates:
- package-ecosystem: 'gomod'
directory: '/'
schedule:
interval: 'daily'
allow:
- dependency-name: "<private-dependency>"
The "private-dependency" does not track versions so I want to update against a specific branch.
I understand I can do this manually by running go get private-dependency#branch but I can't find any documentation on whether I can do so via Dependabot.
I can create a Github Action for running the command and opening a PR but would want to avoid doing so if possible.
Does Dependabot even support updating Go dependencies that track branches? How can I do this using Dependabot?
I opened a customer support ticket with Github and their official response is:
After speaking with Engineering, it was found that according to Golang's documentation the commit-based versions are considered "pseudo-versions" and intended for development. Dependabot seeks for stable versions to suggest as a possible update rather than development versions.
According to this, Dependabot doesn't support this feature yet but they are open to taking a feature request. For our purposes, we started tagging our releases with SemVer and that solved the issue.
Just leaving an answer for posterity and those that might be interested in following this up.

What are the consequences of always using Maven Snapshots?

I work with a small team that manages a large number of very small applications (~100 Portlets). Each portlet has its own git repository. During some code I was reviewing today, someone made a small edit, and then updated their pom.xml version from 1.88-SNAPSHOT to 1.89-SNAPSHOT. I added a comment asking if this is the best way to do releases, but I don't really know the negative consequences of doing this.
Why not do this? I know snapshots are not supposed to be releases, but why not? What are the consequences of using only snapshots? I know maven will not cache snapshots the same as non-snapshots, and so it may download the artifact every time, but let's pretend the caching doesn't matter. From a release-management perspective, why is using a SNAPSHOT version every time and just bumping the number a bad idea?
UPDATE:
Each of these projects results in a war file that will never be available on a maven repo outside of our team, so there are no downstream users.
The main reason for not wanting to do this is that the whole Maven eco-system relies on a specific definition of what a snapshot version is. And this definition is not the one you're setting in your question: it is only supposed to represent a version currently in active development, and it is not suppose to be a stable version. The consequence is that a lot of the tools built around Maven assumes this definition by default:
The maven-release-plugin will not let you prepare a release with a snapshot version as released version. So you'll need to resort to tagging by hand on your version control, or make your own scripts. This also means that the users of those libraries won't be able to use this plugin with default configuration, they'll need to set allowTimestampedSnapshots.
The versions-maven-plugin which can be used to automatically update to the latest release version won't work properly as well, so your users won't be able to use it without configuration pain.
Repository managers, like Artifactory or Nexus, comes built-in with a clear distinction of repositories hosting snapshot dependencies and release dependencies. For example, if you use shared Nexus company-wide, it could be configured to purge old snapshots so this would break things for you... Imagine someone depends on 1.88-SNAPSHOT and it is completely removed: you'll have to go back in time and redeploy it, until the next removal... Also, certain Artifactory internal repositories can be configured not to accept any snapshots, so you won't be able to deploy it there; the users will be forced, again, to add more repository configuration to point at those that do allow snapshots, which they may not want to do.
Maven is about convention before configuration, meaning that all Maven projects should try to share the same semantics (directory layout, versioning...). New developers that would access your project will be confused and lose time trying to understand why your project is build the way it is.
In the end, doing this will just cause more pain on the users and will not simplify a single thing for you. Probably, you could make it somewhat work, but when something is going to break (because of company policy, or some other future change), don't act surprised...
Tunaki gave a lot of reasonable points why you break Maven best practices, and I fully support that view. But even if you don't care about "conventions of other companies", there are reasons:
If you are not doing CI (and consider every build as potential release), you need to distinguish between versions which should go productive and those who are just for testing. If everything is SNAPSHOT, this is hard to do.
If someone (accidentally) deploys a second 1.88-SNAPSHOT, it will be the new 1.88-SNAPSHOT, hiding the old one (which is available by a concrete timestamp, but this is messy). Release versions cannot be deployed twice.

Should I increase the version number in my project if a dependency changes?

Let's suppose I have a project called myLib-1.1.0. This project has a dependency on lib-dependency-1.2.3.
If there's a new version for this dependency and I need to use it, should I change my project version as well? No other modifications are made to myLib.
At the same time myLib is a dependency for various other projects. My main concern is the impact of a small change in a dependency might have upstream.
Yes. In maven, released versions are immutable. If you release 1.1.0 with a dependency to lib-dependency-1.2.3 then that's it.
If you change to depend on lib-dependency-1.2.4 then that's a new version. You should not redeploy 1.1.0 since some people might have already pulled that (supposedly immutable) 1.1.0.
So that means you need a different version, even if it's a just a new qualifier (myLib-1.1.0-RC-2 for example, but better just 1.1.1)
Maven doesn't recheck remote repos for release versions once it has it in the local repo, so if someone has 1.1.0 already locally, they will not get the new, fixed 1.1.0.
And about your rippling problem. Upstream projects should depend on the lowest acceptable released version. i.e. if the upstream project itself is ok with myLib-1.1.0 because it doesn't need (indirectly) lib-dependency-1.2.4 then it should stay with 1.1.0
Any code change that potentially affects the behavior should be given a new version number, in other words: anything that's not an absolute trivial change should be given a new version number. A changed dependency would definitely qualify for that because, unless you do a thorough code inspection of the dependency, you have no reason to assume that they only made absolute trivial changes.
Changes are often advertised as "small" (similar to being absolutely trivial as I call it above), but they hardly ever are. They may be negligible in someone's use case, but not in someone else's use case. I've even seen circumstances where there were only changes to Javadocs in a project that would break things down the line. (You could argue about how smart it is for someone to depend that strongly on Javadoc, but that's besides the point, isn't it?)
That is not to say that you can't accumulate changes and release a bunch of them as a single release. While accumulating, your project is in flux, and should have a ...-SNAPSHOT version. There should be no two versions of myLib-1.1.0 (without the -SNAPSHOT) that have even the least little change.
The fact that you're re-releasing your project also makes explicit the fact that regression testing and such should be redone to validate that it's still working with the changes in its dependency.

What is the most effective way to lock down external dependency "versions" in Golang?

By default, Go pulls imported dependencies by grabbing the latest version in master (github) or default (mercurial) if it cannot find the dependency on your GOPATH. And while this workflow is quite simple to grasp, it has become somewhat difficult to tightly control. Because all software change incurs some risk, I'd like to reduce the risk of this potential change in a manageable and repeatable way and avoid inadvertently picking up changes of a dependency, especially when running clean builds via CI server or preparing to deploy.
What is the most effective way I can pin (i.e. lock down or capture) a package dependency so I don't find myself unable to reproduce an old package, or even worse, unexpectedly broken when I'm about to release?
---- Update ----
Additional info on the Current State of Go Packaging. While I ended up (as of 7.20.13) capturing dependencies in a 3rd party folder and managing updates (ala Camlistore), I'm still looking for a better way...
Here is a great list of options.
Also, be sure to see the go 1.5 vendor/ experiment to learn about how go might deal with the problem in future versions.
You might find the way Camlistore does it interesting.
See the third party directory and in particular the update.pl and rewrite-imports.sh script. These scripts update the external repositories, change imports if necessary and make sure that a static version of external repositories is checked in with the rest of the camlistore code.
This means that camlistore has a completely repeatable build as it is self contained, but the third party components can be updated under the control of the camlistore developers.
There is a project to help you in managing your dependencies. Check gopack
godep
I started using godep early last year (2014) and have been very happy with it (it met the concerns I mentioned in my original question). I am no longer using custom scripts to manage the vendoring of dependencies as godep just takes care of it. It has been excellent for ensuring that no drift is introduced regardless of timing or a machine's package state. It works with the existing mechanism of go get and introduces the ability to pin (godep save) and restore (godep restore) based on Godeps/godeps.json.
Check it out:
https://github.com/tools/godep
There is no built in tooling for this in go. However you can fork the dependencies yourself either on local disk or in a cloud service and only merge in upstream changes once you've vetted them.
The 3rd party repositories are completely under your control. 'go get' clones tip, you're right, but you're free to checkout any revision of the cloned-by-go-get or cloned-by-you repository. As long as you don't do 'go get -u', nothing touches your 3rd party repositories already sitting at your hard disk.
Effectively, your external, locally cloned, dependencies are always locked down by default.

Resources