Release version 0.3.0

This commit is contained in:
2025-12-17 12:33:30 +01:00
parent b94c0fc050
commit da06943f29
10 changed files with 148 additions and 51 deletions

View File

@@ -1,3 +1,11 @@
## [0.3.0] - 2025-12-17
* - Introduced a layered Docker architecture: Infinito.Nexus now builds on pre-built pkgmgr base images, with a clear separation between base tooling, application source, and runtime logic.
- Standardized container paths (`/opt/src/infinito`) and switched to a global virtual environment to ensure reproducible builds and consistent test execution.
- Unit and lint tests now run reliably on this new layer model, both locally and in CI.
- Refactored build, setup, and deploy workflows to match the new layered design and improve maintainability.
## [0.2.1] - 2025-12-10
* restored full deployability of the Sphinx app by fixing the application_id scoping bug.

View File

@@ -1,27 +1,55 @@
import os
import warnings
from typing import Optional
_SOUND_DISABLED_REASON: Optional[str] = None
_SOUND_WARNED: bool = False
def _warn_sound_disabled_once() -> None:
"""
Emit the 'Sound support disabled' warning at most once per Python process.
Important:
- Do NOT warn at import time (avoids noisy unit test output).
- Warn only when a sound function is actually called.
"""
global _SOUND_WARNED
if _SOUND_WARNED:
return
if not _SOUND_DISABLED_REASON:
return
_SOUND_WARNED = True
warnings.warn(
f"Sound support disabled: {_SOUND_DISABLED_REASON}",
RuntimeWarning,
stacklevel=2,
)
class DummySound:
@staticmethod
def play_start_sound() -> None:
pass
_warn_sound_disabled_once()
@staticmethod
def play_infinito_intro_sound() -> None:
pass
_warn_sound_disabled_once()
@staticmethod
def play_finished_successfully_sound() -> None:
pass
_warn_sound_disabled_once()
@staticmethod
def play_finished_failed_sound() -> None:
pass
_warn_sound_disabled_once()
@staticmethod
def play_warning_sound() -> None:
pass
_warn_sound_disabled_once()
try:
@@ -210,7 +238,9 @@ try:
cls._prepare_and_play(freqs)
@classmethod
def _prepare_and_play(cls, freqs: list[float], durations: list[float] | None = None) -> None:
def _prepare_and_play(
cls, freqs: list[float], durations: list[float] | None = None
) -> None:
count = len(freqs)
if durations is None:
@@ -223,5 +253,7 @@ try:
cls._play(np.concatenate(waves))
except ImportError as exc:
warnings.warn(f"Sound support disabled: {exc}", RuntimeWarning)
# Do NOT warn at import time — this module is used in many unit tests / subprocess calls.
# Warn only when a sound method is actually invoked.
_SOUND_DISABLED_REASON = str(exc)
Sound = DummySound

View File

@@ -4,7 +4,7 @@ build-backend = "setuptools.build_meta"
[project]
name = "infinito-nexus"
version = "0.0.0"
version = "0.3.0"
description = "Infinito.Nexus"
readme = "README.md"
requires-python = ">=3.10"

View File

@@ -23,5 +23,3 @@ galaxy_info:
repository: https://s.infinito.nexus/code
issue_tracker_url: https://s.infinito.nexus/issues
documentation: "https://docs.infinito.nexus/"
dependencies: []

View File

@@ -3,32 +3,45 @@
name: nextcloud-client
state: present
- name: Link homefolders to cloud
ansible.builtin.file:
src: "{{nextcloud_cloud_directory}}{{ item }}"
dest: "{{nextcloud_user_home_directory}}{{ item }}"
owner: "{{ users[desktop_username].username }}"
group: "{{ users[desktop_username].username }}"
state: link
force: yes
ignore_errors: true # Just temporary @todo remove
loop:
- Templates
- Documents
- Videos
- Pictures
- Music
- Desktop
- Software
- Downloads
- Workspaces
- Books
- Screenshots
- name: Initialize dotlinker mapping list
ansible.builtin.set_fact:
nextcloud_dotlinker_mappings: []
- name: Link dump folder
ansible.builtin.file:
src: "{{nextcloud_cloud_directory}}InstantUpload"
dest: "{{nextcloud_user_home_directory}}Dump"
owner: "{{ users[desktop_username].username }}"
group: "{{ users[desktop_username].username }}"
state: link
- name: Build dotlinker mappings for Nextcloud folders
ansible.builtin.set_fact:
nextcloud_dotlinker_mappings: >-
{{
nextcloud_dotlinker_mappings + [
{
'name': 'nextcloud-' ~ (item | lower),
'backend': 'cloud',
'src': nextcloud_user_home_directory ~ item,
'dest': nextcloud_cloud_directory ~ item
}
]
}}
loop: "{{ nextcloud_dotlinker_folders }}"
- name: Add dump mapping (Dump -> InstantUpload)
ansible.builtin.set_fact:
nextcloud_dotlinker_mappings: >-
{{
nextcloud_dotlinker_mappings + [
{
'name': 'nextcloud-dump',
'backend': 'cloud',
'src': nextcloud_user_home_directory ~ 'Dump',
'dest': nextcloud_cloud_directory ~ 'InstantUpload'
}
]
}}
- name: Apply Nextcloud folder mappings via dotlinker
ansible.builtin.include_role:
name: desk-dotlinker
vars:
dotlinker_user: "{{ users[desktop_username].username }}"
dotlinker_config_path: "{{ nextcloud_user_home_directory }}.config/dotlinker/config.yaml"
dotlinker_replace: true
dotlinker_apply: true
dotlinker_mappings: "{{ nextcloud_dotlinker_mappings }}"

View File

@@ -1,4 +1,17 @@
application_id: desk-nextcloud
nextcloud_user_home_directory: "/home/{{ users[desktop_username].username }}/"
nextcloud_cloud_fqdn: "{{ applications | get_app_conf(application_id, 'credentials.cloud_fqdn') }}"
nextcloud_cloud_directory: '{{ nextcloud_user_home_directory }}Clouds/{{nextcloud_cloud_fqdn}}/{{ users[desktop_username].username }}/'
nextcloud_cloud_directory: "{{ nextcloud_user_home_directory }}Clouds/{{ nextcloud_cloud_fqdn }}/{{ users[desktop_username].username }}/"
nextcloud_dotlinker_folders:
- Templates
- Documents
- Videos
- Pictures
- Music
- Desktop
- Software
- Downloads
- Workspaces
- Books
- Screenshots

View File

@@ -5,6 +5,7 @@
- sys-bkp-provider
- sys-ctl-alm-compose
- sys-lock
- dev-nix
- include_tasks: 02_pkgmgr_routines.yml
when: backup_docker_to_local_folder is not defined

View File

@@ -1,19 +1,50 @@
- block:
- name: "pkgmgr install {{ BKP_DOCKER_2_LOC_PKG }}"
include_role:
name: pkgmgr-install
vars:
package_name: "{{ BKP_DOCKER_2_LOC_PKG }}"
- name: "Install/update {{ BKP_DOCKER_2_LOC_PKG }} via pkgmgr (nix run)"
become: true
ansible.builtin.command:
argv:
- nix
- run
- --no-write-lock-file
- "github:kevinveenbirkenbach/package-manager#pkgmgr"
- --
- update
- "{{ BKP_DOCKER_2_LOC_PKG }}"
- --dependencies
- --clone-mode
- shallow
register: pkgmgr_update_result
changed_when: >
('already up to date' not in ((pkgmgr_update_result.stdout | default('') | lower)
~ ' ' ~ (pkgmgr_update_result.stderr | default('') | lower)))
and
('no command defined' not in ((pkgmgr_update_result.stdout | default('') | lower)
~ ' ' ~ (pkgmgr_update_result.stderr | default('') | lower)))
failed_when: >
(pkgmgr_update_result.rc != 0)
and
('no command defined' not in ((pkgmgr_update_result.stdout | default('') | lower)
~ ' ' ~ (pkgmgr_update_result.stderr | default('') | lower)))
- name: "Retrieve {{ BKP_DOCKER_2_LOC_PKG }} path from pkgmgr"
command: "pkgmgr path {{ BKP_DOCKER_2_LOC_PKG }}"
- name: "Retrieve {{ BKP_DOCKER_2_LOC_PKG }} path via pkgmgr (nix run)"
become: true
ansible.builtin.command:
argv:
- nix
- run
- --no-write-lock-file
- "github:kevinveenbirkenbach/package-manager#pkgmgr"
- --
- path
- "{{ BKP_DOCKER_2_LOC_PKG }}"
register: pkgmgr_output
changed_when: false
- name: Set fact for backup_docker_to_local_folder
set_fact:
backup_docker_to_local_folder: "{{ pkgmgr_output.stdout }}/"
ansible.builtin.set_fact:
backup_docker_to_local_folder: "{{ (pkgmgr_output.stdout | trim) ~ '/' }}"
changed_when: false
when: backup_docker_to_local_folder is not defined
vars:
BKP_DOCKER_2_LOC_PKG: backup-docker-to-local

View File

@@ -6,7 +6,7 @@ configuration:
default_push_create_private: True # Default private when creating a new repository with push-to-create.
features:
matomo: true
css: false
css: true
desktop: true
central_database: true
ldap: true

View File

@@ -15,6 +15,7 @@ GITEA_LDAP_AUTH_ARGS:
- '--bind-password "{{ LDAP.BIND_CREDENTIAL }}"'
- '--user-search-base "{{ LDAP.DN.OU.USERS }}"'
- '--user-filter "(&(objectClass=inetOrgPerson)(uid=%s))"'
- '--admin-filter "(memberOf=cn={{ application_id }}-administrator,{{ LDAP.DN.OU.ROLES }})"'
- '--username-attribute "{{ LDAP.USER.ATTRIBUTES.ID }}"'
- '--firstname-attribute "{{ LDAP.USER.ATTRIBUTES.FIRSTNAME }}"'
- '--surname-attribute "{{ LDAP.USER.ATTRIBUTES.SURNAME }}"'