mirror of
https://github.com/borgmatic-collective/borgmatic.git
synced 2026-07-25 19:23:00 +02:00
Compare commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
fd59776f91 | ||
|
|
9fd28d2eed | ||
|
|
f5c61c8013 | ||
|
|
88cb49dcc4 | ||
|
|
73235e59be | ||
|
|
7076a7ff86 | ||
|
|
d6e376d32d | ||
|
|
9016f4be43 | ||
|
|
d543109ef4 | ||
|
|
7085a45649 | ||
|
|
cf4c603f1d | ||
|
|
c43b50b6e6 | ||
|
|
c072678936 | ||
|
|
631da1465e | ||
|
|
f29519a5cd | ||
|
|
5d82b42ab8 | ||
|
|
4897a78fd3 | ||
|
|
a1d986d952 | ||
|
|
717c90a7d0 | ||
|
|
8fde19a7dc | ||
|
|
ad7198ba66 | ||
|
|
eb4b4cc92b | ||
|
|
41bf520585 | ||
|
|
c0ae01f5d5 | ||
|
|
8b8f92d717 | ||
|
|
ccd1627175 | ||
|
|
b8a7e23f46 | ||
|
|
1f4f28b4dc | ||
|
|
ea6cd53067 | ||
|
|
267138776d |
+13
-56
@@ -1,10 +1,10 @@
|
||||
---
|
||||
kind: pipeline
|
||||
name: python-3-5-alpine-3-10
|
||||
name: python-3-6-alpine-3-9
|
||||
|
||||
services:
|
||||
- name: postgresql
|
||||
image: postgres:11.6-alpine
|
||||
image: postgres:11.9-alpine
|
||||
environment:
|
||||
POSTGRES_PASSWORD: test
|
||||
POSTGRES_DB: test
|
||||
@@ -16,29 +16,7 @@ services:
|
||||
|
||||
steps:
|
||||
- name: build
|
||||
image: python:3.5-alpine3.10
|
||||
pull: always
|
||||
commands:
|
||||
- scripts/run-full-tests
|
||||
---
|
||||
kind: pipeline
|
||||
name: python-3-6-alpine-3-10
|
||||
|
||||
services:
|
||||
- name: postgresql
|
||||
image: postgres:11.6-alpine
|
||||
environment:
|
||||
POSTGRES_PASSWORD: test
|
||||
POSTGRES_DB: test
|
||||
- name: mysql
|
||||
image: mariadb:10.3
|
||||
environment:
|
||||
MYSQL_ROOT_PASSWORD: test
|
||||
MYSQL_DATABASE: test
|
||||
|
||||
steps:
|
||||
- name: build
|
||||
image: python:3.6-alpine3.10
|
||||
image: alpine:3.9
|
||||
pull: always
|
||||
commands:
|
||||
- scripts/run-full-tests
|
||||
@@ -48,7 +26,7 @@ name: python-3-7-alpine-3-10
|
||||
|
||||
services:
|
||||
- name: postgresql
|
||||
image: postgres:11.6-alpine
|
||||
image: postgres:11.9-alpine
|
||||
environment:
|
||||
POSTGRES_PASSWORD: test
|
||||
POSTGRES_DB: test
|
||||
@@ -60,51 +38,29 @@ services:
|
||||
|
||||
steps:
|
||||
- name: build
|
||||
image: python:3.7-alpine3.10
|
||||
image: alpine:3.10
|
||||
pull: always
|
||||
commands:
|
||||
- scripts/run-full-tests
|
||||
---
|
||||
kind: pipeline
|
||||
name: python-3-7-alpine-3-7
|
||||
name: python-3-8-alpine-3-13
|
||||
|
||||
services:
|
||||
- name: postgresql
|
||||
image: postgres:10.11-alpine
|
||||
image: postgres:13.1-alpine
|
||||
environment:
|
||||
POSTGRES_PASSWORD: test
|
||||
POSTGRES_DB: test
|
||||
- name: mysql
|
||||
image: mariadb:10.1
|
||||
image: mariadb:10.5
|
||||
environment:
|
||||
MYSQL_ROOT_PASSWORD: test
|
||||
MYSQL_DATABASE: test
|
||||
|
||||
steps:
|
||||
- name: build
|
||||
image: python:3.7-alpine3.7
|
||||
pull: always
|
||||
commands:
|
||||
- scripts/run-full-tests
|
||||
---
|
||||
kind: pipeline
|
||||
name: python-3-8-alpine-3-10
|
||||
|
||||
services:
|
||||
- name: postgresql
|
||||
image: postgres:11.6-alpine
|
||||
environment:
|
||||
POSTGRES_PASSWORD: test
|
||||
POSTGRES_DB: test
|
||||
- name: mysql
|
||||
image: mariadb:10.3
|
||||
environment:
|
||||
MYSQL_ROOT_PASSWORD: test
|
||||
MYSQL_DATABASE: test
|
||||
|
||||
steps:
|
||||
- name: build
|
||||
image: python:3.8-alpine3.10
|
||||
image: alpine:3.13
|
||||
pull: always
|
||||
commands:
|
||||
- scripts/run-full-tests
|
||||
@@ -122,6 +78,7 @@ steps:
|
||||
from_secret: docker_password
|
||||
repo: witten/borgmatic-docs
|
||||
dockerfile: docs/Dockerfile
|
||||
when:
|
||||
branch:
|
||||
- master
|
||||
|
||||
trigger:
|
||||
branch:
|
||||
- master
|
||||
|
||||
@@ -1,3 +1,25 @@
|
||||
1.5.14
|
||||
* #390: Add link to Hetzner storage offering from the documentation.
|
||||
* #398: Clarify canonical home of borgmatic in documentation.
|
||||
* #406: Clarify that spaces in path names should not be backslashed in path names.
|
||||
* #423: Fix error handling to error loudly when Borg gets killed due to running out of memory!
|
||||
* Fix build so as not to attempt to build and push documentation for a non-master branch.
|
||||
* "Fix" build failure with Alpine Edge by switching from Edge to Alpine 3.13.
|
||||
* Move #borgmatic IRC channel from Freenode to Libera Chat due to Freenode takeover drama.
|
||||
IRC connection info: https://torsion.org/borgmatic/#issues
|
||||
|
||||
1.5.13
|
||||
* #373: Document that passphrase is used for Borg keyfile encryption, not just repokey encryption.
|
||||
* #404: Add support for ruamel.yaml 0.17.x YAML parsing library.
|
||||
* Update systemd service example to return a permission error when a system call isn't permitted
|
||||
(instead of terminating borgmatic outright).
|
||||
* Drop support for Python 3.5, which has been end-of-lifed.
|
||||
* Add support for Python 3.9.
|
||||
* Update versions of test dependencies (test_requirements.txt and test containers).
|
||||
* Only support black code formatter on Python 3.8+. New black dependencies make installation
|
||||
difficult on older versions of Python.
|
||||
* Replace "improve this documentation" form with link to support and ticket tracker.
|
||||
|
||||
1.5.12
|
||||
* Fix for previous release with incorrect version suffix in setup.py. No other changes.
|
||||
|
||||
|
||||
@@ -11,6 +11,8 @@ borgmatic is simple, configuration-driven backup software for servers and
|
||||
workstations. Protect your files with client-side encryption. Backup your
|
||||
databases too. Monitor it all with integrated third-party services.
|
||||
|
||||
The canonical home of borgmatic is at <a href="https://torsion.org/borgmatic">https://torsion.org/borgmatic</a>.
|
||||
|
||||
Here's an example configuration file:
|
||||
|
||||
```yaml
|
||||
@@ -84,10 +86,10 @@ reference guides</a>.
|
||||
|
||||
## Hosting providers
|
||||
|
||||
Need somewhere to store your encrypted offsite backups? The following hosting
|
||||
providers include specific support for Borg/borgmatic. Using these links and
|
||||
services helps support borgmatic development and hosting. (These are referral
|
||||
links, but without any tracking scripts or cookies.)
|
||||
Need somewhere to store your encrypted off-site backups? The following hosting
|
||||
providers include specific support for Borg/borgmatic—and fund borgmatic
|
||||
development and hosting when you use these links to sign up. (These are
|
||||
referral links, but without any tracking scripts or cookies.)
|
||||
|
||||
<ul>
|
||||
<li class="referral"><a href="https://www.rsync.net/cgi-bin/borg.cgi?campaign=borg&adgroup=borgmatic">rsync.net</a>: Cloud Storage provider with full support for borg and any other SSH/SFTP tool</li>
|
||||
@@ -95,6 +97,10 @@ links, but without any tracking scripts or cookies.)
|
||||
<li class="referral"><a href="https://storage.lima-labs.com/special-pricing-offer-for-borgmatic-users/">Lima-Labs</a>: Affordable, reliable cloud data storage accessable via SSH/SCP/FTP for Borg backups or any other bulk storage needs</li>
|
||||
</ul>
|
||||
|
||||
Additionally, [Hetzner](https://www.hetzner.com/storage/storage-box) has a
|
||||
compatible storage offering, but does not currently fund borgmatic
|
||||
development or hosting.
|
||||
|
||||
## Support and contributing
|
||||
|
||||
### Issues
|
||||
@@ -106,9 +112,11 @@ first](https://projects.torsion.org/user/login). Note that you can login with
|
||||
an existing GitHub account if you prefer.
|
||||
|
||||
If you'd like to chat with borgmatic developers or users, head on over to the
|
||||
`#borgmatic` IRC channel on Freenode, either via <a
|
||||
href="https://webchat.freenode.net/?channels=borgmatic">web chat</a> or a
|
||||
native <a href="irc://chat.freenode.net:6697">IRC client</a>.
|
||||
`#borgmatic` IRC channel on Libera Chat, either via <a
|
||||
href="https://web.libera.chat/#borgmatic">web chat</a> or a
|
||||
native <a href="ircs://irc.libera.chat:6697">IRC client</a>. If you
|
||||
don't get a response right away, please hang around a while—or file a ticket
|
||||
instead.
|
||||
|
||||
Also see the [security
|
||||
policy](https://torsion.org/borgmatic/docs/security-policy/) for any security
|
||||
@@ -120,9 +128,9 @@ Other questions or comments? Contact
|
||||
|
||||
### Contributing
|
||||
|
||||
borgmatic is hosted at <https://torsion.org/borgmatic> with [source code
|
||||
available](https://projects.torsion.org/witten/borgmatic), and is also
|
||||
mirrored on [GitHub](https://github.com/witten/borgmatic) for convenience.
|
||||
borgmatic [source code is
|
||||
available](https://projects.torsion.org/witten/borgmatic) and is also mirrored
|
||||
on [GitHub](https://github.com/witten/borgmatic) for convenience.
|
||||
|
||||
borgmatic is licensed under the GNU General Public License version 3 or any
|
||||
later version.
|
||||
|
||||
@@ -15,11 +15,12 @@ map:
|
||||
- type: str
|
||||
desc: |
|
||||
List of source directories to backup (required). Globs and
|
||||
tildes are expanded.
|
||||
tildes are expanded. Do not backslash spaces in path names.
|
||||
example:
|
||||
- /home
|
||||
- /etc
|
||||
- /var/log/syslog*
|
||||
- /home/user/path with spaces
|
||||
repositories:
|
||||
required: true
|
||||
seq:
|
||||
@@ -123,12 +124,14 @@ map:
|
||||
- type: str
|
||||
desc: |
|
||||
Any paths matching these patterns are excluded from backups.
|
||||
Globs and tildes are expanded. See the output of "borg help
|
||||
patterns" for more details.
|
||||
Globs and tildes are expanded. Do not backslash spaces in
|
||||
path names. See the output of "borg help patterns" for more
|
||||
details.
|
||||
example:
|
||||
- '*.pyc'
|
||||
- /home/*/.cache
|
||||
- /etc/ssl
|
||||
- /home/user/path with spaces
|
||||
exclude_from:
|
||||
seq:
|
||||
- type: str
|
||||
@@ -185,19 +188,20 @@ map:
|
||||
desc: |
|
||||
The standard output of this command is used to unlock the
|
||||
encryption key. Only use on repositories that were
|
||||
initialized with passcommand/repokey encryption. Note that
|
||||
if both encryption_passcommand and encryption_passphrase are
|
||||
set, then encryption_passphrase takes precedence. Defaults
|
||||
to not set.
|
||||
initialized with passcommand/repokey/keyfile encryption.
|
||||
Note that if both encryption_passcommand and
|
||||
encryption_passphrase are set, then encryption_passphrase
|
||||
takes precedence. Defaults to not set.
|
||||
example: "secret-tool lookup borg-repository repo-name"
|
||||
encryption_passphrase:
|
||||
type: str
|
||||
desc: |
|
||||
Passphrase to unlock the encryption key with. Only use on
|
||||
repositories that were initialized with passphrase/repokey
|
||||
encryption. Quote the value if it contains punctuation, so
|
||||
it parses correctly. And backslash any quote or backslash
|
||||
literals as well. Defaults to not set.
|
||||
repositories that were initialized with
|
||||
passphrase/repokey/keyfile encryption. Quote the value if it
|
||||
contains punctuation, so it parses correctly. And backslash
|
||||
any quote or backslash literals as well. Defaults to not
|
||||
set.
|
||||
example: "!\"#$%&'()*+,-./:;<=>?@[\\]^_`{|}~"
|
||||
checkpoint_interval:
|
||||
type: int
|
||||
|
||||
@@ -23,7 +23,7 @@ def exit_code_indicates_error(process, exit_code, borg_local_path=None):
|
||||
command = process.args.split(' ') if isinstance(process.args, str) else process.args
|
||||
|
||||
if borg_local_path and command[0] == borg_local_path:
|
||||
return bool(exit_code >= BORG_ERROR_EXIT_CODE)
|
||||
return bool(exit_code < 0 or exit_code >= BORG_ERROR_EXIT_CODE)
|
||||
|
||||
return bool(exit_code != 0)
|
||||
|
||||
|
||||
+3
-3
@@ -1,4 +1,4 @@
|
||||
FROM python:3.8.1-alpine3.11 as borgmatic
|
||||
FROM python:3.8-alpine3.12 as borgmatic
|
||||
|
||||
COPY . /app
|
||||
RUN pip install --no-cache /app && generate-borgmatic-config && chmod +r /etc/borgmatic/config.yaml
|
||||
@@ -7,7 +7,7 @@ RUN borgmatic --help > /command-line.txt \
|
||||
echo -e "\n--------------------------------------------------------------------------------\n" >> /command-line.txt \
|
||||
&& borgmatic "$action" --help >> /command-line.txt; done
|
||||
|
||||
FROM node:13.7.0-alpine as html
|
||||
FROM node:15.2.1-alpine as html
|
||||
|
||||
ARG ENVIRONMENT=production
|
||||
|
||||
@@ -26,7 +26,7 @@ COPY . /source
|
||||
RUN NODE_ENV=${ENVIRONMENT} npx eleventy --input=/source/docs --output=/output/docs \
|
||||
&& mv /output/docs/index.html /output/index.html
|
||||
|
||||
FROM nginx:1.16.1-alpine
|
||||
FROM nginx:1.19.4-alpine
|
||||
|
||||
COPY --from=html /output /usr/share/nginx/html
|
||||
COPY --from=borgmatic /etc/borgmatic/config.yaml /usr/share/nginx/html/docs/reference/config.yaml
|
||||
|
||||
@@ -1,18 +0,0 @@
|
||||
#suggestion-form textarea {
|
||||
font-family: sans-serif;
|
||||
width: 100%;
|
||||
}
|
||||
|
||||
#suggestion-form label {
|
||||
font-weight: bold;
|
||||
}
|
||||
|
||||
#suggestion-form input[type=email] {
|
||||
font-size: 16px;
|
||||
width: 100%;
|
||||
}
|
||||
|
||||
#suggestion-form .form-error {
|
||||
color: red;
|
||||
}
|
||||
|
||||
@@ -1,33 +0,0 @@
|
||||
<h2>Improve this documentation</h2>
|
||||
|
||||
<p>Have an idea on how to make this documentation even better? Send your
|
||||
feedback below! But if you need help with borgmatic, or have an idea for a
|
||||
borgmatic feature, please use our <a href="https://torsion.org/borgmatic/#issues">issue
|
||||
tracker</a> instead.</p>
|
||||
|
||||
<form id="suggestion-form">
|
||||
<div><label for="suggestion">Documentation suggestion</label></div>
|
||||
<textarea id="suggestion" rows="8" cols="60" name="suggestion"></textarea>
|
||||
<div data-sk-error="suggestion" class="form-error"></div>
|
||||
<input id="_page" type="hidden" name="_page">
|
||||
<input id="_subject" type="hidden" name="_subject" value="borgmatic documentation suggestion">
|
||||
<br />
|
||||
<label for="email">Email address</label>
|
||||
<div><input id="email" type="email" name="email" placeholder="Only required if you want a response!"></div>
|
||||
<div data-sk-error="email" class="form-error"></div>
|
||||
<br />
|
||||
<div><button type="submit">Send</button></div>
|
||||
<br />
|
||||
</form>
|
||||
|
||||
<script>
|
||||
document.getElementById('_page').value = window.location.href;
|
||||
window.sk=window.sk||function(){(sk.q=sk.q||[]).push(arguments)};
|
||||
|
||||
sk('form', 'init', {
|
||||
id: '1d536680ab96',
|
||||
element: '#suggestion-form'
|
||||
});
|
||||
</script>
|
||||
|
||||
<script defer src="https://js.statickit.com/statickit.js"></script>
|
||||
@@ -0,0 +1,17 @@
|
||||
<h2>Improve this documentation</h2>
|
||||
|
||||
<p>Have an idea on how to make this documentation even better? Use our <a
|
||||
href="https://projects.torsion.org/witten/borgmatic/issues">issue tracker</a> to send your
|
||||
feedback!</p>
|
||||
|
||||
<script>
|
||||
document.getElementById('_page').value = window.location.href;
|
||||
window.sk=window.sk||function(){(sk.q=sk.q||[]).push(arguments)};
|
||||
|
||||
sk('form', 'init', {
|
||||
id: '1d536680ab96',
|
||||
element: '#suggestion-form'
|
||||
});
|
||||
</script>
|
||||
|
||||
<script defer src="https://js.statickit.com/statickit.js"></script>
|
||||
@@ -11,7 +11,6 @@
|
||||
{% include 'components/minilink.css' %}
|
||||
{% include 'components/toc.css' %}
|
||||
{% include 'components/info-blocks.css' %}
|
||||
{% include 'components/suggestion-form.css' %}
|
||||
{% include 'prism-theme.css' %}
|
||||
{% include 'asciinema.css' %}
|
||||
{% endset %}
|
||||
|
||||
@@ -28,5 +28,5 @@ headerClass: elv-header-default
|
||||
|
||||
{{ content | safe }}
|
||||
|
||||
{% include 'components/suggestion-form.html' %}
|
||||
{% include 'components/suggestion-link.html' %}
|
||||
</main>
|
||||
|
||||
@@ -68,7 +68,7 @@ sudo pip3 install --upgrade borgmatic
|
||||
|
||||
The main downside of a global install is that borgmatic is less cleanly
|
||||
separated from the rest of your Python software, and there's the theoretical
|
||||
possibility of libary conflicts. But if you're okay with that, for instance
|
||||
possibility of library conflicts. But if you're okay with that, for instance
|
||||
on a relatively dedicated system, then a global install can work out fine.
|
||||
|
||||
|
||||
@@ -93,10 +93,10 @@ installing borgmatic:
|
||||
|
||||
## Hosting providers
|
||||
|
||||
Need somewhere to store your encrypted offsite backups? The following hosting
|
||||
providers include specific support for Borg/borgmatic. Using these links and
|
||||
services helps support borgmatic development and hosting. (These are referral
|
||||
links, but without any tracking scripts or cookies.)
|
||||
Need somewhere to store your encrypted off-site backups? The following hosting
|
||||
providers include specific support for Borg/borgmatic—and fund borgmatic
|
||||
development and hosting when you use these links to sign up. (These are
|
||||
referral links, but without any tracking scripts or cookies.)
|
||||
|
||||
<ul>
|
||||
<li class="referral"><a href="https://www.rsync.net/cgi-bin/borg.cgi?campaign=borg&adgroup=borgmatic">rsync.net</a>: Cloud Storage provider with full support for borg and any other SSH/SFTP tool</li>
|
||||
@@ -104,6 +104,10 @@ links, but without any tracking scripts or cookies.)
|
||||
<li class="referral"><a href="https://storage.lima-labs.com/special-pricing-offer-for-borgmatic-users/">Lima-Labs</a>: Affordable, reliable cloud data storage accessable via SSH/SCP/FTP for Borg backups or any other bulk storage needs</li>
|
||||
</ul>
|
||||
|
||||
Additionally, [Hetzner](https://www.hetzner.com/storage/storage-box) has a
|
||||
compatible storage offering, but does not currently fund borgmatic
|
||||
development or hosting.
|
||||
|
||||
## Configuration
|
||||
|
||||
After you install borgmatic, generate a sample configuration file:
|
||||
@@ -139,8 +143,8 @@ configuration](https://torsion.org/borgmatic/docs/how-to/upgrade/#upgrading-your
|
||||
|
||||
### Encryption
|
||||
|
||||
If you encrypt your Borg repository with a passphrase instead of a key file,
|
||||
you'll either need to set the borgmatic `encryption_passphrase` configuration
|
||||
If you encrypt your Borg repository with a passphrase or a key file, you'll
|
||||
either need to set the borgmatic `encryption_passphrase` configuration
|
||||
variable or set the `BORG_PASSPHRASE` environment variable. See the
|
||||
[repository encryption
|
||||
section](https://borgbackup.readthedocs.io/en/stable/quickstart.html#repository-encryption)
|
||||
|
||||
@@ -7,9 +7,9 @@ ConditionACPower=true
|
||||
[Service]
|
||||
Type=oneshot
|
||||
|
||||
# Security settings for systemd running as root
|
||||
# For more details about this settings check the systemd manuals
|
||||
# https://www.freedesktop.org/software/systemd/man/systemd.exec.html
|
||||
# Security settings for systemd running as root, optional but recommended to improve security. You
|
||||
# can disable individual settings if they cause problems for your use case. For more details, see
|
||||
# the systemd manual: https://www.freedesktop.org/software/systemd/man/systemd.exec.html
|
||||
LockPersonality=true
|
||||
# Certain borgmatic features like Healthchecks integration need MemoryDenyWriteExecute to be off.
|
||||
# But you can try setting it to "yes" for improved security if you don't use those features.
|
||||
@@ -29,6 +29,7 @@ RestrictRealtime=yes
|
||||
RestrictSUIDSGID=yes
|
||||
SystemCallArchitectures=native
|
||||
SystemCallFilter=@system-service
|
||||
SystemCallErrorNumber=EPERM
|
||||
# Restrict write access
|
||||
# Change to 'ProtectSystem=strict' and uncomment 'ProtectHome' to make the whole file
|
||||
# system read-only be default and uncomment 'ReadWritePaths' for the required write access.
|
||||
|
||||
+8
-1
@@ -15,6 +15,12 @@ if [[ ! -f NEWS ]]; then
|
||||
fi
|
||||
|
||||
version=$(head --lines=1 NEWS)
|
||||
|
||||
if [[ $version =~ .*dev* ]]; then
|
||||
echo "Refusing to release a dev version: $version"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
git tag $version
|
||||
git push origin $version
|
||||
git push github $version
|
||||
@@ -32,7 +38,8 @@ twine upload -r pypi dist/borgmatic-*-py3-none-any.whl dist/borgmatic-*-py3-none
|
||||
release_changelog="$(cat NEWS | sed '/^$/q' | grep -v '^\S')"
|
||||
escaped_release_changelog="$(echo "$release_changelog" | sed -z 's/\n/\\n/g' | sed -z 's/\"/\\"/g')"
|
||||
curl --silent --request POST \
|
||||
"https://projects.torsion.org/api/v1/repos/witten/borgmatic/releases?access_token=$projects_token" \
|
||||
"https://projects.torsion.org/api/v1/repos/witten/borgmatic/releases" \
|
||||
--header "Authorization: token $projects_token" \
|
||||
--header "Accept: application/json" \
|
||||
--header "Content-Type: application/json" \
|
||||
--data "{\"body\": \"$escaped_release_changelog\", \"draft\": false, \"name\": \"borgmatic $version\", \"prerelease\": false, \"tag_name\": \"$version\"}"
|
||||
|
||||
@@ -10,9 +10,11 @@
|
||||
|
||||
set -e
|
||||
|
||||
python -m pip install --upgrade pip==20.0.2
|
||||
pip install tox==3.14.3
|
||||
apk add --no-cache python3 py3-pip borgbackup postgresql-client mariadb-client
|
||||
# If certain dependencies of black are available in this version of Alpine, install them.
|
||||
apk add --no-cache py3-typed-ast py3-regex || true
|
||||
python3 -m pip install --upgrade pip==20.2.4 setuptools==50.3.2
|
||||
pip3 install tox==3.20.1
|
||||
export COVERAGE_FILE=/tmp/.coverage
|
||||
tox --workdir /tmp/.tox
|
||||
apk add --no-cache borgbackup postgresql-client mariadb-client
|
||||
tox --workdir /tmp/.tox -e end-to-end
|
||||
tox --workdir /tmp/.tox --sitepackages
|
||||
tox --workdir /tmp/.tox --sitepackages -e end-to-end
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
[metadata]
|
||||
description-file=README.md
|
||||
description_file=README.md
|
||||
|
||||
[tool:pytest]
|
||||
testpaths = tests
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
from setuptools import find_packages, setup
|
||||
|
||||
VERSION = '1.5.12'
|
||||
VERSION = '1.5.14'
|
||||
|
||||
|
||||
setup(
|
||||
@@ -32,7 +32,7 @@ setup(
|
||||
install_requires=(
|
||||
'pykwalify>=1.6.0,<14.06',
|
||||
'requests',
|
||||
'ruamel.yaml>0.15.0,<0.17.0',
|
||||
'ruamel.yaml>0.15.0,<0.18.0',
|
||||
'setuptools',
|
||||
'colorama>=0.4.1,<0.5',
|
||||
),
|
||||
|
||||
+24
-21
@@ -1,25 +1,28 @@
|
||||
appdirs==1.4.3
|
||||
atomicwrites==1.3.0
|
||||
attrs==19.3.0
|
||||
black==19.3b0; python_version >= '3.6'
|
||||
click==7.0
|
||||
colorama==0.4.1
|
||||
coverage==4.5.4
|
||||
appdirs==1.4.4; python_version >= '3.8'
|
||||
atomicwrites==1.4.0
|
||||
attrs==20.3.0; python_version >= '3.8'
|
||||
black==19.10b0; python_version >= '3.8'
|
||||
click==7.1.2; python_version >= '3.8'
|
||||
colorama==0.4.4
|
||||
coverage==5.3
|
||||
docopt==0.6.2
|
||||
flake8==3.7.9
|
||||
flake8==3.8.4
|
||||
flexmock==0.10.4
|
||||
isort==4.3.21
|
||||
isort==5.6.4
|
||||
mccabe==0.6.1
|
||||
more-itertools==7.2.0
|
||||
pluggy==0.13.0
|
||||
py==1.8.0
|
||||
pycodestyle==2.5.0
|
||||
pyflakes==2.1.1
|
||||
more-itertools==8.6.0
|
||||
pluggy==0.13.1
|
||||
pathspec==0.8.1; python_version >= '3.8'
|
||||
py==1.10.0
|
||||
pycodestyle==2.6.0
|
||||
pyflakes==2.2.0
|
||||
pykwalify==1.7.0
|
||||
pytest==5.2.2
|
||||
pytest-cov==2.8.1
|
||||
python-dateutil==2.8.0
|
||||
PyYAML==5.1.2
|
||||
requests==2.22.0
|
||||
ruamel.yaml>0.15.0,<0.17.0
|
||||
toml==0.10.0
|
||||
pytest==6.1.2
|
||||
pytest-cov==2.10.1
|
||||
python-dateutil==2.8.1
|
||||
PyYAML==5.4.1
|
||||
regex; python_version >= '3.8'
|
||||
requests==2.25.0
|
||||
ruamel.yaml>0.15.0,<0.18.0
|
||||
toml==0.10.2; python_version >= '3.8'
|
||||
typed-ast==1.4.2; python_version >= '3.8'
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
version: '3'
|
||||
services:
|
||||
postgresql:
|
||||
image: postgres:12.2-alpine
|
||||
image: postgres:13.1-alpine
|
||||
environment:
|
||||
POSTGRES_PASSWORD: test
|
||||
POSTGRES_DB: test
|
||||
@@ -11,7 +11,7 @@ services:
|
||||
MYSQL_ROOT_PASSWORD: test
|
||||
MYSQL_DATABASE: test
|
||||
tests:
|
||||
image: python:3.8-alpine3.11
|
||||
image: alpine:3.13
|
||||
volumes:
|
||||
- "../..:/app:ro"
|
||||
tmpfs:
|
||||
|
||||
@@ -20,6 +20,7 @@ def generate_configuration(config_path, repository_path):
|
||||
.read()
|
||||
.replace('user@backupserver:sourcehostname.borg', repository_path)
|
||||
.replace('- user@backupserver:{fqdn}', '')
|
||||
.replace('- /home/user/path with spaces', '')
|
||||
.replace('- /home', '- {}'.format(config_path))
|
||||
.replace('- /etc', '')
|
||||
.replace('- /var/log/syslog*', '')
|
||||
|
||||
@@ -88,13 +88,21 @@ def test_log_outputs_skips_error_output_in_exception_for_process_with_none_stdou
|
||||
|
||||
def test_log_outputs_kills_other_processes_when_one_errors():
|
||||
flexmock(module.logger).should_receive('log')
|
||||
flexmock(module).should_receive('exit_code_indicates_error').and_return(True)
|
||||
flexmock(module).should_receive('command_for_process').and_return('grep')
|
||||
|
||||
process = subprocess.Popen(['grep'], stdout=subprocess.PIPE, stderr=subprocess.STDOUT)
|
||||
flexmock(module).should_receive('exit_code_indicates_error').with_args(
|
||||
process, None, 'borg'
|
||||
).and_return(False)
|
||||
flexmock(module).should_receive('exit_code_indicates_error').with_args(
|
||||
process, 2, 'borg'
|
||||
).and_return(True)
|
||||
other_process = subprocess.Popen(
|
||||
['watch', 'true'], stdout=subprocess.PIPE, stderr=subprocess.STDOUT
|
||||
)
|
||||
flexmock(module).should_receive('exit_code_indicates_error').with_args(
|
||||
other_process, None, 'borg'
|
||||
).and_return(False)
|
||||
flexmock(module).should_receive('output_buffer_for_process').with_args(process, ()).and_return(
|
||||
process.stdout
|
||||
)
|
||||
@@ -118,10 +126,15 @@ def test_log_outputs_kills_other_processes_when_one_errors():
|
||||
def test_log_outputs_truncates_long_error_output():
|
||||
flexmock(module).ERROR_OUTPUT_MAX_LINE_COUNT = 0
|
||||
flexmock(module.logger).should_receive('log')
|
||||
flexmock(module).should_receive('exit_code_indicates_error').and_return(True)
|
||||
flexmock(module).should_receive('command_for_process').and_return('grep')
|
||||
|
||||
process = subprocess.Popen(['grep'], stdout=subprocess.PIPE, stderr=subprocess.STDOUT)
|
||||
flexmock(module).should_receive('exit_code_indicates_error').with_args(
|
||||
process, None, 'borg'
|
||||
).and_return(False)
|
||||
flexmock(module).should_receive('exit_code_indicates_error').with_args(
|
||||
process, 2, 'borg'
|
||||
).and_return(True)
|
||||
flexmock(module).should_receive('output_buffer_for_process').and_return(process.stdout)
|
||||
|
||||
with pytest.raises(subprocess.CalledProcessError) as error:
|
||||
|
||||
@@ -447,7 +447,9 @@ def test_collect_configuration_run_summary_logs_outputs_merged_json_results():
|
||||
flexmock(module).should_receive('run_configuration').and_return(['foo', 'bar']).and_return(
|
||||
['baz']
|
||||
)
|
||||
flexmock(module.sys.stdout).should_receive('write').with_args('["foo", "bar", "baz"]').once()
|
||||
stdout = flexmock()
|
||||
stdout.should_receive('write').with_args('["foo", "bar", "baz"]').once()
|
||||
flexmock(module.sys).stdout = stdout
|
||||
arguments = {}
|
||||
|
||||
tuple(
|
||||
|
||||
@@ -28,7 +28,9 @@ def test_forgetful_buffering_handler_emit_forgets_log_records_when_capacity_reac
|
||||
def test_format_buffered_logs_for_payload_flattens_log_buffer():
|
||||
handler = module.Forgetful_buffering_handler(byte_capacity=100, log_level=1)
|
||||
handler.buffer = ['foo\n', 'bar\n']
|
||||
flexmock(module.logging).should_receive('getLogger').and_return(flexmock(handlers=[handler]))
|
||||
logger = flexmock(handlers=[handler])
|
||||
logger.should_receive('removeHandler')
|
||||
flexmock(module.logging).should_receive('getLogger').and_return(logger)
|
||||
|
||||
payload = module.format_buffered_logs_for_payload()
|
||||
|
||||
@@ -39,7 +41,9 @@ def test_format_buffered_logs_for_payload_inserts_truncation_indicator_when_logs
|
||||
handler = module.Forgetful_buffering_handler(byte_capacity=100, log_level=1)
|
||||
handler.buffer = ['foo\n', 'bar\n']
|
||||
handler.forgot = True
|
||||
flexmock(module.logging).should_receive('getLogger').and_return(flexmock(handlers=[handler]))
|
||||
logger = flexmock(handlers=[handler])
|
||||
logger.should_receive('removeHandler')
|
||||
flexmock(module.logging).should_receive('getLogger').and_return(logger)
|
||||
|
||||
payload = module.format_buffered_logs_for_payload()
|
||||
|
||||
@@ -47,9 +51,9 @@ def test_format_buffered_logs_for_payload_inserts_truncation_indicator_when_logs
|
||||
|
||||
|
||||
def test_format_buffered_logs_for_payload_without_handler_produces_empty_payload():
|
||||
flexmock(module.logging).should_receive('getLogger').and_return(
|
||||
flexmock(handlers=[module.logging.Handler()])
|
||||
)
|
||||
logger = flexmock(handlers=[module.logging.Handler()])
|
||||
logger.should_receive('removeHandler')
|
||||
flexmock(module.logging).should_receive('getLogger').and_return(logger)
|
||||
|
||||
payload = module.format_buffered_logs_for_payload()
|
||||
|
||||
|
||||
@@ -21,6 +21,11 @@ from borgmatic import execute as module
|
||||
(flexmock(args=['grep']), 0, 'borg', False),
|
||||
(flexmock(args=['borg']), 0, 'borg', False),
|
||||
(flexmock(args=['borg1']), 0, 'borg1', False),
|
||||
# -9 exit code occurs when child process get SIGKILLed.
|
||||
(flexmock(args=['grep']), -9, None, True),
|
||||
(flexmock(args=['grep']), -9, 'borg', True),
|
||||
(flexmock(args=['borg']), -9, 'borg', True),
|
||||
(flexmock(args=['borg1']), -9, 'borg1', True),
|
||||
(flexmock(args=['borg']), None, None, False),
|
||||
),
|
||||
)
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
[tox]
|
||||
envlist = py35,py36,py37,py38
|
||||
envlist = py36,py37,py38,py39
|
||||
skip_missing_interpreters = True
|
||||
skipsdist = True
|
||||
minversion = 3.14.1
|
||||
@@ -13,8 +13,8 @@ whitelist_externals =
|
||||
passenv = COVERAGE_FILE
|
||||
commands =
|
||||
pytest {posargs}
|
||||
py36,py37,py38: black --check .
|
||||
isort --recursive --check-only --settings-path setup.cfg .
|
||||
py38,py39: black --check .
|
||||
isort --check-only --settings-path setup.cfg .
|
||||
flake8 borgmatic tests
|
||||
|
||||
[testenv:black]
|
||||
@@ -34,4 +34,4 @@ commands =
|
||||
[testenv:isort]
|
||||
deps = {[testenv]deps}
|
||||
commands =
|
||||
isort {posargs:--recursive} --settings-path setup.cfg .
|
||||
isort --settings-path setup.cfg .
|
||||
|
||||
Reference in New Issue
Block a user