mirror of
https://github.com/kevinveenbirkenbach/computer-playbook.git
synced 2026-11-06 10:59:59 +00:00
With the psql command tags gone the OIDC plugin task stays `ok`, but PeerTube was still force-recreated on every deploy: "Back-fill column defaults so bootstrap INSERT keeps NOT NULL" runs an unconditional `ALTER TABLE … SET DEFAULT`, database_query reports every non-SELECT as changed, and the task notifies compose-up, which runs `compose up -d --force-recreate`. A SELECT on information_schema.columns now lists the bootstrap columns (`nodeVersion`, `nodeABIVersion`) that still have no default, and the ALTER with its compose-up notification runs only when that list is not empty. A fresh database still gets the defaults before PeerTube's bootstrap INSERT retries; every later deploy skips the task. The unused register of the ALTER task is gone, and both read-only checks now live under files/sql/check-application/ as the sibling-prefix rule requires. Refs #1164 Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
85 lines
4.1 KiB
YAML
85 lines
4.1 KiB
YAML
---
|
|
# 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
|
|
notify: compose-up
|
|
|
|
- name: "🔍 Resolve {{ application_id }} hosting node + container id"
|
|
ansible.builtin.include_tasks: "{{ lookup('path_absolute', 'roles/sys-svc-compose/tasks/utils/swarm/resolve_host_cid.yml') }}"
|
|
vars:
|
|
resolve_service_key: "{{ entity_name }}"
|
|
resolve_output_prefix: PEERTUBE
|
|
resolve_compose_cid: "{{ PEERTUBE_CONTAINER }}"
|
|
|
|
- name: "⏳ PEERTUBE | Wait for peertube container healthy after schema back-fill"
|
|
ansible.builtin.command:
|
|
argv:
|
|
- container
|
|
- inspect
|
|
- --type
|
|
- container
|
|
- -f
|
|
- "{{ '{{.State.Health.Status}}' }}"
|
|
- "{{ PEERTUBE_LOCAL_CID }}" # nocheck: container-exec-resolver PEERTUBE_LOCAL_CID resolved at delegate_to runtime; container_address would return a manager-only subshell
|
|
register: _peertube_health
|
|
retries: 60
|
|
delay: 5
|
|
until: _peertube_health.rc == 0 and _peertube_health.stdout == "healthy"
|
|
delegate_to: "{{ PEERTUBE_HOST_NODE }}"
|
|
changed_when: false
|