Semantic versioning - major version for a traditional web application - semantic-versioning

I have a Rails app which is a traditional web application (HTTP requests are processed and HTML pages are rendered). As of now, it does not have an APIs that are exposed to other apps.
I want to use semantic versioning for versioning the application. Currently it is at '0.0.0'.
Quoting from the documentation:
MAJOR version when you make incompatible API changes,
MINOR version when you add functionality in a backwards-compatible manner, and
PATCH version when you make backwards-compatible bug fixes.
From what I understand, because there are no applications dependent on mine, the major version will never change. Only the minor and patch versions will change, the major version will always remain 0.
I want to know if my understanding is correct. Is there any scenario in which my major version will change?

Since you're not developing and releasing software package, semantic versioning is not directly applicable. It sounds like a single "release" number could be enough for your use case, since what you need is track when a code change will be in test and in prod. Assuming code must go through test before going to prod, you would update the number whenever you update the test environment with code from the development branch. This way, at a given moment development would have release N, test would have N-1, and prod N-2.
API versioning is a different problem, independent of release numbering. In my experience API users only care about breaking changes, so those need to be versioned. Also, since users are slow to update their apps you must be prepared to keep old versions around indefinitely.

One way you could think about this is to think about the user's flow through the application as the basis for versioning. If a breaking change happens (i.e. the user's flow is changed in a way that makes the old route impossible) then it could be considered breaking. If you're adding new functionality that hasn't existed before (i.e. the user has access to a new feature or sees something new on the website that they can interact with) then that could be considered a minor version increase. If you're deploying minor fixes to things like text, then that could be considered a patch-level change.
The problem with this approach, though, is that you need to understand a user's workflow through the application to be able to correctly increment the major version, and as software developers we're still pretty terrible at doing that properly.
Ref: https://christianlydemann.com/versioning-your-angular-app-automatically-with-standard-version

Related

Version queries in URL to bypass browser cache

I'm writing a web application which will likely be updated frequently, including changes to css and js files which are typically cached aggressively by the browser.
In order for changes to become instantly visible to users, without affecting cache performance, I've come up with the following system:
Every resource file has a version. This version is appended with a ? sign, e.g. main.css becomes main.css?v=147. If I change a file, I increment the version in all references. (In practice I would probably just have a script to increment the version for all resources, every time I deploy an update.)
My questions are:
Is this a reasonable approach for production code? Am I missing something? (Or is there a better way?)
Does the question mark introduce additional overhead? I could incorporate the version number into the filename, if that is more efficient.
The approach sound reasonable. Here are some points to consider:
If you have many different resource files with different version numbers it might be quite some overhead for developers to correctly manage all these and increase them in the correct situations.
You might need to implement a policy for your team
or write a CI task to check that the devs did it right
You could use one version number for all files. For example when you have a version number of the whole app you could use that.
It makes "managing" the versions for developers a no-op.
It changes the links on every deploy
Depending on the number of resource files you have to manage the frequency of deploys vs. the frequency of deploys that change a resource file and the numbers of requests for these resource files one or the other solution might be more performant. This is a question of trade off.

SemVer major upgrade or not?

I have an artifact that is not used directly. These artifacts contain the server that runs users application. The API that is visible to users (i.e. to 3rd parties) is well defined in a separate library.
Now, I am doing some changes in the server. Some public methods get signature change. However, this does not reflect the user, since he does not see the changes.
I am not sure what SemVer defines in this situation. Should I
A) Bump the servers major version, since public method signature is changed, or
B) Bump minor version as this change does not affect the users of the server?
In fact, it seems that in case B the server will never get the major version increase, i.e. it would always stay at 1.x.x since the API for a user is defined in a different library (server is just an implementation of it).
How should I treat this case?
A "public method signature" change sounds like a breaking change to me. But then you say this change doesn't affect the clients. It's a bit confusing. Did you add features to the API? That's a minor bump. If you changed an existing API such that a client must be recompiled or modified in order to continue using it, then you have a major bump. The SemVer spec is quite clear that API changes require either a major or minor bump and everything else falls under the "bug fix" category.
If your change involves adding optional parameters to existing methods or accepting additional constants/enumerations to functions in a way that does not require client code to be recompiled and no behavior changes are visible to clients using the old feature set, you definitely have a minor change.

What does "public api" mean in Semantic Versioning?

I'm learning about how to assign and increment version numbers with the rule called "Semantic Versioning" from http://semver.org/.
Among all its rules, the first one said:
Software using Semantic Versioning MUST declare a public API. This API could be declared in the code itself or exist strictly in documentation. However it is done, it should be precise and comprehensive"
I am confused about "public API". What does it refer to?
Public API refers to the "point of access" that the external world (users, other programs and/or programmers, etc) have to your software.
E.g., if you're developing a library, the public API is the set of all the methods invokations that can be made to your library.
There is understanding that, unless a major version changes, your API will be backwards-compatible, i.e. all the calls that were valid on a version will be valid on a later version.
You can read at point 9 of those rules:
Major version X (X.y.z | X > 0) MUST be incremented if any backwards incompatible changes are introduced to the public API.
I discovered SemVer today and read up on it from several sources to ensure I had fully grasped it.
I am confused about "public API". What does it refer to?
I was also confused about this. I wanted to set about using SemVer immediately to version some of my scripts, but they didn't have a public API and it wasn't even clear to me how they could have one.
The best answer I found is one that explains:
SemVer is explicitly not for versioning all code. It's only for code that has a public API.
Using SemVer to version the wrong software is an all too common source
of frustration. SemVer can't version software that doesn't declare a
public API.
Software that declare a public API include libraries and command line
applications. Software that don't declare a public API include many
games and websites. Consider a blog; unlike a library, it has no
public API. Other pieces of software cannot access it
programmatically. As such, the concept of backward compatibility
doesn't apply to a blog. As we'll explain, semver version numbers
depend on backward compatibility. Because of this dependence, semver
can't version software like blogs.
Source: What Software Can SemVer Version?
It requires a public API in order to effectively apply it's versioning pattern.
For example:
Bug fixes not affecting the API increment the patch version
Backwards compatible API additions/changes increment the minor
version, and...
Backwards incompatible API changes increment the major version.
What represents your API is subjective, as they even state in the SemVer doc:
This may consist of documentation or be enforced by the code itself.
Having read the spec a few times,
Software using Semantic Versioning MUST declare a public API. This API could be declared in the code itself or exist strictly in
documentation. However it is done, it should be precise and
comprehensive.
I wonder whether all it means is that the consumers of your software must be able to establish the precise "semantic" version they are using.
For example, I could produce a simple script where the semantic version is in the name of the script:
DoStuff_1.0.0.ps1
It's public and precise. Not just in my head :)
Semantic versioning is intended to remove the arbitrariness that can be seen when someone decides to select a versioning scheme for their project. To do that, it needs rules, and a public API is a rule that SemVer chose to use. If you are building a personal project, you don't need to follow SemVer, or follow it strictly. You can, for example, choose to loosely interpret is as
MAJOR: Big new feature or major refactor
MINOR: New feature which does not impact the rest of the code much
PATCH: Small bug fix
But the vagueness of this loose interpretation opens you up to arbitrariness again. That might not matter to you, or the people you foresee who will be using your software.
The larger your project is, the more the details of your versioning scheme matters. As someone who has worked in a third level support for a large IT company (which licenses APIs to customers) for quite some time, I have seen the "is it a bug or is it a feature" debate many times. SemVer intends to make such distinctions easier.
A public API can, of course, be a REST API, or the public interface of a software library. The public/private distinction is important, because one should have the freedom to change the private code without it adversely affecting other people. (If someone accesses your private code through, say, reflection, and you make a change which breaks their code, that is their loss.)
But a public API can even be something like command line switches. Think of POSIX compliant CLI tools. These tools are standalone applications. But they are used in shell scripts, so the input they accept, and the output they produce, can matter. The GNU project may choose to reimplement a POSIX standard tool, and include its own features, but in order for a plethora of shell scripts to continue working across different systems, they need to maintain the behaviour of the existing switches for that application. I have seen people having to build wrappers around applications because the output of the version command changes, and they had scripts relying on the output of the version command to be in a certain form. Should the output of the version command be part of the public API, or is what those people using it did a hack? The answer is that it is up to you and what guarantees you make to the people using your software. You might not be able to imagine all use cases. Declaring the intended use of your software creates a contract with your users, which is what a public API is.
SemVer, thus, makes it easier for your uses to know what they are getting when upgrading. Did only the patch level change? Yes, so better install it quick to get the latest patch fix. Did the major version change? Better run a full, potentially expensive, regression test suite to see if my application will still work after the upgrade.

How to manage "3rd party" sub-projects in Perforce?

Our group integrates a bunch of different sub-blocks into our main project and we are trying to determine the best way to manage all of these different pieces of intellectual property. (From here on out I will refer to these sub-projects as pieces of IP "Intellectual Property").
The IP will be a mixture of third party vendor IP, previous projects IP and new to this project IP. Here are some of the ideas we are considering for managing all the different pieces of IP:
Publish releases on a physical drive and have the main project point to the correct releases.
PROS - Little to no dependencies on the SCM: seems simpler to manage initially:
CONS - Must remember to keep each physical design center up to date:
Use Perforce client spec views to include the correct version.
PROS - Able to quickly see what IPs are being used in the client spec:
CONS - With a lot of IPs the client spec becomes very messy and hard to manage: each team member manages there own client spec (inconsistencies): the very thing determining which IP version to use is not under SCM (by default):
Integrate the the different releases into a single one line client view.
PROS - Makes client spec maintenance dead simple: any change to the IP version is easly observable with the standard Perforce tools:
CONS - Not as easy to see what versions of IP we are using:
Our manager prefers #2 because it is easiest for him to look at a client spec and know all the IPs we are using and the versions. The worker bees tend to strongly dislike this one as it means we have to try and keep everyones individual client specs up to date and is not under SCM of the project itself.
How do others handle IP within a Perforce project and what recommendations do you have?
UPDATE:
I am really leaning towards solution #3, it just seems so much cleaner and easier to maintain. If any one can think of why #3 is not a good idea please let me know.
I would go for the third solution too.
I can't think of any downsides, and have not experienced any when faced with similar situations in the past.
You could placate your manager by using a branch spec that clearly spells out which IP versions are branched in. He could then refer to that branch spec instead of a client spec.
Also if you look up 'spec depots' in the help, you can set Perforce up so that it version controls all specs, including branch specs, automatically, which will give you traceability if you alter IP versions.
"each team member manages there own client spec (inconsistencies)"
Don't do that. Have the client spec be a file that is checked in to Perforce.
I would suggest #2 as it is the most transparent system. Yes it will mean some more work keeping clients up to date, but you can minimize that issue by using template clients.
At my work we use template clients that the devs copy from to keep their clients properly configured. We name this with the pattern "0-PRODUCT-BRANCH" (and sometimes add platform if needed). Then it is a one line command from the command line, or a couple clicks from the GUI to update your client. I send notices to the team whenever the template changes.
Now in my case, template changes don't happen very often. There is maybe a max of 5-6 per year, so the hassle level may be different for you.

Lean Software (Webapplication) Release Engineering

I'm looking to re-organize the way we release our internal software. All of the code (PHP webapps, some Java apps and Perl scripts) is checked into Subversion repositories but there are no branches or tags, everything is checked into trunk (only around 1-3 devs per app). On the production linux servers, the software is just directly run from a working svn copy (actually most of the changes happen there as well).
Since we have a lot of small apps and release very often small changes to the running system, I'm looking for a very lean or transparent way to do some release engineering and to clean up this mess abit.
Are there any tools out there that may help me to do so in a heterogenous environment (language-wise) like that?
Or has anyone an idea how to do this in a proper way?
Otherwise I'd thought of writing some release (shell) scripts that automatically create subversion tags from trunk and then do a checkout of the corresponding tag to the production servers. But that sounds kinda hack'ish as well to me.
Thanks,
Haes.
Continuous Integration is definitely the way to go - any CI (even minimalist batch files) is better than none - but it'll only be as good as the policies you have in place. Since your files don't really end up as a 'binary' or 'distributable', marking a release might merely require only that you tag the repository, or even just stash the Subversion revision number somewhere. The important policy that you need is that any release can be reconstructed whenever you need it - so you can compare current and previous releases, or go back to an older release if something goes wrong. Don't worry about the 'overhead' of creating tags in svn - that's very efficient.
A release script that does the subversion tag sounds fine. A CI implementation (I'd recommend CruiseControl since it's ideal for heterogeneous work, although heterogeneity requires a bit more configuration overhead) is great, since you can automatically kick the process off on a subversion checkin, and run automated tests that determine whether it's good enough to tag or not.
I'd definitely not auto-deploy to a release server. A 'staging area' (call it 'nightly build', 'beta test', whatever) would be better. Let your users bang away on that before you decide it's good enough to roll out onto the production servers. And, as long as you've got the policy in place of being able to rollback to an earlier version, you've mitigated the possibility of a bad roll-out.
The auto-checkout onto production servers is the only 'hackish' part - an automated checkout, test, tag, beta deploy is slick enough. Rolling-out to production shouldn't have an easy button, though.
Use tags and branches; make it a part of the development cycle. When you update that "stable-1.0" branch, have tested the change(s) and tagged it "release-1.0.5", you simply do "svn switch" on the server to the new tag. Didn't work, despite having tested it? Switch back, and figure out what's wrong.
But beware, branching in subversion can be a pain, at least pre version 1.5. If you or your developers are not experienced with branches, expect a bit of hassle and/or mistakes in the beginning. But as long as you've committed no code should be lost (at worst simply difficult to merge).
Your developers really should learn how to use branching; it can be very useful for a variety of purposes (not just for release engineering).
Do not automatically switch over code on your production servers; somebody might accidentally hit the wrong button. Production updates should always be done with care. Scripts for adding new tags is, imho, unnecessary due to the simplicity of it, but your mileage may vary.
One last thing, don't allow anyone to have changes on your production server. It might cause conflicts, and those tend to take time to resolve. Not to mention, it destroys your ability to reproduce a given release on different workstations (works fine here! why not on the server? hmm).
Some Continuous Integration Servers do this sort of thing, Hudson, for example, has subversion integration. It can tag, run test, and deploy for you.
i'd use Hudson. in addition to fetching from and tagging in svn (ref sblundy), it can be useful in release management with the proper plugins. f.ex., you could try a plugin to "promote" the builds you deploy to production, and keep a list of both the promoted builds themselves and a change/commit log for the various versions.

Resources