Release: merge development into beta - #337
Conversation
The 1.4.6-beta.20260831102710 release bumped the version on beta. Without this, development stays behind beta and the next development -> beta promotion conflicts on the version file. Version files resolve to development's side, which is the higher line, so this never moves a version backwards.
…4.6-beta.20260831102710 chore(release): sync beta back into development
Co-authored-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com>
Quality Report — ConductionNL/versioniq @
|
| Check | PHP | Vue | Security | License | Tests |
|---|---|---|---|---|---|
| lint | ✅ | ||||
| phpcs | ✅ | ||||
| phpmd | ✅ | ||||
| psalm | ✅ | ||||
| phpstan | ✅ | ||||
| phpmetrics | ✅ | ||||
| eslint | ✅ | ||||
| stylelint | ✅ | ||||
| build | ✅ | ||||
| composer | ✅ | ✅ 29/29 | |||
| npm | ✅ | ✅ 302/302 | |||
| app:check-code | ⏭️ | ||||
| info.xml | ✅ | ||||
| REUSE | ❌ | ||||
| PHPUnit | ✅ | ||||
| Newman | ⏭️ | ||||
| Playwright | ✅ | ||||
| Hydra gates | ✅ |
Quality workflow — 2026-08-31 14:41 UTC
Download the full PDF report from the workflow artifacts.
…em (#339) psalm-baseline.xml held 103 suppressions. Five of them described the analysis setup or a genuinely fragile read rather than an accepted compromise, so they are fixed rather than carried. 103 -> 98. The one worth reading twice was an UndefinedMethod on Doctrine\DBAL\Schema\Table::getColumn, raised against a MIGRATION. A migration that calls a method that does not exist fatals at upgrade time, which is the worst place to find out. It turned out to be a stub gap, not a bug: doctrine/dbal is a runtime dependency of the Nextcloud SERVER and is absent from an app vendor tree, so Psalm reads tests/stubs/server-internals.php, and that stub declared only addColumn, setPrimaryKey, addIndex and addUniqueIndex. The migration is correct. The stub now models getColumn and Column::setDefault, so the next migration that adjusts an existing column is checked instead of suppressed. The other two were a PossiblyNullIterator and a PossiblyUndefinedArrayOffset over $result[releases] in ForgeReleaseSource. performFetch does declare releases on every ok:true branch, but the union collapses to optional keys through useToken generic, so Psalm cannot see it. Reading the key defensively is cheaper than a suppression and is correct either way: a body that arrives without it now yields no advisories instead of iterating null. Verified with the repo own vendor/bin/psalm 5.26.1 on PHP 8.3. Errors with the baseline emptied went 103 -> 98, and the regenerated baseline is green. PHPUnit was NOT run here: it needs the Nextcloud server bootstrap at ../../../tests/bootstrap.php, which only exists inside a server checkout. Co-authored-by: Conduction Release Bot <release-bot@conduction.nl>
Quality Report — ConductionNL/versioniq @
|
| Check | PHP | Vue | Security | License | Tests |
|---|---|---|---|---|---|
| lint | ✅ | ||||
| phpcs | ✅ | ||||
| phpmd | ✅ | ||||
| psalm | ✅ | ||||
| phpstan | ✅ | ||||
| phpmetrics | ✅ | ||||
| eslint | ✅ | ||||
| stylelint | ✅ | ||||
| build | ✅ | ||||
| composer | ✅ | ✅ 29/29 | |||
| npm | ✅ | ✅ 302/302 | |||
| app:check-code | ⏭️ | ||||
| info.xml | ✅ | ||||
| REUSE | ❌ | ||||
| PHPUnit | ✅ | ||||
| Newman | ⏭️ | ||||
| Playwright | ✅ | ||||
| Hydra gates | ✅ |
Quality workflow — 2026-08-31 16:40 UTC
Download the full PDF report from the workflow artifacts.
…e API (#341) OCP\IConfig::getAppValue is @deprecated 29.0.0 with "Use IAppConfig directly". ForgeRegistry read exactly one app value and nothing else off IConfig, so it is a clean swap: IAppConfig::getValueString, same three arguments, and a declared string return instead of a loose one. That precision paid for itself immediately. Five (string)/(bool) casts over self::DEFAULTS became provably redundant and are removed; they were already carried in the baseline, so this is not new debt exposed but old debt closed. 98 -> 92. Six construction sites updated to mock IAppConfig. The three IConfig mocks that remain beside them are OTHER constructor arguments, for PatValidator and ForgeReleaseSource, and are deliberately untouched. AppStoreSource is NOT migrated here on purpose. It also calls getSystemValueString, which exists only on IConfig, so it needs both interfaces injected and that changes a constructor with positional callers in the tests. Worth doing deliberately rather than as a rider on this one. Verified with the repo own vendor/bin/psalm 5.26.1 on PHP 8.3: errors with the baseline emptied went 98 -> 92, regenerated baseline is green. PHPUnit was NOT run here, it needs the Nextcloud server bootstrap that only exists inside a server checkout. Co-authored-by: Conduction Release Bot <release-bot@conduction.nl>
…ue API (#343) Completes the migration started for ForgeRegistry. OCP\IConfig::getAppValue and setAppValue are @deprecated 29.0.0 in favour of IAppConfig. 92 -> 87, and versioniq now has no deprecated app-value call left. This one could not be a straight swap, which is why it was held back from the ForgeRegistry PR: AppStoreSource also calls getSystemValueString, which exists ONLY on IConfig. So it takes BOTH now, IConfig purely for the system value and IAppConfig for the five app values.⚠️ The new parameter goes AFTER the existing IConfig one, and all five test constructions are POSITIONAL, so every one of them is updated in the same commit. Adding a parameter mid-signature without walking the call sites is how a green suite turns into `Argument #N must be of type X` at runtime. The mock stubs move with the calls: getAppValue -> getValueString and setAppValue -> setValueString. setValueString returns bool where setAppValue returned void, so those callbacks return true rather than nothing; a void callback would have handed PHPUnit a null for a bool return. Verified with the repo own vendor/bin/psalm 5.26.1 on PHP 8.3: 92 -> 87 with the baseline emptied, regenerated baseline is green, and the five stale DeprecatedMethod entries are gone rather than merely unused. PHPUnit was NOT run here, it needs the Nextcloud server bootstrap. Co-authored-by: Conduction Release Bot <release-bot@conduction.nl>
Quality Report — ConductionNL/versioniq @
|
| Check | PHP | Vue | Security | License | Tests |
|---|---|---|---|---|---|
| lint | ✅ | ||||
| phpcs | ✅ | ||||
| phpmd | ✅ | ||||
| psalm | ✅ | ||||
| phpstan | ✅ | ||||
| phpmetrics | ✅ | ||||
| eslint | ✅ | ||||
| stylelint | ✅ | ||||
| build | ✅ | ||||
| composer | ✅ | ✅ 29/29 | |||
| npm | ✅ | ✅ 302/302 | |||
| app:check-code | ⏭️ | ||||
| info.xml | ✅ | ||||
| REUSE | ❌ | ||||
| PHPUnit | ❌ | ||||
| Newman | ⏭️ | ||||
| Playwright | ❌ | ||||
| Hydra gates | ❌ |
Quality workflow — 2026-08-31 19:03 UTC
Download the full PDF report from the workflow artifacts.
Quality Report — ConductionNL/versioniq @
|
| Check | PHP | Vue | Security | License | Tests |
|---|---|---|---|---|---|
| lint | ✅ | ||||
| phpcs | ✅ | ||||
| phpmd | ✅ | ||||
| psalm | ✅ | ||||
| phpstan | ✅ | ||||
| phpmetrics | ✅ | ||||
| eslint | ✅ | ||||
| stylelint | ✅ | ||||
| build | ✅ | ||||
| composer | ✅ | ✅ 29/29 | |||
| npm | ✅ | ✅ 302/302 | |||
| app:check-code | ⏭️ | ||||
| info.xml | ✅ | ||||
| REUSE | ❌ | ||||
| PHPUnit | ✅ | ||||
| Newman | ⏭️ | ||||
| Playwright | ✅ | ||||
| Hydra gates | ✅ |
Quality workflow — 2026-08-31 19:14 UTC
Download the full PDF report from the workflow artifacts.
Co-authored-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com>
Quality Report — ConductionNL/versioniq @
|
| Check | PHP | Vue | Security | License | Tests |
|---|---|---|---|---|---|
| lint | ✅ | ||||
| phpcs | ✅ | ||||
| phpmd | ✅ | ||||
| psalm | ✅ | ||||
| phpstan | ✅ | ||||
| phpmetrics | ✅ | ||||
| eslint | ✅ | ||||
| stylelint | ✅ | ||||
| build | ✅ | ||||
| composer | ✅ | ✅ 29/29 | |||
| npm | ✅ | ✅ 302/302 | |||
| app:check-code | ⏭️ | ||||
| info.xml | ✅ | ||||
| REUSE | ❌ | ||||
| PHPUnit | ✅ | ||||
| Newman | ⏭️ | ||||
| Playwright | ✅ | ||||
| Hydra gates | ✅ |
Quality workflow — 2026-08-31 20:48 UTC
Download the full PDF report from the workflow artifacts.
`npm run lint` was `eslint src`, so two whole trees were never linted. Across
the fleet that hid roughly 3,900 errors, none of which any CI leg had shown.
Most of it was the config, not the code, and the same two defects were in
every app.
**scripts/ had no config block at all.** These are CommonJS Node CLI checkers,
and flat config defaults every `.js` to ESM with browser-ish globals, so eslint
read the CommonJS wrapper itself as undefined identifiers: `require`,
`process`, `__dirname`, `__filename`, `module`. A `scripts/**` block now
declares the environment. Declaring beats suppressing here: `no-undef` is the
rule that catches a genuinely misspelled identifier, and dozens of fake
findings would bury a real one. A second block covers `scripts/**/*.mjs`, which
is ESM and needs Node's globals without the CommonJS wrapper.
**The tests block applied a non-TypeScript-aware rule to TypeScript.** It named
`tests/**/*.ts` while setting the CORE `no-unused-vars`, which v9 deliberately
turns off for `.ts` in favour of the `@typescript-eslint` version. The core
rule reads the parameter names inside a function TYPE as bindings, so
t?: (app: string, key: string) => string
reports `app` and `key` as unused variables, and every unused `catch (e)` in a
`.ts` spec reports twice. The block is split now: `.js`/`.mjs` on the core
rule, `.ts`/`.tsx` on the TypeScript one, same patterns on both.
Also: stale `eslint-disable` comments naming plugins eslint 10 no longer
registers, which are themselves errors ("Definition for rule ... was not
found"), and a rule that must not parse shell scripts.
The genuinely real findings were the useful part: dead locals, unused imports,
dead helper functions, unused `catch` bindings, extensionless relative imports,
and a handful of `== null` comparisons spelled out so they still match null AND
undefined.
Verified per app: `npm run lint` 0 errors over src + tests + scripts,
`prettier --check` clean, and the unit suite still green.
Co-authored-by: Conduction Release Bot <release-bot@conduction.nl>
Quality Report — ConductionNL/versioniq @
|
| Check | PHP | Vue | Security | License | Tests |
|---|---|---|---|---|---|
| lint | ✅ | ||||
| phpcs | ✅ | ||||
| phpmd | ✅ | ||||
| psalm | ✅ | ||||
| phpstan | ✅ | ||||
| phpmetrics | ✅ | ||||
| eslint | ✅ | ||||
| stylelint | ✅ | ||||
| build | ✅ | ||||
| composer | ✅ | ✅ 29/29 | |||
| npm | ✅ | ✅ 302/302 | |||
| app:check-code | ⏭️ | ||||
| info.xml | ✅ | ||||
| REUSE | ❌ | ||||
| PHPUnit | ✅ | ||||
| Newman | ⏭️ | ||||
| Playwright | ❌ | ||||
| Hydra gates | ✅ |
Quality workflow — 2026-09-01 10:57 UTC
Download the full PDF report from the workflow artifacts.
The lint pass left two shapes that eslint and prettier both call clean while
the Playwright suite fails to load. `development` collected ZERO tests.
A Playwright callback's destructuring is a FIXTURE REQUEST, not a binding list.
Renaming an unused `request` to `_request` asks for a fixture that does not
exist and the file never loads. The binding is renamed, the key kept:
async ({ page, request: _request }) => {
And the type-import conversion added a second `import type { Page }` to a file
that already imported `Page` alongside `ConsoleMessage`, which is a
duplicate-identifier SyntaxError.
`npx playwright test --list` parses every spec without running one, and is the
check that catches both. A green linter cannot.
Co-authored-by: Conduction Release Bot <release-bot@conduction.nl>
Quality Report — ConductionNL/versioniq @
|
| Check | PHP | Vue | Security | License | Tests |
|---|---|---|---|---|---|
| lint | ✅ | ||||
| phpcs | ✅ | ||||
| phpmd | ✅ | ||||
| psalm | ✅ | ||||
| phpstan | ✅ | ||||
| phpmetrics | ✅ | ||||
| eslint | ✅ | ||||
| stylelint | ✅ | ||||
| build | ✅ | ||||
| composer | ✅ | ✅ 29/29 | |||
| npm | ✅ | ✅ 302/302 | |||
| app:check-code | ⏭️ | ||||
| info.xml | ✅ | ||||
| REUSE | ❌ | ||||
| PHPUnit | ✅ | ||||
| Newman | ⏭️ | ||||
| Playwright | ✅ | ||||
| Hydra gates | ✅ |
Quality workflow — 2026-09-01 12:29 UTC
Download the full PDF report from the workflow artifacts.
… suite (#349) Playwright resolves a fixture BY NAME from the destructured parameter, so renaming an unused one to `_page` asks for a fixture that does not exist. The e2e leg dies before a single test runs and the report contains no test entries at all. Introduced by the pass that let the linter see tests/. The linter was right that the parameters were unused; underscore-prefixing is the fix for an ordinary unused argument and the wrong fix for a Playwright fixture, because the name is the lookup key. Same defect as buildiq#642, found by a fleet sweep. Co-authored-by: Conduction Release Bot <release-bot@conduction.nl>
Quality Report — ConductionNL/versioniq @
|
| Check | PHP | Vue | Security | License | Tests |
|---|---|---|---|---|---|
| lint | ✅ | ||||
| phpcs | ✅ | ||||
| phpmd | ✅ | ||||
| psalm | ✅ | ||||
| phpstan | ✅ | ||||
| phpmetrics | ✅ | ||||
| eslint | ✅ | ||||
| stylelint | ✅ | ||||
| build | ✅ | ||||
| composer | ✅ | ✅ 29/29 | |||
| npm | ✅ | ✅ 302/302 | |||
| app:check-code | ⏭️ | ||||
| info.xml | ✅ | ||||
| REUSE | ❌ | ||||
| PHPUnit | ✅ | ||||
| Newman | ⏭️ | ||||
| Playwright | ✅ | ||||
| Hydra gates | ✅ |
Quality workflow — 2026-09-02 01:03 UTC
Download the full PDF report from the workflow artifacts.
Every push to development fired Code Quality TWICE on the same commit: once for the push event, once for the pull_request event of the permanently-open "Release: merge development into beta", whose head_ref IS development. The concurrency block is not the bug and must not be changed: it suffixes the group by event name deliberately so the push run is NOT cancelled by the PR run, because the push run is the only carrier of Coverage Baseline Check, SBOM and Features Extract. The consequence is that both lanes run to completion, so the duplicate has to be dropped at the job. The PR run is the one to drop: its head sha IS development's, which the push run already decided, and it runs strictly fewer jobs. Not done by removing `beta` from pull_request.branches, though that would also stop it: the release/v* and sync/main-to-beta PRs target beta too and genuinely need their run. Only the head_ref:development PR is redundant. A development -> main promotion PR is skipped by the same clause, for the same reason and just as correctly. Proven on openregister#3370 before rolling out: run 33757014196 (pull_request, sha 4f3ef5e9) completed as `skipped` with ZERO jobs in 72s, while the push run for the same sha ran the full suite. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Automated PR to sync development changes to beta for beta release.
Merging this PR will trigger the beta release workflow.