Commit Graph
148 Commits
Author SHA1 Message Date
Environment TestandClaude Sonnet 4.6 eebb3b9788 refactor(utils): move utils/docker/image_*.py into utils/docker/image/ subpackage
- Move image_discovery.py → utils/docker/image/discovery.py
- Move image_ref.py → utils/docker/image/ref.py
- Add utils/docker/image/__init__.py
- Update all imports and references across cli/, tests/, utils/, and docs/

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-04-10 19:00:02 +02:00
Environment TestandClaude Sonnet 4.6 ce19aff65f feat(mirror): add cleanup module to delete private GHCR packages
Adds cli.mirror.cleanup for deleting GHCR container packages by prefix
and visibility via the GitHub Packages REST API. Supports dry-run mode.
Requires a classic PAT with delete:packages scope (GITHUB_TOKEN from
gh auth or GitHub Actions does not include this scope).

Also adds unit tests and a usage guide at
docs/contributing/flow/security/mirror-cleanup.md.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-04-10 14:54:39 +02:00
Environment TestandClaude Sonnet 4.6 7cb80eb830 fix(mirror): use GITHUB_TOKEN for GHCR push to auto-publish packages
Replaces GHCR_PAT-based authentication with GITHUB_TOKEN across all
mirror and build workflows. Packages pushed from a public repository
with GITHUB_TOKEN are automatically linked to the repository and
inherit its public visibility — no publish step required.

Removes cli.mirror.publish (used a non-existent GitHub REST API
endpoint for changing package visibility), the associated unit tests,
and the GHCR_PAT debug helper. Cleans up all GHCR_PAT/GHCR_USERNAME
references and rewrites the GHCR authentication documentation.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-04-10 14:25:51 +02:00
Environment TestandClaude Sonnet 4.6 aa33256cde feat(mirror): split resolver output, move images to defaults, add lookup plugin
- resolver: output both applications: (config/main.yml compose images) and
  images: (defaults/main.yml images) keyed by source_file
- image_discovery: scan defaults/main.yml instead of vars/main.yml for images:
- mirror_overrides: write mirror URLs to applications.*.compose.services.*
  (mirror_policy-aware) and images_overrides.*.* (always merged, if_missing)
- roles/sys-ctl-hlth-csp, roles/test-e2e-playwright: move images: from
  vars/main.yml to defaults/main.yml for correct Ansible variable precedence
- plugins/lookup/image.py: new Ansible lookup plugin that prefers
  images_overrides over role-local images defaults
- docs: add artefact/image.md and artefact/mirror.md as SPOTs; add
  code/role/image.md contributor guide; link from ci.md
- tests: update test_util, test_mirror_overrides; add test_resolver,
  test_publish (404/401 coverage), test_image (lookup plugin)

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-04-10 11:17:42 +02:00
Environment TestandClaude Sonnet 4.6 1530788dbe feat(mirror): add repository segment to GHCR image path
Image names now follow {owner}/{repository}/mirror/{registry}/{name}
instead of {owner}/mirror/{registry}/{name}.

- GHCRProvider: add `repository` param + `add_args()`/`from_args()` classmethods
  as SPOT for CLI argument registration and provider construction
- sync, resolver: use GHCRProvider.add_args() / from_args() (no duplication)
- Workflows: resolve repository name via scripts/meta/resolve/repository/name.sh
  and pass --ghcr-repository to sync and publish
- mirrors.sh: require and forward GHCR_REPOSITORY env var
- deploy/development/mirrors.py: derive repository from GITHUB_REPOSITORY
- Tests: update expected paths, argv and env fixtures

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-04-10 00:20:41 +02:00
Environment TestandClaude Sonnet 4.6 317287983a fix(mirror): resolve merge conflicts with fix/playwright-pull
Keep new multi-registry logic (feature/pre-commit):
- Merge is_mirrorable_image(), _detect_registry(), image_source() and
  canonical_image_name() into utils/docker/image_discovery.py
- iter_role_images() now scans both config/main.yml and vars/main.yml
  and uses image_source() for full registry-prefixed URLs
- Delete cli/mirror/util.py (superseded by utils/docker/image_discovery)
- model.py re-exports ImageRef from utils.docker.image_discovery
- sync/__main__.py: revert fix/playwright-pull's if/else src URL to
  simple `src = f"docker://{img.source}"` (source already contains
  the full registry prefix)

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-04-09 23:44:58 +02:00
Environment TestandClaude Sonnet 4.6 e8a5896881 feat(mirror): include registry domain in package name and fix multi-registry source URLs
- Add `registry` field to `ImageRef` (default `"docker.io"`)
- Populate `registry` from `_detect_registry()` in `iter_role_images()`
- `GHCRProvider.image_base()` and `GiteaProvider.image_base()` now produce
  `{prefix}/{registry}/{name}` paths (e.g. `mirror/docker.io/nextcloud`,
  `mirror/quay.io/keycloak/keycloak`) instead of flattening slashes to dashes
- Fix `mirror()` in both providers: use `docker://{image.source}` directly
  instead of always prepending `docker://docker.io/`, which broke quay.io/ghcr.io images
- Update tests to reflect new naming convention and add quay.io test case
- Add missing __init__.py files in test subdirectories

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-04-09 22:57:33 +02:00
Environment TestandClaude Sonnet 4.6 3f19ec1df4 fix(mirror): extend registry support and harden publish visibility handling
Extend image mirroring to cover quay.io and ghcr.io in addition to Docker Hub,
and make the publish step non-fatal when the token lacks write:packages scope.

cli/mirror/util.py:
- Add _detect_registry(), _strip_registry_prefix(), is_mirrorable_image()
  to support Docker Hub, quay.io, ghcr.io, and mcr.microsoft.com
- Update canonical_image_name() to strip any known registry prefix so that
  quay.io/keycloak/keycloak -> keycloak/keycloak (mirror/keycloak-keycloak)
- Add image_source() returning full registry-prefixed pull reference
  (docker.io/library/postgres:16, quay.io/keycloak/keycloak:latest, …)
- iter_role_images() now uses is_mirrorable_image + image_source, picking up
  the 17 previously skipped quay.io/ghcr.io images

cli/mirror/sync/__main__.py:
- Use docker://{img.source} directly (no hardcoded docker.io/ prefix)

cli/mirror/publish/__main__.py:
- Detect HTTP 404 on PATCH as _InsufficientTokenError (no retry, graceful
  GHA warning + exit 0) instead of retrying 5x and failing the workflow
- Use pkg.get("url") from listing response as canonical PATCH target URL
- Use safe="/" in urllib.parse.quote so mirror/name stays as literal path
- Do not retry on non-transient 4xx errors (400/401/403)

tests/unit/cli/mirror/test_sync.py:
- Update ImageRef.source to new docker.io/library/… format

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-04-09 22:27:11 +02:00
Environment TestandClaude Sonnet 4.6 9ea2ad6ff1 refactor(docker): introduce utils/docker/image_discovery as single SPOT for image enumeration
- Move iter_role_images + all helpers + ImageRef from cli/mirror/util.py and
  cli/mirror/model.py into utils/docker/image_discovery.py; add source_file field
  to ImageRef to distinguish config/main.yml vs vars/main.yml entries
- Delete cli/mirror/util.py; update all callers to import from utils.docker.image_discovery
- Move utils into subpackages: utils/docker/ (image_ref, paths_utils, hadolint) and
  utils/roles/ (dependency_resolver, resource_validation); update all imports
- Reorganise tests into subpackages: tests/lint/docker/dockerfile/, tests/integration/docker/,
  tests/unit/utils/docker/, tests/unit/utils/roles/; fix parents[N] offsets after relocation
- tests/lint/docker/test_image_versions.py now uses iter_role_images (same SPOT as mirror)
- Add vars/main.yml images.<name>.{image,version} support for non-application roles
  (test-e2e-playwright, sys-ctl-hlth-csp); eliminate hardcoded duplicates in defaults/tasks
- Add web-app-matrix matrix-chatgpt-bot and web-app-mini-qr mini-qr entries in config/main.yml;
  replace hardcoded image strings in vars/templates with lookup('config', ...) references
- Fix sync/__main__.py log line to use correct registry prefix for non-Docker-Hub images
- Update docs/contributing/code/role/dockerfile.md with image declaration rules and SPOT reference

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-04-09 19:32:31 +02:00
Environment TestandClaude Sonnet 4.6 3ea40bbfc5 fix(mirror): fall back to user endpoint when org endpoint returns 404
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-04-09 10:25:58 +02:00
kevinveenbirkenbachandClaude Sonnet 4.6 70055f7861 refactor(mirror): extract visibility logic into standalone publish module
Move _set_public/ensure_public out of GHCRProvider into a new
cli.mirror.publish module that lists all non-public mirror packages
via the GitHub API and sets them public in bulk. The workflow runs
this as a separate step after mirroring. Mirror sync itself no longer
touches visibility.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-04-08 23:19:15 +02:00
kevinveenbirkenbachandClaude Sonnet 4.6 0ce6b1347c refactor(annotations): move to utils/annotations, add step summary support
- Move utils/gha/annotations.py → utils/annotations/message.py
- Move scripts/gha/summarize_annotations.py → utils/annotations/summarize.py
- Keep utils/gha/annotations.py as compatibility shim
- Update all imports across codebase to utils.annotations.message
- Wire tee + summary step into test-code-lint, unit, and integration workflows
- Add unit tests for utils/annotations/summarize (20 tests)

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-04-08 14:05:24 +02:00
kevinveenbirkenbachandClaude Sonnet 4.6 e1966c16da refactor(gha): centralize annotation helpers in utils/gha/annotations.py
Replace copy-pasted ::warning prints and _gha_escape helpers across lint
tests and utils with a shared utility that emits GHA workflow commands in
CI and plain [WARNING]/[ERROR]/[NOTICE] lines locally. Update
test_role_resource_validation to capture stdout instead of stderr.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-04-08 12:32:06 +02:00
kevinveenbirkenbachandClaude Sonnet 4.6 5e970ff5bd feat(gha): introduce utils/gha/annotations for GitHub Actions workflow annotations
- Add utils/gha/annotations.py with warning/error/notice helpers and *_each
  variants that emit one annotation per list item
- Use warning() in GHCRProvider._set_public for missing GHCR_PAT case
- Expose GHCR_PAT_SET env var in mirror step to distinguish missing-PAT from
  real API failures
- Add unit tests for all annotation functions

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-04-08 10:59:46 +02:00
kevinveenbirkenbachandClaude Sonnet 4.6 312233aa42 fix(mirror): use /user/packages endpoint for authenticated user visibility update
/users/{username}/packages does not support PATCH — it is a read-only endpoint
for public data. The correct endpoint for updating visibility of the authenticated
user's packages is /user/packages (without username).

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-04-08 10:23:15 +02:00
kevinveenbirkenbach 33a7eef589 lint 2026-04-08 09:55:32 +02:00
kevinveenbirkenbachandClaude Sonnet 4.6 7c8783c623 fix(mirror): use GHCR_PAT for package visibility API and remove ensure_public from skip path
Root cause: GITHUB_TOKEN in Actions is repo-scoped and cannot change package
visibility in user/org namespaces — all 58 mirror operations failed with 404.

- Use GHCR_PAT (which has write:packages scope) as GITHUB_TOKEN in the mirror
  step, falling back to GITHUB_TOKEN if GHCR_PAT is not set
- Remove ensure_public() call from the already-exists skip path (wrong place:
  existing images were already made public when first mirrored)
- Update test to assert ensure_public is not called for skipped images

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-04-08 09:45:38 +02:00
kevinveenbirkenbach 7bf06efc9e lint 2026-04-08 07:46:15 +02:00
kevinveenbirkenbachandClaude Sonnet 4.6 b3a4a81e01 fix(mirror): remove redundant mirror job and publish images as public
- Remove redundant `images-mirror-missing` job from entry-pull-request-change.yml
  (mirroring already runs via ci-orchestrator for same-repo PRs)
- Set GHCR package visibility to public after each successful mirror via GitHub API
- Add `ensure_public` hook to base class (no-op for other providers)
- Also call `ensure_public` for already-existing images to fix any that are still private
- Pass GITHUB_TOKEN explicitly to the mirror step
- Add unit tests for _set_public (user/org endpoint fallback) and sync skip-path

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-04-08 07:45:33 +02:00
kevinveenbirkenbach c3fb04e91a refactor: share application dependency resolution 2026-04-01 15:13:04 +02:00
kevinveenbirkenbach 00193b4a23 Rename the canonical services map to SERVICE_REGISTRY 2026-03-31 21:43:29 +02:00
kevinveenbirkenbach 9cbb12d540 Propagate host MTU to the local compose network 2026-03-31 21:00:51 +02:00
kevinveenbirkenbach 017818976a test(services): cover pixelfed dashboard dependency 2026-03-30 19:49:42 +02:00
kevinveenbirkenbachandClaude Sonnet 4.6 96649d8c9b refactor(services): centralize frontend service loading with generic lookup plugin
Introduces a SPOT for all frontend service loading in sys-front-inj-all/tasks/01_services.yml,
driven by a new generic `service` lookup plugin that resolves services by key or role name
and returns {id, role, enabled, shared, needed}. Needed = enabled AND shared (direct or
transitive). The canonical key→role mapping moves to group_vars/all/20_services.yml
(previously scattered hardcoded rules). Removes per-role service loads from bigbluebutton,
nextcloud, and dashboard. Renames 01_dependencies.yml→01_services.yml and
08_services.yml→08_daemons.yml. Adds flush_handlers after each service load.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-03-30 08:27:21 +02:00
kevinveenbirkenbachandClaude Sonnet 4.6 18779de223 feat(services-disabler): set enabled/shared false for all roles defining service
Scans roles_dir to find every role whose config/main.yml defines the
disabled service, then creates or updates the compose.services entry in
host_vars for each matching role — including roles not yet present in
applications. roles_dir is now a required parameter (no Optional fallback).

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-03-30 02:02:36 +02:00
kevinveenbirkenbachandClaude Sonnet 4.6 a50c90c733 fix(deploy): resolve SERVICES_DISABLED service names to app IDs and verify inventory
- deploy.py: use find_provider_roles() to map service names (e.g. 'matomo')
  to provider app IDs (e.g. 'web-app-matomo') before filtering deploy_ids;
  forward SERVICES_DISABLED into the container via extra_env
- container.sh: rename INSPECT_CMD to CMD for consistency; fix indentation
- Makefile: expose CMD variable on exec target for non-interactive use
- environment.sh: source scripts/meta/env/all.sh for INVENTORY_DIR; add
  inventory verification after SERVICES_DISABLED deploy using make exec
- variables.md: document CMD variable

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-03-30 01:26:44 +02:00
kevinveenbirkenbachandClaude Sonnet 4.6 135ceefa98 fix(build): add SPOT for local image name and fix missing REPO_PREFIX
Add scripts/meta/resolve/image/local.sh as SPOT for the local Docker
image tag (<repo-basename>/<distro>). Wire it into Makefile build
targets (IMAGE_TAG), compose.py (_base_env sets INFINITO_IMAGE), and
compose.yml (no default fallback). Fix build.sh to accept a pre-set
IMAGE_TAG without requiring REPO_PREFIX. Add make build + build-no-cache
to environment.sh test flow with correct section ordering.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-03-30 00:16:27 +02:00
kevinveenbirkenbachandClaude Sonnet 4.6 9d863f1ef4 feat(inventory): add SERVICES_DISABLED env var support and environment test flow
- Add services_disabler.py: parse SERVICES_DISABLED, disable services in host_vars,
  remove provider roles from inventory
- Wire apply_services_disabled_from_env into cli/create/inventory/cli.py after deploy
- Add unit tests for all services_disabler functions
- Update hardware.md and variables.md with SERVICES_DISABLED documentation
- Update environment.sh: deploy dashboard with SERVICES_DISABLED=matomo first,
  assert dashboard reachable + matomo not reachable, then deploy matomo and assert
  reachable; extract assert_http_status / assert_http_status_not helpers

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-03-29 15:00:24 +02:00
kevinveenbirkenbach 2b0ed2eacf Merge branch 'feature/pixelfed-playwright' into feature/taiga-ldap 2026-03-28 09:22:30 +01:00
kevinveenbirkenbach 67fadb57b8 refactor: normalize inventory filename to devices 2026-03-28 05:40:13 +01:00
kevinveenbirkenbach 2f0edbb2fc Fix oauth2 proxy cookie secret generation 2026-03-26 01:15:08 +01:00
kevinveenbirkenbach fe764735c3 Stabilize webserver and tree unit tests 2026-03-21 11:56:18 +01:00
kevinveenbirkenbach d8218babfc Fix DNS hosts fallback and domains CLI 2026-03-21 09:12:24 +01:00
kevinveenbirkenbach 189267496d Rename module_utils package to utils 2026-03-21 02:05:39 +01:00
kevinveenbirkenbach 44ea2df452 Fix dev workflow image build and docker repo bootstrap 2026-03-19 19:11:51 +01:00
kevinveenbirkenbach ad3f159548 Require Docker Compose in dev packaging 2026-03-19 11:25:49 +01:00
kevinveenbirkenbach ec30948546 fix(deploy): use bash -lc for commands with pipefail 2026-02-21 16:05:42 +01:00
kevinveenbirkenbach 0710c41f91 fix(ci): run mirror resolver with venv python in container 2026-02-20 11:25:46 +01:00
kevinveenbirkenbach 6efde55647 refactor(dashboard): rename web-app-desktop to web-app-dashboard and update service toggle
* replace compose.services.desktop with compose.services.dashboard across all roles
* rename role web-app-desktop to web-app-dashboard
* rename sys-front-inj-desktop to sys-front-inj-dashboard
* update resolver mapping to include web-app-dashboard when dashboard is enabled
* adjust CSP filters to reference dashboard for frame-ancestors handling
* update lookup plugins, filter plugins, templates, vars and run_once flags
* migrate all tests to dashboard naming and service key
* update role dependencies and port mappings
* remove legacy desktop role and variables

BREAKING CHANGE:
The service key compose.services.desktop has been renamed to compose.services.dashboard.
All custom configs, inventories, or overrides must be updated accordingly.

https://chatgpt.com/share/698da7ad-1978-800f-82b4-4755b17be026
2026-02-12 11:12:49 +01:00
kevinveenbirkenbach efe2ea3357 **test: align deployment type tests with invokable-based semantics**
Update unit tests to reflect the new invokable-driven classification logic by mocking invokable path discovery, removing legacy alias expectations, and adding coverage for universal and mixed cases. Also relocate CLI deploy tests into the unit test hierarchy for consistency.
2026-02-10 21:38:02 +01:00
kevinveenbirkenbach 5acce545e1 refactor(cli): remove sound, alarm and server-type flags
Drop the sound/alarm subsystem and deprecated CLI flags.

* Remove --sound, --no-signal and --alarm-timeout
* Remove server-type flag (-T / TEST_DEPLOY_TYPE)
* Delete sound-related modules
* Simplify RunConfig and runner error handling
* Update help output, scripts and tests
* Remove optional audio extras from pyproject.toml

https://chatgpt.com/share/698b74f1-0c0c-800f-98c4-183697d6a2a0
2026-02-10 19:10:37 +01:00
kevinveenbirkenbach 449781fa73 fix(ci): make sufficient_storage JSON-safe and stabilize test matrix generation
Switch sufficient_storage CLI to support JSON output and update CI matrix
generation to use JSON-only pipelines, preventing roles from collapsing
into a single matrix entry.
2026-02-10 14:06:54 +01:00
kevinveenbirkenbach df9a23ceed feat(ci): unify invokable app discovery and add lifecycle filtering
- Move server/workstation/universal resolution into Python CLI
- Add optional --lifecycles filter to cli.meta.applications.type
- Gate invokable roles by galaxy_info.lifecycle in module_utils.invokable
- Replace legacy resolve-invokable-roles.sh with CLI-based implementation
- Apply global hard excludes consistently across all deploy types
- Fix SC2086 issues and make lifecycle argument handling shell-safe
- Extend unit tests to cover lifecycle forwarding and normalization

https://chatgpt.com/share/698b0039-c4c4-800f-b962-7033324c07a8
2026-02-10 11:50:09 +01:00
kevinveenbirkenbach 84782f3b22 refactor(invokable): centralize app discovery, add type grouping, and derive deploy stages from inventory groups
https://chatgpt.com/share/698b0039-c4c4-800f-b962-7033324c07a8
2026-02-10 10:53:53 +01:00
kevinveenbirkenbachandCopilot Autofix powered by AI c84616fd50 Potential fix for code scanning alert no. 168: Module is imported with 'import' and 'import from'
Co-authored-by: Copilot Autofix powered by AI <62310815+github-advanced-security[bot]@users.noreply.github.com>
2026-02-09 07:59:57 +01:00
kevinveenbirkenbach b78ab29218 Renamed config entry from docker to compose
https://chatgpt.com/share/69870f54-d708-800f-9870-e9ae5a4bff44
2026-02-07 11:09:36 +01:00
kevinveenbirkenbach 8a81630391 Added newline at file and POSIX compatible 2026-02-04 19:49:56 +01:00
kevinveenbirkenbach 9a84fafec5 feat(inventory): add mirror_policy to control mirror image overrides
- Default policy (if_missing): manual image/version win, mirror fills blanks only
- Add mirror_policy=force to always overwrite image/version
- Add mirror_policy=skip to ignore mirror completely
- Treat empty/whitespace values as missing
- Preserve non-image/version service keys
- Extend unit tests to cover all mirror policy scenarios

https://chatgpt.com/share/6981036a-7e40-800f-b43e-13c66cc55fac
2026-02-02 21:04:53 +01:00
kevinveenbirkenbach a70a033864 feat(inventory): add --mirror support to override docker images from mirrors file
- add --mirror flag to inventory creator
- resolve mirrors.yml automatically or via explicit path
- apply mirror overrides to applications.*.docker.services.* (image/version only)
- keep existing host_vars keys untouched
- add unit tests for mirror override behavior

https://chatgpt.com/share/6980cdb1-1e5c-800f-b25f-a1af757e4239
2026-02-02 17:15:30 +01:00
kevinveenbirkenbach 4a5736615f Solved falsy file paths 2026-01-29 17:43:22 +01:00