main.ymlΒΆ

---
# nocheck: run-once β€” main.yml is the orchestrator entry point and intentionally
# re-runnable; per-service idempotency is enforced by each loaded role's own
# run_once_<role> flag inside load_service.yml.
#
# SPOT: global loader for all shared services.
#
# Called from tasks/stages/01_constructor.yml before the normal server app pass.
#
# Two-phase contract:
#   1. Preload pass β€” iterate `_ordered_services` in dependency order and
#      load each service body once (`service_loader_preloading: true`).
#   2. Post-load pass β€” flush the `service_loader_post_run` queue that
#      roles registered during preload via this role's `list_or_shoot.yml`.
#      Tasks listed there run with `service_loader_preloading: false`,
#      so they see the fully preloaded service graph.

- name: "πŸ” Discover ordered shared services"
  ansible.builtin.set_fact:
    _ordered_services: >-
      {{
        query(
          'service_registry',
          'ordered',
          roles_dir=(lookup('path_absolute', 'roles'))
        ) | first
      }}

- name: "πŸ” Precompute required shared services (single applications load)"
  ansible.builtin.set_fact:
    _required_service_ids: >-
      {{
        query(
          'service',
          (_ordered_services | map(attribute='id') | list),
          roles_dir=(lookup('path_absolute', 'roles'))
        )
        | selectattr('required')
        | map(attribute='id')
        | list
      }}

- name: "πŸ” Scope the preload to the whitelist's dependency closure"
  ansible.builtin.set_fact:
    _preload_closure: "{{ lookup('application_closure', lookup('deployment').whitelist) }}"

- name: "πŸ”Œ Load shared service"
  include_tasks: load_service.yml
  vars:
    service_key: "{{ service_item.id }}"
    service_role: "{{ service_item.role }}"
    service_run_once_var: "{{ 'run_once_' ~ (service_item.role | replace('-', '_')) }}"
  loop: "{{ _ordered_services }}"
  loop_control:
    loop_var: service_item
    label: "{{ service_item.id }}"

- name: "▢️ Run service-loader post-load roles"
  ansible.builtin.include_role:
    name: "{{ post_run_role }}"
  loop: "{{ service_loader_post_run | unique }}"
  loop_control:
    loop_var: post_run_role