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:
294
deployment/ansible/playbooks/manage/gitea.yml
Normal file
294
deployment/ansible/playbooks/manage/gitea.yml
Normal 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 %}
|
||||
|
||||
================================================================================
|
||||
|
||||
|
||||
162
deployment/ansible/playbooks/manage/traefik.yml
Normal file
162
deployment/ansible/playbooks/manage/traefik.yml
Normal 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 %}
|
||||
|
||||
================================================================================
|
||||
|
||||
|
||||
Reference in New Issue
Block a user