---
# PeerTube v8.x (and intermittently under the rolling `production-bookworm`
# tag) ships a migration that declares `application.nodeVersion` and
# `application.nodeABIVersion` as NOT NULL without a column default, while
# the bootstrap `Application.loadApplication()` only INSERTs `migrationVersion`
# into the single-row `application` table. On a fresh database that INSERT
# fails with
#
# null value in column "nodeVersion" of relation "application" violates
# not-null constraint
#
# and peertube crash-loops on startup before it can add the plugin or serve
# traffic. Related upstream reports (all closed as user error / stale data):
# https://github.com/Chocobozzz/PeerTube/issues/5588 ,
# https://github.com/Chocobozzz/PeerTube/issues/6137 .
#
# The bug is timing-independent inside the container (the INSERT is racing the
# runtime code that would later set `nodeVersion`, not a schema migration), so
# we patch it at the database level: once peertube has created the `application`
# table during its first startup attempt, back-fill column defaults so the
# next restart's INSERT succeeds. Peertube itself overwrites the values with
# real node/ABI version strings on every boot, so the defaults only cover the
# bootstrap INSERT.
#
# Both queries run inside the DB container the `database` lookup resolves
# to (central `svc-db-postgres` in shared mode, per-role `peertube-database`
# in non-shared mode). Running inside the container side-steps the
# controller-side TCP reachability gap that affects non-shared deploys.
- name: "β³ PEERTUBE | Wait for peertube to create the `application` table"
database_query:
mask_values: "{{ MASK_CREDENTIALS_IN_LOGS | bool }}"
config: "{{ lookup('database', application_id) }}"
query: "{{ lookup('file', role_path ~ '/files/sql/check-application/table.sql') }}" # nocheck: database-query-raw controller-read so the SQL travels to the remote swarm host that lacks the repo files
expect_rows: true
register: _peertube_app_table_check
retries: 60
delay: 5
until: >-
_peertube_app_table_check is succeeded
and (_peertube_app_table_check.rows | default([]) | length) > 0
and (_peertube_app_table_check.rows[0][0] | default('')) == 'application'
changed_when: false
- name: "π PEERTUBE | Find the bootstrap columns that still lack a default"
database_query:
mask_values: "{{ MASK_CREDENTIALS_IN_LOGS | bool }}"
config: "{{ lookup('database', application_id) }}"
query: "{{ lookup('file', role_path ~ '/files/sql/check-application/defaults.sql') }}" # nocheck: database-query-raw controller-read so the SQL travels to the remote swarm host that lacks the repo files
expect_rows: true
register: _peertube_app_defaults_missing
changed_when: false
- name: "π§ PEERTUBE | Back-fill column defaults so bootstrap INSERT keeps NOT NULL"
database_query:
mask_values: "{{ MASK_CREDENTIALS_IN_LOGS | bool }}"
config: "{{ lookup('database', application_id) }}"
query: "{{ lookup('file', role_path ~ '/files/sql/backfill-application-defaults.sql') }}" # nocheck: database-query-raw controller-read so the SQL travels to the remote swarm host that lacks the repo files
when: _peertube_app_defaults_missing.rows | length > 0
changed_when: true
notify: compose-up
- name: "β³ PEERTUBE | Wait for peertube container healthy after schema back-fill"
ansible.builtin.include_tasks: utils/wait_healthy.yml
vars:
peertube_health_retries: "{{ PEERTUBE_MIGRATION_HEALTH_RETRIES if (_peertube_upgrade.upgrade | bool) else 60 }}"