Skip to content

feat(maintenance): follow planned maintenance on the applications you use, and read a supplier's roadmap - #1197

Merged
rubenvdlinde merged 3 commits into
developmentfrom
feat/maintenance-roadmap
Sep 29, 2026
Merged

rubenvdlinde merged 3 commits into
developmentfrom
feat/maintenance-roadmap

Conversation

@rubenvdlinde

Copy link
Copy Markdown
Contributor

Change: lifecycle-maintenance-and-supplier-roadmap (archived here as 2026-09-29-lifecycle-maintenance-and-supplier-roadmap; its spec is now openspec/specs/maintenance-and-supplier-roadmap/spec.md). It builds on the usage owners from #1194.

Rows moved to built: stackiq:life-maintenance-window and stackiq:mkt-supplier-roadmap (both rated yes now).

What a user can now do: a supplier opens its application's page and clicks Announce maintenance under Planned maintenance, with a title, a start, an end and the expected impact; the window moves from Planned to In progress, Completed or Cancelled. The business and technical owners of every usage of that application get a Nextcloud notification, and a reminder the day before a planned window starts. The dashboard lists the planned maintenance of the next 30 days on the applications the active organisation uses. The application page shows the supplier's roadmap statement and the application's versions on a timeline, planned versions first; Module versions gains a Planned releases tab and the development date column.

How: the maintenanceWindow schema joins the register (2.5.5) with its lifecycle and two notification rules (maintenance-announced, maintenance-starts-tomorrow) addressed to notifyUserIds. MaintenanceRecipientsListener queues MaintenanceRecipientsJob on create; the job's MaintenanceRecipientService reads the product's usages, maps their owners (contact persons) to Nextcloud users by the system address book UID or a unique e-mail match, and writes notifyUserIds with recipientsResolvedAt, whose change fires the announcement. SettingsService learns the maintenanceWindow_schema key in its three maps. roadmapStatement joins module through register.d/maintenance-and-roadmap.json (module 0.3.4). The dashboard widget type upcoming-maintenance (UpcomingMaintenanceWidget) and the body widget ProductRoadmap are custom because each joins two schemas. Two demo windows per register.

Design changes at build, recorded in the archived design: the schema lives in the register, not in a fragment (fragments only overlay, and the relation gate reads a fragment alone); the listener queues a job instead of writing inside the request (ADR-078); the rules use the relation recipient kind (the field kind takes one string) and fire on recipientsResolvedAt (the changed condition compares scalars only), both read from OpenRegister at 4abd8343; the moduleVersion lifecycle fix (design D5) had already landed in register 2.5.1 (#1140). The rules pass OpenRegister's own NotificationAnnotationValidator (run against the real class; a planted bad recipient kind was reported, so the check can fail).

Scenarios and the tests that prove them:

  • A supplier announces a window; the schema, lifecycle, rules, authorization and roadmap field; the schema id resolves through SettingsService: tests/Unit/Settings/MaintenanceRoadmapFragmentTest.php (6 tests, red on development; the schema id test also found the third map the key was missing from).
  • The owners of every usage are notified: tests/Unit/EventListener/MaintenanceRecipientsListenerTest.php (5 tests, red on development) constructs the real ObjectCreatedEvent shape (a copy of OpenRegister's class in tests/Stubs/Event/), asserts the listener only queues, runs the queued job and asserts three owners from two usages recorded as users.
  • A municipality sees the window on its dashboard, a buyer reads the roadmap, planned releases filter on a real status value, the pages and the seeds against the real schema: tests/vitest/maintenance.spec.js (12 tests, red on development).
  • The four user scenarios: tests/e2e/workflows/maintenance.spec.ts (Playwright, seeds and removes its own rows). It lists (4 tests); it was not run here, because no local instance has a seeded stackiq register.

New text is in English and Dutch. Docs: docs/features/maintenance-and-roadmap.md; its screenshot waits for a seeded instance.

Checks (one run on the branch head, which contains development at a4a28c4): composer check:strict exit 0; PHPUnit (phpunit-unit.xml) 945 tests, 20 errors, all 20 inherited and identical by name to development (MigrateRegisterSlugTest x12, MigrateSchemaApplicationIdTest x7, PortfolioReportControllerTest::testCsvFormatReturnsDownloadResponse: missing Doctrine/Symfony classes in the unit vendor); after the last commit (demo seed only) the two PHP tests that read the mock register rerun green (LifecycleStatesMatchEnumTest, DemoDataServiceTest); npm lint exit 0 (0 errors, warnings inherited), stylelint, format, test:l10n, check:schema-l10n, check:l10n-js, check:manifest, check:vue-demi exit 0; jest exit 0; vitest 350 of 350; Hydra gates at ConductionNL/.github main, full scope with --require-full-coverage: 86 of 86 applicable gates passed.

Live check: after the register re-imports, open an application you supply, click Announce maintenance and save a window next week with impact Unavailable; it lists as Planned. With a usage of that application whose business owner is a contact person matching a Nextcloud user, that user gets the notification after the next cron run. As a user of an organisation with that usage, the dashboard's Planned maintenance lists the window. Fill in Roadmap on the application and add a version in development; the application page shows both.

Inherited: the 20 PHPUnit errors above; 222 eslint warnings, none on a line this change added as an error.

@rubenvdlinde
rubenvdlinde merged commit 100db8c into development Sep 29, 2026
36 of 37 checks passed
@github-actions

Copy link
Copy Markdown
Contributor

Quality Report — ConductionNL/stackiq @ b506c55

Check PHP Vue Security License Tests
lint ✅
phpcs ✅
phpmd ✅
psalm ✅
phpstan ✅
phpmetrics ✅
eslint ✅
stylelint ✅
build ✅
check-manifest ✅
check-vue-demi ✅
test-l10n ✅
format ✅
check-schema-l10n ✅
check-l10n-js ✅
composer ✅ ✅ 130/130
npm ✅ ✅ 807/807
app:check-code ⏭️
info.xml ✅
REUSE ❌
lockfile sync ✅
PHPUnit ❌
Newman ⏭️
Playwright ⏭️ deferred: E2E runs locally and on the promotion path only. This pull request targets development, so the suite is asked once per promotion into beta and main rather than once per push per open pull request. Run it on any branch from the Actions tab, or locally with npx playwright test.
Hydra gates ✅

Quality workflow — 2026-09-29 22:17 UTC

Download the full PDF report from the workflow artifacts.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant