Semantic Versioning for SPServices?

Late last year I committed to put SPServices onto Github to encourage greater collaboration and contribution from the community. It’s definitely there now, and there are several things I’ve been struggling with since I moved it there:

  • What to name each version
  • How many versions to move into the repo
  • Whether it actually will increase community submissions at all
  • etc.

So far, I have done one release while SPServices has been on Github, which was 2014.02 [Codeplex][ [Github]. Even for that one new release, I wasn’t sure how to structure things. Everyone is moving away for including version numbers in their file names. I’m not sure that’s such a good thing. By including the version number in the file name, we can tell – at a glance – what version we’re working with. Since many SPServices users are more on the end user end of the spectrum rather than the developer end, that’s an excellent thing to be able to do.

Andreas Schultz has recommended that I switch to Semantic Versioning in a pull request for bower.json. Bower is a package manager, and there are a host of others: npm, NuGet, Bower, Ender, volo, component, Jam, and the list goes on. The number of these things is increasing fast. (I’d include links, but these things are easy to find.)

This is a tricky one. I’ve watched as this “semantic versioning” thing gets rolling, and I’m not sure how I feel about it.

Over the first several years I increased the versions for SPServices from 0.2.3 to 0.7.2. The fact that I wasn’t getting to version 1.0 was more me being cantankerous than anything else. Then I had 3 or 4 people tell me – separately – that they weren’t allowed to use software in their organizations unless it was version 1.0 or above. What a crock!

So I switched to numbering like 2013.01 back in May, 2013. The version is greater than 1.0! Since then, I’ve had 2013.02, 2013.02a, 2014.01, and 2014.02. It marches forward and gives some indication of what the versions is, or at least its age.

Semantic versioning seems to give people an excuse to introduce breaking changes. Here’s the summary of the idea from the SemVer site:

Given a version number MAJOR.MINOR.PATCH, increment the:

  1. MAJOR version when you make incompatible API changes,
  2. MINOR version when you add functionality in a backwards-compatible manner, and
  3. PATCH version when you make backwards-compatible bug fixes.

Additional labels for pre-release and build metadata are available as extensions to the MAJOR.MINOR.PATCH format.

One of my goals with SPServices going way back to 1999 has been not to introduce *any* breaking changes. I think I’ve done a pretty good job on that, too. Whether you’re using SPServices on SharePoint 2007 with no updates installed or SharePoint 2013 on Office365, it *ought* to work the same way. Code that you wrote with version 0.2.3 *ought* to still work, too, though most likely you’re running a more recent version of jQuery and other things which would make using that ancient version pretty dumb. (That and the fact that the first version didn’t do much.)

If I were to follow the semanatic versioning rules, I’m not sure if I would be at 1.1.14 or 1.14.02 or what. Removing version numbers from files makes me uncomfortable, though.

Switching to semantic versioning seems to be hopping on a train without really understanding if driving is just fine and will get us there at the same time. What are your opinions on this? If you add your $.02 into the comments, please indicate what type of user you are, e.g., end user (“I paste SPCasecadeDropdowns into my forms” or developer “I write solutions using SPServices as the data transport layer” or…

10 Comments

  1. I’d suggest ignoring the “Semantic Versioning” trend. Stick with good ol’ numbers. You will always know version 61 came after version 60 and before version 62. Can’t do that with “-now-supports-REST”.

    Reply
  2. Open question. When you added promises in addition to callbacks, what was spservice returning before? Would that be a breaking change?

    I’m in the 2015.1.0 camp. Use minor and patch as per SemVer but leave the major as the year number that you have right now. Additionally, it looks nearly the same as what you have now so humans can understand 2015.1.0 > 2014.02

    I have lots of worry that 1.2015.1 (or worst 1.15.1) > 2014.02 would not be apparent to people.

    On the patch number – I’m not sure what situation would you release a patch version. When O365 changes break things and we need a new patch in a hurry? How do you handle that situation?

    -dev

    Reply
    • John:

      When I added promises, the old completefunc with async: false continued to work in exactly the same way. When I added caching, ditto. etc. My goal has always been great backward compatibility. So there. I may not have done it all perfectly (I know that I haven’t) but I’ve never intentionally – that I can recall – introduced a breaking change.

      I do think that switching *again* to something like 21.15.01 or 21.0.1 or something would just be silly. At some point, either SPServices will stay static or I’ll produce some new SPServicesREST or something. But that will be a different library because it wouldn’t make sense to haul along all the old SOAP stuff.

      The semantic numbering thing makes *some* sense for me, but I’ve also sat in rooms debating what a “breaking change” even means. Believe me, there is not common thinking about what that concept is. So if people are following the semantic rules but have different ideas about the underlying concepts, I’m not sure what good it’s really going to do, anyway.

      M.

      M.

      Reply
      • Mark,
        Although what you sad is true but only because SPService does not really follow jQuery plugin pattern for jQuery.fn… normally, method attached to jQuery.fn act on a selection of element and the pattern is to always allow chaining by returning the selection back… Plugins that are not meant to act on DOM element should normally create a namaspece against the jQuery object directly (ex. jQuery.SPServices).
        SPServices, up until Promises were introduced, I think was return ‘undefined’… Again, this was non-breaking because the patter usage of SPServices was non-chainable. :)

        I’m posting my comment/feedback on this topic next.

        Reply
  3. Only change things if there’s a good reason to change. Moving to Symantec version numbers won’t make things work any better than they do now and wont help anyone who’s already working with SPServices so it would be a change for the sake of conforming with others, not for improving the product.

    I use SPServices on customer projects to enhance forms and add dynamic functionality.

    Reply
  4. I think “Semantic Versioning” is no better versioning and it’s also not worse. It´s another one.
    A great benefit (for my opinion) were the possibility to integrate the component into bower and npm (if someone use npm for his client components).

    Currently SPServices is the last component in my projects, not supported by bower.

    Here you can see a snapshot of a common bower.json in my projects.

    {
      "name": "SP***AppVS15",
      "private": true,
      "exportsOverride": {
        "bootstrap": {
          "js": "dist/js/*.*",
          "css": "dist/css/*.*",
          "fonts": "dist/fonts/*.*"
        },
        "jquery": {
          "js": "jquery.{js,min.js,min.map}"
        }
      },
      "dependencies": {
        "angular": "~1.3.9",
        "angular-route": "~1.3.9",
        "angular-ui-bootstrap": "~0.12.0",
        "angular-sanitize": "~1.3.9",
        "angular-ui-grid": "~3.0.0-rc.16",
        "angular-ui": "~0.4.0",
        "ui-utils": "~0.1.1",
        "bootstrap": "~3.3.1",
        "jquery-ui": "~1.11.2",
        "lodash": "~2.4.1",
        "moment": "~2.8.4",
        "moment-timezone": "~0.2.5",
        "sp-services-aschulz": "~14.2.0"
      },
      "resolutions": {
        "angular": "~1.3.9"
      }
    }
    

    In the past I inserted the SPServices dependency directly into my project.
    Now I forked the SPServices in GitHub and created a bower entry pointing to my fork.
    The only reason for this indirection is that bower (as far I know) is requiring the “Semantic Versioning”.

    I believe it were a step into the right direction.

    The concrete version (here: “14.2.0”) is just a suggestion as well.

    The only intention for my pull request was the possibility to support bower.

    I’m Dev.

    Reply
    • Andreas,
      Bower (and just about every other package manager) does allow you to still use packages without a version number – some even without their type of “config file” (ex. the bower.json file)… Instead of a version number, you enter the http address to the tarball (ex. https://github.com/sympmarc/SPServices/archive/2013.02a.tar.gz) or the GIT address (ex. https://github.com/sympmarc/SPServices.git#master)… This even works with GISTs… Here is an example from one of my projects:

      "dependencies": {
          "jquery": "1.11.1",
          "jquery-ui": "~1.11.2",
          "requirejs": "~2.1.15",
          "require-less": "~0.1.5",
          "requirejs-text": "~2.0.12",
          "noty": "~2.3.4",
          "knockout": "~3.2.0",
          "spectrum": "~1.6.0",
          "sammy": "~0.7.6",
          "SPWidgets": "git@github.com:purtuga/SPWidgets.git#master",
          "jquery.stickOnScroll": "git@github.com:purtuga/jquery.stickOnScroll.git#master",
          "jquery.todoList": "git@github.com:purtuga/jquery.todoList.git#master"
        },
      

      The only drawback with not having a semantic version is that we can’t take advantage of the features that package managers give you: like ‘update’ would either not work or possibly download a version that you are not prepared to accept (ex. if I define SPSErvices as ~1.2.0, that means that I any patch (3rd digit is larger than what I defined) that is available… During a bower update, it will automatically be installed… This is (in my opinion) one of the true values of package managers… As you stated: before them, we had to manually download and install all depenecies manually..

      (for others: here is a reference to how most package managers use version numbers: https://github.com/npm/node-semver#ranges)

      Reply
  5. Here is my original response on the Pull request:
    ——-
    I too think that going with semantic convention is a good move. And one
    that would support package mangers like bower.

    Marc has been entertaining the thought of adding older versions of
    SPServices to github. This would be the opportunity to re-think the entire
    naming convention. I like John’s suggestion, about keeping the first digit
    as the year. That would more closely resemble what Marc was attempting to
    do with this convention and as John pointed out, it maintains a hierarchal
    structure (2015.0.0 is newer than 2014.0.0).

    My personal thoughts: forget the concept of trying to tie your versions of
    SPServices to a year and instead go with full support of semantic
    versioning. Having the version number imply that there are possible
    backwards incompatible changes is a very beneficial feature. And one that
    all package managers automatically support with special tokens (^2.3.4, or
    ~2.3.4).
    —–
    If wanting to keep the Year in the version as a memory jogger, then favor the suggestion by John.
    Also note that adding the version number does not prevent us from using package managers, as just about all them accept multiple types of input…

    Reply
  6. Like Andreas mentioned, there are popular tools out there that depend on semantic versioning to auto-detect versions (usually as a way to say “use this version or newer, but don’t go up a major version number that will break my app”). If you feel like that’s very important to the SPServices project, then switching to semver makes sense. Traditionally it hasn’t been all that important; most SharePoint devs weren’t using tools like bower or npm because they didn’t exist or were mostly used by non-SharePoint web developers, and SharePoint power users are almost certainly not using them.

    Now that SharePoint is embracing JavaScript, REST, etc., tools like bower and npm will probably be used more and more by SharePoint devs. Is that reason enough to change the version scheme? I think so, but that’s just one opinion.

    In theory, if you never make breaking changes, you could rename your latest version to 1.36.0 (I counted 36 releases so far) and eventually you may get up to 1.284.0 or something if you never make a breaking change and release a bunch of new features over the next few years. Or start at 2015.0.0 and just never change the year (which may be more confusing than ditching the year).

    The change in version scheme might be jarring or confusing to some users, but so was the change to using the year. I think as long as you communicate what changed and why (as you always have done a good job of in the past), users will get it. I’m sure many just go to the CodePlex site and download the latest release without looking too closely at the version numbers.

    I don’t think it should be changed for the sake of conformity or because semantic versioning is somehow “better” (there’s still plenty of debate about it). It should be changed only because you want it to be available to other tools that depend on semantic versioning.

    Reply
  7. Paul, thanks for the hint.

    This is a much better workaround than creating a fork and an associated bower entry :-)
    “sp-services”: “https://github.com/sympmarc/SPServices.git#2014.02”

    And I think changing the future tag-names to semantic versioning is furthermore a good idea.
    (The release names can differ)

    Reply

Have a thought or opinion?