Include pre- and post_tasks transparently for all Ansible roles
Not tested this, but is include_role any help? so instead of a playbook like this,
 ---
 - name: Example
   hosts: all
   roles:
    - first_role
    - second_role
    - third_role

maybe this,
 ---
 - name: Example
   hosts: all
   tasks:
    - etckeeper_task
    - include_role:
        name: first_role
    - etckeeper_task
    - include_role:
        name: second_role
    - etckeeper_task
    - include_role:
        name: third_role
    - etckeeper_task

alternatively (also untested) you could build a role, let's call it wrap_role with tasks/main.yml containing,
---
# Replace this task with your actual before-role etckeeper task,
- name: etckeeper pre-actions
  meta: noop

- include_role:
  name: {{role_name}}

# Replace this task with your actual after-role etckeeper task,
- name: etckeeper post-actions
  meta: noop

Now your top-level playbook can be something like,
 ---
 - name: Example
   hosts: all
   roles:
     - { role: wrap_role, role_name: first_role }
     - { role: wrap_role, role_name: second_role }
     - { role: wrap_role, role_name: third_role }

not ideal based on your question, but at least it leaves the roles untouched, even if you have to alter top-level playbooks. If I get the time I'll test the above suggestions and update this answer accordingly.