File: nut-versioning.adoc

package info (click to toggle)
nut 2.8.4%2Breally-2
  • links: PTS, VCS
  • area: main
  • in suites: forky, sid
  • size: 25,720 kB
  • sloc: ansic: 132,030; sh: 17,256; cpp: 12,566; makefile: 5,646; python: 1,114; perl: 856; xml: 47
file content (460 lines) | stat: -rw-r--r-- 22,560 bytes parent folder | download
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
NUT versioning
==============

Historic note
-------------

Historically, the Network UPS Tools project release and interim iterations
code base versions were identified by three or four numeric components,
roughly following the Semantic Versioning (SEMVER) traditions, later
codified as a formal standard at link:https://semver.org/[semver.org]:

* NUT uses the GNU autotools suite for recipe orchestration, and the version
  string is specified in the `configure.ac` file an `AC_INIT` macro, which
  further generates variables like `PACKAGE_VERSION`, `PACKAGE_URL` and others
  used (substituted) in the actual code base, often via `nut_version.h` file.
* NUT releases were identified by a `MAJOR.MINOR.PATCH` triplet, which
  was not strictly following the standard in that while the "major" part
  did reflect architectural/design changes, and "minor" part reflected some
  significant development milestones or API changes, the "patch" part did
  not correspond to post-release fixes but reflected iterative development,
  of which releases were the better-reviewed snapshots. Such a triplet was
  only spelled in `AC_INIT` for the commit tagged as that release.
* Until NUT v2.6.x, the odd values of the `MINOR` component meant development
  code trees, and even values meant the stable tree. This approach was
  skipped (or effectively abandoned, as over a decade passed) with the
  move to Git branches for development -- as numerous NUT v2.7.x based
  releases were produced, and development continued into NUT v2.8.x.
* NUT development versions were specified by the next commit after a
  release was published, spelling an `AC_INIT` macro argument like
  `MAJOR.MINOR.PATCH.1` to provide a fourth component -- which is
  logically "greater than" `MAJOR.MINOR.PATCH` for comparisons, so that
  the developed version can formally be installed over a preceding
  release (e.g. from custom testing packages).

This configuration with a single development version (`.1`) was not very
helpful for the faster pace of iterations, especially as the Git workflow
and pull requests were adopted as the way of iterating the NUT development.
This did not really help identify the build being tested by CI or reported
by a community member, nor quickly determine if one custom build is "newer"
than another (e.g. can be a recommended upgrade from the previously installed
snapshot to check if some bug was fixed).

Some experiments were done adding the `git describe` output to version
banners reported by programs. These provide the number of commits since
the most-recent known git tag, as well as the git hash of the NUT sources
involved. This made the builds better identifiable, but did not help
compare the feature branches and the main trunk of development: any code
committed after a release has its own count of commits since that tag,
this one number does not really suffice.

Current NUT SEMVER definition
-----------------------------

Since NUT v2.8.3, the definition which goes into `AC_INIT` and further into
the code was extended in a manner similar to what `git describe` produces,
but with added numbers after the common triplet of semantically versioned
numbers: `X.Y.Z(.T(.B(-C+H(+R))))` or `X.Y.Z(.T(.B(-R)))`

* Standard semver (used in releases):
+
NOTE: Historically NUT did not *diligently* follow the standard semver triplet,
primarily because a snapshot of trunk is tested and released, and work
moves on with the PATCH part (rarely MINOR one) incremented; no actual
patches are released to some sustaining track of an older release lineage.
There were large re-designs that got MAJOR up to 2, though.

  - `X`: MAJOR - incompatible API changes
  - `Y`: MINOR - major new features and/or API evolution
  - `Z`: PATCH - bug fixes (and new features like added drivers)
* Extended semver (for snapshots of trunk):
  - T: (optional) Commits on trunk since previous release tag
* Extended semver (for features branched off trunk):
  - B: (optional) Commits on branch since nearest ancestor which is on trunk

The optional suffix (only for commits which are not git tags themselves)
is provided by `git describe`:

* C: Commits on branch since previous release tag
* H: (Short) Git hash (prefixed by "g" character) of the described commit

The pre-release information (if provided/known) would either follow the
optional suffix detailed above, or it would be the suffix itself:

* R: If this commit has a non-release tag, it can be optionally reported
     so we know that a commit some '1234' iterations after release 'N' is
     also a release candidate for 'N+1'. Note that any dash in that tag value
     will be replaced by a plus, e.g. `2.8.2.2878.1-2879+g882dd4b00+v2.8.3+rc6`

The numeric part of NUT SEMVER definition mostly follows https://semver.org/
except that for development iterations the base version may have up to
five dot-separated numeric components (SEMVER triplet for base release,
and additional data described above). Unlike standard semver provisions
for "pre-release versions" (separated by a minus sign after the triplet),
which are "less than" that release for comparisons, the fourth and fifth
components (if present) are "greater than" that release and any preceding
development iterations made after it.

Helper script `tools/gitlog2version.sh` is used to determine the project
version from packager-provided override files (or equivalents provided by
`make dist` in a snapshot/release tarball), git metadata from the current
workspace, or built-in fallback defaults.

Occasionally there may be tagged pre-releases, which follow the standard
semver markup, like `v2.8.0-rc3` (in git), however they would be converted
to NUT SEMVER here (as a number of commits since previous release) by default.

A special case, which can mostly be seen in CI builds, concerns shallow git
checkouts -- when the currently built commit history is "grafted" (perhaps
down to there being only one commit in the whole git index), and we do not
know of any intersections with git tags or development trunk.  In this case,
the script may not only fall back to a built-in version following a legacy
`X.Y.Z.1` pattern for non-release builds (like `2.8.3.1`), but would also
append a `-0-g{HASH}` suffix to the long values (`VER5`, `VER50`, `DECS5`,
`DESC50`) yielding e.g. `2.8.3.1.0-0+gb3f21f9` for a build from a shallow
git checkout of commit `b3f21f9` of a code base which otherwise fell back
to `2.8.3.1` hard-coded in its copy of the script (bumped by a maintainer
as part of the release process).

Using gitlog2version.sh
-----------------------

The script can be controlled by environment variables, including some sourced
from configuration files. It identifies a number of data items, and reports
the one specified by `NUT_VERSION_QUERY` on `stdout`.

NOTE: It does not currently have a query to report "everything" in a manner
that can be processed by `eval` in calling shell scripts (or `Makefile` rule
implementations).

.Environment variables that can be used for external configuration
[opts="header",cols="1,3,2a"]
|=========================================================================
|Variable	| Description	| Example
|`abs_top_srcdir`	| Top source directory	| `/home/abuild/nut`
|`abs_top_builddir`	| Top build directory (defaults to `abs_top_srcdir`)
			| `/home/abuild/.builds/linux/nut`
|`NUT_VERSION_FORCED`	| Set `NUT_VERSION_DEFAULT` (extended NUT SEMVER,
			  may be just a triplet) to this value and enforce
			  `NUT_VERSION_PREFER_GIT=false`. Usually sourced
			  from `${abs_top_srcdir}/VERSION_FORCED` (if present)
			| `2.8.2.2379` `2.8.3-rc3`
			  `2.8.2.2878.3-2881+g45029249f+v2.8.3+rc6`
|`NUT_VERSION_FORCED_SEMVER`	| Set `SEMVER` (exactly a triplet) to this value
			  regardless of `NUT_VERSION_PREFER_GIT` setting. Usually
			  sourced from `${abs_top_srcdir}/VERSION_FORCED_SEMVER`
			  (if present)
			| `2.8.3`
|`NUT_VERSION_DEFAULT`	| Usually sourced from either
			  `${abs_top_builddir}/VERSION_DEFAULT` (if present)
			  or `${abs_top_srcdir}/VERSION_DEFAULT` (if present),
			  in which case the script also defaults
			  `NUT_VERSION_PREFER_GIT=false` (unless it is already
			  specified as `true` or `${abs_top_srcdir}/.git` exists).
			  If no value was provided, a hard-coded value is used
			  (updated as part of maintainers' release rituals).
			| `2.8.2.2379.2-2381+g1faa9945d`
|`NUT_VERSION_PREFER_GIT`	| If not provided by caller, or sourced files,
			  or defaulted with `NUT_VERSION_FORCED` or
			  `NUT_VERSION_DEFAULT` as described above, as a `false`
			  value, then becomes `true` if `${abs_top_srcdir}/.git`
			  exists or `false` otherwise (tarball builds) | `true`
|`NUT_WEBSITE`	| Default website URL, extended for historic sub-sites for
			  a release	| `https://www.networkupstools.org/`
|`NUT_VERSION_GIT_TRUNK`	| Git branch name to use for calculation of
			  current codebase distance from main development (as known
			  in local workspace index); by default, the newest branch named
			  like `master` is located (any competition is same or ancestor)
			| `origin/master`
|`NUT_VERSION_GIT_ALL_TAGS`	| If `true`, consider usual (not "annotated")
			  tags too	| `false`
|`NUT_VERSION_GIT_ALWAYS_DESC`	| If `true`, tell git to return just a commit
			  hash if no tag was matched in index.	| `false`
|=========================================================================

.Intermediate variables in Git workspace processing
[opts="header",cols="1,3,2a"]
|=========================================================================
|Variable	| Description	| Example (development and release)
|`DESC`	| Originates from `git describe`, filtered for releases (`vX.Y.Z`)
		  and ignoring various `rc`, `alpha`, `beta` etc. tags.
		  This yields the tag name, followed by number of commits added to
		  current `HEAD` history since that tag, and the current commit hash.
		  In the resulting string, the git hash is separated by a "plus"
		  sign (as semver build metadata) rather than the "minus" returned
		  by the tool.
		  | `v2.8.2-2381+g1faa9945d`
|`TAG`	| Nearest (annotated by default) tag preceding the `HEAD` in history:
		  the part of `DESC` before the commit count and hash.	| `v2.8.2`
|`BASE`	| The `git merge-base` of current commit and `NUT_VERSION_GIT_TRUNK`
		  (see above). How much of the known trunk history is in current HEAD?
		  This may be "all of it" when we are on that branch or PR made from
		  its tip, "some of it" if looking at a historic snapshot, or "nothing"
		  if looking at the tagged commit (it is the merge base for itself and
		  any of its descendants)	| `e9a48c9afeb4e06c758a3f4215977445c0f64780`
|`SUFFIX`	| Commit count since the tag and hash of the `HEAD` commit;
			  empty e.g. when `HEAD` is the tagged commit	| `-2381+g1faa9945d`
|`VER5`	| Full 5-component version, note we strip leading `v` from the expected
		  `TAG` value	| `2.8.2.2379.2`
|`DESC5`	| Full 5-component version `VER5` concatenated with `SUFFIX`
			| `2.8.2.2379.2-2381+g1faa9945d`
|`VER50`	| `VER5` without trailing `.0` in fifth or fourth component
			| * dev: `2.8.2.2379.2`
			  * trunk: `2.8.2.2379.0` => `2.8.2.2379`
			  * release: `2.8.2.0.0` => `2.8.2`
|`DESC50`	| `VER50` concatenated with `SUFFIX`
			| * release: `2.8.2-2381-g1faa9945d`
|`SEMVER`	| Exactly three leading numeric components.
			  Either `NUT_VERSION_FORCED_SEMVER` (if provided by caller or
			  configuration files), or derived from `VER5` (removing fourth
			  and fifth numbers)	| `2.8.0`
|=========================================================================

.Intermediate variables in default (non-git -- tarball or forced) processing
[opts="header",cols="1,3,2a"]
|=========================================================================
|Variable	| Description	| Example (development and release)
|`NUT_VERSION_DEFAULT_DOTS`	| Processed from `NUT_VERSION_DEFAULT` (see above)
			  to count just the dot characters
			| * dev: `....`
			  * trunk: `...`
			  * release: `..`
|`NUT_VERSION_DEFAULT5_DOTS`	| Grows from `NUT_VERSION_DEFAULT_DOTS`,
			  used to construct `NUT_VERSION_DEFAULT5`
			| `....`
|`NUT_VERSION_DEFAULT5`	| Constructed from `NUT_VERSION_DEFAULT`, adding `.0`
			  numeric components as needed, to have *at least 5* of them
			| `2.8.2.0.0`
|`NUT_VERSION_DEFAULT3_DOTS`	| Decreases from `NUT_VERSION_DEFAULT_DOTS`,
			  used to construct `NUT_VERSION_DEFAULT3`	| `..`
|`NUT_VERSION_DEFAULT3`	| Constructed from `NUT_VERSION_DEFAULT`, adding `.0`
			  numeric components as needed or dropping extras, to have
			  *exactly 3* of them
			| `2.8.0`
|`SUFFIX`		| Empty, unless `NUT_VERSION_DEFAULT` had a suffix
			  for pre-release information roughly matching the
			  `-(rc|alpha|beta)[0-9]*` regular expression
			| `""` `-rc6`
|`VER5`			| Full 5-component version, `NUT_VERSION_DEFAULT5`
			| `2.8.2.2379.2`
|`DESC5`		| Constructed as `${VER5}${SUFFIX}`
			| `2.8.2.2379.2` `2.8.3.0.0-rc6`
|`VER50`		| `NUT_VERSION_DEFAULT` as provided by caller or
			  defaulted, may be with or without trailing `.0` in fifth or
			  fourth components
			| `2.8.2.1`
|`DESC50`		| Constructed as `${VER50}${SUFFIX}`
			| `2.8.2.1` `2.8.3-rc6`
|`BASE`			| Empty (no known common commits with no trunk)	| `""`
|`SEMVER`		| Exactly three leading numeric components.
			  Either `NUT_VERSION_FORCED_SEMVER` (if provided by caller or
			  configuration files), or `NUT_VERSION_DEFAULT3` (see above)
			| `2.8.0`
|`TAG`			| Constructed as `v${NUT_VERSION_DEFAULT3}${SUFFIX}`
			| `v2.8.0` `v2.8.3-rc6`
|=========================================================================

The majority of identified values can be reported for debugging to `stderr`,
currently as a single line (wrapped for readability in the sample below):

----
:; ./tools/gitlog2version.sh
SEMVER=2.8.2;
TRUNK='master';
BASE='e9a48c9afeb4e06c758a3f4215977445c0f64780';
DESC='v2.8.2-2381+g1faa9945d'
=> TAG='v2.8.2' + SUFFIX='-2381+g1faa9945d'
=> VER5='2.8.2.2379.2'
=> VER50='2.8.2.2379.2'
=> DESC50='2.8.2.2379.2-2381+g1faa9945d'
----

.Values reported via `NUT_VERSION_QUERY`
[opts="header",cols="1,3,2a"]
|=========================================================================
|`NUT_VERSION_QUERY`	| Description	| Example (development and release)
|`DESC5`	| Full 5-component version (concatenated with `SUFFIX` for git)
			| * dev: `2.8.2.2379.2-2381+g1faa9945d`
			  * snapshot tarball: `2.8.2.2379.2`
|`DESC50`	| 3-to-5 non-zero component version (concatenated with `SUFFIX`
			  for git)
			| * dev: `2.8.2.2381-2381+g1faa9945d`
			  * snapshot tarball: `2.8.2.1`
|`VER5`		| Full 5-component version
			| * dev: `2.8.2.2379.2`
			  * snapshot tarball: `2.8.2.1.0`
|`VER50`	| 3-to-5 non-zero component version
			| * dev: `2.8.2.2379.2`
			  * release tarball: `2.8.0`
|`SEMVER`	| Exactly three leading numeric components	| `2.8.2`
|`IS_RELEASE`	| `true` if `SEMVER`==`VER50`, `false` otherwise
			| * dev: `false`
			  * rel: `true`
|`IS_PRERELEASE`	| `true` if `SUFFIX_PRERELEASE` is not empty, `false` otherwise
			| * dev: `false`
			  * rel/RC: `true`
|`TAG`	| GIT: Nearest (annotated by default) tag preceding the `HEAD` in history.
		  DEFAULT: Constructed from `SEMVER`
		| `v2.8.2`
|`TAG_PRERELEASE`	| GIT: if the `HEAD` itself has a tag matching
		  the `-(rc|alpha|beta)[0-9]*` regular expression.
		  DEFAULT: Constructed from `NUT_VERSION_DEFAULT3`
		  and `SUFFIX_PRERELEASE`.
		  Empty for not-pre-releases.
		| `v2.8.2-rc3` `""`
|`TRUNK`	| GIT: Branch name used for calculation of current codebase
			  distance from main development.
			  DEFAULT: empty.
			| `master`
|`SUFFIX`	| GIT: Commit count since the tag and hash of the `HEAD` commit
			  DEFAULT: empty for non-prerelease `NUT_VERSION_DEFAULT`
			  values, or either value of `SUFFIX_PRERELEASE` with a
			  leading dash for `NUT_VERSION_DEFAULT` values without
			  git offset info (e.g. `2.8.3.5-rc6` => `-rc6`), or the
			  whole tail with git and pre-release tag info.
			| * dev: `-2381+g1faa9945d`
			  * RC git: `-2381+g1faa9945d+v2.8.3+rc6`
			  * RC default: `-rc6`
|`SUFFIX_PRERELEASE`	| GIT: Constructed from `TAG_PRERELEASE` replacing any
			  dash with a plus character.
			  DEFAULT: empty unless `NUT_VERSION_DEFAULT` has a
			  suffix matching the `-(rc|alpha|beta)[0-9]*`
			  regular expression, or git info followed by
			  the pre-release tag.
                          NOTE: No leading dash in this value (unlike `SUFFIX`).
			| * RC git: `v2.8.3+rc6`
			  * RC default: `rc6`
|`BASE`		| GIT: Newest common commit of development `TRUNK` and the `HEAD`
			  commit (their `git merge-base`).
			  DEFAULT: empty.
			| `e9a48c9afeb4e06c758a3f4215977445c0f64780`
|`URL`	| Clarify the project website URL -- particularly historically
			  frozen snapshots made for releases
			| * dev: `https://www.networkupstools.org/` (default development)
			  * rel: `https://www.networkupstools.org/historic/v2.8.2/index.html`
|`UPDATE_FILE`	| Used in `autogen.sh` and top-level `Makefile.am` to
			  update the `VERSION_DEFAULT` file that goes into "dist"
			  tarballs; prints its contents
			| `NUT_VERSION_DEFAULT='2.8.2.2379.2-2381+g1faa9945d'`
|`UPDATE_FILE_GIT_RELEASE`	| Used in maintainer rituals (requires git) to
			  update the `VERSION_FORCED` and `VERSION_FORCED_SEMVER`
			  files that go into "dist" tarballs; prints their contents
			| `NUT_VERSION_FORCED='2.8.2.2878.3-2881+g45029249f+v2.8.3+rc6'`
			  `NUT_VERSION_FORCED_SEMVER='2.8.3'`
|default	| Report `DESC50`	| `v2.8.2-2381-g1faa9945d`
|=========================================================================

Variables propagated by configure.ac
------------------------------------

.Values reported via `NUT_VERSION_QUERY`
[opts="header",cols="1,3,2a"]
|=========================================================================
|Variable	| Description	| Example (development and release)
|`PACKAGE_VERSION`	| Argument to `AC_INIT` determined by
			  `NUT_VERSION_QUERY=VER50 gitlog2version.sh`
			| * dev: `2.8.2.695.1`
			  * trunk: `2.8.2.695`
			  * release: `2.8.2`
|`PACKAGE_URL`	| Argument to `AC_INIT` determined by
			  `NUT_VERSION_QUERY=URL gitlog2version.sh`
			| * dev/trunk: `https://www.networkupstools.org/`
			  * release: `https://www.networkupstools.org/historic/v2.8.2/index.html`
|`NUT_WEBSITE_BASE`	| Derived from `PACKAGE_URL` without a trailing slash
			  nor `index.html` (prefixed to documentation file URLs, etc.)
			| * dev/trunk: `https://www.networkupstools.org`
			  * release: `https://www.networkupstools.org/historic/v2.8.2`
|`NUT_SOURCE_GITREV`
			| Determined by `NUT_VERSION_QUERY=DESC50 gitlog2version.sh`
			| `2.8.2.695.1-696+g0e00f0777`
|`NUT_SOURCE_GITREV_SEMVER`
			| Determined by `NUT_VERSION_QUERY=SEMVER gitlog2version.sh`
			| `2.8.2`
|`NUT_SOURCE_GITREV_NUMERIC`
			| Determined by `NUT_SOURCE_GITREV` leaving only the numbers,
			  e.g. for PyPI uploads (currently without the total commit count)
			| `2.8.2.695.1'`
|`NUT_SOURCE_GITREV_IS_RELEASE`
			| Determined by `NUT_VERSION_QUERY=IS_RELEASE gitlog2version.sh`
			| `true` or `false`
|`NUT_SOURCE_GITREV_IS_PRERELEASE`
			| Determined by `NUT_VERSION_QUERY=IS_PRERELEASE gitlog2version.sh`
			| `true` or `false`
|`NUT_SOURCE_GITREV_DEVREL`
			| String determined by `NUT_SOURCE_GITREV_IS_RELEASE`
			| `"release"` or `"development iteration"`
|=========================================================================

Variables propagated by nut_version.h
-------------------------------------

.Values encoded via `include/nut_version.h`, generated by `include/Makefile.am`
[opts="header",cols="1,3,2a"]
|=========================================================================
|Variable	| Description	| Example (development and release)
|`#define NUT_VERSION_MACRO "$NUT_VERSION"`
		| Determined by default `gitlog2version.sh` (no `NUT_VERSION_QUERY`)
		  at the moment of latest build, or (as fallback) `PACKAGE_VERSION`
		  set during the last run of `configure` script
		| `2.8.2.695.1`
|`#define NUT_VERSION_SEMVER_MACRO "$GITREV_SEMVER"`
		| Determined by `NUT_VERSION_QUERY=SEMVER gitlog2version.sh` at the
		  moment of latest build, or (as fallback) `NUT_SOURCE_GITREV_SEMVER`
		  set during the last run of `configure` script
		| `2.8.2`
|`#define NUT_VERSION_IS_RELEASE <0-or-1>`
		| Determined by `NUT_VERSION_QUERY=IS_RELEASE gitlog2version.sh`
		  (falls back to `false` if that query fails)
		| * `1` if `$GITREV_IS_RELEASE`
		  * `0` otherwise
|`#define NUT_VERSION_IS_PRERELEASE <0-or-1>`
		| Determined by `NUT_VERSION_QUERY=IS_PRERELEASE gitlog2version.sh`
		  (falls back to `false` if that query fails)
		| * `1` if `$GITREV_IS_PRERELEASE`
		  * `0` otherwise
|=========================================================================

Use in C code
-------------

common-nut_version.c
~~~~~~~~~~~~~~~~~~~~

* The `NUT_VERSION_MACRO` is used in `common/common-nut_version.c` and further
  made known to all code base as a static string `UPS_VERSION` linked via
  `libcommon*.la` internal libraries.
* Method `describe_NUT_VERSION_once()` prepares the string which combines the
  `NUT_VERSION_MACRO` with comments that it is either a `release` or a
  `(development iteration after $NUT_VERSION_SEMVER_MACRO)`, based on
  the value of `NUT_VERSION_IS_RELEASE`.
+
It is used from a number of other methods, such as `print_banner_once()`,
  `nut_report_config_flags()`, and so ends up in version reports of programs
  via their `help()`/`usage()` methods.
* Method `suggest_doc_links()` prepares a uniform bit of text for driver and
  tool programs to report in their `help()`/`usage()` methods, to refer to
  their manual page under the `NUT_WEBSITE_BASE`.

Man pages
~~~~~~~~~

* Manual pages and other documentation consume the `PACKAGE_VERSION`,
  `PACKAGE_VERSION` and `NUT_WEBSITE_BASE` as `asciidoc` attributes
  when rendering HTML/PDF/man document formats.
* The `NUT_WEBSITE_BASE` is also substituted instead of literal
  `https://www.networkupstools.org/*` which follows a `home page:` prefix
  (so that the pages rendered for a release refer to the historic website).

systemd and SMF manifests
~~~~~~~~~~~~~~~~~~~~~~~~~

Service manifests include references to documentation for the tools they wrap,
including published pages under the `NUT_WEBSITE_BASE` for the development or
historic variants of the NUT website.

NUT-Monitor (Python UI) and PyNUTClient
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

* The `PACKAGE_VERSION` and `NUT_WEBSITE_BASE` are reported in the About dialog.
* Version information is propagated into PyPI packages for the `PyNUTClient`
  module.