docopslab-dev 0.1.0 → 0.2.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (99) hide show
  1. checksums.yaml +4 -4
  2. data/README.adoc +645 -318
  3. data/docopslab-dev.gemspec +2 -3
  4. data/docs/agent/index.md +4 -8
  5. data/docs/agent/misc/bash-styles.md +470 -0
  6. data/docs/agent/missions/conduct-release.md +161 -87
  7. data/docs/agent/missions/setup-new-project.md +228 -134
  8. data/docs/agent/roles/devops-release-engineer.md +60 -17
  9. data/docs/agent/roles/docops-engineer.md +84 -20
  10. data/docs/agent/roles/planner-architect.md +22 -0
  11. data/docs/agent/roles/product-engineer.md +63 -15
  12. data/docs/agent/roles/product-manager.md +57 -24
  13. data/docs/agent/roles/project-manager.md +48 -12
  14. data/docs/agent/roles/qa-testing-engineer.md +48 -14
  15. data/docs/agent/roles/tech-docs-manager.md +63 -17
  16. data/docs/agent/roles/tech-writer.md +68 -14
  17. data/docs/agent/skills/asciidoc.md +65 -238
  18. data/docs/agent/skills/bash-cli-dev.md +135 -0
  19. data/docs/agent/skills/code-commenting.md +143 -106
  20. data/docs/agent/skills/fix-broken-links.md +145 -100
  21. data/docs/agent/skills/fix-jekyll-asciidoc-build-errors.md +1 -10
  22. data/docs/agent/skills/fix-spelling-issues.md +0 -3
  23. data/docs/agent/skills/git.md +69 -34
  24. data/docs/agent/skills/github-issues.md +110 -71
  25. data/docs/agent/skills/rake-cli-dev.md +1 -1
  26. data/docs/agent/skills/readme-driven-dev.md +1 -0
  27. data/docs/agent/skills/release-history.md +1 -7
  28. data/docs/agent/skills/ruby.md +18 -7
  29. data/docs/agent/skills/schemagraphy-sgyml.md +3 -0
  30. data/docs/agent/skills/tests-running.md +22 -14
  31. data/docs/agent/skills/tests-writing.md +51 -28
  32. data/docs/agent/skills/write-the-docs.md +71 -9
  33. data/docs/agent/topics/common-project-paths.md +122 -70
  34. data/docs/agent/topics/dev-tooling-usage.md +70 -77
  35. data/docs/agent/topics/devops-ci-cd.md +3 -1
  36. data/docs/agent/topics/product-docs-deployment.md +18 -12
  37. data/docs/library-readme.adoc +39 -0
  38. data/lib/docopslab/dev/cast_ops.rb +199 -0
  39. data/lib/docopslab/dev/config_manager.rb +6 -6
  40. data/lib/docopslab/dev/data_utils.rb +42 -0
  41. data/lib/docopslab/dev/file_utils.rb +18 -7
  42. data/lib/docopslab/dev/git_branch.rb +201 -0
  43. data/lib/docopslab/dev/git_hooks.rb +17 -11
  44. data/lib/docopslab/dev/initializer.rb +13 -4
  45. data/lib/docopslab/dev/library/cache.rb +167 -0
  46. data/lib/docopslab/dev/library/fetch.rb +209 -0
  47. data/lib/docopslab/dev/library.rb +328 -0
  48. data/lib/docopslab/dev/linters.rb +63 -12
  49. data/lib/docopslab/dev/manifest.rb +28 -0
  50. data/lib/docopslab/dev/paths.rb +0 -17
  51. data/lib/docopslab/dev/script_manager.rb +12 -6
  52. data/lib/docopslab/dev/skim.rb +109 -0
  53. data/lib/docopslab/dev/spell_check.rb +2 -2
  54. data/lib/docopslab/dev/sync_ops.rb +94 -33
  55. data/lib/docopslab/dev/tasks.rb +58 -18
  56. data/lib/docopslab/dev/version.rb +1 -1
  57. data/lib/docopslab/dev.rb +75 -35
  58. data/specs/data/default-manifest.yml +15 -5
  59. data/specs/data/library-index.yml +22 -0
  60. data/specs/data/manifest-schema.yaml +142 -4
  61. data/specs/data/tasks-def.yml +122 -10
  62. metadata +28 -39
  63. data/assets/config-packs/actionlint/base.yml +0 -13
  64. data/assets/config-packs/actionlint/project.yml +0 -13
  65. data/assets/config-packs/htmlproofer/base.yml +0 -27
  66. data/assets/config-packs/htmlproofer/project.yml +0 -25
  67. data/assets/config-packs/rubocop/base.yml +0 -130
  68. data/assets/config-packs/rubocop/project.yml +0 -8
  69. data/assets/config-packs/shellcheck/base.shellcheckrc +0 -14
  70. data/assets/config-packs/subtxt/ai-asciidoc-antipatterns.sub.txt +0 -11
  71. data/assets/config-packs/vale/asciidoc/ExplicitSectionIDs.yml +0 -8
  72. data/assets/config-packs/vale/asciidoc/ExtraLineBeforeLevel1.yml +0 -7
  73. data/assets/config-packs/vale/asciidoc/OneSentencePerLine.yml +0 -8
  74. data/assets/config-packs/vale/asciidoc/PreferSourceBlocks.yml +0 -8
  75. data/assets/config-packs/vale/asciidoc/ProperAdmonitions.yml +0 -8
  76. data/assets/config-packs/vale/asciidoc/ProperDLs.yml +0 -7
  77. data/assets/config-packs/vale/asciidoc/UncleanListStart.yml +0 -8
  78. data/assets/config-packs/vale/authoring/ButParagraph.yml +0 -8
  79. data/assets/config-packs/vale/authoring/ExNotEg.yml +0 -8
  80. data/assets/config-packs/vale/authoring/LiteralTerms.yml +0 -20
  81. data/assets/config-packs/vale/authoring/Spelling.yml +0 -679
  82. data/assets/config-packs/vale/base.ini +0 -38
  83. data/assets/config-packs/vale/config/scripts/ExplicitSectionIDs.tengo +0 -56
  84. data/assets/config-packs/vale/config/scripts/ExtraLineBeforeLevel1.tengo +0 -121
  85. data/assets/config-packs/vale/config/scripts/OneSentencePerLine.tengo +0 -53
  86. data/assets/config-packs/vale/project.ini +0 -5
  87. data/assets/hooks/pre-commit +0 -63
  88. data/assets/hooks/pre-push +0 -72
  89. data/assets/scripts/adoc_section_ids.rb +0 -50
  90. data/assets/scripts/build-common.sh +0 -193
  91. data/assets/scripts/build-docker.sh +0 -64
  92. data/assets/scripts/build.sh +0 -56
  93. data/assets/scripts/parse_jekyll_asciidoc_logs.rb +0 -467
  94. data/assets/templates/Gemfile +0 -7
  95. data/assets/templates/Rakefile +0 -3
  96. data/assets/templates/gitignore +0 -69
  97. data/assets/templates/jekyll-asciidoc-fix.prompt.yml +0 -17
  98. data/assets/templates/spellcheck.prompt.yml +0 -16
  99. data/docs/agent/AGENTS.md +0 -229
@@ -16,16 +16,13 @@ Table of Contents
16
16
  - General AsciiDoc Syntax Guidelines
17
17
  - DocOps Lab Specific Syntax Guidelines
18
18
  - Inline Syntax
19
- - Inline Semantics
20
- - Syntax Preferences
19
+ - Inline Semantics
20
+ - Syntax Preferences
21
21
  - Block Syntax
22
- - Block Semantics
23
- - Use Delimited Blocks
24
- - Tables
25
- - Example Blocks
26
- - Special Syntax
27
- - Attributes
28
- - Attribute Formatting
22
+ - Block Semantics
23
+ - Use Delimited Blocks
24
+ - Example Blocks
25
+ - Attribute Formatting
29
26
  - Vale Configuration and Usage
30
27
  - Consumer Mode (Other Projects)
31
28
 
@@ -97,11 +94,11 @@ DocOps Lab documentation largely follows the conventions outlined in the [Recomm
97
94
  Reinforcements and exceptions:
98
95
 
99
96
  - Use `.adoc` extensions _execpt_ for Liquid templates used to render AsciiDoc files, which use `.asciidoc`.
97
+
100
98
  - Use one sentence per line formatting.
101
99
 
102
- - Let hard-returns signal spaces between sentences.
103
- - Also do this for major colon- or semicolon-delimited sentences.
104
100
  - Use ATX-style titles and section headings.
101
+
105
102
  - For DRYness, use attributes for common URLs and paths (see Attribute Formatting).
106
103
 
107
104
  ## DocOps Lab Specific Syntax Guidelines
@@ -115,7 +112,9 @@ The main purpose of inline semantics is to provide a clear indication of the rol
115
112
  We can convey semantics by way of:
116
113
 
117
114
  - declaration by element, role, or class
115
+
118
116
  - text style based on declaration
117
+
119
118
  - browser effects based on declaration and additional data
120
119
 
121
120
  We use the following inline semantic coding in DocOps Lab publications.
@@ -274,13 +273,17 @@ Example single-line admonition block syntax
274
273
  NOTE: This is a single-line admonition block.
275
274
  ```
276
275
 
277
- **Exception to this exception** :
278
- We do not recommend the same-line syntax for admonition blocks other than `NOTE` and `TIP`. For `IMPORTANT`, `CAUTION`, and `WARNING`, use at least the 2-line syntax, if not explicit delimiters.
276
+ <dl>
277
+ <dt class="hdlist1">Exception to this exception</dt>
278
+ <dd>
279
+ We do not recommend the same-line syntax for admonition blocks other than `NOTE` and `TIP`. For `IMPORTANT`, `CAUTION`, and `WARNING`, use at least the 2-line syntax, if not explicit delimiters.
279
280
 
280
- ```asciidoc
281
- [IMPORTANT]
282
- This is a critical notice, but it's not warning you of danger.
283
- ```
281
+ ```asciidoc
282
+ [IMPORTANT]
283
+ This is a critical notice, but it's not warning you of danger.
284
+ ```
285
+ </dd>
286
+ </dl>
284
287
 
285
288
  #### Exception: Single-line terminal commands
286
289
 
@@ -304,145 +307,6 @@ echo "Hello, {what}!"
304
307
  ....
305
308
  ```
306
309
 
307
- ### Tables
308
-
309
- Tables are a special case of block content, and they have their own syntax and limited semantics in AsciiDoc.
310
-
311
- ```asciidoc
312
- [options="header",cols=">1,^1,^1,^1,^1,^1,^1,^1"]
313
- |===
314
- | Format | Human | Cmmts | Nesting | Langs | Apps | Git | Total
315
-
316
- | YAML
317
- | 5
318
- | 5
319
- | 5
320
- | 4
321
- | 4
322
- | 5
323
- | 28
324
-
325
- | TOML
326
- | 5
327
- | 5
328
- | 5
329
- | 3
330
- | 2
331
- | 5
332
- | 26
333
-
334
- | XML
335
- | 2
336
- | 4
337
- | 5
338
- | 5
339
- | 2
340
- | 2
341
- | 20
342
-
343
- | JSON
344
- | 3
345
- | 1
346
- | 5
347
- | 5
348
- | 3
349
- | 3
350
- | 20
351
-
352
- | CSV
353
- | 4
354
- | 0
355
- | 0
356
- | 5
357
- | 1
358
- | 3
359
- | 13
360
- |===
361
- ```
362
-
363
- At least for tables of roughly this size and complexity, the AsciiDoc table syntax is mostly legible pre-conversion.
364
-
365
- And such tables convert fairly nicely to HTML, PDF, and even ePub output formats.
366
-
367
- Example 2. Example table output
368
-
369
- <table class="tableblock frame-all grid-all stretch">
370
- <colgroup>
371
- <col style="width: 12.5%;">
372
- <col style="width: 12.5%;">
373
- <col style="width: 12.5%;">
374
- <col style="width: 12.5%;">
375
- <col style="width: 12.5%;">
376
- <col style="width: 12.5%;">
377
- <col style="width: 12.5%;">
378
- <col style="width: 12.5%;">
379
- </colgroup>
380
- <thead>
381
- <tr>
382
- <th class="tableblock halign-right valign-top">Format</th>
383
- <th class="tableblock halign-center valign-top">Human</th>
384
- <th class="tableblock halign-center valign-top">Cmmts</th>
385
- <th class="tableblock halign-center valign-top">Nesting</th>
386
- <th class="tableblock halign-center valign-top">Langs</th>
387
- <th class="tableblock halign-center valign-top">Apps</th>
388
- <th class="tableblock halign-center valign-top">Git</th>
389
- <th class="tableblock halign-center valign-top">Total</th>
390
- </tr>
391
- </thead>
392
- <tbody>
393
- <tr>
394
- <td class="tableblock halign-right valign-top"><p class="tableblock">YAML</p></td>
395
- <td class="tableblock halign-center valign-top"><p class="tableblock">5</p></td>
396
- <td class="tableblock halign-center valign-top"><p class="tableblock">5</p></td>
397
- <td class="tableblock halign-center valign-top"><p class="tableblock">5</p></td>
398
- <td class="tableblock halign-center valign-top"><p class="tableblock">4</p></td>
399
- <td class="tableblock halign-center valign-top"><p class="tableblock">4</p></td>
400
- <td class="tableblock halign-center valign-top"><p class="tableblock">5</p></td>
401
- <td class="tableblock halign-center valign-top"><p class="tableblock">28</p></td>
402
- </tr>
403
- <tr>
404
- <td class="tableblock halign-right valign-top"><p class="tableblock">TOML</p></td>
405
- <td class="tableblock halign-center valign-top"><p class="tableblock">5</p></td>
406
- <td class="tableblock halign-center valign-top"><p class="tableblock">5</p></td>
407
- <td class="tableblock halign-center valign-top"><p class="tableblock">5</p></td>
408
- <td class="tableblock halign-center valign-top"><p class="tableblock">3</p></td>
409
- <td class="tableblock halign-center valign-top"><p class="tableblock">2</p></td>
410
- <td class="tableblock halign-center valign-top"><p class="tableblock">5</p></td>
411
- <td class="tableblock halign-center valign-top"><p class="tableblock">26</p></td>
412
- </tr>
413
- <tr>
414
- <td class="tableblock halign-right valign-top"><p class="tableblock">XML</p></td>
415
- <td class="tableblock halign-center valign-top"><p class="tableblock">2</p></td>
416
- <td class="tableblock halign-center valign-top"><p class="tableblock">4</p></td>
417
- <td class="tableblock halign-center valign-top"><p class="tableblock">5</p></td>
418
- <td class="tableblock halign-center valign-top"><p class="tableblock">5</p></td>
419
- <td class="tableblock halign-center valign-top"><p class="tableblock">2</p></td>
420
- <td class="tableblock halign-center valign-top"><p class="tableblock">2</p></td>
421
- <td class="tableblock halign-center valign-top"><p class="tableblock">20</p></td>
422
- </tr>
423
- <tr>
424
- <td class="tableblock halign-right valign-top"><p class="tableblock">JSON</p></td>
425
- <td class="tableblock halign-center valign-top"><p class="tableblock">3</p></td>
426
- <td class="tableblock halign-center valign-top"><p class="tableblock">1</p></td>
427
- <td class="tableblock halign-center valign-top"><p class="tableblock">5</p></td>
428
- <td class="tableblock halign-center valign-top"><p class="tableblock">5</p></td>
429
- <td class="tableblock halign-center valign-top"><p class="tableblock">3</p></td>
430
- <td class="tableblock halign-center valign-top"><p class="tableblock">3</p></td>
431
- <td class="tableblock halign-center valign-top"><p class="tableblock">20</p></td>
432
- </tr>
433
- <tr>
434
- <td class="tableblock halign-right valign-top"><p class="tableblock">CSV</p></td>
435
- <td class="tableblock halign-center valign-top"><p class="tableblock">4</p></td>
436
- <td class="tableblock halign-center valign-top"><p class="tableblock">0</p></td>
437
- <td class="tableblock halign-center valign-top"><p class="tableblock">0</p></td>
438
- <td class="tableblock halign-center valign-top"><p class="tableblock">5</p></td>
439
- <td class="tableblock halign-center valign-top"><p class="tableblock">1</p></td>
440
- <td class="tableblock halign-center valign-top"><p class="tableblock">3</p></td>
441
- <td class="tableblock halign-center valign-top"><p class="tableblock">13</p></td>
442
- </tr>
443
- </tbody>
444
- </table>
445
-
446
310
  ### Example Blocks
447
311
 
448
312
  Use example blocks liberally. If something fits the description of being an example — especially if the words “example” or “sample” are used in the title, caption, or surrounding text referring to a given block of _anything_…​ then **wrap it in an example block**.
@@ -450,9 +314,13 @@ Use example blocks liberally. If something fits the description of being an exam
450
314
  Instances of the following block types may commonly be instances of examples, and just as commonly they may not be.
451
315
 
452
316
  - figures (diagrams, illustrations, screenshots)
317
+
453
318
  - tables
319
+
454
320
  - code listings
321
+
455
322
  - literal blocks (sample prompts, logs, etc)
323
+
456
324
  - rich-text snippets (rendered results, a user story, etc)
457
325
 
458
326
  Whenever any such instances _are examples_, prepend and append them with example blocks, and prefer to title them at the exampple-block level rather than the inner-content level.
@@ -471,61 +339,11 @@ require 'jekyll'
471
339
  ====
472
340
  ```
473
341
 
474
- ## Special Syntax
475
-
476
- ### Attributes
477
-
478
342
  ### Attribute Formatting
479
343
 
480
344
  AsciiDoc attributes are often used to store reusable matter. In certain contexts, attributes should follow a formatting convention that makes them easier to name and recall.
481
345
 
482
- #### Boolean Attributes
483
-
484
- Use toggles to set or conditionalize states such as:
485
-
486
- - intended audience type or role
487
-
488
- - `audience-agent`
489
- - `audience-beginner`
490
- - ``
491
- - target platform or format
492
-
493
- - `env-github`
494
- - `site-gen-jekyll`
495
- - `backend-pdf`
496
-
497
- These kinds of attributes are passed depending on how the AsciiDoc is converted. Platform and format indicators tend to get argued by the converter at runtime.
498
-
499
- But you can also look check for statuses that might be set in previous files depending on the use-case of the output.
500
-
501
- Testing for _existence_ of a target platform
502
-
503
- ```asciidoc
504
- ifdef::audience-level-beginner[]
505
- As a beginner, you will see extra content in parts of this guide.
506
-
507
- If you are an expert, skip to the <<expert-guide>>.
508
- endif::[]
509
- ```
510
-
511
- Testing for _non-existence_ of a target audience type.
512
-
513
- ```asciidoc
514
- ifndef::audience-agent[]
515
- This content is _not_ to appear in docs generated for AI agents.
516
- endif::[]
517
- ```
518
-
519
- It is generally advised to create two versions of any such indicator that may need to be resolve a variable placeholder later.
520
-
521
- Setting open-ended key and boolean simultaneously
522
-
523
- ```asciidoc
524
- :audience-level: beginner
525
- :audience-level-beginner: true
526
-
527
- Later we can reference the {audience-level}, which might be overwritten by an attribute passed at runtime.
528
- ```
346
+ For a complete guidance on attribute naming and usage, see [DocOps Lab AsciiDoc Attributes Naming and Usage](/docs/asciidoc-attributes/).
529
347
 
530
348
  #### URL Attributes
531
349
 
@@ -539,20 +357,15 @@ Where:
539
357
 
540
358
  - `syntax_` is one of
541
359
 
542
- - `href_` (external)
543
- - `xref_` (local)
544
- - none (skip it — presumed to be a straight URL)
545
360
  - `area_` is a component or category like `docs_` or `pages_`, mainly to ensure unique slugs across divisions
546
- - `form` is the way the resource is presented:
547
361
 
548
- - `link` (includes linked text _and_ the URL)
549
- - `url` (just the URL)
362
+ - `form` is the way the resource is presented:
550
363
 
551
364
  Examples
552
365
 
553
366
  ```asciidoc
554
- :docopslab_hub_url: https://github.com/DocOps
555
- :href_docopslab_aylstack_url: {docopslab_hub_url}/aylstack/
367
+ :docopslab_src_www_url: https://github.com/DocOps
368
+ :href_docopslab_aylstack_url: {docopslab_src_www_url}/aylstack/
556
369
  :href_docopslab_aylstack_link: link:{href_docopslab_aylstack_url}[AYL DocStack]
557
370
  ```
558
371
 
@@ -566,44 +379,58 @@ Linting for documentation quality and consistency, both AsciiDoc markup syntax a
566
379
 
567
380
  This tool provides a custom styles package and a modified configuration system, enabling multi-file merging.
568
381
 
569
- **Base config** :
570
- `.config/.vendor/docopslab/vale.ini` (from source)
571
-
572
- **Project config** :
573
- `.config/vale.local.ini` (inherits via `BasedOnStyles`)
574
-
575
- **Ephemeral config** :
576
- `.config/vale.ini` (merged from base and target)
577
-
578
- **Sync command** :
579
- `bundle exec rake labdev:sync:vale`
580
-
581
- ### Consumer Mode (Other Projects)
382
+ <dl>
383
+ <dt class="hdlist1">Base config</dt>
384
+ <dd>
385
+ `.config/.vendor/docopslab/vale.ini` (from source)
386
+ </dd>
387
+ <dt class="hdlist1">Project config</dt>
388
+ <dd>
389
+ `.config/vale.local.ini` (inherits via `BasedOnStyles`)
390
+ </dd>
391
+ <dt class="hdlist1">Ephemeral config</dt>
392
+ <dd>
393
+ `.config/vale.ini` (merged from base and target)
394
+ </dd>
395
+ <dt class="hdlist1">Sync command</dt>
396
+ <dd>
397
+ `bundle exec rake labdev:sync:vale`
398
+ </dd>
399
+ </dl>
400
+
401
+ ## Consumer Mode (Other Projects)
582
402
 
583
403
  For all other projects, the gem works in a standard package consumption mode:
584
404
 
585
405
  - The project’s `vale.ini` should list all desired packages, including a URL to the stable, published `DocOpsLabStyles.zip`.
406
+
586
407
  - The `labdev:sync:styles` task simply runs `vale sync` in the proper context, downloading all listed packages into a local `.vale/styles` directory.
587
408
 
588
- > **TIP:** The `labdev:sync:vale` task updates both the base config and the styles package.
409
+ > **TIP:** The `labdev:sync:vale` task updates both the base config and the style packages.
410
+
411
+ A project’s `.config/vale.local.ini` should look something like the one for this repository (DocOps/lab).
589
412
 
590
- The `.config/vale.ini` for consumer projects (based on the gem’s template) should look like this:
413
+ A snippet from DocOps/lab’s `.config/vale.local.ini`
591
414
 
592
415
  ```ini
593
- # CONSUMER MODE CONFIG
416
+ MinAlertLevel = warning
417
+ StylesPath = .vendor/vale/styles
594
418
 
595
- StylesPath = .vale/styles
419
+ [asciidoctor]
420
+ missing-attribute = drop
421
+ safe = unsafe
422
+ experimental = YES
596
423
 
597
- # List all packages, including the URL to the central DocOpsLabStyles package.
598
- # TODO: Update with the real URL.
599
- Packages = RedHat, proselint, write-good, https://example.com/path/to/DocOpsLabStyles.zip
424
+ [_blog/*.adoc]
425
+ DocOpsLab-AsciiDoc.ExplicitSectionIDs = NO
600
426
 
601
- [*.adoc]
602
- BasedOnStyles = RedHat, DocOpsLab-Authoring, DocOpsLab-AsciiDoc
427
+ [_docs/agent/**/*.adoc]
428
+ DocOpsLab-AsciiDoc.ExplicitSectionIDs = NO
429
+ DocOpsLab-AsciiDoc.ExtraLineBeforeLevel1 = NO
603
430
  ```
604
431
 
605
432
  This dual-mode system provides a robust workflow for both developing and consuming the centralized Vale styles.
606
433
 
607
- > **NOTE:** For full Vale configuration settings (“keys”) reference, see [the Vale documentation](https://vale.sh/docs/configuration).
434
+ > **NOTE:** For full Vale configuration settings (“keys”) reference, see the [official Vale documentation](https://vale.sh/docs/vale-ini).
608
435
  > **NOTE:** For information on managing DocOps Lab’s Vale styles, see [the `docopslab-dev` gem README](https://github.com/DocOps/lab/blob/main/gems/docopslab-dev/README.adoc).
609
436
 
@@ -0,0 +1,135 @@
1
+ # Bash CLI Development for Agents
2
+
3
+ This document is intended for AI agents operating within a DocOps Lab environment.
4
+
5
+ > **TIP:** Use this guide in combination with the general Bash coding skill.
6
+
7
+ Table of Contents
8
+
9
+ - Bash CLIs
10
+ - Bash CLI Model
11
+ - General CLI Principles
12
+ - When NOT to Use a CLI
13
+ - Semantic CLI Namespaces
14
+ - General CLI Conventions
15
+
16
+ ## Bash CLIs
17
+
18
+ Bash scripts are often used for simple CLIs that wrap around more complex operations. Most repo-wide chores that do not require specialized Ruby-based tools like Asciidoctor or other gems are handled with Bash scripts (The significant exception to this are multi-repo libraries like the [DocOps Lab Devtool](/docs/lab-dev-setup/).)
19
+
20
+ The one truly major Bash CLI we maintain is `docksh`, our Docker shell utility for launching properly configured containers for development, testing, and deployment (sourced in `box`).
21
+
22
+ ### Bash CLI Model
23
+
24
+ Base CLIs are relatively open ended. Developers should consider how the script might change, but unless it is intended to be elaborate from the start, there is not much reason to fuss over complicated structures.
25
+
26
+ > **TIP:** See [DocOps Lab Bash Coding Guide](/docs/bash-styles/) for details about implementing Bash CLIs.
27
+
28
+ Let’s examine our typical Bash script CLI structure:
29
+
30
+ ```
31
+ ./bashscript.sh [arguments] [options]
32
+ ```
33
+
34
+ If a Bash script is likely to eventually need to encompass multiple arguments or options, consider making it a Rake task and invoking Ruby scripts, instead.
35
+
36
+ ## General CLI Principles
37
+
38
+ Most of our user-facing applications are Ruby gems, and most of those are intended to be used via three primary interfaces:
39
+
40
+ 1. An application specific, openly designed CLI utility.
41
+
42
+ 2. An application configuration file.
43
+
44
+ 3. Subject-matter content or domain-specific data of some kind.
45
+
46
+ By way of these three interfaces, users can operate the application in a way that is optimized for their particular use case.
47
+
48
+ CLIs should allow for runtime configuration overrides and even runtime content/data overrides. But most of all they should focus on conveniently putting power in users' hands.
49
+
50
+ This means leaving the CLI model open to the task at hand, but it also means adhering to some conventions that apply generally to both Ruby and Bash CLIs.
51
+
52
+ ### When NOT to Use a CLI
53
+
54
+ Even when an application offers a mature, well-designed CLI, there are times when either an application programming interface (API) or a domain-specific language (DSL) is preferable. Typically we want to keep complicated shell commands out of core products and CI/CD pipelines, in favor of native or RESTful APIs or else config-driven or DSL-driven utilities.
55
+
56
+ ### Semantic CLI Namespaces
57
+
58
+ When designing CLIs, consider the namespaces of the elements we use: subcommands, arguments, and options/flags.
59
+
60
+ Subcommands should be verbs or nouns that declare operations or contexts. At each position, these elements should be organizable into meaningful categories.
61
+
62
+ Arguments should be meaningful nouns that represent the primary _subject or subjects_ of the command.
63
+
64
+ ### General CLI Conventions
65
+
66
+ The definitive reference on CLI design is the [CLI Guidelines](https://clig.dev/) project.
67
+
68
+ #### Option format
69
+
70
+ <dl>
71
+ <dt class="hdlist1">Use spaces rather than `=` to assign values to options.</dt>
72
+ <dd>
73
+ Flag forms such as `--option-name value` are preferred over `--option-name=value`.
74
+ </dd>
75
+ <dt class="hdlist1">Provide long- and short- form flag aliases for common options.</dt>
76
+ <dd>
77
+ For ex: `-h` and `--help`, `-c` and `--config`.
78
+ </dd>
79
+ <dt class="hdlist1">Use `--no-` prefix for negated boolean flags when applicable.</dt>
80
+ <dd>
81
+ For ex: `--no-cache` to disable caching.
82
+ </dd>
83
+ </dl>
84
+
85
+ #### Command structure
86
+
87
+ <dl>
88
+ <dt class="hdlist1">Use subcommand only with apps that perform categorically diverse operations,</dt>
89
+ <dd>
90
+ Prefer flag combinations when possible. Subcommands signal a shift in execution context, and thus they can be greatly helpful when needed. Otherwise, reserve the first argument slot for something a meaningful arbitrary argument.
91
+
92
+ A CLI with very handy subcommands
93
+
94
+ ```
95
+ git fetch
96
+ git commmit
97
+ git merge
98
+ ```
99
+
100
+ No subcommand needed
101
+
102
+ ```
103
+ rhx 1.2.1 --config test-config.yml --mapping apis/jira.yml --verbose --fetch --yaml
104
+ rhx 1.2.1 --config test-config.yml --html
105
+ ```
106
+
107
+ And yes, of course you can combine fixed subcommands with arbitrary arguments.
108
+
109
+ ```
110
+ git diff README.adoc
111
+ ```
112
+ </dd>
113
+ <dt class="hdlist1">Avoid using Unix-style argument structures.</dt>
114
+ <dd>
115
+ Arbitrary arguments should come _before_ options, even if that is counter-intuitive. Typically in our apps, users are modifying commands that get executed on the same target, so if the target is an arbitrary file path or version number, it should closely follow the command as an early argument.
116
+
117
+ Preferred argument order
118
+
119
+ ```
120
+ cliname targetfile --option1 value1 --option2 value2 --verbose --force
121
+ ```
122
+
123
+ This structure lets users more conveniently change the parts of the command-line that will need more frequent changing.
124
+ </dd>
125
+ <dt class="hdlist1">Accommodate Unix-style CLIs by adding named options for every arbitrary argument supported.</dt>
126
+ <dd>
127
+ The trick is to enable those cases where the subject path or code _is_ what gets changed most often.
128
+
129
+ ```
130
+ rhx --yaml --version 1.2.6
131
+ rhx --yaml --version 1.3.1
132
+ ```
133
+ </dd>
134
+ </dl>
135
+