{"id":9339,"date":"2022-01-06T18:25:34","date_gmt":"2022-01-06T23:25:34","guid":{"rendered":"https:\/\/blogs.pacasmayo.com\/felipe\/?p=9339"},"modified":"2022-03-16T05:37:45","modified_gmt":"2022-03-16T10:37:45","slug":"semantic-versioning-semver","status":"publish","type":"post","link":"https:\/\/blogs.pacasmayo.com\/felipe\/2022\/01\/06\/semantic-versioning-semver\/","title":{"rendered":"Semantic Versioning &#8211; SemVer"},"content":{"rendered":"\n<p><a href=\"https:\/\/blogs.pacasmayo.com\/felipe\/2022\/01\/06\/versionado-semantico-semver\/\">Spanish version<\/a><\/p>\n\n\n\n<h2 class=\"wp-block-heading\">Simple description<\/h2>\n\n\n\n<p>If you need to know all the details of the SemVer specification, please visit the specification <a href=\"https:\/\/semver.org\">website<\/a>, here we will only briefly discuss the main points and some practical applications.<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>2.3.8-alpha3.1\n^ ^ ^ ^\n| | | |\n| | | --&gt; Prelaunch\n| | --&gt; Patch\n| --&gt; Minor\n--&gt; Major<\/code><\/pre>\n\n\n\n<ul class=\"wp-block-list\"><li>Use Patch for bug correction, 100% backward compatible <\/li><li>Use Minor to add new functionality without breaking compatibility <\/li><li>Use Major to introduce major changes that have the potential to break backward compatibility <\/li><li>Use Pre-Release while developing a new version<\/li><\/ul>\n\n\n\n<h2 class=\"wp-block-heading\">Best practices in the use of Semantic Versioning<\/h2>\n\n\n\n<h3 class=\"wp-block-heading\">Single Source of Truth<\/h3>\n\n\n\n<p>It is of paramount importance in software development that there is a single source of truth for the entire process, and this is especially important with regard to version. There should be no question as to which version of the source code was used to build each piece of software. Choose a source of truth for the package version and make sure that version is reflected throughout the process.<\/p>\n\n\n\n<figure class=\"wp-block-image size-large is-resized\"><img loading=\"lazy\" decoding=\"async\" src=\"https:\/\/plantuml.com\/plantuml\/png\/VP2_RhGm4CHxFyMAhuRYIoekGlS8gLAbyU65isACupyeKSIxnrvZeslIi3l3QEoVhyvpwyEY61_zQa7WXcerQ86x91YRf4A0ng9PdOoHxswM_brxFlVR_-wfUsvID7hmpt25iqNK5oKrzkVQ2UxkA2uUltosuOS1KFM2dfC26BaLq6nedLnrVvPl360lURS6EsAofu3Q8zk1iS-00S58W-auggEog7pPRq4g4KNabLEaBKiDU7HrFovHf0at9TsTxSTxDAzy_E0pmi9r79QkQHOwkFOtRxa4HVKoJb5_O1FnpWHkqBO3FL8HXJiFSWWpVI2Ap4bV-ban4z-3Kq93HgVsIfxJfpxcOq4rX_f4nuINjgsvOb9VDQ-eHLZKBm00\" alt=\"\" width=\"508\" height=\"378\"\/><\/figure>\n\n\n\n<h3 class=\"wp-block-heading\">Automatic sync<\/h3>\n\n\n\n<p>Once you&#8217;ve chosen the single source for the version, look for tools that allow you to automate most of the version synchronization at different stages of the software development process (SDLC). It is inevitable that the version is present in different forms and places of the process, so it is necessary that, as far as possible, the process by which the version spreads to these different stages and places be automatic to prevent a desynchronization.<\/p>\n\n\n\n<p>For example, the version appears in a package meta file in text form, also in a repository tag and package meta description, and potentially in various other places along the way.<\/p>\n\n\n\n<h3 class=\"wp-block-heading\">Intentional versioning<\/h3>\n\n\n\n<p>Don&#8217;t fall for the temptation of updating the version automatically. It is very easy for developers to create a simple utility that updates the version each time we make a change to the code or each time we compile the application. And while it is true, that saves us a few milliseconds, it goes against the best practices of the semantic version, where each change to the version is intentional and calculated in such a way that the version reflects the changes in the application.<\/p>\n\n\n\n<h3 class=\"wp-block-heading\">Refuse to unintentionally rewrite the version<\/h3>\n\n\n\n<p>To avoid confusion, it is preferable that a version cannot be used twice, it is better if there is some way to prevent it by default. Systems like the npm package manager reject a second package with the same version, but allow you to delete the current version and rewrite it in case it is absolutely necessary to use a version that was used by mistake. Choose tools that allow you at some point in the pipeline to detect and reject two different packages with the same version.<\/p>\n\n\n\n<h2 class=\"wp-block-heading\">SemVer in specific tools<\/h2>\n\n\n\n<h3 class=\"wp-block-heading\">NPM<\/h3>\n\n\n\n<h4 class=\"wp-block-heading\">Versioning your package or application<\/h4>\n\n\n\n<p>NPM is the NodeJS package manager and has native support for SemVer, that is, you don&#8217;t need to install a separate tool for all Semantic Versioning management in your package, although there are tools for advanced use if necessary. I think it will be enough to show an example to document how easy it is to do semantic versioning in NPM.<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code># start creating a new package\n# (you'll have answer several questions\n# like who will support the package, descripci\u00f3n, etc.)\nnpm init\n# now you'll have a file called package.json\n# inside which you'll the a field called version\n# now bump the version\nnpm version patch\n# verify in package.json and you'll notice\n# that version is now 1.0.1\n# if you are working on a version not ready for release\n# you can increment the pre-release version\nnpm version prerelease\n# version is now 1.0.2-0\n# let's say you are still working on that pre-release\nnpm version prerelease\n# version is now 1.0.2-1\n# whenever you are ready to release that version\nnpm version patch\n# version is now 1.0.2 \n# note that you were already working\n# on 1.0.2 but it has now dropped the prerelease portion\n# now you can publish this version\n# rmember to always use the SemVer concepts\n# meaning\n# patch to fix problems\nnpm version minor\n# now version is 1.1.0, which means that you\n# have added new functionality\nnpm version major\n# now version is 2.0.0, which means tha\n# that you have changed something that could break\n# the functionality of existing installations\n<\/code><\/pre>\n\n\n\n<h4 class=\"wp-block-heading\">Versioning your dependencies<\/h4>\n\n\n\n<p>As you saw, it is very easy to use SemVer when the tools you use support it natively. But, it is also necessary to use the concepts of SemVer when your application or package depends on other packages; NPM also handles this natively. For example,<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code># Let's say that in your package you need to parse a swagger file\n# YOU MUST NOT write your own parser :)\n# There is a parser called swagger-parser,\n# you want to install it and you don't care about the version\nnpm install swagger-parser\n+ swagger-parser@10.0.3\n# this will install the latest version 10.0.3\n# but, the library has changed since last time\n# you used it and prefer to use the previous version\n# If you know the exact version, you can install it like this\nnpm install swagger-parser@2.0.0\n+ swagger-parser@2.0.0\n# if you prefer the minor version 2.0,\n# but you don't know what the last variation\n# of that version is, you can use the tilde ~\nnpm install swagger-parser@~2.0.0\n+ swagger-parser@2.0.1\n# if you are adventurous but you don't want to\n# that a new version break compatibility\n# with your package, then you can\n# ask for the latest minor version\n# using the caret or hat ^\nnpm install swagger-parser@^2.0.0\n+ swagger-parser@2.5.0\n<\/code><\/pre>\n\n\n\n<p>Another aspect of a mature package manager is creating a lock file. That is, while it is true that the developer wants a certain level of flexibility in the version of the package they receive, the application operator will want a high level of stability in the application that they keep in production. To achieve this balance, package managers like NPM create a file parallel to package.json in which they store the specific version of each of the dependencies that were installed. This is key so that, when building the version that will run in production, it contains the exact same versions that the developer used during development and that were used during unit testing and integration. Otherwise, operators could not be confident that what they are putting in production is identical to what was originally intended.<\/p>\n\n\n\n<p>NPM has an additional advantage and that is that when you use the npm manager to version your package or application, it automatically adds a git tag to your repository, we will see it in action in the next section.<\/p>\n\n\n\n<h3 class=\"wp-block-heading\">Git<\/h3>\n\n\n\n<p>Git tags are not strictly compatible with SemVer, that is, one can assign any word as a tag (although there are very strict rules regarding which characters are valid). So while almost any word is valid as a git tag, most software development teams use conventions to equate tag with version. The most used convention is to prefix the semantic version with the letter v; thus semantic version 2.3.8 will be labeled in git as v2.3.8. Again, there are no hard and fast rules, but it&#8217;s important that the whole team accepts a standard nomenclature by convention.<\/p>\n\n\n\n<p>All modern software development systems support semantic versioning in package handling and it is important to keep git tag synchronization in parallel with the package itself. But, you must remember that git tags are not reusable (even though they can be deleted and recreated, this is not recommended), and therefore you must tag when the version is ready to be promoted.<\/p>\n\n\n\n<p>My recommendation is that the source of truth is the version in the package and that git be synchronized manually or automatically. Use strict SemVer in versioning the package and the current convention is to add the &#8216;v&#8217; to the git tag.<\/p>\n\n\n\n<div class=\"wp-block-image\"><figure class=\"alignright size-large\"><img decoding=\"async\" src=\"https:\/\/plantuml.com\/plantuml\/png\/ZT71Rjim30RWkvxY1t982qH6cw67hPSUXW4z37i6sM8iOH9fIFGoFywUPIysPKw7BaEmdaoBDlbHVAhgYiuvcT-1-M0nHiKGQFWgioAxo6Ozc-QKp4NQzjW_sBnOfgCzp3ne57Ofwl9e2atar02j9ayPtwZKbiLKg50YLmaRlElkk_VsRdSExb-2lG6whiEnH2KCuia0QtFdFQnrAVqv6IJdzh0Ps-TJcZogPD8GUTmQuCLV0-mCAN6C_3ytZY4cmiqXSgo1_2rYnGtBxQEvc2T7be8DN93YKAdy_D66s7TtvjBxZ_PJ_4uLc_q3B3ulQ1ZyXTcQrtHxa9JaQDMDjIdmh2VJLEX09VQ9e89CPIG8GmEXK1Qb7VfPSMhi63t12nEI34sqc3UjUorwvS9U4Hlg2m-qVkzty9H8gL7E_T0NnqCu_x6-m7wyleggCfadOZ_dz0i0\" alt=\"\"\/><\/figure><\/div>\n\n\n\n<pre class=\"wp-block-code\"><code># as soon as you are going to work on something new, create a branch\ngit checkout main\ngit pull\ngit checkout -b 25-my-new-functionality\n# it is also recommended to create the temporary package semver at the same time\n# current version is 3.1.8\nnpm version prerelease\n# the output will be something like v3.1.9-0\n# now you can work on fixing or implementing\n#encode ...\n#lint\n# unit test\n# during implementation it is recommended\n# to add files and commit multiple times daily\n# it is also recommended that each time the code is pushed\n# to the remote repository, update the prerelease version\n# npm version prerelease\n# 3.1.9-1, 3.1.9-2, etc.\nnpm version prerelease\ngit add --all\ngit commit -m 'I added something'\n# the first time, you must indicate which remote branch to send to\ngit push -u origin 25-my-new-functionality\n# once the code has been implemented, validated and tested\n# then the appropriate version is created (patch, minor or major)\nnpm version minor\n# now the version will be 3.2.0, note that when creating the version it removes the prerelease segment\n# it is also important to note that, in the case of npm\n# and other modern package managers,\n# if you use the version tools,\n# tags will automatically be created in git\ngit add --all\ngit commit -m 'Fixes # 25 - My new functionality'\n# The --follow-tags argument instructs git to send everything, including tags to the remote repo\ngit push --follow-tags\n# if your company does not use a process to do peer code review and the merging of branches\n# then the following lines are called locally\ngit checkout main\ngit pull\ngit merge 25-my-new-functionality\ngit push\n# regardless of whether it is merged on the remote or local system\n# once merged, for cleaning, you must delete the local branch\ngit branch -D 25-my-new-functionality\n<\/code><\/pre>\n\n\n\n<p>Warning<\/p>\n\n\n\n<p>NEVER reuse an already merged branch. If you are using the GitLab flow, which we strongly recommend always start every change from main and merge it back to main and if not, read about the Git flow the GitHub flow or the GitLab flow and choose a flow DO NOT invent your own flow, it will bring you many complications sooner or later.<\/p>\n\n\n\n<p>To ensure that the semantic versions of the package are not contradicted by the git tags, you can take two paths: automate the git tags every time you change the version in the package, or automate the package version every time you tag git. Both ways have their advantages and disadvantages, but it is much better when the technology has already implemented it for you. For example, in the previous case, you may notice that a was never made git tag, and the reason is because the command npm version \u2026takes care of synchronizing the version with a tag in git. This is an excellent evolution of development tools, previously, to keep the two synchronized you had to write code in the hooks of git, or of the tool (prerelease, postversion, etc.).<\/p>\n\n\n\n<h3 class=\"wp-block-heading\">Docker<\/h3>\n\n\n\n<h4 class=\"wp-block-heading\">Versioning your images<\/h4>\n\n\n\n<p>Versioning with docker is a bit more complicated, since the Dockerfile (the text meta file that describes a container) does not have a version-specific field. The possibilities are to use a &#8220;label&#8221; (field supported by Docker) to put stamp a version. But, since a version-specific field is not natively supported by the docker environment, this is a case in which I recommend that the only source of truth regarding the version resides outside the file, and what better than in the tag of git. However, since there is no automatic syncing of the version to the tag, we must ensure that our pipeline takes care of enforcing such a restriction. Also, Docker adds a small change to the Semantic Versioning script.<\/p>\n\n\n\n<p>According to SemVer, each different artifact must have a different major, minor and patch version, thus, the first version released will be 1.0.0, the next patch 1.0.1 and when new functionality is added it will be 1.1.0. Simple, but Docker adds that when releasing 1.0.0, it should be labeled 1, 1.0, and 1.0.0, when the first patch creates version 1.0.1, it should now also be labeled 1 and 1.0. This practice, although accepted in the docker environment, is not 100% compatible with SemVer since version 1.0 of yesterday has the possibility of being different from version 1.0 of today, even so, it is the accepted practice and you have to use it.<\/p>\n\n\n\n<figure class=\"wp-block-table\"><table><tbody><tr><td>Date<\/td><td>Event<\/td><td>Major Label<\/td><td>Minor Label<\/td><td>SemVer Tag<\/td><td>Tag &#8220;latest&#8221;<\/td><\/tr><tr><td>2022-01-01<\/td><td>First version<\/td><td>1<\/td><td>1.0<\/td><td>1.0.0<\/td><td>latest<\/td><\/tr><tr><td>2022-01-02<\/td><td>Small fix<\/td><td>1<\/td><td>1.0<\/td><td>1.0.1<\/td><td>latest<\/td><\/tr><tr><td>2022-01-03<\/td><td>New functionality<\/td><td>1<\/td><td>1.1<\/td><td>1.1.0<\/td><td>latest<\/td><\/tr><\/tbody><\/table><figcaption>In the case of Docker, each image must receive multiple labels, the version of 2022-01-03 will have all \u201c1\u201d, \u201c1.1\u201d, \u201c1.1.0\u201d and \u201clatest\u201d.<\/figcaption><\/figure>\n\n\n\n<p>To comply with SemVer and at the same time with docker best practices, the best place to generate all these tags is the pipeline. But, it is necessary to ensure that the company agrees to use a strict and documented process to avoid confusion.<\/p>\n\n\n\n<p>My recommendation is that the internal tag is &#8220;development&#8221; by default, but that it can be modified during the construction of the image. Also, in case it is necessary to know the version of the image inside the container, it can be put in an environment variable (ENV).<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code># In the Dockerfile\nARG IMAGE_VERSION=\"development\"\nFROM alpine:latest\nENV IMAGE_VERSION=$VERSION\nLABEL version=\"development\"\n\n# At build time\nIMAGE_VERSION=$(git describe --abbrev=0)\ndocker build . --build-arg IMAGE_VERSION=$IMAGE_VERSION --label version=\"$IMAGE_VERSION\" -t myregistry\/myimage:$IMAGE_VERSION<\/code><\/pre>\n\n\n\n<p>Note that when building the image, the last git tag is used to build the image and put it in three places:<\/p>\n\n\n\n<ul class=\"wp-block-list\"><li>As an argument (&#8211;build-arg), which will be used to create an environment variable that can be consumed from within the container<\/li><li>As label (&#8211;label), which will be recorded as \u201cmeta\u201d information of the container<\/li><li>As a tag (-t), which will serve to register it in the corresponding image registry<\/li><\/ul>\n\n\n\n<h4 class=\"wp-block-heading\">Versioning the images you depend on<\/h4>\n\n\n\n<p>During the construction of your application&#8217;s image you will probably use your own images or third party images, it is important that you use your tags well to ensure that your application the image used is the correct one. As we saw earlier, docker recommends that each new version be labeled as latest, but that can be a blessing or a curse, depending on your needs and circumstances. When using latest, you have the confidence of always using the latest version, that is, without effort on your part, your application will always be up to date, that is the good part, however, as you can imagine, you will also be receiving all the new errors that have been introduced in new versions. For applications that run in production, it is necessary to have stability and therefore, it is not recommended that your application uses the latest tag. But, if you have created a mature pipeline, with enough gates to verify that your application is 100% functional before being put in production, then it&#8217;s fine to use latest, but very carefully. In the long run, wearing latest will probably bring you more headaches than blessings, and that&#8217;s why it&#8217;s not highly recommended.<\/p>\n\n\n\n<p>When using base images for your image, be sure to use specific tags in your line FROM to avoid surprises, or at least not to vary the larger version.<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code># Good\nFROM nginx:1.21.5\nFROM nginx:1.21\nFROM nginx:1\n\n# Bad\nFROM nginx\nFROM nginx:latest<\/code><\/pre>\n\n\n\n<p>When using your own images or third party images in your application deployment (compose, helm, etc.), use specific tags.<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>spec:\n  containers:\n  - name: nginx\n    image: nginx:1.21.5\n  - name: myapp\n    image: registry.company.com\/myapp:3.4.6<\/code><\/pre>\n\n\n\n<h3 class=\"wp-block-heading\"><span style=\"color: initial; font-family: -apple-system, BlinkMacSystemFont, &quot;Segoe UI&quot;, Roboto, Oxygen-Sans, Ubuntu, Cantarell, &quot;Helvetica Neue&quot;, sans-serif;\">Pipeline<\/span><\/h3>\n\n\n\n<p>It is extremely important that artifacts created during the pipeline are stamped with the same version that accompanies the text files (source code) that generated the artifact. A great effort should be made that all this happens automatically and manual updates are avoided once the version has been updated in the source code. For example, if an application written in NodeJS is going to be published in a container, there is a great temptation to keep two versions, one within the application and the other for deployment. However, these two are the same, they should be kept in parallel and they should never go out of sync. So, if there is a problem in production, and the production version is 1.3.5, I know exactly which version of the code was used to generate that container. Let&#8217;s see, there are several places that need to be kept in sync:<\/p>\n\n\n\n<ul class=\"wp-block-list\"><li>package.json &#8211; single source of truth<\/li><li>container &#8211; when this container is built, it must reflect the same version of the application installed in it<\/li><li>deployment &#8211; (eg helm) When deploying the application using templates, it is necessary to pass the container version to the template<\/li><\/ul>\n\n\n\n<p>The pipeline should read the application version from the application meta file and use it elsewhere. This is sometimes difficult because pipelines tend to be segregated into multiple steps and not all steps have access to the original application meta file. In those cases, there must be an initial step that extracts the version from the meta file and passes it as an environment variable to the other steps in the pipeline. For example, in GitLab CI an artifact is created with an .env file to pass the information to the other steps in the pipeline:<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>setup:\n  script:\n    - echo \"APP_VERSION=\"$(node -p require('.\/package.json').version\") >> build.env\n  artifacts:\n    reports:\n      dotenv: build.env\n\nbuild:\n  dependencies:\n    - setup\n  script:\n    - docker build . --build-arg IMAGE_VERSION=$APP_VERSION --label version=\"$APP_VERSION\" -t myregistry\/myapp:$APP_VERSION\n\ndeploy:\n  dependencies:\n    - setup\n  script:\n    - RELEASE_NAME=myapp_$APP_VERSION\n    - helm upgrade --set image=$CI_REGISTRY_IMAGE --set tag=$APP_VERSION --install $RELEASE_NAME chartmuseum\/myapp<\/code><\/pre>\n","protected":false},"excerpt":{"rendered":"<p>Spanish version Simple description If you need to know all the details of the SemVer specification, please visit [&hellip;]<\/p>\n","protected":false},"author":1,"featured_media":9318,"comment_status":"open","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"fifu_image_url":"","fifu_image_alt":"","footnotes":""},"categories":[38],"tags":[39],"class_list":["post-9339","post","type-post","status-publish","format-standard","has-post-thumbnail","hentry","category-technology","tag-tecnologia"],"yoast_head":"<!-- This site is optimized with the Yoast SEO plugin v27.3 - https:\/\/yoast.com\/product\/yoast-seo-wordpress\/ -->\n<title>Semantic Versioning - SemVer - El blog de Felipe<\/title>\n<meta name=\"robots\" content=\"index, follow, max-snippet:-1, max-image-preview:large, max-video-preview:-1\" \/>\n<link rel=\"canonical\" href=\"https:\/\/blogs.pacasmayo.com\/felipe\/2022\/01\/06\/semantic-versioning-semver\/\" \/>\n<meta property=\"og:locale\" content=\"en_US\" \/>\n<meta property=\"og:type\" content=\"article\" \/>\n<meta property=\"og:title\" content=\"Semantic Versioning - SemVer - El blog de Felipe\" \/>\n<meta property=\"og:description\" content=\"Spanish version Simple description If you need to know all the details of the SemVer specification, please visit [&hellip;]\" \/>\n<meta property=\"og:url\" content=\"https:\/\/blogs.pacasmayo.com\/felipe\/2022\/01\/06\/semantic-versioning-semver\/\" \/>\n<meta property=\"og:site_name\" content=\"El blog de Felipe\" \/>\n<meta property=\"article:published_time\" content=\"2022-01-06T23:25:34+00:00\" \/>\n<meta property=\"article:modified_time\" content=\"2022-03-16T10:37:45+00:00\" \/>\n<meta property=\"og:image\" content=\"https:\/\/blogs.pacasmayo.com\/felipe\/files\/2022\/01\/image.png\" \/>\n\t<meta property=\"og:image:width\" content=\"1500\" \/>\n\t<meta property=\"og:image:height\" content=\"1000\" \/>\n\t<meta property=\"og:image:type\" content=\"image\/png\" \/>\n<meta name=\"author\" content=\"AI\" \/>\n<meta name=\"twitter:card\" content=\"summary_large_image\" \/>\n<meta name=\"twitter:label1\" content=\"Written by\" \/>\n\t<meta name=\"twitter:data1\" content=\"AI\" \/>\n\t<meta name=\"twitter:label2\" content=\"Est. reading time\" \/>\n\t<meta name=\"twitter:data2\" content=\"14 minutes\" \/>\n<script type=\"application\/ld+json\" class=\"yoast-schema-graph\">{\"@context\":\"https:\\\/\\\/schema.org\",\"@graph\":[{\"@type\":\"Article\",\"@id\":\"https:\\\/\\\/blogs.pacasmayo.com\\\/felipe\\\/2022\\\/01\\\/06\\\/semantic-versioning-semver\\\/#article\",\"isPartOf\":{\"@id\":\"https:\\\/\\\/blogs.pacasmayo.com\\\/felipe\\\/2022\\\/01\\\/06\\\/semantic-versioning-semver\\\/\"},\"author\":{\"name\":\"AI\",\"@id\":\"https:\\\/\\\/blogs.pacasmayo.com\\\/felipe\\\/#\\\/schema\\\/person\\\/e32bfb69f0dcbed869e838474a34d240\"},\"headline\":\"Semantic Versioning &#8211; SemVer\",\"datePublished\":\"2022-01-06T23:25:34+00:00\",\"dateModified\":\"2022-03-16T10:37:45+00:00\",\"mainEntityOfPage\":{\"@id\":\"https:\\\/\\\/blogs.pacasmayo.com\\\/felipe\\\/2022\\\/01\\\/06\\\/semantic-versioning-semver\\\/\"},\"wordCount\":2125,\"commentCount\":1,\"publisher\":{\"@id\":\"https:\\\/\\\/blogs.pacasmayo.com\\\/felipe\\\/#organization\"},\"image\":{\"@id\":\"https:\\\/\\\/blogs.pacasmayo.com\\\/felipe\\\/2022\\\/01\\\/06\\\/semantic-versioning-semver\\\/#primaryimage\"},\"thumbnailUrl\":\"https:\\\/\\\/blogs.pacasmayo.com\\\/felipe\\\/files\\\/2022\\\/01\\\/image.png\",\"keywords\":[\"Tecnolog\u00eda\"],\"articleSection\":[\"Technology\"],\"inLanguage\":\"en-US\",\"potentialAction\":[{\"@type\":\"CommentAction\",\"name\":\"Comment\",\"target\":[\"https:\\\/\\\/blogs.pacasmayo.com\\\/felipe\\\/2022\\\/01\\\/06\\\/semantic-versioning-semver\\\/#respond\"]}]},{\"@type\":\"WebPage\",\"@id\":\"https:\\\/\\\/blogs.pacasmayo.com\\\/felipe\\\/2022\\\/01\\\/06\\\/semantic-versioning-semver\\\/\",\"url\":\"https:\\\/\\\/blogs.pacasmayo.com\\\/felipe\\\/2022\\\/01\\\/06\\\/semantic-versioning-semver\\\/\",\"name\":\"Semantic Versioning - SemVer - El blog de Felipe\",\"isPartOf\":{\"@id\":\"https:\\\/\\\/blogs.pacasmayo.com\\\/felipe\\\/#website\"},\"primaryImageOfPage\":{\"@id\":\"https:\\\/\\\/blogs.pacasmayo.com\\\/felipe\\\/2022\\\/01\\\/06\\\/semantic-versioning-semver\\\/#primaryimage\"},\"image\":{\"@id\":\"https:\\\/\\\/blogs.pacasmayo.com\\\/felipe\\\/2022\\\/01\\\/06\\\/semantic-versioning-semver\\\/#primaryimage\"},\"thumbnailUrl\":\"https:\\\/\\\/blogs.pacasmayo.com\\\/felipe\\\/files\\\/2022\\\/01\\\/image.png\",\"datePublished\":\"2022-01-06T23:25:34+00:00\",\"dateModified\":\"2022-03-16T10:37:45+00:00\",\"breadcrumb\":{\"@id\":\"https:\\\/\\\/blogs.pacasmayo.com\\\/felipe\\\/2022\\\/01\\\/06\\\/semantic-versioning-semver\\\/#breadcrumb\"},\"inLanguage\":\"en-US\",\"potentialAction\":[{\"@type\":\"ReadAction\",\"target\":[\"https:\\\/\\\/blogs.pacasmayo.com\\\/felipe\\\/2022\\\/01\\\/06\\\/semantic-versioning-semver\\\/\"]}]},{\"@type\":\"ImageObject\",\"inLanguage\":\"en-US\",\"@id\":\"https:\\\/\\\/blogs.pacasmayo.com\\\/felipe\\\/2022\\\/01\\\/06\\\/semantic-versioning-semver\\\/#primaryimage\",\"url\":\"https:\\\/\\\/blogs.pacasmayo.com\\\/felipe\\\/files\\\/2022\\\/01\\\/image.png\",\"contentUrl\":\"https:\\\/\\\/blogs.pacasmayo.com\\\/felipe\\\/files\\\/2022\\\/01\\\/image.png\",\"width\":1500,\"height\":1000},{\"@type\":\"BreadcrumbList\",\"@id\":\"https:\\\/\\\/blogs.pacasmayo.com\\\/felipe\\\/2022\\\/01\\\/06\\\/semantic-versioning-semver\\\/#breadcrumb\",\"itemListElement\":[{\"@type\":\"ListItem\",\"position\":1,\"name\":\"Portada\",\"item\":\"https:\\\/\\\/blogs.pacasmayo.com\\\/felipe\\\/\"},{\"@type\":\"ListItem\",\"position\":2,\"name\":\"Semantic Versioning &#8211; SemVer\"}]},{\"@type\":\"WebSite\",\"@id\":\"https:\\\/\\\/blogs.pacasmayo.com\\\/felipe\\\/#website\",\"url\":\"https:\\\/\\\/blogs.pacasmayo.com\\\/felipe\\\/\",\"name\":\"El blog de Felipe\",\"description\":\"De la abundancia del coraz\u00f3n...\",\"publisher\":{\"@id\":\"https:\\\/\\\/blogs.pacasmayo.com\\\/felipe\\\/#organization\"},\"potentialAction\":[{\"@type\":\"SearchAction\",\"target\":{\"@type\":\"EntryPoint\",\"urlTemplate\":\"https:\\\/\\\/blogs.pacasmayo.com\\\/felipe\\\/?s={search_term_string}\"},\"query-input\":{\"@type\":\"PropertyValueSpecification\",\"valueRequired\":true,\"valueName\":\"search_term_string\"}}],\"inLanguage\":\"en-US\"},{\"@type\":\"Organization\",\"@id\":\"https:\\\/\\\/blogs.pacasmayo.com\\\/felipe\\\/#organization\",\"name\":\"El blog de Felipe\",\"url\":\"https:\\\/\\\/blogs.pacasmayo.com\\\/felipe\\\/\",\"logo\":{\"@type\":\"ImageObject\",\"inLanguage\":\"en-US\",\"@id\":\"https:\\\/\\\/blogs.pacasmayo.com\\\/felipe\\\/#\\\/schema\\\/logo\\\/image\\\/\",\"url\":\"https:\\\/\\\/blogs.pacasmayo.com\\\/felipe\\\/files\\\/2019\\\/11\\\/cropped-caricatura_felipe.jpg\",\"contentUrl\":\"https:\\\/\\\/blogs.pacasmayo.com\\\/felipe\\\/files\\\/2019\\\/11\\\/cropped-caricatura_felipe.jpg\",\"width\":1360,\"height\":598,\"caption\":\"El blog de Felipe\"},\"image\":{\"@id\":\"https:\\\/\\\/blogs.pacasmayo.com\\\/felipe\\\/#\\\/schema\\\/logo\\\/image\\\/\"}},{\"@type\":\"Person\",\"@id\":\"https:\\\/\\\/blogs.pacasmayo.com\\\/felipe\\\/#\\\/schema\\\/person\\\/e32bfb69f0dcbed869e838474a34d240\",\"name\":\"AI\",\"image\":{\"@type\":\"ImageObject\",\"inLanguage\":\"en-US\",\"@id\":\"https:\\\/\\\/secure.gravatar.com\\\/avatar\\\/4afeebd1deb1471ed6e7e21e6dc44176da2cb2ef0704b36e720ef8656e34bd65?s=96&d=mm&r=g\",\"url\":\"https:\\\/\\\/secure.gravatar.com\\\/avatar\\\/4afeebd1deb1471ed6e7e21e6dc44176da2cb2ef0704b36e720ef8656e34bd65?s=96&d=mm&r=g\",\"contentUrl\":\"https:\\\/\\\/secure.gravatar.com\\\/avatar\\\/4afeebd1deb1471ed6e7e21e6dc44176da2cb2ef0704b36e720ef8656e34bd65?s=96&d=mm&r=g\",\"caption\":\"AI\"},\"description\":\"Este art\u00edculo ha sido seleccionado y parcialmente escrito e ilustrado por Inteligencia Artificial (AI) basado en noticias disponibles.\",\"url\":\"https:\\\/\\\/blogs.pacasmayo.com\\\/felipe\\\/author\\\/ai\\\/\"}]}<\/script>\n<!-- \/ Yoast SEO plugin. -->","yoast_head_json":{"title":"Semantic Versioning - SemVer - El blog de Felipe","robots":{"index":"index","follow":"follow","max-snippet":"max-snippet:-1","max-image-preview":"max-image-preview:large","max-video-preview":"max-video-preview:-1"},"canonical":"https:\/\/blogs.pacasmayo.com\/felipe\/2022\/01\/06\/semantic-versioning-semver\/","og_locale":"en_US","og_type":"article","og_title":"Semantic Versioning - SemVer - El blog de Felipe","og_description":"Spanish version Simple description If you need to know all the details of the SemVer specification, please visit [&hellip;]","og_url":"https:\/\/blogs.pacasmayo.com\/felipe\/2022\/01\/06\/semantic-versioning-semver\/","og_site_name":"El blog de Felipe","article_published_time":"2022-01-06T23:25:34+00:00","article_modified_time":"2022-03-16T10:37:45+00:00","og_image":[{"width":1500,"height":1000,"url":"https:\/\/blogs.pacasmayo.com\/felipe\/files\/2022\/01\/image.png","type":"image\/png"}],"author":"AI","twitter_card":"summary_large_image","twitter_misc":{"Written by":"AI","Est. reading time":"14 minutes"},"schema":{"@context":"https:\/\/schema.org","@graph":[{"@type":"Article","@id":"https:\/\/blogs.pacasmayo.com\/felipe\/2022\/01\/06\/semantic-versioning-semver\/#article","isPartOf":{"@id":"https:\/\/blogs.pacasmayo.com\/felipe\/2022\/01\/06\/semantic-versioning-semver\/"},"author":{"name":"AI","@id":"https:\/\/blogs.pacasmayo.com\/felipe\/#\/schema\/person\/e32bfb69f0dcbed869e838474a34d240"},"headline":"Semantic Versioning &#8211; SemVer","datePublished":"2022-01-06T23:25:34+00:00","dateModified":"2022-03-16T10:37:45+00:00","mainEntityOfPage":{"@id":"https:\/\/blogs.pacasmayo.com\/felipe\/2022\/01\/06\/semantic-versioning-semver\/"},"wordCount":2125,"commentCount":1,"publisher":{"@id":"https:\/\/blogs.pacasmayo.com\/felipe\/#organization"},"image":{"@id":"https:\/\/blogs.pacasmayo.com\/felipe\/2022\/01\/06\/semantic-versioning-semver\/#primaryimage"},"thumbnailUrl":"https:\/\/blogs.pacasmayo.com\/felipe\/files\/2022\/01\/image.png","keywords":["Tecnolog\u00eda"],"articleSection":["Technology"],"inLanguage":"en-US","potentialAction":[{"@type":"CommentAction","name":"Comment","target":["https:\/\/blogs.pacasmayo.com\/felipe\/2022\/01\/06\/semantic-versioning-semver\/#respond"]}]},{"@type":"WebPage","@id":"https:\/\/blogs.pacasmayo.com\/felipe\/2022\/01\/06\/semantic-versioning-semver\/","url":"https:\/\/blogs.pacasmayo.com\/felipe\/2022\/01\/06\/semantic-versioning-semver\/","name":"Semantic Versioning - SemVer - El blog de Felipe","isPartOf":{"@id":"https:\/\/blogs.pacasmayo.com\/felipe\/#website"},"primaryImageOfPage":{"@id":"https:\/\/blogs.pacasmayo.com\/felipe\/2022\/01\/06\/semantic-versioning-semver\/#primaryimage"},"image":{"@id":"https:\/\/blogs.pacasmayo.com\/felipe\/2022\/01\/06\/semantic-versioning-semver\/#primaryimage"},"thumbnailUrl":"https:\/\/blogs.pacasmayo.com\/felipe\/files\/2022\/01\/image.png","datePublished":"2022-01-06T23:25:34+00:00","dateModified":"2022-03-16T10:37:45+00:00","breadcrumb":{"@id":"https:\/\/blogs.pacasmayo.com\/felipe\/2022\/01\/06\/semantic-versioning-semver\/#breadcrumb"},"inLanguage":"en-US","potentialAction":[{"@type":"ReadAction","target":["https:\/\/blogs.pacasmayo.com\/felipe\/2022\/01\/06\/semantic-versioning-semver\/"]}]},{"@type":"ImageObject","inLanguage":"en-US","@id":"https:\/\/blogs.pacasmayo.com\/felipe\/2022\/01\/06\/semantic-versioning-semver\/#primaryimage","url":"https:\/\/blogs.pacasmayo.com\/felipe\/files\/2022\/01\/image.png","contentUrl":"https:\/\/blogs.pacasmayo.com\/felipe\/files\/2022\/01\/image.png","width":1500,"height":1000},{"@type":"BreadcrumbList","@id":"https:\/\/blogs.pacasmayo.com\/felipe\/2022\/01\/06\/semantic-versioning-semver\/#breadcrumb","itemListElement":[{"@type":"ListItem","position":1,"name":"Portada","item":"https:\/\/blogs.pacasmayo.com\/felipe\/"},{"@type":"ListItem","position":2,"name":"Semantic Versioning &#8211; SemVer"}]},{"@type":"WebSite","@id":"https:\/\/blogs.pacasmayo.com\/felipe\/#website","url":"https:\/\/blogs.pacasmayo.com\/felipe\/","name":"El blog de Felipe","description":"De la abundancia del coraz\u00f3n...","publisher":{"@id":"https:\/\/blogs.pacasmayo.com\/felipe\/#organization"},"potentialAction":[{"@type":"SearchAction","target":{"@type":"EntryPoint","urlTemplate":"https:\/\/blogs.pacasmayo.com\/felipe\/?s={search_term_string}"},"query-input":{"@type":"PropertyValueSpecification","valueRequired":true,"valueName":"search_term_string"}}],"inLanguage":"en-US"},{"@type":"Organization","@id":"https:\/\/blogs.pacasmayo.com\/felipe\/#organization","name":"El blog de Felipe","url":"https:\/\/blogs.pacasmayo.com\/felipe\/","logo":{"@type":"ImageObject","inLanguage":"en-US","@id":"https:\/\/blogs.pacasmayo.com\/felipe\/#\/schema\/logo\/image\/","url":"https:\/\/blogs.pacasmayo.com\/felipe\/files\/2019\/11\/cropped-caricatura_felipe.jpg","contentUrl":"https:\/\/blogs.pacasmayo.com\/felipe\/files\/2019\/11\/cropped-caricatura_felipe.jpg","width":1360,"height":598,"caption":"El blog de Felipe"},"image":{"@id":"https:\/\/blogs.pacasmayo.com\/felipe\/#\/schema\/logo\/image\/"}},{"@type":"Person","@id":"https:\/\/blogs.pacasmayo.com\/felipe\/#\/schema\/person\/e32bfb69f0dcbed869e838474a34d240","name":"AI","image":{"@type":"ImageObject","inLanguage":"en-US","@id":"https:\/\/secure.gravatar.com\/avatar\/4afeebd1deb1471ed6e7e21e6dc44176da2cb2ef0704b36e720ef8656e34bd65?s=96&d=mm&r=g","url":"https:\/\/secure.gravatar.com\/avatar\/4afeebd1deb1471ed6e7e21e6dc44176da2cb2ef0704b36e720ef8656e34bd65?s=96&d=mm&r=g","contentUrl":"https:\/\/secure.gravatar.com\/avatar\/4afeebd1deb1471ed6e7e21e6dc44176da2cb2ef0704b36e720ef8656e34bd65?s=96&d=mm&r=g","caption":"AI"},"description":"Este art\u00edculo ha sido seleccionado y parcialmente escrito e ilustrado por Inteligencia Artificial (AI) basado en noticias disponibles.","url":"https:\/\/blogs.pacasmayo.com\/felipe\/author\/ai\/"}]}},"_links":{"self":[{"href":"https:\/\/blogs.pacasmayo.com\/felipe\/wp-json\/wp\/v2\/posts\/9339","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/blogs.pacasmayo.com\/felipe\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/blogs.pacasmayo.com\/felipe\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/blogs.pacasmayo.com\/felipe\/wp-json\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/blogs.pacasmayo.com\/felipe\/wp-json\/wp\/v2\/comments?post=9339"}],"version-history":[{"count":3,"href":"https:\/\/blogs.pacasmayo.com\/felipe\/wp-json\/wp\/v2\/posts\/9339\/revisions"}],"predecessor-version":[{"id":9432,"href":"https:\/\/blogs.pacasmayo.com\/felipe\/wp-json\/wp\/v2\/posts\/9339\/revisions\/9432"}],"wp:featuredmedia":[{"embeddable":true,"href":"https:\/\/blogs.pacasmayo.com\/felipe\/wp-json\/wp\/v2\/media\/9318"}],"wp:attachment":[{"href":"https:\/\/blogs.pacasmayo.com\/felipe\/wp-json\/wp\/v2\/media?parent=9339"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/blogs.pacasmayo.com\/felipe\/wp-json\/wp\/v2\/categories?post=9339"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/blogs.pacasmayo.com\/felipe\/wp-json\/wp\/v2\/tags?post=9339"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}