restic-profile-cli 0.4.0__tar.gz → 0.5.0__tar.gz

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 (140) hide show
  1. {restic_profile_cli-0.4.0 → restic_profile_cli-0.5.0}/.ansible-lint +10 -17
  2. restic_profile_cli-0.5.0/.github/dependabot.yml +19 -0
  3. restic_profile_cli-0.5.0/.github/workflows/ci.yaml +127 -0
  4. {restic_profile_cli-0.4.0 → restic_profile_cli-0.5.0}/.github/workflows/docs.yaml +16 -11
  5. restic_profile_cli-0.5.0/.github/workflows/publish-to-pypi.yaml +57 -0
  6. {restic_profile_cli-0.4.0 → restic_profile_cli-0.5.0}/.gitignore +4 -1
  7. {restic_profile_cli-0.4.0 → restic_profile_cli-0.5.0}/.pre-commit-config.yaml +6 -5
  8. restic_profile_cli-0.5.0/AGENTS.md +87 -0
  9. {restic_profile_cli-0.4.0 → restic_profile_cli-0.5.0}/CHANGELOG.md +46 -0
  10. restic_profile_cli-0.5.0/PKG-INFO +98 -0
  11. restic_profile_cli-0.5.0/README.md +73 -0
  12. restic_profile_cli-0.5.0/README.zh-CN.md +72 -0
  13. {restic_profile_cli-0.4.0 → restic_profile_cli-0.5.0}/docs/restic-profile/cli.md +2 -2
  14. {restic_profile_cli-0.4.0 → restic_profile_cli-0.5.0}/docs/restic-profile/cli.zh.md +2 -2
  15. {restic_profile_cli-0.4.0 → restic_profile_cli-0.5.0}/docs/restic-profile/examples.md +1 -1
  16. {restic_profile_cli-0.4.0 → restic_profile_cli-0.5.0}/docs/restic-profile/examples.zh.md +1 -1
  17. {restic_profile_cli-0.4.0 → restic_profile_cli-0.5.0}/docs/restic-profile/toml-config.md +2 -2
  18. {restic_profile_cli-0.4.0 → restic_profile_cli-0.5.0}/docs/restic-profile/toml-config.zh.md +2 -2
  19. {restic_profile_cli-0.4.0 → restic_profile_cli-0.5.0}/docs/restic-rest-server.md +1 -1
  20. {restic_profile_cli-0.4.0 → restic_profile_cli-0.5.0}/docs/restic-rest-server.zh.md +2 -2
  21. restic_profile_cli-0.5.0/extensions/molecule/config.yml +49 -0
  22. restic_profile_cli-0.5.0/extensions/molecule/default/create.yml +82 -0
  23. restic_profile_cli-0.5.0/extensions/molecule/default/destroy.yml +29 -0
  24. restic_profile_cli-0.5.0/extensions/molecule/default/molecule.yml +7 -0
  25. restic_profile_cli-0.5.0/extensions/molecule/inventory/group_vars/test_resources.yml +28 -0
  26. restic_profile_cli-0.5.0/extensions/molecule/inventory/hosts.yml +41 -0
  27. restic_profile_cli-0.5.0/extensions/molecule/restic_profile/basic/absent-verify.yml +38 -0
  28. restic_profile_cli-0.5.0/extensions/molecule/restic_profile/basic/cleanup.yml +21 -0
  29. restic_profile_cli-0.5.0/extensions/molecule/restic_profile/basic/converge.yml +62 -0
  30. restic_profile_cli-0.5.0/extensions/molecule/restic_profile/basic/molecule.yml +22 -0
  31. restic_profile_cli-0.5.0/extensions/molecule/restic_profile/basic/prepare.yml +31 -0
  32. restic_profile_cli-0.5.0/extensions/molecule/restic_profile/basic/verify.yml +231 -0
  33. restic_profile_cli-0.5.0/extensions/molecule/restic_profile/user_scope/absent-verify.yml +45 -0
  34. restic_profile_cli-0.5.0/extensions/molecule/restic_profile/user_scope/cleanup.yml +47 -0
  35. restic_profile_cli-0.5.0/extensions/molecule/restic_profile/user_scope/converge.yml +37 -0
  36. restic_profile_cli-0.5.0/extensions/molecule/restic_profile/user_scope/molecule.yml +20 -0
  37. restic_profile_cli-0.5.0/extensions/molecule/restic_profile/user_scope/prepare.yml +58 -0
  38. restic_profile_cli-0.5.0/extensions/molecule/restic_profile/user_scope/verify.yml +135 -0
  39. restic_profile_cli-0.5.0/extensions/molecule/restic_rest_server/basic/absent-verify.yml +63 -0
  40. restic_profile_cli-0.5.0/extensions/molecule/restic_rest_server/basic/cleanup.yml +53 -0
  41. restic_profile_cli-0.5.0/extensions/molecule/restic_rest_server/basic/converge.yml +21 -0
  42. restic_profile_cli-0.5.0/extensions/molecule/restic_rest_server/basic/molecule.yml +15 -0
  43. restic_profile_cli-0.5.0/extensions/molecule/restic_rest_server/basic/prepare.yml +5 -0
  44. restic_profile_cli-0.5.0/extensions/molecule/restic_rest_server/basic/verify.yml +113 -0
  45. restic_profile_cli-0.5.0/extensions/molecule/shared/prepare.yml +35 -0
  46. {restic_profile_cli-0.4.0 → restic_profile_cli-0.5.0}/galaxy.yml +2 -3
  47. {restic_profile_cli-0.4.0 → restic_profile_cli-0.5.0}/justfile +23 -2
  48. restic_profile_cli-0.5.0/meta/runtime.yml +2 -0
  49. {restic_profile_cli-0.4.0 → restic_profile_cli-0.5.0}/plugins/filter/restic_profile.py +4 -7
  50. {restic_profile_cli-0.4.0 → restic_profile_cli-0.5.0}/plugins/modules/systemd_timer_state.py +12 -14
  51. {restic_profile_cli-0.4.0 → restic_profile_cli-0.5.0}/pyproject.toml +9 -1
  52. {restic_profile_cli-0.4.0 → restic_profile_cli-0.5.0}/requirements.yaml +2 -0
  53. {restic_profile_cli-0.4.0 → restic_profile_cli-0.5.0}/roles/restic_profile/defaults/main.yaml +1 -1
  54. {restic_profile_cli-0.4.0 → restic_profile_cli-0.5.0}/roles/restic_profile/meta/main.yaml +6 -2
  55. {restic_profile_cli-0.4.0 → restic_profile_cli-0.5.0}/roles/restic_profile/tasks/_service_target.yaml +28 -5
  56. {restic_profile_cli-0.4.0 → restic_profile_cli-0.5.0}/roles/restic_profile/tasks/install.yaml +25 -1
  57. {restic_profile_cli-0.4.0 → restic_profile_cli-0.5.0}/roles/restic_profile/tasks/main.yaml +0 -10
  58. {restic_profile_cli-0.4.0 → restic_profile_cli-0.5.0}/roles/restic_profile/tasks/preflight.yaml +11 -0
  59. {restic_profile_cli-0.4.0 → restic_profile_cli-0.5.0}/roles/restic_profile/templates/etc/restic-profile/restic-profile.toml.j2 +49 -48
  60. {restic_profile_cli-0.4.0 → restic_profile_cli-0.5.0}/roles/restic_profile/vars/main.yaml +3 -0
  61. {restic_profile_cli-0.4.0 → restic_profile_cli-0.5.0}/roles/restic_rest_server/meta/main.yaml +6 -2
  62. {restic_profile_cli-0.4.0 → restic_profile_cli-0.5.0}/roles/restic_rest_server/tasks/install.yaml +35 -2
  63. {restic_profile_cli-0.4.0 → restic_profile_cli-0.5.0}/roles/restic_rest_server/tasks/service.yaml +10 -1
  64. {restic_profile_cli-0.4.0 → restic_profile_cli-0.5.0}/ruff.toml +3 -8
  65. {restic_profile_cli-0.4.0 → restic_profile_cli-0.5.0}/src/restic_profile/cli.py +8 -22
  66. {restic_profile_cli-0.4.0 → restic_profile_cli-0.5.0}/src/restic_profile/config.py +57 -48
  67. {restic_profile_cli-0.4.0 → restic_profile_cli-0.5.0}/src/restic_profile/notify.py +17 -13
  68. {restic_profile_cli-0.4.0 → restic_profile_cli-0.5.0}/src/restic_profile/runner.py +15 -33
  69. {restic_profile_cli-0.4.0 → restic_profile_cli-0.5.0}/src/restic_profile/templates/notify_success.md.j2 +5 -5
  70. {restic_profile_cli-0.4.0 → restic_profile_cli-0.5.0}/tests/restic_profile/test_cli.py +44 -33
  71. {restic_profile_cli-0.4.0 → restic_profile_cli-0.5.0}/tests/restic_profile/test_config.py +44 -3
  72. {restic_profile_cli-0.4.0 → restic_profile_cli-0.5.0}/tests/restic_profile/test_filters.py +26 -74
  73. {restic_profile_cli-0.4.0 → restic_profile_cli-0.5.0}/tests/restic_profile/test_notify.py +28 -7
  74. {restic_profile_cli-0.4.0 → restic_profile_cli-0.5.0}/tests/restic_profile/test_runner.py +40 -66
  75. restic_profile_cli-0.5.0/uv.lock +2149 -0
  76. restic_profile_cli-0.4.0/.devcontainer/devcontainer.json +0 -19
  77. restic_profile_cli-0.4.0/.dockerignore +0 -8
  78. restic_profile_cli-0.4.0/.github/workflows/publish-to-pypi.yaml +0 -40
  79. restic_profile_cli-0.4.0/.github/workflows/publish-to-test-pypi.yaml +0 -51
  80. restic_profile_cli-0.4.0/.prettierignore +0 -0
  81. restic_profile_cli-0.4.0/AGENTS.md +0 -51
  82. restic_profile_cli-0.4.0/Dockerfile +0 -15
  83. restic_profile_cli-0.4.0/PKG-INFO +0 -87
  84. restic_profile_cli-0.4.0/README.md +0 -63
  85. restic_profile_cli-0.4.0/README.zh-CN.md +0 -59
  86. restic_profile_cli-0.4.0/meta/runtime.yml +0 -2
  87. restic_profile_cli-0.4.0/roles/restic_profile/handlers/main.yaml +0 -5
  88. restic_profile_cli-0.4.0/roles/restic_profile/molecule/default/converge.yaml +0 -69
  89. restic_profile_cli-0.4.0/roles/restic_profile/molecule/default/molecule.yaml +0 -53
  90. restic_profile_cli-0.4.0/roles/restic_profile/molecule/default/prepare.yaml +0 -44
  91. restic_profile_cli-0.4.0/roles/restic_profile/molecule/default/verify.yaml +0 -636
  92. restic_profile_cli-0.4.0/roles/restic_profile/vars/archlinux.yml +0 -2
  93. restic_profile_cli-0.4.0/roles/restic_profile/vars/debian.yml +0 -2
  94. restic_profile_cli-0.4.0/roles/restic_profile/vars/default.yml +0 -2
  95. restic_profile_cli-0.4.0/roles/restic_profile/vars/redhat.yml +0 -2
  96. restic_profile_cli-0.4.0/roles/restic_profile/vars/suse.yml +0 -2
  97. restic_profile_cli-0.4.0/uv.lock +0 -1279
  98. {restic_profile_cli-0.4.0 → restic_profile_cli-0.5.0}/.copier-answers.yml +0 -0
  99. {restic_profile_cli-0.4.0 → restic_profile_cli-0.5.0}/.editorconfig +0 -0
  100. {restic_profile_cli-0.4.0 → restic_profile_cli-0.5.0}/.yamlfmt.yaml +0 -0
  101. {restic_profile_cli-0.4.0 → restic_profile_cli-0.5.0}/LICENSE +0 -0
  102. {restic_profile_cli-0.4.0 → restic_profile_cli-0.5.0}/ansible.cfg +0 -0
  103. {restic_profile_cli-0.4.0 → restic_profile_cli-0.5.0}/docs/ansible-toolchain.md +0 -0
  104. {restic_profile_cli-0.4.0 → restic_profile_cli-0.5.0}/docs/ansible-toolchain.zh.md +0 -0
  105. {restic_profile_cli-0.4.0 → restic_profile_cli-0.5.0}/docs/index.md +0 -0
  106. {restic_profile_cli-0.4.0 → restic_profile_cli-0.5.0}/docs/index.zh.md +0 -0
  107. {restic_profile_cli-0.4.0 → restic_profile_cli-0.5.0}/mkdocs.yml +0 -0
  108. {restic_profile_cli-0.4.0 → restic_profile_cli-0.5.0}/playbooks/go_build/restic-rest-server.yaml +0 -0
  109. {restic_profile_cli-0.4.0 → restic_profile_cli-0.5.0}/playbooks/go_build/restic.yaml +0 -0
  110. {restic_profile_cli-0.4.0 → restic_profile_cli-0.5.0}/playbooks/restic-profile.yaml +0 -0
  111. {restic_profile_cli-0.4.0 → restic_profile_cli-0.5.0}/playbooks/restic-rest-server.yaml +0 -0
  112. {restic_profile_cli-0.4.0 → restic_profile_cli-0.5.0}/roles/restic_profile/tasks/_config_target.yaml +0 -0
  113. {restic_profile_cli-0.4.0 → restic_profile_cli-0.5.0}/roles/restic_profile/tasks/_remove_target.yaml +0 -0
  114. {restic_profile_cli-0.4.0 → restic_profile_cli-0.5.0}/roles/restic_profile/tasks/cleanup_orphans.yaml +0 -0
  115. {restic_profile_cli-0.4.0 → restic_profile_cli-0.5.0}/roles/restic_profile/tasks/config.yaml +0 -0
  116. {restic_profile_cli-0.4.0 → restic_profile_cli-0.5.0}/roles/restic_profile/tasks/hooks.yaml +0 -0
  117. {restic_profile_cli-0.4.0 → restic_profile_cli-0.5.0}/roles/restic_profile/tasks/hooks_phase.yaml +0 -0
  118. {restic_profile_cli-0.4.0 → restic_profile_cli-0.5.0}/roles/restic_profile/tasks/persist_registry.yaml +0 -0
  119. {restic_profile_cli-0.4.0 → restic_profile_cli-0.5.0}/roles/restic_profile/tasks/remove.yaml +0 -0
  120. {restic_profile_cli-0.4.0 → restic_profile_cli-0.5.0}/roles/restic_profile/tasks/service.yaml +0 -0
  121. {restic_profile_cli-0.4.0 → restic_profile_cli-0.5.0}/roles/restic_profile/templates/etc/restic-profile/restic-profile.env.j2 +0 -0
  122. {restic_profile_cli-0.4.0 → restic_profile_cli-0.5.0}/roles/restic_profile/templates/etc/systemd/system/restic-profile.service.j2 +0 -0
  123. {restic_profile_cli-0.4.0 → restic_profile_cli-0.5.0}/roles/restic_profile/templates/etc/systemd/system/restic-profile.timer.j2 +0 -0
  124. {restic_profile_cli-0.4.0 → restic_profile_cli-0.5.0}/roles/restic_profile/templates/usr/local/bin/restic-profile-scope.j2 +0 -0
  125. {restic_profile_cli-0.4.0 → restic_profile_cli-0.5.0}/roles/restic_rest_server/defaults/main.yaml +0 -0
  126. {restic_profile_cli-0.4.0 → restic_profile_cli-0.5.0}/roles/restic_rest_server/files/users.htpasswd +0 -0
  127. {restic_profile_cli-0.4.0 → restic_profile_cli-0.5.0}/roles/restic_rest_server/handlers/main.yaml +0 -0
  128. {restic_profile_cli-0.4.0 → restic_profile_cli-0.5.0}/roles/restic_rest_server/tasks/main.yaml +0 -0
  129. {restic_profile_cli-0.4.0 → restic_profile_cli-0.5.0}/roles/restic_rest_server/tasks/preflight.yaml +0 -0
  130. {restic_profile_cli-0.4.0 → restic_profile_cli-0.5.0}/roles/restic_rest_server/templates/restic-rest-server.env.j2 +0 -0
  131. {restic_profile_cli-0.4.0 → restic_profile_cli-0.5.0}/roles/restic_rest_server/templates/restic-rest-server.service.j2 +0 -0
  132. {restic_profile_cli-0.4.0 → restic_profile_cli-0.5.0}/roles/restic_rest_server/vars/archlinux.yml +0 -0
  133. {restic_profile_cli-0.4.0 → restic_profile_cli-0.5.0}/roles/restic_rest_server/vars/debian.yml +0 -0
  134. {restic_profile_cli-0.4.0 → restic_profile_cli-0.5.0}/roles/restic_rest_server/vars/default.yml +0 -0
  135. {restic_profile_cli-0.4.0 → restic_profile_cli-0.5.0}/roles/restic_rest_server/vars/redhat.yml +0 -0
  136. {restic_profile_cli-0.4.0 → restic_profile_cli-0.5.0}/roles/restic_rest_server/vars/suse.yml +0 -0
  137. {restic_profile_cli-0.4.0 → restic_profile_cli-0.5.0}/src/restic_profile/__init__.py +0 -0
  138. {restic_profile_cli-0.4.0 → restic_profile_cli-0.5.0}/src/restic_profile/__main__.py +0 -0
  139. {restic_profile_cli-0.4.0 → restic_profile_cli-0.5.0}/src/restic_profile/templates/notify_failure.md.j2 +0 -0
  140. {restic_profile_cli-0.4.0 → restic_profile_cli-0.5.0}/tests/restic_profile/conftest.py +0 -0
@@ -2,11 +2,10 @@
2
2
  # ansible-lint configuration
3
3
  # https://ansible.readthedocs.io/projects/lint/configuring/
4
4
  #
5
- # Run with: ansible-lint
6
- # ansible-lint
7
-
8
- # Use the 'basic' profile - enforces the most important rules without
9
- # being overly strict for a project that is still evolving.
5
+ # Run with: ansible-lint
6
+ #
7
+ # Use the 'production' profile - the strictest built-in profile, which
8
+ # includes the checks from every lower profile as well.
10
9
  # Profiles in ascending order of strictness:
11
10
  # min → basic → moderate → safety → shared → production
12
11
  profile: production
@@ -15,13 +14,13 @@ profile: production
15
14
  exclude_paths:
16
15
  - .venv/
17
16
  - .git/
17
+ - .molecule/
18
18
  - site/
19
19
  - dist/
20
- - molecule/
21
20
  - examples/
22
21
  - playbooks/host_vars/
23
22
  - playbooks/group_vars/
24
- - mkdocs.yaml
23
+ - mkdocs.yml
25
24
 
26
25
  # Rules to warn about instead of failing on.
27
26
  # These are either stylistic preferences or rules that generate too many
@@ -38,13 +37,7 @@ warn_list:
38
37
  skip_list:
39
38
  - name[casing]
40
39
 
41
- # Lint only the paths relevant to Ansible content; ignore the Python
42
- # source tree and documentation.
43
- kinds:
44
- - playbook: "playbooks/*.yaml"
45
- - tasks: "roles/*/tasks/*.yaml"
46
- - handlers: "roles/*/handlers/*.yaml"
47
- - vars: "roles/*/vars/*.yaml"
48
- - defaults: "roles/*/defaults/*.yaml"
49
- - meta: "roles/*/meta/*.yaml"
50
- - yaml: "roles/*/molecule/**/*.yaml"
40
+ # Do not add a `kinds:` mapping back. The default kind detection already
41
+ # covers every path in this repository; remapping role `defaults/` or `vars/`
42
+ # files to a custom kind silently disables `var-naming[no-role-prefix]`, and
43
+ # remapping Molecule playbooks to the plain "yaml" kind skips playbook rules.
@@ -0,0 +1,19 @@
1
+ ---
2
+ # Keep SHA-pinned GitHub Actions and uv dependencies up to date. Version
3
+ # updates wait out a 7-day cooldown (security updates are exempt) so a
4
+ # compromised release is likely to be yanked before Dependabot opens a PR.
5
+ version: 2
6
+ updates:
7
+ - package-ecosystem: github-actions
8
+ directory: /
9
+ schedule:
10
+ interval: weekly
11
+ cooldown:
12
+ default-days: 7
13
+
14
+ - package-ecosystem: uv
15
+ directory: /
16
+ schedule:
17
+ interval: weekly
18
+ cooldown:
19
+ default-days: 7
@@ -0,0 +1,127 @@
1
+ ---
2
+ name: ci
3
+
4
+ on:
5
+ # Reusable entry point for publish-to-pypi and any future caller.
6
+ workflow_call: ~
7
+ workflow_dispatch: ~
8
+ push:
9
+ branches:
10
+ - master
11
+ - dev
12
+ pull_request:
13
+
14
+ permissions:
15
+ contents: read
16
+
17
+ concurrency:
18
+ group: ci-${{ github.workflow }}-${{ github.ref }}
19
+ cancel-in-progress: ${{ github.event_name == 'pull_request' }}
20
+
21
+ jobs:
22
+ python:
23
+ name: Python ${{ matrix.python-version }}
24
+ runs-on: ubuntu-24.04
25
+ timeout-minutes: 20
26
+ strategy:
27
+ fail-fast: false
28
+ matrix:
29
+ python-version:
30
+ - "3.11"
31
+ - "3.12"
32
+ - "3.13"
33
+ - "3.14"
34
+
35
+ steps:
36
+ - name: Check out the repository
37
+ uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1
38
+ with:
39
+ persist-credentials: false
40
+
41
+ - name: Install uv
42
+ uses: astral-sh/setup-uv@07a047e608db84b3d8c06cd9a7c7dcc9c355c18e # v10.3.2
43
+ with:
44
+ python-version: ${{ matrix.python-version }}
45
+
46
+ - name: Install the project
47
+ run: uv sync --locked --group dev
48
+
49
+ - name: Lint and format check
50
+ run: |
51
+ uv run ruff check src/ tests/ plugins/
52
+ uv run ruff format --check src/ tests/ plugins/
53
+
54
+ - name: Type check
55
+ run: uv run ty check src/ plugins/
56
+
57
+ - name: Run tests
58
+ run: uv run pytest -v tests/
59
+
60
+ - name: Build documentation
61
+ if: matrix.python-version == '3.13'
62
+ run: NO_MKDOCS_2_WARNING=1 uv run mkdocs build --strict
63
+
64
+ ansible-lint:
65
+ name: Ansible lint
66
+ runs-on: ubuntu-24.04
67
+ timeout-minutes: 20
68
+ steps:
69
+ - name: Check out the repository
70
+ uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1
71
+ with:
72
+ persist-credentials: false
73
+
74
+ - name: Install uv
75
+ uses: astral-sh/setup-uv@07a047e608db84b3d8c06cd9a7c7dcc9c355c18e # v10.3.2
76
+ with:
77
+ python-version: "3.13"
78
+
79
+ - name: Install the project
80
+ run: uv sync --locked --group dev
81
+
82
+ - name: Install the collection and scenario requirements
83
+ run: |
84
+ mkdir -p .ansible/collections
85
+ uv run ansible-galaxy collection install --force --collections-path .ansible/collections .
86
+ uv run ansible-galaxy collection install -r requirements.yaml -p .ansible/collections
87
+
88
+ - name: Run ansible-lint
89
+ run: uv run ansible-lint
90
+
91
+ molecule:
92
+ name: Molecule
93
+ runs-on: ubuntu-24.04
94
+ timeout-minutes: 60
95
+ steps:
96
+ - name: Check out the repository
97
+ uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1
98
+ with:
99
+ persist-credentials: false
100
+
101
+ - name: Install uv
102
+ uses: astral-sh/setup-uv@07a047e608db84b3d8c06cd9a7c7dcc9c355c18e # v10.3.2
103
+ with:
104
+ python-version: "3.13"
105
+
106
+ - name: Install the project
107
+ run: uv sync --locked --group dev
108
+
109
+ # Rootful Podman is required for the systemd containers (the same
110
+ # recipe as ak1ra-lab/docker-systemd). The runner needs Python and uv
111
+ # for Molecule and for the role's local wheel build.
112
+ - name: Install Podman
113
+ run: |
114
+ sudo apt-get update
115
+ sudo apt-get install -y podman
116
+
117
+ - name: Install the collection and scenario requirements
118
+ run: |
119
+ mkdir -p .ansible/collections
120
+ uv run ansible-galaxy collection install --force --collections-path .ansible/collections .
121
+ uv run ansible-galaxy collection install -r requirements.yaml -p .ansible/collections
122
+
123
+ - name: Run the Molecule scenarios
124
+ run: >-
125
+ sudo env "PATH=${PWD}/.venv/bin:${PATH}"
126
+ MOLECULE_GLOB='extensions/molecule/**/molecule.yml'
127
+ molecule test --all
@@ -8,50 +8,55 @@ on:
8
8
  - master
9
9
  paths:
10
10
  - "docs/**"
11
- - "README.md"
12
11
  - "mkdocs.yml"
13
12
  - ".github/workflows/docs.yaml"
14
13
 
15
14
  permissions:
16
15
  contents: read
17
16
 
18
- pages: write
19
- id-token: write
20
-
21
17
  concurrency:
22
18
  group: docs
23
19
  cancel-in-progress: false
24
20
 
25
21
  jobs:
26
22
  build:
27
- runs-on: ubuntu-latest
23
+ runs-on: ubuntu-24.04
24
+ timeout-minutes: 15
28
25
  steps:
29
- - uses: actions/checkout@v6
26
+ - name: Check out the repository
27
+ uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1
30
28
  with:
29
+ persist-credentials: false
31
30
  fetch-depth: 0
32
31
  fetch-tags: true
33
32
 
34
33
  - name: Install uv
35
- uses: astral-sh/setup-uv@v7
34
+ uses: astral-sh/setup-uv@07a047e608db84b3d8c06cd9a7c7dcc9c355c18e # v10.3.2
35
+ with:
36
+ python-version: "3.13"
36
37
 
37
38
  - name: Install the project
38
39
  run: uv sync --locked --group docs
39
40
 
40
41
  - name: Build documentation
41
- run: NO_MKDOCS_2_WARNING=1 uv run mkdocs build
42
+ run: NO_MKDOCS_2_WARNING=1 uv run mkdocs build --strict
42
43
 
43
44
  - name: Upload artifact
44
- uses: actions/upload-pages-artifact@v4
45
+ uses: actions/upload-pages-artifact@fc324d3547104276b827a68afc52ff2a11cc49c9 # v5.0.0
45
46
  with:
46
47
  path: site
47
48
 
48
49
  deploy:
49
50
  needs: build
50
- runs-on: ubuntu-latest
51
+ runs-on: ubuntu-24.04
52
+ timeout-minutes: 10
53
+ permissions:
54
+ pages: write
55
+ id-token: write
51
56
  environment:
52
57
  name: github-pages
53
58
  url: ${{ steps.deployment.outputs.page_url }}
54
59
  steps:
55
60
  - name: Deploy to GitHub Pages
56
61
  id: deployment
57
- uses: actions/deploy-pages@v5
62
+ uses: actions/deploy-pages@368f82528645a54fb793d4d04e342629a3f51346 # v5.0.1
@@ -0,0 +1,57 @@
1
+ ---
2
+ name: publish-to-pypi
3
+
4
+ on:
5
+ workflow_dispatch: ~
6
+ push:
7
+ tags:
8
+ - "v*"
9
+
10
+ permissions:
11
+ contents: read
12
+
13
+ jobs:
14
+ # Run the complete reusable suite (Python tests, ansible-lint, Molecule)
15
+ # before anything is uploaded.
16
+ ci:
17
+ permissions:
18
+ contents: read
19
+ # ./ is used instead of the newer $/ self-repository syntax because
20
+ # actionlint 1.7.12 (latest at the time of writing) cannot parse $/ yet.
21
+ uses: ./.github/workflows/ci.yaml
22
+
23
+ build-n-push:
24
+ name: upload release to PyPI
25
+ needs: ci
26
+ runs-on: ubuntu-24.04
27
+ timeout-minutes: 20
28
+ environment:
29
+ name: pypi
30
+ url: https://pypi.org/project/restic-profile/
31
+
32
+ permissions:
33
+ contents: read
34
+ id-token: write
35
+
36
+ steps:
37
+ - name: Check out the repository
38
+ uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1
39
+ with:
40
+ persist-credentials: false
41
+ fetch-depth: 0
42
+ fetch-tags: true
43
+
44
+ - name: Install uv
45
+ uses: astral-sh/setup-uv@07a047e608db84b3d8c06cd9a7c7dcc9c355c18e # v10.3.2
46
+ with:
47
+ python-version: "3.13"
48
+ enable-cache: false
49
+
50
+ - name: Install the project
51
+ run: uv sync --locked --group dev
52
+
53
+ - name: Build a binary wheel and a source tarball
54
+ run: uv build -v
55
+
56
+ - name: Publish package distributions to PyPI
57
+ uses: pypa/gh-action-pypi-publish@7245906fb61fa33a13554f9d5fb856fe61758086 # v1.14.3
@@ -327,6 +327,7 @@ __marimo__/
327
327
 
328
328
  # Ansible
329
329
  .ansible/*
330
+ .molecule/
330
331
  inventory/*.yaml
331
332
  playbooks/host_vars/**/*.yaml
332
333
  playbooks/group_vars/**/*.yaml
@@ -351,6 +352,8 @@ credentials.yaml
351
352
  examples/*
352
353
 
353
354
  ## LLM
354
- docs/sessions/*
355
+ .agents/sessions/*
355
356
  .agents/state/sessions/*
356
357
  .antigravitycli/*
358
+ .opencode/
359
+ openspec/
@@ -28,14 +28,14 @@ repos:
28
28
  - id: trailing-whitespace
29
29
 
30
30
  - repo: https://github.com/astral-sh/ruff-pre-commit
31
- rev: v0.15.20
31
+ rev: v0.17.2
32
32
  hooks:
33
33
  - id: ruff-check
34
34
  args: [--fix]
35
35
  - id: ruff-format
36
36
 
37
37
  - repo: https://github.com/astral-sh/uv-pre-commit
38
- rev: 0.11.27
38
+ rev: 0.12.10
39
39
  hooks:
40
40
  - id: uv-lock
41
41
 
@@ -43,15 +43,16 @@ repos:
43
43
  hooks:
44
44
  - id: ty
45
45
  name: ty
46
- entry: uv run ty check
46
+ entry: uv run ty check src/ plugins/
47
47
  language: system
48
- files: ^src/
48
+ files: ^(src|plugins)/
49
49
  types_or: [python, pyi]
50
+ pass_filenames: false
50
51
  require_serial: true
51
52
 
52
53
  - id: ansible-lint
53
54
  name: ansible-lint
54
- entry: ansible-lint
55
+ entry: uv run ansible-lint
55
56
  language: system
56
57
  types: [yaml]
57
58
  require_serial: true
@@ -0,0 +1,87 @@
1
+ # AGENTS.md
2
+
3
+ `restic-profile` = a Python CLI (`src/restic_profile/`, tests mirror it under
4
+ `tests/`) plus Ansible roles (`roles/restic_profile`, `roles/restic_rest_server`).
5
+ See `README.md` for the deployment workflow.
6
+
7
+ ## Tooling - use these, not the defaults
8
+
9
+ `just <recipe>` is a convenience wrapper for humans; each recipe is a thin
10
+ `uv run ...` (see `justfile`). Agents can call `uv run ...` directly when that is
11
+ more flexible - the two are equivalent, not mutually exclusive.
12
+
13
+ - Env/deps: **uv** (`just sync` = `uv sync --group dev`). Never `pip`/`poetry`/`pipenv`.
14
+ The `dev` group includes the Ansible toolchain (`ansible-core`, `ansible-lint`,
15
+ `molecule`).
16
+ - Lint+format: **ruff** (`just lint` = `uv run ruff check --fix` then
17
+ `uv run ruff format`, over `src/ tests/ plugins/`). Never `black`/`isort`/`flake8`.
18
+ - Typecheck: **ty** (astral-sh/ty), `src/ plugins/` only
19
+ (`just typecheck` = `uv run ty check src/ plugins/`). Never `mypy`.
20
+ - Tests: **pytest**. `just test *ARGS` = `uv run pytest -v {{ARGS}} tests/` - ARGS
21
+ go *before* `tests/`, so `just test -k <pattern>`. Or run
22
+ `uv run pytest -v tests/test_file.py` directly.
23
+ - Ansible lint: `just ansible-lint` (installs the collection and requirements
24
+ first, then runs `uv run ansible-lint`).
25
+ - Molecule: `just molecule-test` / `just molecule-test-one <scenario>` /
26
+ `just molecule-list` (see Testing below).
27
+ - Docs: `just docs-build` = `NO_MKDOCS_2_WARNING=1 uv run mkdocs build`.
28
+ - Build: `just build` = `uv build`.
29
+
30
+ Python changes MUST pass lint, typecheck, and test before commit.
31
+
32
+ ## Ansible (self-contained layout)
33
+
34
+ `ansible.cfg` pins `roles_path=./roles` and `collections_path=./.ansible/collections`
35
+ so role and collection resolution never reaches user-level/parent paths. The
36
+ inventory path still includes `~/.ansible/inventory` by design. Playbooks
37
+ reference roles by FQCN (`ak1ra_lab.restic_profile.*`). Before running
38
+ `ansible-lint` or any playbook, install the dependencies into the project-local
39
+ tree:
40
+
41
+ ```shell
42
+ ansible-galaxy collection install -r requirements.yaml -p ./.ansible/collections
43
+ ```
44
+
45
+ - `requirements.yaml` deps: `ansible.posix`, `community.general`,
46
+ `containers.podman`, `community.docker`, and `ak1ra_lab.general` (not on
47
+ Galaxy, pulled from git).
48
+ - `ansible-lint` (non-`offline` mode, run from repo root) auto-installs
49
+ `requirements.yaml` into its own cache dir `./.ansible/collections` - computed
50
+ by ansible-compat from the project dir, ignoring `ansible.cfg`'s `collections_path`.
51
+
52
+ Ansible changes MUST pass `ansible-lint` before commit.
53
+
54
+ ## Testing (Molecule)
55
+
56
+ Ansible behavior is covered by ansible-native Molecule scenarios under
57
+ `extensions/molecule/` (collection layout; the old role-level legacy scenario
58
+ has been removed).
59
+
60
+ - `config.yml` - shared config: test inventory, project-local collections path,
61
+ `shared_state: true`, and the component test sequence.
62
+ - `default/` - the only lifecycle manager (`create` / `destroy`); it creates the
63
+ shared systemd containers from `ghcr.io/ak1ra-lab/docker-systemd`.
64
+ - `restic_profile/basic` - system-scope backup and retention-only profiles on
65
+ Debian 13, Ubuntu 26.04, Rocky 10, and Fedora 44.
66
+ - `restic_profile/user_scope` - user-scope timer on Debian 13, including the
67
+ PAM/linger prerequisites for the per-user systemd manager.
68
+ - `restic_rest_server/basic` - Debian package deployment, htpasswd auth, and
69
+ explicit test teardown.
70
+
71
+ Prerequisites: `just ansible-collection-install` and
72
+ `just ansible-requirements-install`, plus `uv` and a container runtime
73
+ (rootless Podman works; CI uses rootful Podman). The container images and
74
+ supported host matrix are documented in `extensions/molecule/inventory/`.
75
+ Role, task, or template changes SHOULD pass the relevant Molecule scenario;
76
+ run the full suite before a release. Molecule caches scenario state: after
77
+ changing a `molecule.yml`, run `uv run molecule reset` (or `molecule destroy`)
78
+ so prepare/create are re-run. A distro is eligible for the matrix only when
79
+ its image's bundled Python satisfies the project's `>=3.11` floor; drop the
80
+ distro instead of installing a newer Python next to it.
81
+
82
+ ## Docs (bilingual)
83
+
84
+ `docs/` is served by mkdocs with the i18n plugin (`docs_structure: suffix`):
85
+ every page has an English `*.md` and a Simplified-Chinese `*.zh.md` sibling
86
+ (e.g. `cli.md` + `cli.zh.md`). When adding or changing user-facing behavior,
87
+ update BOTH language files.
@@ -5,6 +5,52 @@ All notable changes to this project will be documented in this file.
5
5
  The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/),
6
6
  and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
7
7
 
8
+ ## [0.5.0] - 2026-10-24
9
+
10
+ ### Added
11
+
12
+ - Add Python 3.14 to the published package classifiers
13
+ - Validate `restic_profile_state` against `present`/`absent` during preflight
14
+ - Create the `restic_rest_server_backup_dir` storage root with service-user
15
+ ownership before starting `rest-server`
16
+
17
+ ### Changed
18
+
19
+ - Limit the official distribution matrix to the latest tested releases:
20
+ Debian 13, Ubuntu 26.04, Rocky Linux 10, and Fedora 44; drop EL 9 and
21
+ Fedora 43 from the role metadata
22
+ - Raise the minimum supported `ansible-core` version to 2.18
23
+ - Escape user-provided values when rendering `restic-profile.toml` so quotes,
24
+ backslashes, and newlines in credentials or paths produce valid TOML
25
+ - Treat notification delivery as best-effort: transport errors are logged and
26
+ no longer mask the backup or retention result
27
+ - Use `module.run_command` in the `systemd_timer_state` module instead of
28
+ calling `subprocess` directly
29
+
30
+ ### Removed
31
+
32
+ - Remove the Test PyPI publishing workflow and its README badge
33
+
34
+ ### Fixed
35
+
36
+ - Accept the required profile name with `--unlock` instead of rejecting the
37
+ combination as invalid
38
+ - Keep `--unlock` in dry-run mode when `--dry-run notify` is used
39
+ - Report inline retention failures as retention failures instead of backup
40
+ failures
41
+ - Stop active timers before `daemon-reload` when their scheduling changes
42
+ - Align package-cache refresh and platform metadata across all supported
43
+ distributions
44
+ - Reject unknown keys in the TOML configuration instead of silently ignoring
45
+ them
46
+
47
+ ## [0.4.1] - 2026-08-11
48
+
49
+ ### Changed
50
+
51
+ - Update the built-in `notify_success.md.j2` template formatting for headings
52
+ and diff summary list items
53
+
8
54
  ## [0.4.0] - 2026-08-11
9
55
 
10
56
  ### Added
@@ -0,0 +1,98 @@
1
+ Metadata-Version: 2.5
2
+ Name: restic-profile-cli
3
+ Version: 0.5.0
4
+ Summary: Profile-based restic wrapper with Ansible deployment support
5
+ Project-URL: Homepage, https://github.com/ak1ra-lab/restic-profile
6
+ Project-URL: Repository, https://github.com/ak1ra-lab/restic-profile
7
+ Project-URL: Documentation, https://ak1ra-lab.github.io/restic-profile/
8
+ Author-email: ak1ra <git@ak1ra.xyz>
9
+ License-Expression: MIT
10
+ License-File: LICENSE
11
+ Keywords: ansible,backup,restic
12
+ Classifier: Development Status :: 4 - Beta
13
+ Classifier: Programming Language :: Python :: 3
14
+ Classifier: Programming Language :: Python :: 3 :: Only
15
+ Classifier: Programming Language :: Python :: 3.11
16
+ Classifier: Programming Language :: Python :: 3.12
17
+ Classifier: Programming Language :: Python :: 3.13
18
+ Classifier: Programming Language :: Python :: 3.14
19
+ Requires-Python: >=3.11
20
+ Requires-Dist: argcomplete>=3.7.0
21
+ Requires-Dist: chaos-utils>=0.5.0
22
+ Requires-Dist: jinja2>=3.1.2
23
+ Requires-Dist: pydantic>=2.13.3
24
+ Description-Content-Type: text/markdown
25
+
26
+ # restic-profile
27
+
28
+ **English** | [简体中文](https://github.com/ak1ra-lab/restic-profile/blob/master/README.zh-CN.md)
29
+
30
+ [![GitHub Actions Workflow Status](https://img.shields.io/github/actions/workflow/status/ak1ra-lab/restic-profile/.github%2Fworkflows%2Fpublish-to-pypi.yaml)](https://github.com/ak1ra-lab/restic-profile/actions/workflows/publish-to-pypi.yaml)
31
+ [![PyPI - Version](https://img.shields.io/pypi/v/restic-profile-cli)](https://pypi.org/project/restic-profile-cli/)
32
+ [![Docs](https://img.shields.io/badge/docs-online-0a7ea4)](https://ak1ra-lab.github.io/restic-profile/)
33
+
34
+ Profile-based [restic](https://restic.net/) wrapper, deployed with Ansible.
35
+
36
+ This repository is an Ansible collection (`ak1ra_lab.restic_profile`) plus the
37
+ `restic-profile` CLI it installs:
38
+
39
+ - **restic-profile** - reads a TOML config and runs `restic backup` / `forget` /
40
+ `prune` with hooks and IM notifications.
41
+ - **restic_profile** role - deploys the CLI, renders the TOML config, and manages
42
+ one systemd timer per profile (including user-level `systemd_scope: user`).
43
+ - **restic_rest_server** role - deploys a [rest-server](https://github.com/restic/rest-server)
44
+ instance for remote backup storage.
45
+
46
+ ## Install the CLI
47
+
48
+ Install the CLI on its own - Ansible, root, and systemd are not needed. `restic`
49
+ must be installed and on `PATH`:
50
+
51
+ ```shell
52
+ uv tool install restic-profile-cli
53
+ restic-profile --help
54
+ ```
55
+
56
+ Start from the [TOML config template][toml].
57
+
58
+ ## Deploy with Ansible
59
+
60
+ ```shell
61
+ git clone https://github.com/ak1ra-lab/restic-profile.git
62
+ cd restic-profile
63
+ ansible-galaxy collection install -r requirements.yaml -p ./.ansible/collections
64
+ ansible-galaxy collection install --force --collections-path .ansible/collections .
65
+ ```
66
+
67
+ Pick an example from [Ansible examples][examples], fill in your `host_vars`, and
68
+ run the playbook. See [Ansible toolchain][toolchain] for the control-node setup;
69
+ building restic from source (`restic_profile_restic_install_source: go_build`)
70
+ also needs a `go` toolchain.
71
+
72
+ ## Documentation
73
+
74
+ Full documentation: <https://ak1ra-lab.github.io/restic-profile/>
75
+
76
+ - [Ansible examples][examples]
77
+ - [TOML config template][toml]
78
+ - [CLI reference][cli]
79
+ - [restic-rest-server][server]
80
+ - [Ansible toolchain][toolchain]
81
+
82
+ ## Development
83
+
84
+ ```shell
85
+ uv sync --group dev
86
+ just lint
87
+ just typecheck
88
+ just test
89
+ ```
90
+
91
+ See [AGENTS.md](https://github.com/ak1ra-lab/restic-profile/blob/master/AGENTS.md)
92
+ for the Ansible, Molecule, and documentation workflow.
93
+
94
+ [examples]: https://ak1ra-lab.github.io/restic-profile/restic-profile/examples/
95
+ [toml]: https://ak1ra-lab.github.io/restic-profile/restic-profile/toml-config/
96
+ [cli]: https://ak1ra-lab.github.io/restic-profile/restic-profile/cli/
97
+ [server]: https://ak1ra-lab.github.io/restic-profile/restic-rest-server/
98
+ [toolchain]: https://ak1ra-lab.github.io/restic-profile/ansible-toolchain/