fix(console): comprehensive TUI rendering fixes

- Fix Enter key detection: handle multiple Enter key formats (\n, \r, \r\n)
- Reduce flickering: lower render frequency from 60 FPS to 30 FPS
- Fix menu bar visibility: re-render menu bar after content to prevent overwriting
- Fix content positioning: explicit line positioning for categories and commands
- Fix line shifting: clear lines before writing, control newlines manually
- Limit visible items: prevent overflow with maxVisibleCategories/Commands
- Improve CPU usage: increase sleep interval when no events processed

This fixes:
- Enter key not working for selection
- Strong flickering of the application
- Menu bar not visible or being overwritten
- Top half of selection list not displayed
- Lines being shifted/misaligned
This commit is contained in:
2025-11-10 11:06:07 +01:00
parent 6bc78f5540
commit 8f3c15ddbb
106 changed files with 9082 additions and 4483 deletions

View File

@@ -0,0 +1,294 @@
---
# Consolidated Gitea Management Playbook
# Consolidates: fix-gitea-timeouts.yml, fix-gitea-traefik-connection.yml,
# fix-gitea-ssl-routing.yml, fix-gitea-servers-transport.yml,
# fix-gitea-complete.yml, restart-gitea-complete.yml,
# restart-gitea-with-cache.yml
#
# Usage:
# # Restart Gitea
# ansible-playbook -i inventory/production.yml playbooks/manage/gitea.yml --tags restart
#
# # Fix timeouts (restart Gitea and Traefik)
# ansible-playbook -i inventory/production.yml playbooks/manage/gitea.yml --tags fix-timeouts
#
# # Fix SSL/routing issues
# ansible-playbook -i inventory/production.yml playbooks/manage/gitea.yml --tags fix-ssl
#
# # Complete fix (runner stop + restart + service discovery)
# ansible-playbook -i inventory/production.yml playbooks/manage/gitea.yml --tags complete
- name: Manage Gitea
hosts: production
gather_facts: yes
become: no
vars:
gitea_stack_path: "{{ stacks_base_path }}/gitea"
traefik_stack_path: "{{ stacks_base_path }}/traefik"
gitea_runner_path: "{{ stacks_base_path }}/../gitea-runner"
gitea_url: "https://{{ gitea_domain }}"
gitea_container_name: "gitea"
traefik_container_name: "traefik"
tasks:
- name: Display management plan
ansible.builtin.debug:
msg: |
================================================================================
GITEA MANAGEMENT
================================================================================
Running management tasks with tags: {{ ansible_run_tags | default(['all']) }}
Available actions:
- restart: Restart Gitea container
- fix-timeouts: Restart Gitea and Traefik to fix timeouts
- fix-ssl: Fix SSL/routing issues
- fix-servers-transport: Update ServersTransport configuration
- complete: Complete fix (stop runner, restart services, verify)
================================================================================
# ========================================
# COMPLETE FIX (--tags complete)
# ========================================
- name: Check Gitea Runner status
ansible.builtin.shell: |
cd {{ gitea_runner_path }}
docker compose ps gitea-runner 2>/dev/null || echo "Runner not found"
register: runner_status
changed_when: false
failed_when: false
tags:
- complete
- name: Stop Gitea Runner to reduce load
ansible.builtin.shell: |
cd {{ gitea_runner_path }}
docker compose stop gitea-runner
register: runner_stop
changed_when: runner_stop.rc == 0
failed_when: false
when: runner_status.rc == 0
tags:
- complete
# ========================================
# RESTART GITEA (--tags restart, fix-timeouts, complete)
# ========================================
- name: Check Gitea container status before restart
ansible.builtin.shell: |
cd {{ gitea_stack_path }}
docker compose ps {{ gitea_container_name }}
register: gitea_status_before
changed_when: false
tags:
- restart
- fix-timeouts
- complete
- name: Restart Gitea container
ansible.builtin.shell: |
cd {{ gitea_stack_path }}
docker compose restart {{ gitea_container_name }}
register: gitea_restart
changed_when: gitea_restart.rc == 0
tags:
- restart
- fix-timeouts
- complete
- name: Wait for Gitea to be ready (direct check)
ansible.builtin.shell: |
cd {{ gitea_stack_path }}
for i in {1..30}; do
if docker compose exec -T {{ gitea_container_name }} curl -f http://localhost:3000/api/healthz >/dev/null 2>&1; then
echo "Gitea is ready"
exit 0
fi
sleep 2
done
echo "Gitea not ready after 60 seconds"
exit 1
register: gitea_ready
changed_when: false
failed_when: false
tags:
- restart
- fix-timeouts
- complete
# ========================================
# RESTART TRAEFIK (--tags fix-timeouts, complete)
# ========================================
- name: Check Traefik container status before restart
ansible.builtin.shell: |
cd {{ traefik_stack_path }}
docker compose ps {{ traefik_container_name }}
register: traefik_status_before
changed_when: false
tags:
- fix-timeouts
- complete
- name: Restart Traefik to refresh service discovery
ansible.builtin.shell: |
cd {{ traefik_stack_path }}
docker compose restart {{ traefik_container_name }}
register: traefik_restart
changed_when: traefik_restart.rc == 0
when: traefik_auto_restart | default(false) | bool
tags:
- fix-timeouts
- complete
- name: Wait for Traefik to be ready
ansible.builtin.wait_for:
timeout: 30
delay: 2
changed_when: false
when: traefik_restart.changed | default(false) | bool
tags:
- fix-timeouts
- complete
# ========================================
# FIX SERVERS TRANSPORT (--tags fix-servers-transport)
# ========================================
- name: Sync Gitea stack configuration
ansible.builtin.synchronize:
src: "{{ playbook_dir }}/../../stacks/gitea/"
dest: "{{ gitea_stack_path }}/"
delete: no
recursive: yes
rsync_opts:
- "--chmod=D755,F644"
- "--exclude=.git"
- "--exclude=*.log"
- "--exclude=data/"
- "--exclude=volumes/"
tags:
- fix-servers-transport
- name: Restart Gitea container to apply new labels
ansible.builtin.shell: |
cd {{ gitea_stack_path }}
docker compose up -d --force-recreate {{ gitea_container_name }}
register: gitea_restart_transport
changed_when: gitea_restart_transport.rc == 0
tags:
- fix-servers-transport
# ========================================
# VERIFICATION (--tags fix-timeouts, fix-ssl, complete)
# ========================================
- name: Wait for Gitea to be reachable via Traefik (with retries)
ansible.builtin.uri:
url: "{{ gitea_url }}/api/healthz"
method: GET
status_code: [200]
validate_certs: false
timeout: 10
register: gitea_health_via_traefik
until: gitea_health_via_traefik.status == 200
retries: 15
delay: 2
changed_when: false
failed_when: false
when: (traefik_restart.changed | default(false) | bool) or (gitea_restart.changed | default(false) | bool)
tags:
- fix-timeouts
- fix-ssl
- complete
- name: Check if Gitea is in Traefik service discovery
ansible.builtin.shell: |
cd {{ traefik_stack_path }}
docker compose exec -T {{ traefik_container_name }} traefik show providers docker 2>/dev/null | grep -i "gitea" || echo "NOT_FOUND"
register: traefik_gitea_service_check
changed_when: false
failed_when: false
when: (traefik_restart.changed | default(false) | bool) or (gitea_restart.changed | default(false) | bool)
tags:
- fix-timeouts
- fix-ssl
- complete
- name: Final status check
ansible.builtin.uri:
url: "{{ gitea_url }}/api/healthz"
method: GET
status_code: [200]
validate_certs: false
timeout: 10
register: final_status
changed_when: false
failed_when: false
tags:
- fix-timeouts
- fix-ssl
- complete
# ========================================
# SUMMARY
# ========================================
- name: Summary
ansible.builtin.debug:
msg: |
================================================================================
GITEA MANAGEMENT SUMMARY
================================================================================
Actions performed:
{% if 'complete' in ansible_run_tags %}
- Gitea Runner: {% if runner_stop.changed | default(false) %}✅ Stopped{% else %} Not active or not found{% endif %}
{% endif %}
{% if 'restart' in ansible_run_tags or 'fix-timeouts' in ansible_run_tags or 'complete' in ansible_run_tags %}
- Gitea Restart: {% if gitea_restart.changed %}✅ Performed{% else %} Not needed{% endif %}
- Gitea Ready: {% if gitea_ready.rc == 0 %}✅ Ready{% else %}❌ Not ready{% endif %}
{% endif %}
{% if 'fix-timeouts' in ansible_run_tags or 'complete' in ansible_run_tags %}
- Traefik Restart: {% if traefik_restart.changed %}✅ Performed{% else %} Not needed (traefik_auto_restart=false){% endif %}
{% endif %}
{% if 'fix-servers-transport' in ansible_run_tags %}
- ServersTransport Update: {% if gitea_restart_transport.changed %}✅ Applied{% else %} Not needed{% endif %}
{% endif %}
Final Status:
{% if 'fix-timeouts' in ansible_run_tags or 'fix-ssl' in ansible_run_tags or 'complete' in ansible_run_tags %}
- Gitea via Traefik: {% if final_status.status == 200 %}✅ Reachable (Status: 200){% else %}❌ Not reachable (Status: {{ final_status.status | default('TIMEOUT') }}){% endif %}
- Traefik Service Discovery: {% if 'NOT_FOUND' not in traefik_gitea_service_check.stdout %}✅ Gitea found{% else %}❌ Gitea not found{% endif %}
{% endif %}
{% if final_status.status == 200 and 'NOT_FOUND' not in traefik_gitea_service_check.stdout %}
✅ SUCCESS: Gitea is now reachable via Traefik!
URL: {{ gitea_url }}
Next steps:
1. Test Gitea in browser: {{ gitea_url }}
{% if 'complete' in ansible_run_tags %}
2. If everything is stable, you can reactivate the runner:
cd {{ gitea_runner_path }} && docker compose up -d gitea-runner
3. Monitor if the runner overloads Gitea again
{% endif %}
{% else %}
⚠️ PROBLEM: Gitea is not fully reachable
Possible causes:
{% if final_status.status != 200 %}
- Gitea does not respond via Traefik (Status: {{ final_status.status | default('TIMEOUT') }})
{% endif %}
{% if 'NOT_FOUND' in traefik_gitea_service_check.stdout %}
- Traefik Service Discovery has not recognized Gitea yet
{% endif %}
Next steps:
1. Wait 1-2 minutes and test again: curl -k {{ gitea_url }}/api/healthz
2. Check Traefik logs: cd {{ traefik_stack_path }} && docker compose logs {{ traefik_container_name }} --tail=50
3. Check Gitea logs: cd {{ gitea_stack_path }} && docker compose logs {{ gitea_container_name }} --tail=50
4. Run diagnosis: ansible-playbook -i inventory/production.yml playbooks/diagnose/gitea.yml
{% endif %}
================================================================================

View File

@@ -0,0 +1,162 @@
---
# Consolidated Traefik Management Playbook
# Consolidates: stabilize-traefik.yml, disable-traefik-auto-restarts.yml
#
# Usage:
# # Stabilize Traefik (fix acme.json, ensure running, monitor)
# ansible-playbook -i inventory/production.yml playbooks/manage/traefik.yml --tags stabilize
#
# # Disable auto-restarts
# ansible-playbook -i inventory/production.yml playbooks/manage/traefik.yml --tags disable-auto-restart
- name: Manage Traefik
hosts: production
gather_facts: yes
become: no
vars:
traefik_stack_path: "{{ stacks_base_path }}/traefik"
traefik_container_name: "traefik"
traefik_stabilize_wait_minutes: "{{ traefik_stabilize_wait_minutes | default(10) }}"
traefik_stabilize_check_interval: 60
tasks:
- name: Display management plan
ansible.builtin.debug:
msg: |
================================================================================
TRAEFIK MANAGEMENT
================================================================================
Running management tasks with tags: {{ ansible_run_tags | default(['all']) }}
Available actions:
- stabilize: Fix acme.json, ensure running, monitor stability
- disable-auto-restart: Check and document auto-restart mechanisms
================================================================================
# ========================================
# STABILIZE (--tags stabilize)
# ========================================
- name: Fix acme.json permissions
ansible.builtin.file:
path: "{{ traefik_stack_path }}/acme.json"
state: file
mode: '0600'
owner: "{{ ansible_user | default('deploy') }}"
group: "{{ ansible_user | default('deploy') }}"
register: acme_permissions_fixed
tags:
- stabilize
- name: Ensure Traefik container is running
ansible.builtin.shell: |
cd {{ traefik_stack_path }}
docker compose up -d {{ traefik_container_name }}
register: traefik_start
changed_when: traefik_start.rc == 0
tags:
- stabilize
- name: Wait for Traefik to be ready
ansible.builtin.wait_for:
timeout: 30
delay: 2
changed_when: false
tags:
- stabilize
- name: Monitor Traefik stability
ansible.builtin.shell: |
cd {{ traefik_stack_path }}
docker compose ps {{ traefik_container_name }} --format "{{ '{{' }}.State{{ '}}' }}" | head -1 || echo "UNKNOWN"
register: traefik_state_check
changed_when: false
until: traefik_state_check.stdout == "running"
retries: "{{ (traefik_stabilize_wait_minutes | int * 60 / traefik_stabilize_check_interval) | int }}"
delay: "{{ traefik_stabilize_check_interval }}"
tags:
- stabilize
- name: Check Traefik logs for restarts during monitoring
ansible.builtin.shell: |
cd {{ traefik_stack_path }}
docker compose logs {{ traefik_container_name }} --since "{{ traefik_stabilize_wait_minutes }}m" 2>&1 | grep -iE "stopping server gracefully|I have to go" | wc -l
register: restarts_during_monitoring
changed_when: false
tags:
- stabilize
# ========================================
# DISABLE AUTO-RESTART (--tags disable-auto-restart)
# ========================================
- name: Check Ansible traefik_auto_restart setting
ansible.builtin.shell: |
grep -r "traefik_auto_restart" /home/deploy/deployment/ansible/inventory/group_vars/ 2>/dev/null | head -5 || echo "No traefik_auto_restart setting found"
register: ansible_auto_restart_setting
changed_when: false
tags:
- disable-auto-restart
- name: Check for cronjobs that restart Traefik
ansible.builtin.shell: |
(crontab -l 2>/dev/null || true) | grep -E "traefik|docker.*compose.*restart.*traefik|docker.*stop.*traefik" || echo "No cronjobs found"
register: traefik_cronjobs
changed_when: false
tags:
- disable-auto-restart
- name: Check systemd timers for Traefik
ansible.builtin.shell: |
systemctl list-timers --all --no-pager | grep -E "traefik|docker.*compose.*traefik" || echo "No Traefik-related timers"
register: traefik_timers
changed_when: false
tags:
- disable-auto-restart
# ========================================
# SUMMARY
# ========================================
- name: Summary
ansible.builtin.debug:
msg: |
================================================================================
TRAEFIK MANAGEMENT SUMMARY
================================================================================
{% if 'stabilize' in ansible_run_tags %}
Stabilization:
- acme.json permissions: {% if acme_permissions_fixed.changed %}✅ Fixed{% else %} Already correct{% endif %}
- Traefik started: {% if traefik_start.changed %}✅ Started{% else %} Already running{% endif %}
- Stability monitoring: {{ traefik_stabilize_wait_minutes }} minutes
- Restarts during monitoring: {{ restarts_during_monitoring.stdout | default('0') }}
{% if (restarts_during_monitoring.stdout | default('0') | int) == 0 %}
✅ Traefik ran stable during monitoring period!
{% else %}
⚠️ {{ restarts_during_monitoring.stdout }} restarts detected during monitoring
→ Run diagnosis: ansible-playbook -i inventory/production.yml playbooks/diagnose/traefik.yml --tags restart-source
{% endif %}
{% endif %}
{% if 'disable-auto-restart' in ansible_run_tags %}
Auto-Restart Analysis:
- Ansible setting: {{ ansible_auto_restart_setting.stdout | default('Not found') }}
- Cronjobs: {{ traefik_cronjobs.stdout | default('None found') }}
- Systemd timers: {{ traefik_timers.stdout | default('None found') }}
Recommendations:
{% if 'traefik_auto_restart.*true' in ansible_auto_restart_setting.stdout %}
- Set traefik_auto_restart: false in group_vars
{% endif %}
{% if 'No cronjobs' not in traefik_cronjobs.stdout %}
- Remove or disable cronjobs that restart Traefik
{% endif %}
{% if 'No Traefik-related timers' not in traefik_timers.stdout %}
- Disable systemd timers that restart Traefik
{% endif %}
{% endif %}
================================================================================