Why do some GitHub repos have 0.x.y releases if version 1.0.0 is the first public API release per SemVer2? Isn't 0.x.y development before the first complete working code you want to release to the public (i.e. wouldn't anything pre-1.0 not be usable)? I am specifically referring to repos that want to claim they are following semantic versioning.
THOUGHT: Is a release in the 0.x.y phase usable code that just doesn't have API documentation yet? Is that what that means?
e.g. Tensorflow has releases on GitHub starting at 0.5.0. Is this acceptable per semantic versioning, or are they simply not following semver and using something else?
From the spec:
4. Major version zero (0.y.z) is for initial development. Anything MAY change at any time. The public API SHOULD NOT be considered stable.
Why do some GitHub repos have 0.x.y releases if version 1.0.0 is the first public API release per SemVer2?
Because the maintainers do not wish to give the impression that their code/API's are stable or ready for production. They are reserving the right to remove or modify any of their API's without warning, for any reason they deem appropriate.
THOUGHT: Is a release in the 0.x.y phase usable code that just doesn't have API documentation yet? Is that what that means?
It means exactly what the spec says it means. If that's not clear enough, then you'd have to ask each of those repo's maintainers, what they think it means. In general, you should always treat prerelease versions as dangerous, unreliable, and subject to change without notice. Do not deploy any prerelease version into production, without thorough testing prior to deployment.
e.g. Tensorflow has releases on GitHub starting at 0.5.0. Is this acceptable per semantic versioning, or are they simply not following semver and using something else?
You should ask them if they are following SemVer. Any random version triple may have the appearance of a SemVer string, but that does not mean the publisher is adhering to SemVer. If they say they are SemVer and the first publicly available version is 0.5.0, that's perfectly acceptable. It is common practice to start at 0.1.0 for prerelease of the first feature(s), but there is no rule that requires it. There is also no requirement that older, possibly less stable versions, be left in public view. Nor is there a requirement for continuity of the version history. Any random version may be removed from public view for any reason the publisher deems sufficient cause to remove them.
When a publisher issues their first major version, they are saying "here's an API that we will not break". The SemVer spec allows them to fix bugs in their code and documentation with patch level version bumps, and add non-breaking features with minor level version bumps. The spec does not say how big those bumps should be.
Related
I've been thinking about semantic versioning recently and thought of a hypothetical situation that I can't quite seem to reconcile.
My understanding of the Semantic Versioning Scheme is as follows:
A particular unique state of computer software can be identified with a 3-part version number of the form:
M.m.p
Where
M = Major #
m = Minor #
p = patch #
A major change is any change to the software such that the new version with the change is no longer compatible with the previous version before the change. A minor change is any feature added or removed from the software that does not compromise compatibility with its previous version before the change. and any change that fixes a bug or error is just a patch change. Whenever a major change occurs M is incremented and m and p are reset back to 0. Similarly when a minor change occurs m is incremented and p is reset back to 0. and patch changes merely increment p
(I know there are additional components of semantic versioning like -alpha, -beta and so on but for now I am keeping it simple and constrained to the above)
The Hypothetical situation that is confusing me is this:
Suppose a software project exists in a certain state X.Y.Z in a repository of a version control system (for the sake of the hypothetical lets assume this is Git/GitHub). Suppose there are two developer A and B for the software project. Each clones down a copy of the software project in state X.Y.Z in order to work on some change for it, both are working on a different change (they may be of the same type - M/m/p but the content is different).
Now suppose that developer A finishes their change (whether it be major, minor or patch) and pushes it to the repository (thereby changing the state of the software project to (X.Y.Z)+1 [again we don't know the nature of the change here]). And suppose they do this before developer B is finished with their changes.
How should this influence the work flow of developer B?
if A's change was just a patch should developer B just ignore the update and continue working on their change as if nothing happened (especially if their change was major)?
if A's change was minor or major should developer B scrap whatever progress they've made on their change and start over on the assumption that A's change will have influence on theirs (B's)?
With the nature of problem outline above how should updating semantic versions be handled between multiple developers?
Usually, this is handled by communication. Major versions are rare and planned, so they are overwhelmingly planned and communicated ahead of time.
For the difference between minor and patch versions, there's often some sort of branching scheme. For example, Git LFS uses a branch like release-3.1 for the 3.1.x branch and main for minor versions. All code goes into main, and then if a patch release needs to be done, the changes are cherry-picked into the release-* branches. The core team discusses the plans for the next release and whether they'd like to do a periodic minor release next or whether they think a patch release is necessary.
Of course, there are many other ways to handle this and this is just one. But communication among developers about expectations for the project and plans is going to be important anyway, so it's an ideal approach to decide the way the project would like to deal with managing this kind of issue.
This conundrum only arises as a product of a common misunderstanding about how versioning actually works. Ask yourself "what am I versioning here?".
It was a long standing practice to maintain the version number in a revision controlled file, where it could be modified by developers. In hind sight, it's a terrible practice, but actually made sense to us at the time. But let's stop and think about what it is we are versioning and look at how all the various artifacts are tracked in modern development systems.
One best practice today, that wasn't very common a couple decades ago, is to use a revision control system to automagically track changes to files. Developers no longer have to remember to bump a revision number at the top of each source file when they make changes. Instead, the RCS tracks file version when they are committed (not on every change!). Still most of the various RCS's offered a means to automatically update the source file header, but that practice is rarely used today because it's redundant/wasteful and does not scale well.
Another best practice today is to use some form of semantic versioning on publication artifacts, and there's a lot of variation in the tooling that supports that, but most of it is embedded in a handful of packaging tools and package archive services/feeds. Note that not every change in the source code requires a version bump here. The RCS tracks individual changes committed by developers and the release/publication management system determines the appropriate version to apply to the packaging artifacts.
The primary best practice today is the use of build pipelines. Modern DevOps best practice is to build the product on managed servers for all forms of publication. You typically have separate internal and external publication requirements, but they are all built in controlled, non-developer environments.
Add something like semantic commits (Brk, NB, NIB, and many other notations) to commit messages, automated test results and publication/release policies, and the appropriate version number to apply to any artifact can be derived automatically.
Suggested policies are:
No single developer can publish an artifact to a public facing feed.
Developer builds are versioned based on highest release version available for the repo hash they forked from, plus a -a.Dev. prerelease tag.
No -a.Dev. prerelease artifact shall be shared beyond the developers own workstation.
Continuous integration builds shall be published internally as YYYY.MMDD.Increment-a.Integration
Etc.
Note that the possible variations are endless and determined by your organizations internal needs and commitments to customers.
Circling back on your conundrum, it should be obvious by now that it is a fallacy that the version number should be changed for every change in the source code. Modern tooling and best practices negate the need for it, and it is no longer desired.
If you look through my history of answers here, you should find several rants on why the RCS is not the correct place to track version numbers, but the primary reason is, we just don't use the RCS to store the artifacts we publish. It's okay to add publication tags to specific RCS states for developer convenience, but for CI/CD environments, the best place to keep the product version number, is in your publication feed system or an independent database.
I'm trying to figure out a scenario, but I can't find any relevant information on the web.
Let's say I am deploying an Android Application (v1.0.0) with the backend (v1.0.0).
At some point, I will make some changes and update the app to v1.0.1 and the backend to v1.0.1 and they will work perfectly.
But how can I also support the previous version of the application (maybe the new server version provides another format of response for one specific request)?
I thought of having separate deployments for every version of the server, but for many updates, that would mean a big resources impact.
Also, forcing the users to update doesn't seem a good option in my opinion.
Essentially you can go multiple ways of doing it. Really depends on your requirements, but usually the reality is a mixture of the things below.
As a rule of thumb, think in data model that will be held compatible. If the contract can not be kept or your realize major changes are needed, introduce a new version of API. If old clients can not be supported, force update. You can also agree on a policy on how long to support each previous versions and then force update, this will make your life much easier and simpler, than maintaining tens of versions of APIs.
Backwards compatible data model
You must think backwards with each release:
Think of incremental modelling with each release cycle. So you can keep things.
When you forget about it and you need to switch behavior based on data:
Happened to me in my trainee years. Simply you have to decode which version it might be, based on the data if you forget to add protocol version. From the beginning you can always have a version field on the data. Moreover, you can also add a set of compatible parser versions.
Include protocol version in data:
{
"data": [ arbitrary data model],
"protocolVersion": "v1"
}
Based on the protocol version, you can decide how to process the data on the server side. You don't need to keep client version in mind, only the protocol's. Since it can be that you release: 1.0.0, 1.0.1, 1.1.0, and you only change protocol in 1.2.0.
But I think the problem is the that as data changes subsequently, so does behavior on server side processing.
Versioned API
Sometimes you see different paths for major versions:
/api/v1/query
/api/v2/query
Used when backwards compatibility is broken or after total reconsideration. Therefore not every version will have an increment.
Use a query parameter with the client version:
/api/query?v=1.0
/api/query?v=1.1
Similar to previous one, just written differently. Although I think this is not the way you want to go down.
Track client releases and used service versions
In reality there are multiple requests and multiple versions of services being used all times per one client version. This makes things even harder to maintain.
All the time, document and track. Version and release management is very important. Know the git hash from which version you built, many time it can get confusing and you just changed only one parameter after release as a quick fix and the day after nothing is compatible anymore.
Map all service versions to the client version at each release, know which commit you really built and use tagging and release management.
Test everything before each release
Have clear requirements for your backwards compatibility. Maybe you only support two older versions, then test with all the two clients, new client with the to be released server. Document everything. And when you meet your criteria for release, go with it.
Summary
Reality is a mixture of solutions. Have clear requirements on the backward compatibility. Therefore you can test before each release. When it is necessary, force update. Keep track of releases, and document each client versions with all the services being used with their versions.
Use switch case at the server for each different version of the app.
Is there a way to advertise and have consumers tell from the available REST APIs for repos or their branches or releases that particular releases or major version branches are actively supported, maintenance support, or unsupported? Or application of some common support policy, like "n-2 major releases supported"?
This is towards writing automation that can alert, or even automate updating of dependent versions based on availability (e.g., there's a supported version to upgrade from my maintenance version).
From the GitHub API alone, no, as the notion of "support" is not a primary notion.
You could setup for a release naming convention, which would then allow the interpretation of the repos/releases API.
Or describe that support explicitly in the README that you can get through the repos/contents API.
But any solution you might consider will involve some kind of convention/normalization.
On GitHub, sometimes I see projects with "1.x" and "2.x" branches, in addition to tags. Take the Grails SpringSec plugin for example. It has both a master and 1.x branch, as well as several tags.
This has me curious:
At what point would these "1.x" and "2.x" (etc.) "version branches" be created? At what point would they be merged back with master?
At what point would artifacts be built from these "version branches"? In other words, "1.x" could mean "1.0.0" or "1.5.29"...but the latest version might be "1.7.14". What's the relation between the "1.x" branch and the "1.7.14" version of the binary (JAR, ZIP, whatever)?
If you're already going to go with "version branches", then what purpose would a tag possibly serve?
Here's a brief explanation of how branches and tags work and how best to use them.
1. Branches
Branches provide a means to separate your code into different development streams. Initially you start with one main branch (be it master, trunk or other common names). As your project evolves, you start needing certain stability while developing.
A good way to guarantee this is to start using more than one branch for your work. Consider the following: you're working on a feature whose development effort would be high and/or long-term. You wouldn't want to have this in your main branch, if it's something that will change the behavior of your currently existing code, as while it's work-in-progress, you might break things for other people. So, this is when you normally create feature (or topic) branches. When your code becomes stable enough, you merge your feature branch with the respective master. This approach helps you work in isolation from the rest of the developers. They can check your work and comment on it, propose fixes and all at the same time while keeping your master stable.
2. Tags
Tags are something to be considered permanent. They are a marker of your code at a given point in time. When you release version 1.2.3, you need to be able to tell exactly what was in this release, if somebody reports a bug, so that you would be able to reproduce it easily and also check if it has been resolved during development at a later stage when you've released newer versions.
3. Working With Branches And Releasing From Them
Consider you have multiple clients. Assume ClientA has a contract with you that they will pay to use version 1.2.3, while ClientB is a new client interested in your ground-breaking work on some feature in version 2.x that ClientA isn't all hyped up about and therefore not so willing to upgrade to. Your contract states that each client gets service for a year after their payment for your licenses. Yes, generally companies should push for their clients to upgrade to newer versions of their product/service, but quite often the clients are large institutions in which the pace of work and decision-taking is much slower than desired.
So, in order to be able to support both clients, you need to make sure that you have a proper branching strategy and that you will be able to work in isolation. This normally means you have a main branch like master on which all your bleeding-edge development is done. When certain features are ready, if they are needed on the respective branches for those clients, they are merged to their branches. So, if you have feature-15 developed on master and it's something that is needed for ClientB, you only merge it to their branch. If ClientA has reported a critical issue which seems to be only relevant to their product version and not reproducible in later versions, you apply a fix just for them and rollout a release.
Quite often, your contracts are such that you don't give your clients certain functionality, unless they've paid for it. Your pricing model could be annual service which covers free upgrades for the whole year, covering minor and major version. You could also have some clients which you've signed a few years ago and who are very slow at upgrading and thus this need for keeping different version lines alive for a longer period.
3.1. Branching and Tagging In a Multi-branch Environment
Consider you have the following branches:
master : latest development (3.x)
1.x : for your clients who insist on using older versions of your code
2.x : for a bit more up-to-date clients.
Branch 1.x will be used for releasing 1.x-SNAPSHOT-s; 2.0 for 2.x-SNAPSHOT and the master -- for your yet unreleased work on 3.x. Normally, it's a good idea to have a branch per major version which you are actively supporting. For minors you would branch off that branch (for example, version 2.0.3 would be off branch 2.0.x). When your work on a given iteration of features is considered done and stable enough, you create a tag off that branch for the version under development and you bump the version of your current development to the next minor version. I'm talking abstractly, as you haven't mentioned what build tool you're using. With Maven, for example, the version currently under development would be a SNAPSHOT and if your currently released one was from branch 2.x and your development version was 2.3-SNAPSHOT, then your newly released version would be 2.3 and your next development version would be 2.4-SNAPSHOT.
I hope this all makes more sense now.
First of all the 1.x branch is technically just a branch name, like dev, aFeature or any other string.
This is a different model of version control. For example it makes sense, if you sell different licences for different versions.
In this model, you normally don't merge the branches back into the master. You start these branches if you start a new version. Then you maintain them parallel to the master branch.
You then build your releases (you called them artifacts) directly on those branches, by setting "Tags". After that you can go on developing on the same branch. For example:
We create a branch 2.x. After developing a while on that branch, we just create a Tag 2.1.0 and go on developing on that branch. After some bug fixes on the same branch a Tag 2.1.1 and so on. The same work is done for branch 3.x and 4.x.
So the purpose of the Tags is, to freeze a certain state of the code and provide it to the end users.
I'm looking for a version numbering scheme/pattern/system for an application that is currently branched into several versions with shell game style release dates. This has made versioning a nightmare. I'd like to just use the typical Major.Minor.Revision however this will break down for me quickly the way things are presently run around here.
Here is my inventory...
1.0.0 - Production version.
1.0.1 - Production revision version with bug fixes.
1.1.0 - Production minor version with new features due in July (regulations compliance, must be done).
1.2.0 - Production minor version with new features to integrate with not-yet-released-still-under-development System A.
2.0.0 - Development major version "2.0" of the product (code migrated to newer platform, usability improved).
And to make it more fun, they are planning another project (new features) for integration with a different system.
1.3.0 - Production minor version with new features integrating with System B.
Adding to the complexity is the fact that we don't know exactly when (read: the order in which) these will "go live". If one of the systems we are integrating with gets delayed, then management changes the release schedule. So version 1.2.0 today could get delayed and then the build we tagged as 1.3.0 would drop first. Coordinating with QA is difficult enough already without changing version labels at the end of the cycle.
Questions? Thoughts? Small furry animals?
peace|dewde
Sounds to me like you don't want to use version numbers specifically.
You can use codenames, (Windows did this with each of their releases before they were released).
You basically need something more than numbers to distinguish in house which branch you are talking about. As the versions are released you can slap a Major.Minor.Revision stamp on them, but until then you need to name them in a way that will be recognizable.
Split them into branches and sub-branches.
Make sure that anything dependant on a higher branch has a derivative name.
So, you could call a branch ProductionMac, and a branch ProductionWindows, and that way you would know instantly that they are not to be merged, and that they both derive from production.
The most important thing to maintain is the structural hierarchy. Version numbers do this fairly well, but you have to keep adding "." for each new layer, which is annoying and completely undescriptive (much like naming your variables variableOne,variableTwo,variableThree) So, make sure that however you choose to label each branch, it is still obvious which branches are related to which other branches.
Sounds like numbers aren't going to help much, I'd go with naming the releases after small furry animals.
Or, name each release after the project that spawned it ('UI overhaul', 'June maintenance' etc), and then only assign it a version number when it goes live?
I'd use a dictionary to map between internal development numbers and external "release" numbers, then use the internal development numbers internally and only expose the "release" numbers when you're ready to release it out of development.
Bonus points if you use an intermediate map using irrational numbers. "How is development on release 3.14159 going?" "Oh, not bad, but I'm still fixing a bug we found in release 2.71828183." "What? That bug? That was supposed to be fixed with minor release 1.73205!" :-)
As others have suggested, use a non-numeric codename internally, and apply a number as each component is released.
Appending a revision/build number to your versioning can help you match this internal codename to the external version number (and can aid in communication with QA).
For example:
RegulationCompliance r1234 corresponds to the release 1.1.0.1234.
Based on what you describe, I agree with the first couple of posts. Meaningful, unique names relevant to the scope/feature-set are probably the way to go for each branch. Numbered versions seem reasonable within each named branch.
What you really need... is Gmail-style labeling... for your versioning!
nth-ing the previous posts.
We have our build system increment the build # after each build (whether or not it is to be released) which is what dev/QA uses to identify builds. The final version # is ONLY exposed to the outside world when QA releases. So there are really multiple builds of 1.3.0.x, but only one true 1.3.0.
Here is another alternative I considered while churning on this yesterday. Perhaps I need to rethink what is considered major. Integrating with another system may be a small quantity of work, but if it impacts the scheduling and release dates and version in such a significant way, as it does for me here, maybe that alone is a large enough impact to bump the branch up to major status. Then some of my headache would be minimized.
The most likely scenarios for releasing versions out of order revolve around the minor iterations. The major ones take a coordinated, cross-departmental effort. You can see them on the horizon. The minor ones sneak up on you and fork everything up.
"Here are the new compliance
regulations. If they don't go live by
July 15th, we will be fined $500,000.
Per day."
"What? When did you get these?"
"Last July. Weren't you CC'd on the
distribution?"
** facepalm **
I still think Devinb's answer is best. But I wanted to throw this out here for others in this dilemma.
peace|dewde