The article comes from a time curious about the change log
of a fairly familiar extension is chat ++ . When looking at the change log
in this repo, I find the versioning rules quite miscellaneous . For example being in 5.6.3 jumps to 5.7.0 but not to 5.6.4 . After a while of research and stupid question, I got a brother who gave keyword Semantic versioning
to explain how to set the version for each release
.
But before explaining the other “formula” for versioning, we will learn a bit about Semantic versioning
see what they are? and solve what purpose.
1. How did semantic versioning come about?
The story is that one fine day, I need to retrieve information of A-star singers for the purpose of displaying on my website. Fortunately, after a while of searching, there is also a service, I temporarily call service X that provides an API that displays the entire list of information of these singers.
When information about this API, I can list a few notable components as follows:
- API URL: https: // xxx / list-singer
- METHOD: GET
- Response:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 | <span class="token punctuation">{</span> <span class="token double-quoted-string string">"id"</span> <span class="token punctuation">:</span> <span class="token number">1</span> <span class="token punctuation">,</span> <span class="token double-quoted-string string">"name"</span> <span class="token punctuation">:</span> <span class="token double-quoted-string string">"Ưng Hoàng Hôn"</span> <span class="token punctuation">,</span> <span class="token double-quoted-string string">"company"</span> <span class="token punctuation">:</span> <span class="token double-quoted-string string">"XXX"</span> <span class="token punctuation">.</span> <span class="token punctuation">.</span> <span class="token punctuation">.</span> <span class="token punctuation">}</span> <span class="token punctuation">,</span> <span class="token punctuation">{</span> <span class="token double-quoted-string string">"id"</span> <span class="token punctuation">:</span> <span class="token number">2</span> <span class="token punctuation">,</span> <span class="token double-quoted-string string">"name"</span> <span class="token punctuation">:</span> <span class="token double-quoted-string string">"Sơn Tường MTP"</span> <span class="token punctuation">,</span> <span class="token double-quoted-string string">"company"</span> <span class="token punctuation">:</span> <span class="token double-quoted-string string">"YYY"</span> <span class="token punctuation">}</span> <span class="token punctuation">{</span> <span class="token double-quoted-string string">"id"</span> <span class="token punctuation">:</span> <span class="token number">3</span> <span class="token punctuation">,</span> <span class="token double-quoted-string string">"name"</span> <span class="token punctuation">:</span> <span class="token double-quoted-string string">"Chi Peo"</span> <span class="token punctuation">,</span> <span class="token double-quoted-string string">"company"</span> <span class="token punctuation">:</span> <span class="token double-quoted-string string">"ZZZ"</span> <span class="token punctuation">}</span> |
So in my code, just call the API and assign it to a variable named singers
1 2 3 4 5 6 7 8 9 10 11 12 | <span class="token variable">$client</span> <span class="token operator">=</span> <span class="token keyword">new</span> <span class="token class-name"> GuzzleHttp Client</span> <span class="token punctuation">(</span> <span class="token punctuation">)</span> <span class="token punctuation">;</span> <span class="token variable">$request</span> <span class="token operator">=</span> <span class="token variable">$client</span> <span class="token operator">-</span> <span class="token operator">></span> <span class="token function">get</span> <span class="token punctuation">(</span> <span class="token single-quoted-string string">'http://myexample.com'</span> <span class="token punctuation">)</span> <span class="token punctuation">;</span> <span class="token variable">$singers</span> <span class="token operator">=</span> <span class="token variable">$request</span> <span class="token operator">-</span> <span class="token operator">></span> <span class="token function">getBody</span> <span class="token punctuation">(</span> <span class="token punctuation">)</span> <span class="token punctuation">;</span> Ở ngoài view hiển thị dữ liệu dạng @ <span class="token keyword">foreach</span> <span class="token punctuation">(</span> <span class="token variable">$singers</span> <span class="token keyword">as</span> <span class="token variable">$singer</span> <span class="token punctuation">)</span> <span class="token operator"><</span> tr <span class="token operator">></span> <span class="token operator"><</span> td <span class="token operator">></span> <span class="token punctuation">{</span> <span class="token punctuation">{</span> <span class="token variable">$singer</span> <span class="token operator">-</span> <span class="token operator">></span> <span class="token property">name</span> <span class="token punctuation">}</span> <span class="token punctuation">}</span> <span class="token operator"><</span> <span class="token operator">/</span> td <span class="token operator">></span> <span class="token operator"><</span> td <span class="token operator">></span> <span class="token punctuation">{</span> <span class="token punctuation">{</span> <span class="token variable">$singer</span> <span class="token operator">-</span> <span class="token operator">></span> <span class="token property">company</span> <span class="token punctuation">}</span> <span class="token punctuation">}</span> <span class="token operator"><</span> <span class="token operator">/</span> td <span class="token operator">></span> <span class="token operator"><</span> <span class="token operator">/</span> tr <span class="token operator">></span> @ <span class="token keyword">endforeach</span> |
That’s good, I’ve completed listing singers based on a public API. But after a while, on the website, I suddenly saw an error of name undefined
. After a while debugging, I discovered the other API end had changed the format response
returned.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 | <span class="token comment">// Before</span> <span class="token punctuation">{</span> <span class="token double-quoted-string string">"id"</span> <span class="token punctuation">:</span> <span class="token number">1</span> <span class="token punctuation">,</span> <span class="token double-quoted-string string">"name"</span> <span class="token punctuation">:</span> <span class="token double-quoted-string string">"Ưng Hoàng Hôn"</span> <span class="token punctuation">,</span> <span class="token double-quoted-string string">"company"</span> <span class="token punctuation">:</span> <span class="token double-quoted-string string">"XXX"</span> <span class="token punctuation">.</span> <span class="token punctuation">.</span> <span class="token punctuation">.</span> <span class="token punctuation">}</span> <span class="token punctuation">,</span> <span class="token comment">// After</span> <span class="token punctuation">{</span> data <span class="token punctuation">:</span> <span class="token punctuation">{</span> <span class="token double-quoted-string string">"id"</span> <span class="token punctuation">:</span> <span class="token number">1</span> <span class="token punctuation">,</span> <span class="token double-quoted-string string">"name"</span> <span class="token punctuation">:</span> <span class="token double-quoted-string string">"Ưng Hoàng Hôn"</span> <span class="token punctuation">,</span> <span class="token double-quoted-string string">"company"</span> <span class="token punctuation">:</span> <span class="token double-quoted-string string">"XXX"</span> <span class="token punctuation">.</span> <span class="token punctuation">.</span> <span class="token punctuation">.</span> <span class="token punctuation">}</span> <span class="token punctuation">,</span> status <span class="token punctuation">:</span> <span class="token number">200</span> <span class="token punctuation">,</span> <span class="token punctuation">}</span> <span class="token punctuation">,</span> |
So I just fixed the bug and wrote an email to curse the supplier, saying why did you change the reponse code leading to an error in my system. And given the provider that during operation, there was a client side that needed to provide additional status code
and something else, so the dev team had to change the response.
Based on the above bogus story we can realize two problems about how to develop an API as follows.
- On the
client
side, in particular, the developer has to depend on the API response leading to when the API changes, theclient
also changes. We try to imagine a service of ours that needs to call 100 vendors providing APIs, so it is the developer ‘s job to just eat and modify the code according to the API response.
This problem is called Dependency hell – Passively Dependency
- On the
vendor
side that provides the API, they will have to be more careful in the process of changing the response, how even if there is an additionalresponse
– as in the above story status does not affect the logic of theclient
‘s code. But it is difficult tochiều lòng
all vendors so there are some API providers who choose to not improve the response any more, with the criterion:Nếu nó đang hoạt động, đừng sửa nó
.
This issue is called version lock – No further development is possible.
To solve the above problem, the above developers thought of versioning for thay đổi
. How to make each response change, here temporarily considered a release, they will provide a new version to ensure that will not affect the old version. For example, at the top of the post they are there
- API URL: https: // xxx / list-singer
Now after versioning for releases, the URL will change to v1 format
- API URL: https: // xxx / v1 / list-singer
When there is a change, there will be another version of v2 for example
- API URL: https: // xxx / v2 / list-singer In order not to affect API calls of old
client
but to be able to develop new versions.
Or when we install a package form
1 2 | "laravelcollective/html": "^5.8.0", |
After the developer releases version 5.9.0
, it does not affect the currently used version.
2. Rules of versioning
In the previous section, we talked about the need for version
but there is no specific rule. Without rules there are a few minor problems, for example when, during the maintain, some minor logic fixes that do not affect the old logic need to be versioned.
The first versioning rule was created by Tom Preston-Werner , who is also the inventor of Gravatar
and co-owner of GitHub
.
1 2 | Ảnh: wikipedia |
This rule is based on 3 main numbers MAJOR
, MINOR
, PATCH
. It corresponds to 3 numbers in defining the version of an API or a package.
To explain the above 3 keywords we go into the following specific example.
- For the first version
/v1/users/:id
, we write an api that returns the following data:
1 2 3 4 5 | <span class="token punctuation">{</span> <span class="token double-quoted-string string">"id"</span> <span class="token punctuation">:</span> <span class="token number">1</span> <span class="token punctuation">,</span> <span class="token double-quoted-string string">"name"</span> <span class="token punctuation">:</span> <span class="token double-quoted-string string">"sunh"</span> <span class="token punctuation">}</span> |
- Then we need to add some information about the age, for example, we update it to.
1 2 3 4 5 6 | <span class="token punctuation">{</span> <span class="token double-quoted-string string">"id"</span> <span class="token punctuation">:</span> <span class="token number">1</span> <span class="token punctuation">,</span> <span class="token double-quoted-string string">"name"</span> <span class="token punctuation">:</span> <span class="token double-quoted-string string">"sunh"</span> <span class="token punctuation">,</span> <span class="token double-quoted-string string">"age"</span> <span class="token punctuation">:</span> <span class="token double-quoted-string string">"24"</span> <span class="token punctuation">}</span> |
=> This new api only adds the “age” field, and the 2 old schools are still compatible with the previous one, so this is called MINOR change
, something that doesn’t affect the old active part. And as such, the api version remains v1.
Then, we realize that returning string age is an error, and we correct it to a number. => This new api just fixes the data type, fixes a small error, doesn’t add anything new and is still compatible with the previous version, so it is called PATCH
(patch). And so the api version remains v1.
At some point, we find that our api needs to return more information than just the user information.
1 2 3 4 5 6 7 | <span class="token punctuation">{</span> <span class="token double-quoted-string string">"data"</span> <span class="token punctuation">:</span> <span class="token punctuation">{</span> <span class="token double-quoted-string string">"id"</span> <span class="token punctuation">:</span> <span class="token number">1</span> <span class="token punctuation">,</span> <span class="token double-quoted-string string">"name"</span> <span class="token punctuation">:</span> <span class="token double-quoted-string string">"sunh"</span> <span class="token punctuation">,</span> <span class="token double-quoted-string string">"age"</span> <span class="token punctuation">:</span> <span class="token number">24</span> <span class="token punctuation">}</span> <span class="token punctuation">,</span> <span class="token double-quoted-string string">"meta"</span> <span class="token punctuation">:</span> <span class="token punctuation">{</span> <span class="token double-quoted-string string">"source"</span> <span class="token punctuation">:</span> <span class="token double-quoted-string string">"foobar"</span> <span class="token punctuation">}</span> <span class="token punctuation">}</span> |
=> This new api is completely different from v1 running, if we fix the code, the calling parts will be okay. So we have to write a new api labeled / v2 / users /: id. This is MAJOR
or breaking change
, the change is not compatible with the old version.
So in short
MAJOR
: Represents a major change, not compatible with the old version.PATCH
: Representing small changes, still compatible with the old version, often changes will be someupdate
. It makes me refer toPUT
,PATCH
inHttp request methods
.MINOR
: Represent for small changes, still compatible with the old version, it will be different fromPATCH
that instead ofupdate
something willcreate
something.
Based on the above explanation, we can completely rely on the circumstances of each different release to decide to increase the MAJOR
, PATCH
or MINOR
.
3. Some notes on using Semantic versioning
Some note of versioning is defined in semver . I ask for permission to translate again.
- Software using
Semantic versioning(semver)
must be apublic API
. However, with theinternal api
I think you should also version todeploy zero time
if you build BE and FE in 2 separate repos. This is also a bit long. So if you want to learn more, please comment below me to explain. - A correctly defined version must include 3 XYZ numbers corresponding to
MAJOR
,PATCH
, andMINOR
. Each element must increment1.9.0 -> 1.10.0 -> 1.11.0
. From now on when calling X, Y, Z, they are mistakenly understood as the numbers above. These numbers should be positive integers with no leading zeros.
1 2 3 4 5 6 7 8 | <span class="token comment">// Good</span> <span class="token number">1.1</span> <span class="token number">.1</span> <span class="token number">1.0</span> <span class="token number">.0</span> <span class="token comment">// Bad</span> <span class="token number">1.01</span> <span class="token number">.01</span> <span class="token number">1.</span> <span class="token operator">-</span> <span class="token number">1.</span> <span class="token operator">-</span> <span class="token number">1.</span> <span class="token number">1.00</span> <span class="token number">.00</span> |
- When a
package
has been released. Not allowed to change content in thatversion
, but must release in anotherversion
. Although the change is the smallest. Major version zero(0.yz)
is for development. This is not considered a stable release for use.Version 1.0.0
defined for the firstrelease
. The decision that X, Y, Z will increase in subsequent releases depends on different circumstances.Patch version Z (xyZ | x > 0)
must be incremented for each fix. I have mentioned this above.Minor version Y (xYz | x > 0)
must be incremented if there is something new, which is compatible with the old version. It must also be increased if some functionality in the API is not used. It can be incremented if there is an improvement in the code.Patch version
must reset to 0 ifMinor version
increases.Major version X (Xyz | X > 0)
must be incremented if there is a major change, not compatible with the old version. It may include alterations ofY, Z
Patch
andminor
must be reset to 0 ifX
is incremented.pre-release
can be further represented by adding a hyphen (-) to theASCII
. Thepre-release
signifies that this is not a completeversion
. For example1.0.0-alpha, 1.0.0-alpha.1, 1.0.0-0.3.7, 1.0.0-x.7.z.92, 1.0.0-xyz.–.
.- The priority of software using
semver
is defined as follows
- The priority depends on the magnitude of X, Y, Z from left to right. Example
1.0.0 <2.0.0 <2.1.0 <2.1.1
- Priority of version
release
takes precedence overpre-release
version. Example1.0.0-alpha < 1.0.0
- Priority of
pre-release
versions is also evaluated from left to right, numbers with numbers, letters and letters. For example1.0.0-alpha < 1.0.0-alpha.1 < 1.0.0-alpha.beta < 1.0.0-beta < 1.0.0-beta.2 < 1.0.0-beta.11 < 1.0.0-rc.1 < 1.0.0
4. Summary
Above I have introduced to you why to type version for each release and use Semantic versioning
. Once we have understanding of version
we will avoid making mistakes in the release
times. Evaluate whether changes affect logic or not.
Semantic
also not the principle of typing the only version, in addition it also has a full number type, including 4 more parts: Major.Minor.Revision.Build
. You can learn more.
Based on the knowledge of the article, we also partly explain why chat++
in 5.6.3 jumps to 5.7.0 but not to 5.6.4 , right.
Thank you for watching the article, if the article is useful, you press upvote
to support me and follow
to receive notification every time I have a new article.
5. References
My posts include the research and comments of the members of Avengers Group
to make the article more complete. Also referenced from the official Semantic Versioning documentation . You probably should read that more.