Commit Graph

10 Commits

Author SHA1 Message Date
64be713b97 ci: add rsync + AppImage host tools (file, libfuse2, desktop-file-utils)
Some checks failed
CI / Quality (push) Failing after 3m49s
Release / Linux AppImage (push) Has been cancelled
After the QML/C++ build started succeeding, `make appimage` failed at
the staging-symfony step ("rsync: No such file or directory") — slim
runner image again. Adding:

  - rsync                — used by examples/todo/Makefile to stage a
                           --no-dev composer copy of the Symfony tree
                           into build/staging-symfony/.
  - file                 — appimagetool/linuxdeploy invoke `file` to
                           detect ELF type (AppImage, AppDir contents).
  - libfuse2             — AppImage runtime mounts the squashfs via
                           libfuse2; without it appimagetool refuses
                           to assemble. (Alternative is
                           APPIMAGE_EXTRACT_AND_RUN=1 but installing
                           libfuse2 keeps the script unchanged.)
  - desktop-file-utils   — appimagetool validates the bundled
                           .desktop file via desktop-file-validate.

ci.yml only needs cmake + ninja + rsync (the symfony staging happens
in `make build` which it runs too, after the QML build) — no AppImage
assembly there.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-03 10:40:54 +02:00
fca2378d63 ci: install cmake + ninja-build (act-runner image is slim)
Some checks failed
CI / Quality (push) Waiting to run
Release / Linux AppImage (push) Failing after 4m12s
GitHub-hosted ubuntu-latest preinstalls cmake and ninja. Gitea's
act-runner uses a minimal Ubuntu image (catthehacker/ubuntu:act-*)
which doesn't, so the build step fails with "cmake: command not
found" (exit 127).

apt-get update was already run by install-qt-action's deps step
earlier in the job, so the lists are populated — just install.

Same step added to ci.yml and release.yml.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-03 10:14:04 +02:00
6c1a3364c4 ci: drop modules:'qtquickcontrols2' (rolled into base Qt 6)
Some checks failed
CI / Quality (push) Failing after 3m40s
Release / Linux AppImage (push) Has been cancelled
aqt's "modules" list is for *additional* modules beyond the base Qt
install (qt5compat, qtcharts, qtmultimedia, qtwebsockets, etc.).
QtQuick.Controls 2 was a separately-shipped Qt 5 module, but in Qt
6.0+ it was folded into qtdeclarative — part of every base install.

aqt 3.3 rejects the obsolete name with:
  ERROR: The packages ['qtquickcontrols2'] were not found while
         parsing XML of package information!

Project's CMakeLists request `Core Gui Quick QuickControls2 Network
Qml` — all in base Qt 6.5. No `modules:` line needed.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-03 10:08:43 +02:00
badb5056c9 ci: pin Qt install dir for act-runner (runner.temp comes through empty)
Some checks failed
CI / Quality (push) Failing after 3m14s
Release / Linux AppImage (push) Has been cancelled
install-qt-action defaults `dir:` to `${{ runner.temp }}` if unset.
GitHub-hosted runners populate runner.temp; Gitea/Forgejo's act-runner
leaves it as the empty string. The action then rejects the empty path
with `TypeError: "dir" input may not be empty`.

Hardcoding `dir: ${{ github.workspace }}/qt` works on both — workspace
is always populated and writable, and the path is inside the job's
working tree so it's auto-cleaned with the workspace.

Same change in ci.yml and release.yml.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-03 10:03:31 +02:00
eac914d2d4 ci: work around install-qt-action propagating cache:true to setup-python
Some checks failed
CI / Quality (push) Failing after 3m13s
Release / Linux AppImage (push) Has been cancelled
jurplel/install-qt-action@v4 invokes actions/setup-python internally
with the same `cache:` value the user passes to the Qt action. Our
`cache: true` (intended for Qt's own install cache) gets propagated
verbatim, so setup-python receives `cache: 'true'` — which it rejects
with "Caching for 'true' is not supported" because the only valid
values are 'pip' / 'pipenv' / 'poetry'. Surfaces consistently on
Gitea/Forgejo's act-runner.

Workaround: provide our own actions/setup-python@v5 step (Python is
needed for aqtinstall, the tool install-qt-action uses to fetch Qt),
and set `setup-python: false` on the Qt action so it skips the
broken internal call. Qt's own install cache (the `cache: true` we
actually want) keeps working.

Applied to both .gitea/workflows/ci.yml and .gitea/workflows/release.yml.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-03 09:57:48 +02:00
d8726bac94 Fix CI: bump PHP requirement to ^8.4 (Symfony 8 enforces it)
CI was failing on the Install-bundle-dependencies step because
shivammathur/setup-php was installing 8.3 while Symfony 8.x dependencies
declare php >= 8.4. Local composer install worked because the dev box
runs PHP 8.5.5; CI doesn't.

Bumps:
  - framework/php/composer.json
  - framework/skeleton/symfony/composer.json
  - examples/todo/symfony/composer.json
  - .gitea/workflows/ci.yml         php-version: '8.3' → '8.4'
  - .gitea/workflows/release.yml    same
  - PLAN.md §13 Phase 1 *Detailed scope* PHP minimum row

PHPStan / cs-fixer / PHPUnit stay green locally.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-02 19:53:00 +02:00
adc0cdc11d Phase 3 sub-commit 5: maker-output snapshot test + phase closure
framework/php/tests/snapshot/ holds reference output for every shipped
maker (resource Todo, command MarkAllDone, window Todo). The
run.sh script:

  - git-archives the skeleton into a temp dir
  - composer-installs against the bundle's real path
  - removes the existing maker outputs so the regenerators don't bail
  - runs the three makers
  - diffs each generated file against the matching baseline

CI / make quality fail on any drift; if a template change is intended,
the baselines must be regenerated in the same commit. Wired into:

  - framework/skeleton/Makefile's `quality` target (local/dev runs)
  - .gitea/workflows/ci.yml (CI runs after qmllint)

Plus a few hardenings discovered while wiring this up:

  - The resource maker template now injects NormalizerInterface
    (not SerializerInterface — that interface lacks ::normalize()).
    All Todo controllers re-rendered to match.
  - The command maker template emits a $this->em->flush() so the
    injected EntityManager isn't a property.onlyWritten violation
    in PHPStan after the user fills in the body.
  - phpstan.neon and php-cs-fixer's Finder both exclude tests/snapshot
    so the baselines aren't auto-rewritten or analysed as live code.

CI workflow now also installs FrankenPHP, builds the todo example, and
runs the bridge-integration test from Phase 3 sub-commit 4.

Phase 3 done. Outstanding follow-ups (deferred per spec): the
qmltestrunner-driven QML unit tests, make:bridge:event,
make:bridge:read-model, ReactiveObject pagination.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-02 16:03:41 +02:00
d4343977e1 Phase 3 sub-commit 1: ReactiveObject (single-entity twin)
ReactiveObject mirrors ReactiveListModel for a single entity. Loads via
GET <baseUrl><source>, stays in sync via Mercure SSE on `topic`, and
exposes the entity's JSON keys on a `data` QQmlPropertyMap so QML reads
them as `obj.data.title` with bindings that re-evaluate on change.

Properties:
  - source / topic / baseUrl / token (configuration)
  - data (QQmlPropertyMap*)            — entity fields
  - ready                              — initial fetch finished
  - exists                             — entity present (false on 404 / delete)
  - pending                            — at least one optimistic mutation in flight
  - error

invoke(method, path, body, optimistic) is identical in shape to
ReactiveListModel.invoke(): apply optimistic to `data`, send the
request with an Idempotency-Key, clear `pending` on the matching
Mercure echo, roll back on 4xx/5xx or 10s timeout. The rollback
restores backed-up values and removes keys we added optimistically.

Wired into the QML module; the skeleton builds clean. Used by Phase 3
sub-commit 3's todo edit form.

Includes the merged CI trigger change (workflow now runs on `main`
branch only, not `dev` — keeps Gitea-runner pressure low while we're
iterating on dev).

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-02 15:12:50 +02:00
7323b9affe Phase 1 sub-commit 7: CI quality job
Some checks failed
CI / Quality (push) Has been cancelled
PHPStan (level 6 + symfony extension) and PHP CS Fixer (Symfony +
PHP83Migration ruleset) configs at framework/php/. composer.json
exposes phpstan / cs:check / cs:fix / phpunit / quality scripts.
PHPStan-clean across the bundle; cs:check is happy after auto-fix
applied @Symfony idioms (yoda, leading-backslash JSON_*, blank-line
before return). Test mocks consolidated into a HubSpy helper to keep
PHPStan happy about by-ref captures.

Skeleton's Makefile target `quality` chains `composer quality` (in
framework/php/) with cmake's all_qmllint target. Local run is green —
11 tests / 32 assertions, no PHPStan errors, cs-fixer clean, qmllint
emits advisory warnings only.

Layout fix in skeleton's Main.qml: status-dot Rectangles inside
RowLayout now use Layout.preferredWidth/Height instead of width/height
to satisfy Quick.layout-positioning checks.

.gitea/workflows/ci.yml replaces the placeholder with a real `quality`
job: setup-php, composer install (cached), the four PHP checks, Qt 6
via install-qt-action (cached), QML module build, qmllint via the
all_qmllint CMake target. Workflow exists from this commit onward
even if a runner isn't provisioned yet.

bridge:doctor lost the Publisher dependency since it was only used as
a "service is wired" marker — the command being injectable already
proves that.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-02 02:15:06 +02:00
9001386f92 Phase 1 sub-commit 1: scaffold framework, skeleton, CI
All checks were successful
CI / Quality (push) Successful in 48s
Stands up the directory structure Phase 1 fills in over subsequent
sub-commits: framework/php (Composer package php-qml/bridge),
framework/qml (Qt module placeholder), framework/skeleton (Caddyfile +
Makefile stubs), and .gitea/workflows/ci.yml. Root .gitignore covers
the build/composer/Symfony/Qt/CMake/IDE artefacts the rest of Phase 1
will produce. No bundle code, no Qt module sources, no working dev mode
yet — those land in sub-commits 2-7. Spike still in place.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-02 00:59:06 +02:00