How to launch playbook only on the first host of each inventory group? ...  I cannot "hardcode" the groups upfront ... the complete inventory which consist out of 150 or more host groups ...
From the question and description you've provided I understand that you like to dynamically limit the execution of a playbook to certain hosts and groups. As it is still not clear (for me) what exactly and where you try to achieve, I'll provide one possible approach with CLI tools. Within a playbook and for tasks there would be other options available.
An example inventory hosts like
[tomcat]
tomcat1.example.com
tomcat2.example.com
tomcat3.example.com
[apache]
apache1.example.com
apache2.example.com
apache3.example.com
[sql]
sql1.example.com
sql2.example.com
sql3.example.com
ansible-inventory -i hosts --graph
@all:
  |--@apache:
  |  |--apache1.example.com
  |  |--apache2.example.com
  |  |--apache3.example.com
  |--@sql:
  |  |--sql1.example.com
  |  |--sql2.example.com
  |  |--sql3.example.com
  |--@tomcat:
  |  |--tomcat1.example.com
  |  |--tomcat2.example.com
  |  |--tomcat3.example.com
  |--@ungrouped:
with a group list
ansible-inventory -i hosts --list | jq --raw-output '.all.children[]'
apache
sql
tomcat
ungrouped
and example playbook groups.yml like
---
- hosts: '*'
  become: false
  gather_facts: false
  tasks:
  - name: Show Facts
    debug:
      msg: "{{ item }}"
    when: item == inventory_hostname
    loop: "{{ ansible_play_hosts }}"
called via
LIMIT=$(ansible-inventory -i hosts --list | jq --raw-output '.all.children[]' | head -n -1 | sed s/$/[0]/ | tr '\n' ',' | rev | cut -c2- | rev)
echo ${LIMIT}
apache[0],sql[0],tomcat[0]
ansible-playbook -i hosts groups.yml --limit="${LIMIT}"
will result into an oputput of
TASK [Show Facts] ****************************************
ok: [apache1.example.com] => (item=apache1.example.com) =>
  msg: apache1.example.com
ok: [tomcat1.example.com] => (item=tomcat1.example.com) =>
  msg: tomcat1.example.com
ok: [sql1.example.com] => (item=sql1.example.com) =>
  msg: sql1.example.com
As one can see it is executing on the first host of each inventory group only.
The approach is using
- an environment variable LIMITto store the generated list for--limit
- the ansible-iventoryto listallgroup
- removes the default group ungroupedfrom the output
- defines one list element by adding [0]
- creates an CSV from the output by exchanging line breaks \nwith,
- and deletes the last ,
Similar Q&A
Further Readings and used during research
Since there might be other or better solutions possible ...
Follow-Ups