Internal Applications: When Semantic Versioning Doesn't Make Sense
Semantic Versioning (or SemVer) is great for libraries and open source applications. It allows development teams to communicate to user and downstream developers the scope of changes in a release. One of the most important indicators in versioning is backwards compatibility (BC). SemVer makes any BC break clear. Web services and public APIs are another excellent use case for SemVer.
As much as I love semantic versioning for public projects, I am not convinced about using it for internal projects.
Libraries, be they internal or publicly released should follow the semantic version spec. Not only does this encourage reuse and sharing of libraries, it also displays good manners towards your fellow developers. Internal API endpoints should also comply with SemVer, but versioning end points should only expose major.minor in the version string. Again this will help maintain good relations with other devs.
End users of your application probably won't care if you drop jQuery in favour of straight JS, swap Apache for nginx or even if you upgrade to PHP 7/Python 3.x. Some users will care if you move a button. They won't care that the underlying data model and classes remain unchanged and so this is only a patch release. In the mind of those users, the button move is a BC break, because you changed their UI. At the end of the day, users don't care about version numbers, they care about features and bug fixes.
Regardless of the versioning system used, changes should be documented in a changelog. The changelog shouldn't just be a list of git commits streamed into a text file. This changelog should be something a non technical user can get their head around. This allows all stakeholders to clearly see the incremental improvement in the system.
In my mind SemVer breaks down when it comes to these types of (web) applications. Without a doubt any of the external integration points of the app should use semantic versioning. However the actual app versioning should just increment. I recommend using date based version numbering, such as 201512010 for the first release on 1 December 2015. The next release on that same day, if required, would be 201512011 and so on. If you release many times per day then you might want to consider a 2 or 3 digit counter component.
The components that make up your application such as the libraries, docker base images, ansible playbooks and so on should be using SemVer. Your build and test infrastructure should be able to create reproducible builds of the full stack if you reference specific versions or dependencies.
Instead of conditioning end users to understand semantic versioning, energy should be expended on teaching users to understand continuous delivery and deployment. The app is going to grow and evolve, tagging a release should be something a script can do. It shouldn't need 5 people in the tea room trying to work out if a feature can go in or not because it might be considered a BC break.
When building an application, get the code written and have people using it. If they're not happy, continue to iterate.