confctl 2.2.3 → 3.0.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 (178) hide show
  1. checksums.yaml +4 -4
  2. data/.git-hooks/pre_commit/nixfmt.rb +13 -0
  3. data/.github/workflows/rspec.yml +64 -0
  4. data/.github/workflows/rubocop.yml +27 -0
  5. data/.github/workflows/tests.yml +139 -0
  6. data/.gitignore +12 -7
  7. data/.overcommit.yml +2 -0
  8. data/.rspec +1 -0
  9. data/.rubocop.yml +8 -1
  10. data/AGENTS.md +42 -0
  11. data/CHANGELOG.md +54 -0
  12. data/Gemfile +3 -2
  13. data/Gemfile.lock +198 -0
  14. data/README.md +166 -58
  15. data/Rakefile +5 -0
  16. data/confctl.gemspec +20 -2
  17. data/docs/carrier.md +3 -3
  18. data/docs/flake-inputs.md +159 -0
  19. data/docs/swpins-to-flakes.md +325 -0
  20. data/example/cluster/module-list.nix +2 -1
  21. data/example/cluster/nixos-machine/config.nix +12 -2
  22. data/example/cluster/nixos-machine/hardware.nix +6 -1
  23. data/example/cluster/vpsadminos-container/config.nix +6 -1
  24. data/example/cluster/vpsadminos-container/module.nix +4 -1
  25. data/example/cluster/vpsadminos-machine/config.nix +6 -1
  26. data/example/cluster/vpsadminos-machine/hardware.nix +6 -1
  27. data/example/cluster/vpsadminos-machine/module.nix +5 -2
  28. data/example/cluster/vpsfreecz-vps/config.nix +6 -1
  29. data/example/cluster/vpsfreecz-vps/module.nix +4 -1
  30. data/example/configs/swpins.nix +8 -3
  31. data/example/environments/base.nix +6 -1
  32. data/example/swpins/core.json +35 -0
  33. data/example-flake/.gitignore +2 -0
  34. data/example-flake/README.md +38 -0
  35. data/example-flake/cluster/cluster.nix +5 -0
  36. data/example-flake/cluster/module-list.nix +4 -0
  37. data/example-flake/cluster/nested/nixos-machine/config.nix +25 -0
  38. data/example-flake/cluster/nested/nixos-machine/hardware.nix +9 -0
  39. data/example-flake/cluster/nested/nixos-machine/module.nix +8 -0
  40. data/example-flake/cluster/nixos-machine/config.nix +25 -0
  41. data/example-flake/cluster/nixos-machine/hardware.nix +9 -0
  42. data/example-flake/cluster/nixos-machine/module.nix +8 -0
  43. data/example-flake/cluster/vpsadminos-container/config.nix +28 -0
  44. data/example-flake/cluster/vpsadminos-container/module.nix +8 -0
  45. data/example-flake/cluster/vpsadminos-machine/config.nix +27 -0
  46. data/example-flake/cluster/vpsadminos-machine/hardware.nix +9 -0
  47. data/example-flake/cluster/vpsadminos-machine/module.nix +8 -0
  48. data/example-flake/cluster/vpsfreecz-vps/config.nix +31 -0
  49. data/example-flake/cluster/vpsfreecz-vps/module.nix +8 -0
  50. data/example-flake/configs/confctl.nix +10 -0
  51. data/example-flake/data/default.nix +5 -0
  52. data/example-flake/data/ssh-keys.nix +7 -0
  53. data/example-flake/environments/base.nix +18 -0
  54. data/example-flake/flake.lock +75 -0
  55. data/example-flake/flake.nix +36 -0
  56. data/example-flake/modules/module-list.nix +13 -0
  57. data/example-flake/shell.nix +11 -0
  58. data/flake.lock +159 -0
  59. data/flake.nix +189 -0
  60. data/gemset.nix +1022 -0
  61. data/lib/confctl/cli/app.rb +145 -0
  62. data/lib/confctl/cli/attr_filters.rb +1 -1
  63. data/lib/confctl/cli/cluster.rb +681 -108
  64. data/lib/confctl/cli/command.rb +24 -2
  65. data/lib/confctl/cli/configuration.rb +171 -106
  66. data/lib/confctl/cli/generation.rb +65 -1
  67. data/lib/confctl/cli/inputs/channels.rb +190 -0
  68. data/lib/confctl/cli/inputs/machines.rb +83 -0
  69. data/lib/confctl/cli/inputs/root.rb +101 -0
  70. data/lib/confctl/cli/inputs.rb +5 -0
  71. data/lib/confctl/cli/log_view.rb +21 -10
  72. data/lib/confctl/cli/migrate/swpins_to_flakes.rb +866 -0
  73. data/lib/confctl/cli/migrate.rb +5 -0
  74. data/lib/confctl/cli/output_formatter.rb +5 -5
  75. data/lib/confctl/cli/swpins/base.rb +9 -0
  76. data/lib/confctl/cli/swpins/channel.rb +2 -5
  77. data/lib/confctl/cli/swpins/cluster.rb +2 -5
  78. data/lib/confctl/cli/swpins/core.rb +2 -5
  79. data/lib/confctl/config_type.rb +7 -0
  80. data/lib/confctl/flake_lock.rb +78 -0
  81. data/lib/confctl/flake_lock_diff.rb +36 -0
  82. data/lib/confctl/generation/build.rb +131 -24
  83. data/lib/confctl/generation/build_list.rb +4 -3
  84. data/lib/confctl/generation/unified.rb +14 -1
  85. data/lib/confctl/git_repo_mirror.rb +2 -2
  86. data/lib/confctl/health_checks/run_command.rb +3 -2
  87. data/lib/confctl/health_checks/systemd/properties.rb +1 -1
  88. data/lib/confctl/health_checks/systemd/property_list.rb +2 -2
  89. data/lib/confctl/inputs/commit_message.rb +125 -0
  90. data/lib/confctl/inputs/git_commit.rb +17 -0
  91. data/lib/confctl/inputs/nix_output_guard.rb +37 -0
  92. data/lib/confctl/inputs/setter.rb +179 -0
  93. data/lib/confctl/inputs/updater.rb +76 -0
  94. data/lib/confctl/inputs.rb +5 -0
  95. data/lib/confctl/inputs_info.rb +50 -0
  96. data/lib/confctl/line_buffer.rb +1 -1
  97. data/lib/confctl/machine.rb +18 -3
  98. data/lib/confctl/machine_control.rb +8 -2
  99. data/lib/confctl/machine_list.rb +2 -2
  100. data/lib/confctl/machine_status.rb +63 -20
  101. data/lib/confctl/nix/args.rb +48 -0
  102. data/lib/confctl/nix.rb +30 -437
  103. data/lib/confctl/nix_build_flake.rb +95 -0
  104. data/lib/confctl/nix_copy.rb +14 -2
  105. data/lib/confctl/nix_flake.rb +449 -0
  106. data/lib/confctl/nix_format.rb +3 -3
  107. data/lib/confctl/nix_legacy.rb +467 -0
  108. data/lib/confctl/swpins/change_set.rb +24 -2
  109. data/lib/confctl/swpins/specs/base.rb +2 -2
  110. data/lib/confctl/ui.rb +19 -0
  111. data/lib/confctl/version.rb +1 -1
  112. data/man/index.html +11 -0
  113. data/man/man8/confctl-options.nix.8.html +113 -0
  114. data/man/man8/confctl.8 +152 -21
  115. data/man/man8/confctl.8.html +355 -0
  116. data/man/man8/confctl.8.md +148 -17
  117. data/man/style.css +301 -0
  118. data/nix/evaluator.nix +94 -69
  119. data/nix/flake/mk-confctl-devshell.nix +85 -0
  120. data/nix/flake/mk-confctl-outputs.nix +522 -0
  121. data/nix/flake/mk-config-devshell.nix +168 -0
  122. data/nix/lib/default.nix +118 -65
  123. data/nix/lib/machine/default.nix +65 -45
  124. data/nix/lib/machine/info.nix +16 -5
  125. data/nix/lib/swpins/eval.nix +42 -29
  126. data/nix/lib/swpins/options.nix +6 -2
  127. data/nix/machines.nix +23 -15
  128. data/nix/modules/cluster/default.nix +104 -41
  129. data/nix/modules/confctl/carrier/base.nix +11 -4
  130. data/nix/modules/confctl/carrier/carrier-env.rb +2 -2
  131. data/nix/modules/confctl/carrier/netboot/build-netboot-server.rb +50 -13
  132. data/nix/modules/confctl/carrier/netboot/nixos.nix +56 -24
  133. data/nix/modules/confctl/configuration-info.nix +17 -0
  134. data/nix/modules/confctl/generations.nix +2 -2
  135. data/nix/modules/confctl/host.nix +13 -0
  136. data/nix/modules/confctl/inputs-info.nix +21 -0
  137. data/nix/modules/confctl/kexec-netboot/default.nix +13 -6
  138. data/nix/modules/confctl/kexec-netboot/kexec-netboot.8.adoc +3 -0
  139. data/nix/modules/confctl/kexec-netboot/kexec-netboot.rb +25 -16
  140. data/nix/modules/confctl/nix.nix +31 -1
  141. data/nix/modules/confctl/swpins.nix +13 -6
  142. data/nix/modules/module-list.nix +4 -2
  143. data/nix/modules/system-list.nix +4 -1
  144. data/nix/package.nix +37 -0
  145. data/shell.nix +39 -8
  146. data/skills/confctl-configuration-update/SKILL.md +228 -0
  147. data/skills/confctl-configuration-update/agents/openai.yaml +4 -0
  148. data/skills/confctl-release/SKILL.md +102 -0
  149. data/skills/confctl-release/agents/openai.yaml +4 -0
  150. data/spec/confctl/cli/cluster_health_check_spec.rb +43 -0
  151. data/spec/confctl/cli/cluster_skip_current_deploy_spec.rb +157 -0
  152. data/spec/confctl/cli/cluster_status_flake_spec.rb +83 -0
  153. data/spec/confctl/cli/inputs_set_output_spec.rb +70 -0
  154. data/spec/confctl/configuration_spec.rb +45 -0
  155. data/spec/confctl/inputs_spec.rb +104 -0
  156. data/spec/confctl/machine_control_spec.rb +112 -0
  157. data/spec/confctl/machine_list_spec.rb +47 -0
  158. data/spec/confctl/nix_flake_spec.rb +41 -0
  159. data/spec/confctl/swpins_spec.rb +106 -0
  160. data/spec/generation/build_modes_spec.rb +132 -0
  161. data/spec/inputs/commit_message_spec.rb +205 -0
  162. data/spec/inputs/nix_cached_fallback_spec.rb +50 -0
  163. data/spec/inputs/nix_output_guard_spec.rb +45 -0
  164. data/spec/spec_helper.rb +12 -0
  165. data/spec/support/cli_helper.rb +57 -0
  166. data/test-runner.sh +7 -0
  167. data/tests/all-tests.nix +30 -0
  168. data/tests/make-test.nix +15 -0
  169. data/tests/runner/extensions/confctl_helpers.rb +238 -0
  170. data/tests/runner/extensions/hostfwd_ports.rb +41 -0
  171. data/tests/suite/auto_rollback.nix +344 -0
  172. data/tests/suite/carrier/deploy.nix +751 -0
  173. data/tests/suite/carrier/netboot.nix +849 -0
  174. data/tests/suite/deploy/base.nix +806 -0
  175. data/tests/suite/deploy/flakes.nix +1 -0
  176. data/tests/suite/deploy/swpins.nix +1 -0
  177. metadata +104 -4
  178. data/nix/modules/confctl/overlays.nix +0 -15
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 145a3b775c32414d32bf6dba2e9dbf69db302f1893f92f78cd5c5dc3f7bdca4a
4
- data.tar.gz: fb1357049bec71e36b4d6fc9e76d0bf0ac8e620f10e7a3ebed8056ba8d6fc848
3
+ metadata.gz: 0d4e43b6438198685eefeb53d560cc7d048de7ba59179aa091ddda7d34f9f90c
4
+ data.tar.gz: 513a4cce72db36f303c996f8d48ea28af1810cdca2dda257345ad3b0ba264e7b
5
5
  SHA512:
6
- metadata.gz: 30fa519e81a6bc96de302e573cfdef8d4aef4a5f0ce918778e94132c7cc6de661c26d3206c9223b4b9e1dbd295c4d4a902100504d0563f8ba64e015db022c952
7
- data.tar.gz: 1158a757fea8cd633edc95b976e6db9ec65797fa1623f3cb20912b870dc0b6180bbdc37e5e7d788c8ddb5505d819a8322ff4d7f4e72e3f9b2fd50fe250a3486b
6
+ metadata.gz: '04186167e0a5bfc5ac3a691592e531e5b84325097241572d5ad789dfdce7514c98de7f73332967323ff0036b447cd8ef988f9e2a94ea0cbb7ee76c256c0cfea4'
7
+ data.tar.gz: 8e0ee73aacf5b159c9d81b403fff47deddfc7036d715e47d84c362ffc2938acac63a6b797117f55fef4c3714fe8c22a36088edfa5e1f25aba6d14694fedfc1aa
@@ -0,0 +1,13 @@
1
+ module Overcommit::Hook::PreCommit
2
+ class Nixfmt < Base
3
+ def run
4
+ nix_files = applicable_files.select { |v| v.end_with?('.nix') }
5
+ return :pass if nix_files.empty?
6
+
7
+ output = `nixfmt --check #{nix_files.map { |v| "\"#{v}\"" }.join(' ')}`
8
+ return :pass if $?.exitstatus == 0
9
+
10
+ [:fail, output]
11
+ end
12
+ end
13
+ end
@@ -0,0 +1,64 @@
1
+ name: RSpec
2
+
3
+ on:
4
+ push:
5
+
6
+ jobs:
7
+ rspec:
8
+ name: rspec (ruby ${{ matrix.ruby-version }})
9
+ strategy:
10
+ fail-fast: false
11
+ matrix:
12
+ ruby-version: ["3.3", "3.4", "4.0"]
13
+
14
+ runs-on: ubuntu-latest
15
+ permissions:
16
+ contents: read
17
+
18
+ steps:
19
+ - name: Check out source
20
+ uses: actions/checkout@v6
21
+ with:
22
+ fetch-depth: 1
23
+
24
+ - name: Install Nix
25
+ uses: cachix/install-nix-action@v31
26
+
27
+ - name: Prepare per-user Nix gcroots
28
+ shell: bash
29
+ run: |
30
+ set -euo pipefail
31
+
32
+ user="$(id -un)"
33
+ group="$(id -gn)"
34
+ gcroot_dir="/nix/var/nix/gcroots/per-user/${user}"
35
+
36
+ sudo mkdir -p "$gcroot_dir"
37
+ sudo chown "${user}:${group}" "$gcroot_dir"
38
+
39
+ - name: Set up Nix test dependencies
40
+ shell: bash
41
+ run: |
42
+ set -euo pipefail
43
+
44
+ nix profile install --accept-flake-config nixpkgs#nix-prefetch-git
45
+
46
+ nixpkgs_path="$(
47
+ nix eval --raw --impure \
48
+ --extra-experimental-features 'nix-command flakes' \
49
+ --expr '(let f = builtins.getFlake (toString ./.); in f.inputs.nixpkgs.outPath)'
50
+ )"
51
+
52
+ echo "CONFCTL_TEST_NIXPKGS=${nixpkgs_path}" >>"$GITHUB_ENV"
53
+ echo "NIX_PATH=nixpkgs=${nixpkgs_path}" >>"$GITHUB_ENV"
54
+
55
+ - name: Set up Ruby + Bundler cache
56
+ uses: ruby/setup-ruby@v1
57
+ with:
58
+ ruby-version: ${{ matrix.ruby-version }}
59
+ bundler-cache: true
60
+
61
+ - name: Run RSpec
62
+ shell: bash
63
+ run: |
64
+ bundle exec rspec
@@ -0,0 +1,27 @@
1
+ name: RuboCop
2
+
3
+ on:
4
+ push:
5
+
6
+ jobs:
7
+ rubocop:
8
+ runs-on: ubuntu-latest
9
+ permissions:
10
+ contents: read
11
+
12
+ steps:
13
+ - name: Check out source
14
+ uses: actions/checkout@v6
15
+ with:
16
+ fetch-depth: 1
17
+
18
+ - name: Set up Ruby + Bundler cache
19
+ uses: ruby/setup-ruby@v1
20
+ with:
21
+ ruby-version: "3.4"
22
+ bundler-cache: true
23
+
24
+ - name: Run RuboCop
25
+ shell: bash
26
+ run: |
27
+ bundle exec rubocop --parallel --force-exclusion
@@ -0,0 +1,139 @@
1
+ name: Tests
2
+
3
+ on:
4
+ workflow_dispatch:
5
+ inputs:
6
+ stop_on_failure:
7
+ description: Stop scheduling after the first unexpected result
8
+ required: true
9
+ default: false
10
+ type: boolean
11
+ push:
12
+ paths:
13
+ - .github/workflows/tests.yml
14
+ - flake.nix
15
+ - flake.lock
16
+ - Gemfile
17
+ - Gemfile.lock
18
+ - bin/**
19
+ - lib/**
20
+ - libexec/**
21
+ - nix/**
22
+ - tests/**
23
+ - test-runner.sh
24
+
25
+ permissions:
26
+ contents: read
27
+
28
+ jobs:
29
+ test:
30
+ name: Run ci-tagged tests
31
+ runs-on: self-hosted
32
+ timeout-minutes: 360
33
+
34
+ steps:
35
+ - name: Checkout confctl
36
+ uses: actions/checkout@v7
37
+ with:
38
+ fetch-depth: 1
39
+
40
+ - name: Reset per-user Nix gcroots
41
+ shell: bash
42
+ run: |
43
+ set -euo pipefail
44
+
45
+ user="$(id -un)"
46
+ gcroot_dir="/nix/var/nix/gcroots/per-user/${user}"
47
+
48
+ if [ ! -d "$gcroot_dir" ]; then
49
+ echo "Missing gcroots directory: $gcroot_dir" >&2
50
+ exit 1
51
+ fi
52
+
53
+ if [ ! -w "$gcroot_dir" ]; then
54
+ echo "Gcroots directory is not writable: $gcroot_dir" >&2
55
+ ls -ld "$gcroot_dir" >&2
56
+ exit 1
57
+ fi
58
+
59
+ find "$gcroot_dir" -mindepth 1 -maxdepth 1 -exec rm -rf -- {} +
60
+
61
+ - name: Prepare test state
62
+ id: prepare-tests
63
+ uses: vpsfreecz/vpsadminos/.github/actions/prepare-test-state@staging
64
+
65
+ - name: Run tests
66
+ id: run-tests
67
+ timeout-minutes: 320
68
+ shell: bash
69
+ env:
70
+ STOP_ON_FAILURE: ${{ github.event.inputs.stop_on_failure || 'false' }}
71
+ run: |
72
+ set -o pipefail
73
+
74
+ args=(
75
+ test
76
+ -f
77
+ --jobs auto
78
+ -t ci
79
+ --state-dir "$TEST_RUNNER_STATE_DIR"
80
+ )
81
+
82
+ if [[ "$STOP_ON_FAILURE" == "true" ]]; then
83
+ args+=(--stop-on-failure)
84
+ fi
85
+
86
+ ./test-runner.sh "${args[@]}" | tee test.log
87
+
88
+ - name: Upload full test logs
89
+ id: upload-test-logs
90
+ if: >-
91
+ (failure() || cancelled()) &&
92
+ steps.prepare-tests.outcome == 'success' &&
93
+ steps.run-tests.outcome != 'skipped'
94
+ uses: vpsfreecz/vpsadminos/.github/actions/upload-test-logs@staging
95
+ with:
96
+ name: confctl-test-logs-${{ github.run_id }}
97
+ paths: |
98
+ ${{ steps.prepare-tests.outputs.state-directory }}/**/*.log
99
+ ${{ steps.prepare-tests.outputs.state-directory }}/**/*.txt
100
+
101
+ - name: Evaluate test results
102
+ if: >-
103
+ always() &&
104
+ steps.prepare-tests.outcome == 'success' &&
105
+ steps.run-tests.outcome != 'skipped'
106
+ uses: vpsfreecz/vpsadminos/.github/actions/evaluate-test-results@staging
107
+ with:
108
+ log-file: test.log
109
+
110
+ - name: Summarise test logs
111
+ if: >-
112
+ always() &&
113
+ steps.prepare-tests.outcome == 'success' &&
114
+ steps.run-tests.outcome != 'skipped'
115
+ uses: vpsfreecz/vpsadminos/.github/actions/summarise-test-logs@staging
116
+ with:
117
+ logs-root: ${{ steps.prepare-tests.outputs.state-directory }}
118
+
119
+ - name: Cleanup test state
120
+ if: always()
121
+ uses: vpsfreecz/vpsadminos/.github/actions/cleanup-test-state@staging
122
+ with:
123
+ state-directory: ${{ steps.prepare-tests.outputs.state-directory }}
124
+ prepare-outcome: ${{ steps.prepare-tests.outcome }}
125
+ test-outcome: ${{ steps.run-tests.outcome }}
126
+ upload-outcome: ${{ steps.upload-test-logs.outcome }}
127
+
128
+ - name: Cleanup per-user Nix gcroots
129
+ if: always()
130
+ shell: bash
131
+ run: |
132
+ set -euo pipefail
133
+
134
+ user="$(id -un)"
135
+ gcroot_dir="/nix/var/nix/gcroots/per-user/${user}"
136
+
137
+ if [ -d "$gcroot_dir" ] && [ -w "$gcroot_dir" ]; then
138
+ find "$gcroot_dir" -mindepth 1 -maxdepth 1 -exec rm -rf -- {} +
139
+ fi
data/.gitignore CHANGED
@@ -1,9 +1,14 @@
1
- Gemfile.lock
2
- pkg
3
- man/style.css
4
- man/*.html
5
- man/**/*.html
6
- man/man?/*.?
7
- html_doc
1
+ .bin/
2
+ .bundle/
3
+ .cache/
4
+ .confctl/
8
5
  .gems
6
+ .man/
7
+ .rubocop_cache/
9
8
  .yardoc
9
+ html_doc
10
+ man/**/*.html
11
+ man/*.html
12
+ man/man?/*.?
13
+ man/style.css
14
+ pkg
data/.overcommit.yml CHANGED
@@ -1,4 +1,6 @@
1
1
  PreCommit:
2
+ Nixfmt:
3
+ enabled: true
2
4
  RuboCop:
3
5
  enabled: true
4
6
  CommitMsg:
data/.rspec ADDED
@@ -0,0 +1 @@
1
+ --require spec_helper
data/.rubocop.yml CHANGED
@@ -1,7 +1,10 @@
1
1
  inherit_from: .rubocop_todo.yml
2
+ inherit_mode:
3
+ merge:
4
+ - Exclude
2
5
 
3
6
  AllCops:
4
- TargetRubyVersion: 3.1.0
7
+ TargetRubyVersion: 3.3.0
5
8
  NewCops: enable
6
9
  Exclude:
7
10
  - '*.rb'
@@ -41,6 +44,8 @@ Naming/HeredocDelimiterNaming:
41
44
  Enabled: false
42
45
  Naming/MethodParameterName:
43
46
  Enabled: false
47
+ Naming/PredicateMethod:
48
+ Enabled: false
44
49
 
45
50
  Style/CaseEquality:
46
51
  Enabled: false
@@ -59,6 +64,8 @@ Style/MultilineBlockChain:
59
64
  Enabled: false
60
65
  Style/NumericPredicate:
61
66
  EnforcedStyle: comparison
67
+ Style/OneClassPerFile:
68
+ Enabled: false
62
69
  Style/PreferredHashMethods:
63
70
  EnforcedStyle: verbose
64
71
  Style/SafeNavigation:
data/AGENTS.md ADDED
@@ -0,0 +1,42 @@
1
+ # Repository Guidelines
2
+
3
+ ## Project Structure & Module Organization
4
+ - `lib/` Ruby sources; CLI commands under `lib/confctl/cli`, Nix build helpers in `lib/confctl/nix*`, health checks in `lib/confctl/health_checks`.
5
+ - `bin/confctl` entrypoint; `libexec/` helper scripts; `template/` ERB for generated docs; rendered man pages live in `man/man8/`.
6
+ - `nix/` contains Nix modules and overlays; `example/` provides a sample cluster and swpins setup; `docs/` holds focused guides; release gems are stored in `pkg/`.
7
+
8
+ ## Build, Test, and Development Commands
9
+ - Enter `nix develop` to get Ruby, bundler, nixfmt, and the `confctl` binstub wired to the local sources.
10
+ - `bundle exec rubocop` lints Ruby; pre-commit hook also runs `nixfmt` on Nix files.
11
+ - `bundle exec rspec` (or `bundle exec rake spec`) runs the automated Ruby tests.
12
+ - Format Nix code with `nixfmt` (or `nixfmt-tree` to format directories) from inside the shell.
13
+ - `bundle exec rake md2man:man` regenerates manpages; `bundle exec rake confctl-options` rebuilds the options reference from templates.
14
+ - Package the gem with `bundle exec rake build` (outputs to `pkg/`) and install locally with `bundle exec rake install`.
15
+
16
+ ## Coding Style & Naming Conventions
17
+ - Ruby target version 3.1; use 2-space indents, LF endings, UTF-8 (`.editorconfig`).
18
+ - Snake_case for methods/variables, CamelCase for classes/modules, kebab-case for CLI commands/flags; keep option names consistent with existing Nix modules.
19
+ - RuboCop config is permissive on metrics—still prefer small, single-purpose methods and early returns; avoid introducing new global state.
20
+
21
+ ## Testing Guidelines
22
+ - Run `bundle exec rspec` for automated coverage and `bundle exec rubocop` for linting.
23
+ - Keep focused manual runs of the commands you touch (build, deploy, swpins, health checks) against a local configuration such as `example/`.
24
+ - When fixing a bug, add a minimal regression check in RSpec if practical and document the manual steps you executed.
25
+
26
+ ## Commit & Pull Request Guidelines
27
+ - Before preparing or publishing a confctl version release, read
28
+ [`skills/confctl-release/SKILL.md`](skills/confctl-release/SKILL.md). It covers
29
+ Bundix metadata, release commit ordering, package verification and publication.
30
+ - Commit subjects are short and imperative. Without a prefix, capitalize the first word. With a `topic/component:` prefix, keep the first word after `:` lowercase. Avoid trailing periods and bundle related changes together.
31
+ - Write commit messages in a temporary file and pass them to `git commit -F`
32
+ or `git commit --amend -F`. Wrap message lines to 80 columns.
33
+ - Commit messages must explain what problem or goal the change addresses.
34
+ - For fixes, explain how the change fixes or works around the problem. For
35
+ new functionality, explain how the new behavior works.
36
+ - Flake input updates (`vpsadminos`) flow:
37
+ 1. Read current rev: `nix flake metadata --json . | jq -r '.locks.nodes.vpsadminos.locked.rev'`.
38
+ 2. Update input: `nix flake update vpsadminos` (or `nix flake lock --update-input vpsadminos`).
39
+ 3. Verify only `flake.lock` changed for this update commit.
40
+ 4. Commit with subject format: `flake: vpsadminos <old9> -> <new9>` (example: `flake: vpsadminos 2cab01000 -> 08bb11324`).
41
+ - Describe PRs clearly with motivation, scope, and manual verification notes; link relevant issues and update docs/manpages when behavior changes.
42
+ - Run rspec, rubocop, and nixfmt before pushing; ensure generated artifacts (`man/`, `pkg/` when releasing) reflect your changes.
data/CHANGELOG.md CHANGED
@@ -1,3 +1,57 @@
1
+ # Wed Oct 07 2026 -- version 3.0.0
2
+
3
+ Software pins (`swpins`) remain supported in v3.0.0 and will be removed in v4.
4
+ Use [the migration guide](docs/swpins-to-flakes.md) to move existing
5
+ configurations to flake inputs.
6
+
7
+ ## Flake configurations
8
+
9
+ - Add a flake backend for building and deploying NixOS and vpsAdminOS machines
10
+ - Create flake-based configurations by default with `confctl init`; use
11
+ `confctl init --swpins` for the legacy software pin workflow
12
+ - Add `confctl inputs` commands to list, update and set input revisions at the
13
+ root, channel and machine levels, with optional commits and changelogs
14
+ - Map dependency roles to flake inputs through channels and per-machine overrides;
15
+ see [docs/flake-inputs.md](docs/flake-inputs.md)
16
+ - Add `confctl migrate swpins-to-flakes`, including `--dry-run` and individual
17
+ migration steps
18
+ - Record flake inputs in build generations and show their revisions in generation
19
+ listings, status, diffs and changelogs
20
+ - Record the configuration source revision in deployed machine metadata
21
+ - Add flake packages, configuration development shells and an example flake
22
+ configuration
23
+ - Support optional impure evaluation and legacy `NIX_PATH` mappings for flake
24
+ builds
25
+ - Evaluate only requested flake build outputs and build machine metadata as JSON
26
+ - Group shared input changelogs and report resolved revisions after setting inputs
27
+ - Fail input updates when Nix falls back to cached GitHub metadata
28
+
29
+ ## Deployment and fixes
30
+
31
+ - Skip deployment to machines already using the target generation, avoiding
32
+ unnecessary copying, activation, reboots and health checks
33
+ - Support custom SSH ports through `host.port`, including Nix copies
34
+ - Preserve spaces and shell metacharacters in remote command arguments
35
+ - Fix deployment confirmation on localhost
36
+ - Support CLI output and progress reporting without a terminal
37
+ - Reuse prefetched Git checkouts when updating software pins and fix commits of
38
+ changed software pin files
39
+ - Fix garbage collection roots for software pin paths
40
+ - Support NixOS in `kexec-netboot`, stream downloads and add `--no-sync`
41
+ - Honor NixOS PXE kernel parameters and preserve the init path for carried images
42
+ - Add RSpec coverage and integration tests for flakes, software pins, automatic
43
+ rollback, carriers and netboot
44
+ - Refresh Ruby dependencies, including the vpsAdmin and HaveAPI clients
45
+
46
+ ## Upgrade notes
47
+
48
+ - Require Ruby 3.3 or newer (previously Ruby 3.1)
49
+ - Remove the `confReplaceVarsWith` compatibility wrapper; confctl's Nix modules
50
+ now require `pkgs.replaceVarsWith`
51
+ - Existing software pin configurations and generations remain supported. Migrating
52
+ to flakes is optional in v3.0.0. Keep the migration on a configuration branch;
53
+ confctl v2 cannot use the resulting flake configuration.
54
+
1
55
  # Fri Jun 06 2025 -- version 2.2.3
2
56
  - Open git commit editor only when running in a terminal
3
57
 
data/Gemfile CHANGED
@@ -1,8 +1,9 @@
1
1
  source 'https://rubygems.org'
2
2
  gemspec
3
3
 
4
- group :development do
4
+ group :development, :test do
5
5
  gem 'overcommit'
6
- gem 'rubocop', '~> 1.75.0'
6
+ gem 'rspec', '~> 3.13'
7
+ gem 'rubocop', '~> 1.85.0'
7
8
  gem 'rubocop-rake'
8
9
  end
data/Gemfile.lock ADDED
@@ -0,0 +1,198 @@
1
+ PATH
2
+ remote: .
3
+ specs:
4
+ confctl (3.0.0)
5
+ curses
6
+ gli (~> 2.22.0)
7
+ json
8
+ md2man
9
+ rainbow (~> 3.1.1)
10
+ rake
11
+ require_all (~> 2.0.0)
12
+ tty-command (~> 0.10.1)
13
+ tty-cursor (~> 0.7.1)
14
+ tty-pager (~> 0.14.0)
15
+ tty-progressbar (~> 0.18.2)
16
+ tty-spinner (~> 0.9.3)
17
+ vpsfree-client (~> 0.19.0)
18
+
19
+ GEM
20
+ remote: https://rubygems.org/
21
+ specs:
22
+ activesupport (8.1.4)
23
+ base64
24
+ bigdecimal
25
+ concurrent-ruby (~> 1.0, >= 1.3.1)
26
+ connection_pool (>= 2.2.5)
27
+ drb
28
+ i18n (>= 1.6, < 2)
29
+ json
30
+ logger (>= 1.4.2)
31
+ minitest (>= 5.1)
32
+ securerandom (>= 0.3)
33
+ tzinfo (~> 2.0, >= 2.0.5)
34
+ uri (>= 0.13.1)
35
+ ast (2.4.3)
36
+ base64 (0.3.0)
37
+ bigdecimal (4.1.3)
38
+ binman (5.1.0)
39
+ opener (>= 0.1.0, < 1)
40
+ childprocess (5.1.0)
41
+ logger (~> 1.5)
42
+ concurrent-ruby (1.3.8)
43
+ connection_pool (3.0.2)
44
+ curses (1.7.0)
45
+ diff-lcs (1.6.2)
46
+ domain_name (0.6.20260921)
47
+ drb (2.2.3)
48
+ gli (2.22.2)
49
+ ostruct
50
+ hana (1.3.7)
51
+ haveapi-client (0.29.8)
52
+ activesupport (>= 7.0)
53
+ highline (~> 3.1)
54
+ json
55
+ require_all (~> 2.0.0)
56
+ rest-client (~> 2.1.0)
57
+ ruby-progressbar (~> 1.13.0)
58
+ highline (3.1.2)
59
+ reline
60
+ http-accept (1.7.0)
61
+ http-cookie (1.1.6)
62
+ domain_name (~> 0.5)
63
+ i18n (1.15.2)
64
+ concurrent-ruby (~> 1.0)
65
+ iniparse (1.5.0)
66
+ io-console (0.9.4)
67
+ json (2.21.2)
68
+ json_schemer (2.5.0)
69
+ bigdecimal
70
+ hana (~> 1.3)
71
+ regexp_parser (~> 2.0)
72
+ simpleidn (~> 0.2)
73
+ language_server-protocol (3.17.0.6)
74
+ lint_roller (1.1.0)
75
+ logger (1.7.0)
76
+ mcp (0.25.0)
77
+ json_schemer (>= 2.4)
78
+ md2man (5.1.2)
79
+ binman (~> 5.0)
80
+ redcarpet (~> 3.0)
81
+ rouge (~> 3.0)
82
+ mime-types (3.7.0)
83
+ logger
84
+ mime-types-data (~> 3.2025, >= 3.2025.0507)
85
+ mime-types-data (3.2026.1006)
86
+ minitest (6.0.6)
87
+ drb (~> 2.0)
88
+ prism (~> 1.5)
89
+ netrc (0.11.0)
90
+ opener (0.1.0)
91
+ ostruct (0.6.3)
92
+ overcommit (0.73.0)
93
+ childprocess (>= 0.6.3, < 6)
94
+ iniparse (~> 1.4)
95
+ rexml (>= 3.4.2)
96
+ parallel (1.28.0)
97
+ parser (3.3.12.0)
98
+ ast (~> 2.4.1)
99
+ racc
100
+ pastel (0.8.0)
101
+ tty-color (~> 0.5)
102
+ prism (1.9.0)
103
+ racc (1.8.1)
104
+ rainbow (3.1.1)
105
+ rake (13.4.2)
106
+ redcarpet (3.6.1)
107
+ regexp_parser (2.13.1)
108
+ reline (0.7.0)
109
+ io-console (~> 0.5)
110
+ require_all (2.0.0)
111
+ rest-client (2.1.0)
112
+ http-accept (>= 1.7.0, < 2.0)
113
+ http-cookie (>= 1.0.2, < 2.0)
114
+ mime-types (>= 1.16, < 4.0)
115
+ netrc (~> 0.8)
116
+ rexml (3.4.4)
117
+ rouge (3.30.0)
118
+ rspec (3.13.2)
119
+ rspec-core (~> 3.13.0)
120
+ rspec-expectations (~> 3.13.0)
121
+ rspec-mocks (~> 3.13.0)
122
+ rspec-core (3.13.6)
123
+ rspec-support (~> 3.13.0)
124
+ rspec-expectations (3.13.5)
125
+ diff-lcs (>= 1.2.0, < 2.0)
126
+ rspec-support (~> 3.13.0)
127
+ rspec-mocks (3.13.8)
128
+ diff-lcs (>= 1.2.0, < 2.0)
129
+ rspec-support (~> 3.13.0)
130
+ rspec-support (3.13.7)
131
+ rubocop (1.85.1)
132
+ json (~> 2.3)
133
+ language_server-protocol (~> 3.17.0.2)
134
+ lint_roller (~> 1.1.0)
135
+ mcp (~> 0.6)
136
+ parallel (~> 1.10)
137
+ parser (>= 3.3.0.2)
138
+ rainbow (>= 2.2.2, < 4.0)
139
+ regexp_parser (>= 2.9.3, < 3.0)
140
+ rubocop-ast (>= 1.49.0, < 2.0)
141
+ ruby-progressbar (~> 1.7)
142
+ unicode-display_width (>= 2.4.0, < 4.0)
143
+ rubocop-ast (1.50.0)
144
+ parser (>= 3.3.7.2)
145
+ prism (~> 1.7)
146
+ rubocop-rake (0.7.1)
147
+ lint_roller (~> 1.1)
148
+ rubocop (>= 1.72.1)
149
+ ruby-progressbar (1.13.0)
150
+ securerandom (0.4.1)
151
+ simpleidn (0.3.0)
152
+ strings (0.2.1)
153
+ strings-ansi (~> 0.2)
154
+ unicode-display_width (>= 1.5, < 3.0)
155
+ unicode_utils (~> 1.4)
156
+ strings-ansi (0.2.0)
157
+ tty-color (0.6.0)
158
+ tty-command (0.10.1)
159
+ pastel (~> 0.8)
160
+ tty-cursor (0.7.1)
161
+ tty-pager (0.14.0)
162
+ strings (~> 0.2.0)
163
+ tty-screen (~> 0.8)
164
+ tty-progressbar (0.18.3)
165
+ strings-ansi (~> 0.2)
166
+ tty-cursor (~> 0.7)
167
+ tty-screen (~> 0.8)
168
+ unicode-display_width (>= 1.6, < 3.0)
169
+ tty-screen (0.8.2)
170
+ tty-spinner (0.9.3)
171
+ tty-cursor (~> 0.7)
172
+ tzinfo (2.0.6)
173
+ concurrent-ruby (~> 1.0)
174
+ unicode-display_width (2.6.0)
175
+ unicode_utils (1.4.0)
176
+ uri (1.1.1)
177
+ vpsadmin-client (4.2.1)
178
+ base64
179
+ curses
180
+ haveapi-client (~> 0.29.6)
181
+ json
182
+ ruby-progressbar
183
+ vpsfree-client (0.19.0)
184
+ vpsadmin-client (~> 4.0)
185
+
186
+ PLATFORMS
187
+ ruby
188
+ x86_64-linux
189
+
190
+ DEPENDENCIES
191
+ confctl!
192
+ overcommit
193
+ rspec (~> 3.13)
194
+ rubocop (~> 1.85.0)
195
+ rubocop-rake
196
+
197
+ BUNDLED WITH
198
+ 2.5.7