Borgmatic 2.0 executes commands multiple times #1060

Closed
opened 2025-04-08 04:36:05 +00:00 by vitoyucepi · 4 comments

What I'm trying to do and why

While migrating the borgmatic configs from 1.9.14 to 2.0.1, I ran into the problem with the new hooks.

Steps to reproduce

I am using the python:3.13-slim container image to reproduce the problem.

  1. apt-get update;
    apt-get install --no-install-recommends -y pkg-config libssl-dev liblz4-dev libzstd-dev libxxhash-dev libacl1-dev gcc;
    pip install borgmatic==2.0.1 borgbackup;
    
  2. 1.conf
    source_directories:
      - /root
    
    repositories:
      - path: /tmp/test1
    
    skip_actions:
      - prune
    
    before_backup:
      - "echo 'Starting a backup.'"
    after_backup:
      - "echo 'Finished a backup.'"
    
    before_prune:
      - "echo 'Starting pruning.'"
    after_prune:
      - "echo 'Finished pruning.'"
    
    before_compact:
      - "echo 'Starting compaction.'"
    after_compact:
      - "echo 'Finished compaction.'"
    
    before_check:
      - "echo 'Starting checks.'"
    after_check:
      - "echo 'Finished checks.'"
    
    before_extract:
      - "echo 'Starting extracting.'"
    after_extract:
      - "echo 'Finished extracting.'"
    
  3. 2.conf
    source_directories:
      - /root
    
    repositories:
      - path: /tmp/test2
    
    skip_actions:
      - prune
    
    commands:
      - before: action
        when: [create]
        run: ["echo 'Starting create.'"]
      - after: action
        when: [create]
        run: ["echo 'Finished create.'"]
      - before: action
        when: [prune]
        run: ["echo 'Starting prune.'"]
      - after: action
        when: [prune]
        run: ["echo 'Finished prune.'"]
      - before: action
        when: [compact]
        run: ["echo 'Starting compact.'"]
      - after: action
        when: [compact]
        run: ["echo 'Finished compact.'"]
      - before: action
        when: [check]
        run: ["echo 'Starting check.'"]
      - after: action
        when: [check]
        run: ["echo 'Finished check.'"]
    
  4. export BORG_PASSPHRASE=1;
    borgmatic -c 1.conf init -e repokey;
    borgmatic -c 2.conf init -e repokey;
    borgmatic -c 1.conf;
    borgmatic -c 2.conf;
    

Actual behavior

When I use borgmatic==1.9.14, the output is

Starting a backup.
Finished a backup.
Starting compaction.
Finished compaction.
Starting checks.
Finished checks.

When I use borgmatic==2.0.1, the output is

Starting create.
Starting prune.
Starting compact.
Starting check.
Finished create.
Finished prune.
Finished compact.
Finished check.
Starting create.
Starting prune.
Starting compact.
Starting check.
Finished create.
Finished prune.
Finished compact.
Finished check.
Starting create.
Starting prune.
Starting compact.
Starting check.
Finished create.
Finished prune.
Finished compact.
Finished check.
Starting create.
Starting prune.
Starting compact.
Starting check.
Finished create.
Finished prune.
Finished compact.
Finished check.

Expected behavior

Borgmatic should not run hooks multiple times.

Other notes / implementation ideas

No response

borgmatic version

2.0.1

borgmatic installation method

pip

Borg version

1.4.0

Python version

Python 3.13.2

Database version (if applicable)

N/A

Operating system and version

Debian 12

### What I'm trying to do and why While migrating the borgmatic configs from 1.9.14 to 2.0.1, I ran into the problem with the new hooks. ### Steps to reproduce I am using the `python:3.13-slim` container image to reproduce the problem. 1. ```sh apt-get update; apt-get install --no-install-recommends -y pkg-config libssl-dev liblz4-dev libzstd-dev libxxhash-dev libacl1-dev gcc; pip install borgmatic==2.0.1 borgbackup; ``` 2. `1.conf` ```conf source_directories: - /root repositories: - path: /tmp/test1 skip_actions: - prune before_backup: - "echo 'Starting a backup.'" after_backup: - "echo 'Finished a backup.'" before_prune: - "echo 'Starting pruning.'" after_prune: - "echo 'Finished pruning.'" before_compact: - "echo 'Starting compaction.'" after_compact: - "echo 'Finished compaction.'" before_check: - "echo 'Starting checks.'" after_check: - "echo 'Finished checks.'" before_extract: - "echo 'Starting extracting.'" after_extract: - "echo 'Finished extracting.'" ``` 1. `2.conf` ```conf source_directories: - /root repositories: - path: /tmp/test2 skip_actions: - prune commands: - before: action when: [create] run: ["echo 'Starting create.'"] - after: action when: [create] run: ["echo 'Finished create.'"] - before: action when: [prune] run: ["echo 'Starting prune.'"] - after: action when: [prune] run: ["echo 'Finished prune.'"] - before: action when: [compact] run: ["echo 'Starting compact.'"] - after: action when: [compact] run: ["echo 'Finished compact.'"] - before: action when: [check] run: ["echo 'Starting check.'"] - after: action when: [check] run: ["echo 'Finished check.'"] ``` 1. ```sh export BORG_PASSPHRASE=1; borgmatic -c 1.conf init -e repokey; borgmatic -c 2.conf init -e repokey; borgmatic -c 1.conf; borgmatic -c 2.conf; ``` ### Actual behavior When I use `borgmatic==1.9.14`, the output is ``` Starting a backup. Finished a backup. Starting compaction. Finished compaction. Starting checks. Finished checks. ``` When I use `borgmatic==2.0.1`, the output is ``` Starting create. Starting prune. Starting compact. Starting check. Finished create. Finished prune. Finished compact. Finished check. Starting create. Starting prune. Starting compact. Starting check. Finished create. Finished prune. Finished compact. Finished check. Starting create. Starting prune. Starting compact. Starting check. Finished create. Finished prune. Finished compact. Finished check. Starting create. Starting prune. Starting compact. Starting check. Finished create. Finished prune. Finished compact. Finished check. ``` ### Expected behavior Borgmatic should not run hooks multiple times. ### Other notes / implementation ideas _No response_ ### borgmatic version 2.0.1 ### borgmatic installation method pip ### Borg version 1.4.0 ### Python version Python 3.13.2 ### Database version (if applicable) N/A ### Operating system and version Debian 12
Owner

Thanks for the detailed ticket and repro steps! I've got a repro here, so I'll let you know what I find.

Thanks for the detailed ticket and repro steps! I've got a repro here, so I'll let you know what I find.
Owner

Wow, this is embarrassing. The whole list of action command hooks get run once for each action that borgmatic's executed with (implicitly or explicitly). That's why you're seeing all the duplication. I don't think I ever noticed this during development because I was mostly manual testing with single actions on the command-line. And the automated tests don't cover this particular use case (yet).

Wow, this is embarrassing. The whole list of action command hooks get run once for each action that borgmatic's executed with (implicitly or explicitly). That's why you're seeing all the duplication. I don't think I ever noticed this during development because I was mostly manual testing with single actions on the command-line. And the automated tests don't cover this particular use case (yet).
Owner

This is fixed in main and will be part of the next release.

Side note: This also uncovered that action command hooks execute before/after actions listed in skip_actions. That should probably be remedied as well.

Thanks again!

This is fixed in main and will be part of the next release. Side note: This also uncovered that `action` command hooks execute before/after actions listed in `skip_actions`. That should probably be remedied as well. Thanks again!
Owner

Released in borgmatic 2.0.2!

Released in borgmatic 2.0.2!
Sign in to join this conversation.
No milestone
No assignees
2 participants
Notifications
Due date
The due date is invalid or out of range. Please use the format "yyyy-mm-dd".

No due date set.

Dependencies

No dependencies set

Reference
borgmatic-collective/borgmatic#1060
No description provided.