@sebastienrousseau/dotfiles 0.2.518 → 0.2.520

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 (163) hide show
  1. package/CHANGELOG.md +191 -0
  2. package/README.md +1164 -164
  3. package/docs/ARCHITECTURE.md +117 -0
  4. package/docs/COPYRIGHT +1 -1
  5. package/docs/ECOSYSTEM.md +220 -0
  6. package/docs/GOLD-STANDARD-AUDIT.md +352 -0
  7. package/docs/GOVERNANCE.md +1 -1
  8. package/docs/MAINTAINERS.md +1 -1
  9. package/docs/MINIMUM-TOOLCHAIN.md +100 -0
  10. package/docs/README.md +1 -1
  11. package/docs/STRUCTURE.md +1 -1
  12. package/docs/architecture/ARCHITECTURE.md +11 -108
  13. package/docs/architecture/REPO_LAYOUT.md +4 -4
  14. package/docs/guides/MACOS_ICLOUD_SYMLINKS.md +121 -0
  15. package/docs/index.md +3 -3
  16. package/docs/manual/00-introduction.md +1 -1
  17. package/docs/manual/03-reference/01-dot-cli.md +28 -3
  18. package/docs/manual/command-index.md +24 -4
  19. package/docs/manual/concept-index.md +2 -0
  20. package/docs/migration/README.md +81 -0
  21. package/docs/migration/from-bare-git-repo.md +156 -0
  22. package/docs/migration/from-gnu-stow.md +165 -0
  23. package/docs/migration/from-plain-chezmoi.md +148 -0
  24. package/docs/migration/from-yadm.md +187 -0
  25. package/docs/operations/PERFORMANCE_BUDGETS.md +196 -0
  26. package/docs/operations/REGISTRY.md +1 -1
  27. package/docs/operations/RELEASE_PIPELINE.md +4 -4
  28. package/docs/operations/TESTING.md +3 -3
  29. package/docs/operations/TRACEABILITY.md +1 -0
  30. package/docs/packaging.md +222 -0
  31. package/docs/reference/FEATURE-MATRIX.md +646 -0
  32. package/docs/reference/TOOLS.md +1 -1
  33. package/docs/reference/UTILS.md +1 -0
  34. package/docs/security/COMPLIANCE.md +1 -1
  35. package/docs/security/DISCLOSURE.md +4 -4
  36. package/docs/security/FUZZING.md +113 -18
  37. package/docs/security/KEY_ROTATION.md +1 -1
  38. package/docs/security/SCORECARD.md +3 -3
  39. package/docs/security/VERIFY_RELEASE.md +2 -2
  40. package/install.sh +6 -6
  41. package/package.json +2 -2
  42. package/scripts/ci/check-copyright-headers.sh +1 -1
  43. package/scripts/ci/check-shell-preamble.sh +1 -1
  44. package/scripts/ci/guard-gitleaks-checkout.sh +1 -1
  45. package/scripts/demo/record.sh +1 -1
  46. package/scripts/diagnostics/a2a-conformance.sh +1 -1
  47. package/scripts/diagnostics/alias-governance.sh +30 -3
  48. package/scripts/diagnostics/aliases-cheatsheet.sh +1 -1
  49. package/scripts/diagnostics/aliases-manifest.sh +1 -1
  50. package/scripts/diagnostics/attest-verify.sh +147 -0
  51. package/scripts/diagnostics/benchmark.sh +1 -1
  52. package/scripts/diagnostics/conflicts.sh +1 -1
  53. package/scripts/diagnostics/doctor-unified.sh +6 -2
  54. package/scripts/diagnostics/doctor.sh +56 -10
  55. package/scripts/diagnostics/drift-dashboard.sh +3 -2
  56. package/scripts/diagnostics/health.sh +43 -10
  57. package/scripts/diagnostics/history-analysis.sh +1 -1
  58. package/scripts/diagnostics/mcp-doctor.sh +2 -2
  59. package/scripts/diagnostics/perf.sh +1 -1
  60. package/scripts/diagnostics/scorecard.sh +3 -2
  61. package/scripts/diagnostics/secret-governance.sh +1 -1
  62. package/scripts/diagnostics/security-score.sh +1 -1
  63. package/scripts/diagnostics/smoke-test.sh +1 -1
  64. package/scripts/diagnostics/snapshot.sh +1 -1
  65. package/scripts/diagnostics/verify.sh +1 -1
  66. package/scripts/diagnostics/verify_state.sh +1 -1
  67. package/scripts/diagnostics/version-locks.sh +1 -1
  68. package/scripts/diagnostics/workstation-attestation.sh +26 -1
  69. package/scripts/dot/commands/agent.sh +64 -14
  70. package/scripts/dot/commands/agents.sh +24 -8
  71. package/scripts/dot/commands/ai.sh +20 -7
  72. package/scripts/dot/commands/aliases.sh +1 -1
  73. package/scripts/dot/commands/appearance.sh +1 -1
  74. package/scripts/dot/commands/completion.sh +42 -5
  75. package/scripts/dot/commands/core.sh +1 -1
  76. package/scripts/dot/commands/diagnostics.sh +1 -1
  77. package/scripts/dot/commands/env-emit.sh +1 -1
  78. package/scripts/dot/commands/fleet.sh +41 -18
  79. package/scripts/dot/commands/init.sh +1 -1
  80. package/scripts/dot/commands/lint.sh +1 -1
  81. package/scripts/dot/commands/manual.sh +1 -1
  82. package/scripts/dot/commands/meta.sh +115 -10
  83. package/scripts/dot/commands/patterns.sh +1 -1
  84. package/scripts/dot/commands/registry.sh +43 -7
  85. package/scripts/dot/commands/restore.sh +1 -1
  86. package/scripts/dot/commands/secrets.sh +1 -1
  87. package/scripts/dot/commands/security.sh +1 -1
  88. package/scripts/dot/commands/tools.sh +21 -7
  89. package/scripts/fonts/install-nerd-fonts.sh +1 -1
  90. package/scripts/fonts/patch-fonts.sh +1 -1
  91. package/scripts/git-hooks/install.sh +1 -1
  92. package/scripts/git-hooks/pre-commit-audit.sh +2 -2
  93. package/scripts/lib/secrets_provider.sh +19 -4
  94. package/scripts/nvim/headless-upgrade.lua +81 -0
  95. package/scripts/ops/ai-setup.sh +1 -1
  96. package/scripts/ops/bundle.sh +1 -1
  97. package/scripts/ops/chaos.sh +1 -1
  98. package/scripts/ops/chezmoi-apply.sh +1 -1
  99. package/scripts/ops/chezmoi-diff.sh +1 -1
  100. package/scripts/ops/chezmoi-remove.sh +3 -3
  101. package/scripts/ops/chezmoi-update.sh +6 -2
  102. package/scripts/ops/heal-chezmoi.sh +1 -1
  103. package/scripts/ops/heal-system.sh +1 -1
  104. package/scripts/ops/heal-tools.sh +1 -1
  105. package/scripts/ops/heal.sh +1 -1
  106. package/scripts/ops/post-apply-repair.sh +1 -1
  107. package/scripts/ops/prewarm.sh +1 -1
  108. package/scripts/ops/release.sh +1 -1
  109. package/scripts/ops/rollback.sh +11 -2
  110. package/scripts/ops/setup.sh +1 -1
  111. package/scripts/ops/teleport.sh +1 -1
  112. package/scripts/qa/check-feature-matrix.sh +296 -0
  113. package/scripts/qa/check-version-consistency.sh +7 -119
  114. package/scripts/qa/coverage-baseline.sh +1 -1
  115. package/scripts/qa/docs-coverage.sh +9 -3
  116. package/scripts/qa/examples-coverage.sh +1 -1
  117. package/scripts/qa/reliability-audit.sh +1 -1
  118. package/scripts/qa/scorecard-snapshot.sh +1 -1
  119. package/scripts/qa/traceability-coverage.sh +9 -2
  120. package/scripts/qa/validate-examples.sh +66 -3
  121. package/scripts/qa/wsl-contract.sh +1 -1
  122. package/scripts/secrets/age-init.sh +1 -1
  123. package/scripts/secrets/create-secrets-file.sh +1 -1
  124. package/scripts/secrets/encrypt-ssh-key.sh +1 -1
  125. package/scripts/security/backup.sh +1 -1
  126. package/scripts/security/check-disclosure-key-expiry.sh +1 -1
  127. package/scripts/security/dns-doh.sh +1 -1
  128. package/scripts/security/encryption-check.sh +1 -1
  129. package/scripts/security/enforce-policies.sh +315 -98
  130. package/scripts/security/firewall.sh +1 -1
  131. package/scripts/security/lock-configs.sh +1 -1
  132. package/scripts/security/lock-screen.sh +1 -1
  133. package/scripts/security/manage-secrets.sh +1 -1
  134. package/scripts/security/ssh-cert.sh +1 -1
  135. package/scripts/security/telemetry-kill.sh +1 -1
  136. package/scripts/security/usb-safety.sh +1 -1
  137. package/scripts/theme/apply-gnome-theme.sh +1 -1
  138. package/scripts/theme/extract-heic-frames.sh +1 -1
  139. package/scripts/theme/extract-theme.py +284 -6
  140. package/scripts/theme/install-boot-logo.sh +1 -1
  141. package/scripts/theme/install-catppuccin-themes.sh +1 -1
  142. package/scripts/theme/install-cursors.sh +1 -1
  143. package/scripts/theme/install-file-icons.sh +1 -1
  144. package/scripts/theme/install-grub-theme.sh +1 -1
  145. package/scripts/theme/install-lock-icon.sh +1 -1
  146. package/scripts/theme/merge-wallpaper.sh +1 -1
  147. package/scripts/theme/rebuild-themes.sh +64 -5
  148. package/scripts/theme/switch.sh +46 -19
  149. package/scripts/theme/wallpaper-rotate.sh +1 -1
  150. package/scripts/theme/wallpaper-sync.sh +1 -1
  151. package/scripts/tools/cmatrix.sh +1 -1
  152. package/scripts/tools/detect-collisions.py +1 -1
  153. package/scripts/tools/emoji-picker.sh +1 -1
  154. package/scripts/tools/figlet-banner.sh +1 -1
  155. package/scripts/tools/log-rotate.sh +1 -1
  156. package/scripts/tools/lolcat-wrap.sh +1 -1
  157. package/scripts/tools/pipes.sh +1 -1
  158. package/scripts/tuning/linux.sh +1 -1
  159. package/scripts/tuning/macos.sh +1 -1
  160. package/scripts/uninstall.sh +1 -1
  161. package/scripts/verify-release-versions +156 -0
  162. package/scripts/version-sync.sh +63 -3
  163. package/LICENSE +0 -21
@@ -1,124 +1,12 @@
1
1
  #!/usr/bin/env bash
2
- # SPDX-License-Identifier: MIT
2
+ # SPDX-License-Identifier: Apache-2.0 OR MIT
3
3
  # Copyright (c) 2015-2026 Sebastien Rousseau
4
4
  #
5
- # Verify that every "live" version reference matches the canonical
6
- # version in .chezmoidata.toml. The intent is to catch drift between
7
- # the source-of-truth and the human-visible surfaces (CLI banner, man
8
- # page, badge URL, etc.) BEFORE it ships.
5
+ # Compatibility wrapper. The canonical name for this gate is
6
+ # `scripts/verify-release-versions` (the name the repository standard
7
+ # uses); this path is kept so existing callers — the `version-consistency`
8
+ # pre-commit hook, older docs, muscle memory keep working.
9
9
  #
10
- # Historical references (CHANGELOG entries, audit-doc closed-cycle
11
- # tables, roadmap docs that mention previous versions) are NOT
12
- # checked — they are intentionally pinned to the version they
13
- # describe.
14
- #
15
- # Usage:
16
- # scripts/qa/check-version-consistency.sh # verify
17
- # scripts/qa/check-version-consistency.sh --fix # auto-fix
18
- # scripts/qa/check-version-consistency.sh --quiet # rc-only
19
- #
20
- # Exit codes:
21
- # 0 every live reference matches
22
- # 1 drift detected (with diff printed unless --quiet)
23
- # 2 bad usage / missing canonical version
24
-
10
+ # Do not add logic here. Edit scripts/verify-release-versions.
25
11
  set -euo pipefail
26
-
27
- REPO_ROOT="$(cd "$(dirname "${BASH_SOURCE[0]}")/../.." && pwd)"
28
- cd "$REPO_ROOT"
29
-
30
- # ── Parse flags ─────────────────────────────────────────────────────────
31
- fix=0
32
- quiet=0
33
- for arg in "$@"; do
34
- case "$arg" in
35
- --fix) fix=1 ;;
36
- --quiet | -q) quiet=1 ;;
37
- -h | --help)
38
- sed -n '2,21p' "$0"
39
- exit 0
40
- ;;
41
- *)
42
- echo "unknown flag: $arg" >&2
43
- exit 2
44
- ;;
45
- esac
46
- done
47
-
48
- _log() { ((quiet)) || printf '%s\n' "$*"; }
49
- _err() { printf 'check-version-consistency: %s\n' "$*" >&2; }
50
-
51
- # ── Canonical version ──────────────────────────────────────────────────
52
- canonical="$(grep -E '^dotfiles_version[[:space:]]*=' defaults/.chezmoidata.toml |
53
- head -1 | sed -E 's/.*"([^"]+)".*/\1/')"
54
-
55
- if [[ -z "$canonical" ]]; then
56
- _err 'failed to read dotfiles_version from defaults/.chezmoidata.toml'
57
- exit 2
58
- fi
59
- _log "canonical: $canonical (defaults/.chezmoidata.toml)"
60
-
61
- # ── Per-file expected-substring map ────────────────────────────────────
62
- # Each entry: PATH|MATCH_PATTERN|EXPECTED_STRING
63
- # MATCH_PATTERN is a fixed substring to grep for on the file to
64
- # locate the version-bearing line; we then verify it contains the
65
- # expected substring rendered with $canonical. version-sync.sh
66
- # already handles many files (it reads package.json as source);
67
- # this list captures the surfaces version-sync.sh historically
68
- # missed — bento.sh banner, man-page header, dispatcher header.
69
- specs=(
70
- "package.json|\"version\"|\"version\": \"${canonical}\""
71
- "bin/dot|^VERSION=|VERSION=\"${canonical}\""
72
- "bin/dot|^# Dotfiles CLI Entry Point - v|# Dotfiles CLI Entry Point - v${canonical}"
73
- "share/man/man1/dot.1|^.TH DOT 1|dotfiles v${canonical}"
74
- "lib/dot/bento.sh|D O T F I L E S|[v${canonical}]"
75
- "README.md|img.shields.io/badge/Version|Version-v${canonical}-blue"
76
- "CLAUDE.md|^Chezmoi-managed dotfiles|Version \`${canonical}\`"
77
- "AGENTS.md|^Chezmoi-managed dotfiles|Version \`${canonical}\`"
78
- )
79
-
80
- drift=0
81
- for spec in "${specs[@]}"; do
82
- IFS='|' read -r path pattern expected <<<"$spec"
83
- if [[ ! -f "$path" ]]; then
84
- _err "MISSING: $path (declared in spec list)"
85
- drift=$((drift + 1))
86
- continue
87
- fi
88
- line="$(grep -E "$pattern" "$path" | head -1 || true)"
89
- if [[ -z "$line" ]]; then
90
- _err "PATTERN NOT FOUND: '$pattern' in $path"
91
- drift=$((drift + 1))
92
- continue
93
- fi
94
- if [[ "$line" != *"$expected"* ]]; then
95
- _err "DRIFT in $path"
96
- _err " found: $line"
97
- _err " expected: contains '$expected'"
98
- drift=$((drift + 1))
99
- if ((fix)); then
100
- # Auto-fix: only safe when the file contains a previous v0.X.YYY
101
- # we can sed-replace. Skip otherwise.
102
- old="$(printf '%s' "$line" | grep -oE 'v[0-9]+\.[0-9]+\.[0-9]+' | head -1)"
103
- if [[ -n "$old" ]] && [[ "$old" != "v${canonical}" ]]; then
104
- sed -i.bak "s|${old}|v${canonical}|g" "$path" && rm -f "$path.bak"
105
- _log " fixed: $path ($old → v${canonical})"
106
- fi
107
- fi
108
- fi
109
- done
110
-
111
- if ((drift > 0)); then
112
- if ((fix)); then
113
- _log ""
114
- _log "Auto-fixed where safe. Re-run without --fix to verify."
115
- else
116
- _log ""
117
- _log "Tip: rerun with --fix to auto-correct (only safe substitutions)."
118
- _log " For non-trivial drift, edit the file manually then re-run."
119
- fi
120
- exit 1
121
- fi
122
-
123
- _log "all $((${#specs[@]})) live version surfaces match $canonical"
124
- exit 0
12
+ exec bash "$(cd "$(dirname "${BASH_SOURCE[0]}")/../.." && pwd)/scripts/verify-release-versions" "$@"
@@ -1,5 +1,5 @@
1
1
  #!/usr/bin/env bash
2
- # SPDX-License-Identifier: MIT
2
+ # SPDX-License-Identifier: Apache-2.0 OR MIT
3
3
  # Copyright (c) 2015-2026 Sebastien Rousseau
4
4
  set -euo pipefail
5
5
 
@@ -1,5 +1,5 @@
1
1
  #!/usr/bin/env bash
2
- # SPDX-License-Identifier: MIT
2
+ # SPDX-License-Identifier: Apache-2.0 OR MIT
3
3
  # Copyright (c) 2015-2026 Sebastien Rousseau
4
4
  set -euo pipefail
5
5
 
@@ -10,7 +10,7 @@ DOT_CLI="$REPO_ROOT/bin/dot"
10
10
  UTILS_DOC="$REPO_ROOT/docs/reference/UTILS.md"
11
11
  AI_DOC="$REPO_ROOT/docs/AI.md"
12
12
  SCRIPTS_DOC="$REPO_ROOT/docs/reference/SCRIPTS.md"
13
- ARCH_DOC="$REPO_ROOT/docs/architecture/ARCHITECTURE.md"
13
+ ARCH_DOC="$REPO_ROOT/docs/ARCHITECTURE.md"
14
14
  FUNCTION_GROUPS_JSON="$REPO_ROOT/defaults/.chezmoitemplates/functions/groups.json"
15
15
  MIN_DOCS_COVERAGE="${MIN_DOCS_COVERAGE:-100}"
16
16
 
@@ -104,7 +104,13 @@ main() {
104
104
  check_ai_provider_docs
105
105
  check_utility_docs
106
106
  check_function_group_docs
107
- report_coverage
107
+ # Capture the coverage threshold verdict — without this the final
108
+ # `printf PASS...` overwrites report_coverage's exit code and CI
109
+ # never sees a coverage regression.
110
+ if ! report_coverage; then
111
+ printf 'FAIL: docs coverage below MIN_DOCS_COVERAGE=%s%%\n' "$MIN_DOCS_COVERAGE" >&2
112
+ return 1
113
+ fi
108
114
 
109
115
  printf 'PASS: public dot commands, utility entrypoints, AI providers, and function groups are documented at or above the required threshold\n'
110
116
  }
@@ -1,5 +1,5 @@
1
1
  #!/usr/bin/env bash
2
- # SPDX-License-Identifier: MIT
2
+ # SPDX-License-Identifier: Apache-2.0 OR MIT
3
3
  # Copyright (c) 2015-2026 Sebastien Rousseau
4
4
  # =============================================================================
5
5
  # examples-coverage.sh — enforce that every core feature domain ships a
@@ -1,5 +1,5 @@
1
1
  #!/usr/bin/env bash
2
- # SPDX-License-Identifier: MIT
2
+ # SPDX-License-Identifier: Apache-2.0 OR MIT
3
3
  # Copyright (c) 2015-2026 Sebastien Rousseau
4
4
  set -euo pipefail
5
5
 
@@ -1,5 +1,5 @@
1
1
  #!/usr/bin/env bash
2
- # SPDX-License-Identifier: MIT
2
+ # SPDX-License-Identifier: Apache-2.0 OR MIT
3
3
  # Copyright (c) 2015-2026 Sebastien Rousseau
4
4
  #
5
5
  # Fetch the current OpenSSF Scorecard result and refresh the
@@ -1,5 +1,5 @@
1
1
  #!/usr/bin/env bash
2
- # SPDX-License-Identifier: MIT
2
+ # SPDX-License-Identifier: Apache-2.0 OR MIT
3
3
  # Copyright (c) 2015-2026 Sebastien Rousseau
4
4
  set -euo pipefail
5
5
 
@@ -109,7 +109,14 @@ main() {
109
109
  } | sort -u
110
110
  )
111
111
 
112
- report_traceability
112
+ # Capture report_traceability's exit — without this the trailing
113
+ # `printf PASS...` returns 0 and overwrites the awk threshold verdict,
114
+ # so a below-threshold run silently exits 0 (same bug as docs-coverage.sh).
115
+ if ! report_traceability; then
116
+ printf 'FAIL: traceability coverage below MIN_TRACEABILITY_COVERAGE=%s%%\n' \
117
+ "$MIN_TRACEABILITY_COVERAGE" >&2
118
+ return 1
119
+ fi
113
120
 
114
121
  printf 'PASS: core internal behaviors have implementation, test, and documentation traceability at or above the required threshold\n'
115
122
  }
@@ -1,5 +1,5 @@
1
1
  #!/usr/bin/env bash
2
- # SPDX-License-Identifier: MIT
2
+ # SPDX-License-Identifier: Apache-2.0 OR MIT
3
3
  # Copyright (c) 2015-2026 Sebastien Rousseau
4
4
  set -euo pipefail
5
5
 
@@ -7,16 +7,74 @@ SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
7
7
  REPO_ROOT="$(cd "$SCRIPT_DIR/../.." && pwd)"
8
8
  EXAMPLES_DIR="$REPO_ROOT/examples"
9
9
 
10
+ # Per-example wall-clock budget. Bounding each example individually means one
11
+ # slow or hanging example is reported by name instead of silently consuming the
12
+ # whole script's budget and surfacing as an opaque rc=124 from the caller.
13
+ EXAMPLE_TIMEOUT="${EXAMPLE_TIMEOUT:-60}"
14
+
15
+ usage() {
16
+ cat <<'USAGE'
17
+ Usage: validate-examples.sh [--help]
18
+
19
+ Runs every executable example in examples/ and fails if any of them fails or
20
+ exceeds the per-example timeout.
21
+
22
+ Environment:
23
+ EXAMPLE_TIMEOUT Per-example timeout in seconds (default: 60). Set to 0 to
24
+ disable the timeout.
25
+ USAGE
26
+ }
27
+
28
+ # Parse arguments before doing any work. Previously this script ignored its
29
+ # arguments entirely, so `--help` silently executed the whole examples suite —
30
+ # which meant asking for help ran a multi-minute job.
31
+ case "${1:-}" in
32
+ -h | --help)
33
+ usage
34
+ exit 0
35
+ ;;
36
+ "") ;;
37
+ *)
38
+ printf 'Unknown option: %s\n\n' "$1" >&2
39
+ usage >&2
40
+ exit 2
41
+ ;;
42
+ esac
43
+
10
44
  if [ ! -d "$EXAMPLES_DIR" ]; then
11
45
  echo "No examples directory found: $EXAMPLES_DIR" >&2
12
46
  exit 1
13
47
  fi
14
48
 
49
+ # Resolve a timeout binary. GNU coreutils ships `timeout`; on macOS it is
50
+ # `gtimeout` when coreutils is installed. Without either, run unbounded rather
51
+ # than failing outright.
52
+ timeout_cmd=()
53
+ if [ "$EXAMPLE_TIMEOUT" != "0" ]; then
54
+ if command -v timeout >/dev/null 2>&1; then
55
+ timeout_cmd=(timeout --kill-after=5 "$EXAMPLE_TIMEOUT")
56
+ elif command -v gtimeout >/dev/null 2>&1; then
57
+ timeout_cmd=(gtimeout --kill-after=5 "$EXAMPLE_TIMEOUT")
58
+ else
59
+ printf 'warning: no timeout binary found; examples run unbounded\n' >&2
60
+ fi
61
+ fi
62
+
15
63
  found=0
64
+ failed=0
16
65
  while IFS= read -r -d '' example; do
17
66
  found=1
18
- printf 'Running example: %s\n' "$(basename "$example")"
19
- bash "$example"
67
+ name="$(basename "$example")"
68
+ printf 'Running example: %s\n' "$name"
69
+ rc=0
70
+ "${timeout_cmd[@]+"${timeout_cmd[@]}"}" bash "$example" </dev/null || rc=$?
71
+ if [ "$rc" -eq 124 ]; then
72
+ printf 'FAIL: %s exceeded the %ss timeout\n' "$name" "$EXAMPLE_TIMEOUT" >&2
73
+ failed=$((failed + 1))
74
+ elif [ "$rc" -ne 0 ]; then
75
+ printf 'FAIL: %s exited %s\n' "$name" "$rc" >&2
76
+ failed=$((failed + 1))
77
+ fi
20
78
  done < <(find "$EXAMPLES_DIR" -maxdepth 1 -type f -name "*.sh" -print0 | sort -z)
21
79
 
22
80
  if [ "$found" -eq 0 ]; then
@@ -24,4 +82,9 @@ if [ "$found" -eq 0 ]; then
24
82
  exit 1
25
83
  fi
26
84
 
85
+ if [ "$failed" -ne 0 ]; then
86
+ printf '%s example(s) failed.\n' "$failed" >&2
87
+ exit 1
88
+ fi
89
+
27
90
  printf 'Examples passed.\n'
@@ -1,5 +1,5 @@
1
1
  #!/usr/bin/env bash
2
- # SPDX-License-Identifier: MIT
2
+ # SPDX-License-Identifier: Apache-2.0 OR MIT
3
3
  # Copyright (c) 2015-2026 Sebastien Rousseau
4
4
  set -euo pipefail
5
5
 
@@ -1,5 +1,5 @@
1
1
  #!/usr/bin/env bash
2
- # SPDX-License-Identifier: MIT
2
+ # SPDX-License-Identifier: Apache-2.0 OR MIT
3
3
  # Copyright (c) 2015-2026 Sebastien Rousseau
4
4
  set -euo pipefail
5
5
 
@@ -1,5 +1,5 @@
1
1
  #!/usr/bin/env bash
2
- # SPDX-License-Identifier: MIT
2
+ # SPDX-License-Identifier: Apache-2.0 OR MIT
3
3
  # Copyright (c) 2015-2026 Sebastien Rousseau
4
4
  set -euo pipefail
5
5
 
@@ -1,5 +1,5 @@
1
1
  #!/usr/bin/env bash
2
- # SPDX-License-Identifier: MIT
2
+ # SPDX-License-Identifier: Apache-2.0 OR MIT
3
3
  # Copyright (c) 2015-2026 Sebastien Rousseau
4
4
  set -euo pipefail
5
5
 
@@ -1,5 +1,5 @@
1
1
  #!/usr/bin/env bash
2
- # SPDX-License-Identifier: MIT
2
+ # SPDX-License-Identifier: Apache-2.0 OR MIT
3
3
  # Copyright (c) 2015-2026 Sebastien Rousseau
4
4
  ## Create compressed backup of home directory.
5
5
  ##
@@ -1,5 +1,5 @@
1
1
  #!/usr/bin/env bash
2
- # SPDX-License-Identifier: MIT
2
+ # SPDX-License-Identifier: Apache-2.0 OR MIT
3
3
  # Copyright (c) 2015-2026 Sebastien Rousseau
4
4
  #
5
5
  # scripts/security/check-disclosure-key-expiry.sh
@@ -1,5 +1,5 @@
1
1
  #!/usr/bin/env bash
2
- # SPDX-License-Identifier: MIT
2
+ # SPDX-License-Identifier: Apache-2.0 OR MIT
3
3
  # Copyright (c) 2015-2026 Sebastien Rousseau
4
4
  set -euo pipefail
5
5
 
@@ -1,5 +1,5 @@
1
1
  #!/usr/bin/env bash
2
- # SPDX-License-Identifier: MIT
2
+ # SPDX-License-Identifier: Apache-2.0 OR MIT
3
3
  # Copyright (c) 2015-2026 Sebastien Rousseau
4
4
  set -euo pipefail
5
5