chore(ci): remove dead Forgejo/Codeberg CI configuration #823
Workflow file for this run
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| name: Code Quality | |
| on: | |
| push: | |
| # An ALLOW-LIST of branch prefixes is a gate with a hole in it, and the | |
| # hole is SILENT: a branch matching nothing gets no CI at all, and its last | |
| # visible status is whatever it inherited — indistinguishable, on every | |
| # dashboard, from a branch that passed. | |
| # | |
| # Two live examples, both found 2026-08-14: `perf/**` was uncovered in | |
| # openconnector, where a merge carrying unresolved conflict markers and 84 | |
| # failing tests was pushed and nothing ran; and `feat/**` was uncovered in | |
| # openregister — note the list said `feature/**`, so every branch anyone | |
| # named `feat/...` had been running unchecked. | |
| # | |
| # Prefixes are added rather than replaced with `**` because this workflow is | |
| # expensive (PHPUnit matrix, Newman, Playwright). The fast structural checks | |
| # DO run on `**` — see merge-hygiene.yml, added in the same change. | |
| # | |
| # ⚠️ Adding prefixes is not the durable fix; the next invented one is | |
| # uncovered again. The durable fix is branch protection requiring a PR into | |
| # development, which the pull_request trigger below already gates correctly. | |
| branches: | |
| - main | |
| - development | |
| - feature/** | |
| - feat/** | |
| - bugfix/** | |
| - hotfix/** | |
| - perf/** | |
| - refactor/** | |
| - chore/** | |
| - fix/** | |
| pull_request: | |
| branches: [main, master, development, beta] | |
| workflow_dispatch: | |
| # Deduplicating a `push` run against the `pull_request` run for the SAME head | |
| # ref is the point of this block, and for a feature branch it is exactly right: | |
| # two runs of identical jobs, one of them wasted. | |
| # | |
| # It is wrong for `main` and `development`, because the push run there is NOT a | |
| # duplicate — it is the only carrier of the push-only jobs: "Coverage Baseline | |
| # Check" (`github.event_name == 'push'`), "SBOM" and "Features Extract". And | |
| # those two branches always have an open PR whose `head_ref` IS the branch | |
| # name: the standing "Release: merge development into beta" (#126 here). | |
| # `github.head_ref` on that PR run and `github.ref_name` on the push run both | |
| # render the identical group `quality-development`, and `cancel-in-progress` | |
| # then kills whichever started first — normally the push run. | |
| # | |
| # HONEST SCOPE OF THE EVIDENCE HERE: unlike most of the fleet, this repo shows | |
| # NO concurrency-cancelled `development` push run in its last 20 (its two | |
| # cancellations are the shared workflow's 45-minute cap, not this block), and | |
| # its push-only jobs demonstrably DO execute — run 31035521461 and 31030407282 | |
| # both report Coverage Baseline Check success. So this change is PREVENTIVE, | |
| # not a repair of an observed outage: the collision is latent in the expression | |
| # and has simply not won the race here yet. It is applied for fleet uniformity | |
| # with openconnector#1158, where the same expression cancelled 15 of the last | |
| # 20 push runs. | |
| # | |
| # Suffixing only the default-branch push keeps feature-branch dedup untouched | |
| # (`quality-feature/x` for both events, exactly as before) and gives the two | |
| # default branches' push runs a lane of their own. | |
| concurrency: | |
| # SUFFIXED BY EVENT NAME, not just by `-push`. | |
| # | |
| # The previous expression gave a push on `development` its own lane | |
| # (`-push`) but left EVERYTHING ELSE sharing `quality-development` — and | |
| # that is not a quiet lane: `Sync to Beta` keeps a PR open whose head_ref | |
| # IS `development`, so its run computes the same group and is re-triggered | |
| # on every merge. | |
| # | |
| # A `workflow_dispatch` therefore shared a group with that PR and was | |
| # cancelled by it. Measured on shillinq 2026-08-21: dispatch 32487948678 | |
| # cancelled by pull_request run 32490160836 (head_branch `development`). | |
| # A run someone deliberately asked for could essentially never complete. | |
| # | |
| # That reaches past ad-hoc verification: the fleet gate-drift sweep | |
| # (.github#523) dispatches per app with `--ref development`, because | |
| # `schedule:` cannot choose a branch. Under the old group those runs are | |
| # cancelled and report neither pass nor fail — and a routine that produces | |
| # no verdict is indistinguishable from one that never ran. | |
| # | |
| # This is hermiq's form, already live there. Pull requests keep the bare | |
| # group (so a PR still supersedes its own earlier run); push, dispatch and | |
| # schedule each get their own lane. | |
| group: quality-${{ github.head_ref || github.ref_name }}${{ (github.event_name != 'pull_request' && (github.ref_name == 'main' || github.ref_name == 'development')) && format('-{0}', github.event_name) || '' }} | |
| cancel-in-progress: true | |
| # Permission CEILING for the called quality pipeline. GitHub statically | |
| # validates the called workflow's declared job permissions against this | |
| # grant — even for jobs that are disabled — so it must cover the maximum | |
| # any nested job declares: journeydoc-capture (contents+actions write), | |
| # update-baseline / features-extract (contents write), and the Quality | |
| # Report PR comment (issues / pull-requests write). | |
| permissions: | |
| contents: write | |
| actions: write | |
| issues: write | |
| pull-requests: write | |
| jobs: | |
| quality: | |
| uses: ConductionNL/.github/.github/workflows/quality.yml@main | |
| with: | |
| app-name: keepiq | |
| php-version: "8.3" | |
| php-test-versions: '["8.3", "8.4"]' | |
| # Order matters: the PHPUnit matrix uses the whole list, but the E2E | |
| # (Playwright), Newman and Journeydoc jobs all check out | |
| # `fromJSON(nextcloud-test-refs)[0]` as their single server. That server | |
| # has to be one OpenRegister can load, because `additional-apps` below | |
| # installs it and keepiq's AppHost integration delegates to it — | |
| # OpenRegister's lib/ContextChat/ContentProvider.php implements | |
| # `OCP\ContextChat\IContentProvider`, which exists in stable32 and NOT in | |
| # stable31 (verified: raw.githubusercontent.com returns 404 for the | |
| # stable31 path). On stable31 every `occ` invocation printed | |
| # `Interface "OCP\ContextChat\IContentProvider" not found` while loading | |
| # commands from openregister's info.xml. | |
| # | |
| # The earlier reorder fixed the FIRST-entry problem for E2E/Newman/Journeydoc | |
| # but left "stable31 is still covered by the PHPUnit matrix" — and that leg | |
| # is broken by the same fact. The phpunit job ALSO installs `additional-apps` | |
| # (shared quality.yml, "Checkout additional apps" + "Enabling app: …"), and | |
| # its `occ app:enable openregister` failure is only a ::warning::, so the | |
| # stable31 leg ran on without OpenRegister loaded. openregister has since | |
| # made the floor explicit — `<nextcloud min-version="32"/>`, 8d5181f7a — so | |
| # NC31 is now a configuration this fixture cannot produce at all. | |
| # | |
| # Removing stable31 corrects an impossible configuration; it does not reduce | |
| # coverage, because nothing was being covered on that leg. | |
| # | |
| # THE LIST IS THE WHOLE DECLARED RANGE. appinfo/info.xml declares | |
| # <nextcloud min-version="32" max-version="34"/>, so 32, 33 and 34 each get | |
| # a leg. Adopting NC 34 by REPLACING the list left 32 and 33 advertised to | |
| # the App Store with no job touching them — the declared floor became the | |
| # untested end, which is the same drift as never testing 34, reversed. | |
| # stable34 leads because newman, playwright and journeydoc-capture all read | |
| # `fromJSON(inputs.nextcloud-test-refs)[0]` as their single server. | |
| nextcloud-test-refs: '["stable34", "stable32", "stable33"]' | |
| enable-psalm: true | |
| enable-phpstan: true | |
| enable-phpmetrics: true | |
| enable-frontend: true | |
| enable-eslint: true | |
| enable-phpunit: true | |
| enable-newman: true | |
| # Keepiq adopts OpenRegister's AppHost engine in lib/AppInfo/Application.php | |
| # (ADR-040 / ADR-022) and ships lib/Settings/keepiq_register.json, so | |
| # OpenRegister must be present in the test instance — otherwise | |
| # SettingsService::isOpenRegisterAvailable() is false, InitializeSettings | |
| # skips the register import with a warning, and the app boots without the | |
| # host engine it delegates to. | |
| # | |
| # NOTE the org is ConductionNL, not Conduction. `Conduction` does not | |
| # exist, and the shared workflow clones additional-apps UNAUTHENTICATED — | |
| # so a bad ref does not report a clean 404. git falls through to | |
| # credential prompting and the step dies with | |
| # fatal: could not read Username for 'https://github.com' (exit 128) | |
| # which reads as an auth problem rather than a typo. Six fleet repos hit | |
| # this; in pipelinq it killed all four PHPUnit legs and the E2E job at the | |
| # clone step, so those gates had never executed a single test. | |
| additional-apps: '[{"repo":"ConductionNL/openregister","app":"openregister","ref":"development"}]' | |
| enable-sbom: true | |
| # ── E2E browser tests ──────────────────────────────────────────────── | |
| # `playwright-test-path` does double duty in the shared workflow: | |
| # 1. it is the directory the "Validate Playwright tests exist" step | |
| # counts *.spec.ts in; | |
| # 2. it is the FIRST place the run step looks for a config — | |
| # `${playwright-test-path}/playwright.config.ts`, falling back to | |
| # the repo root only if that file is absent. | |
| # We ship tests/e2e/playwright.config.ts precisely so lookup (2) hits it. | |
| # The run step passes no `--project`, so the root config would run BOTH | |
| # of its projects — including `visual`, whose own header records that a | |
| # CI Linux runner cannot byte-match a dev-container PNG baseline. The | |
| # tests/e2e config declares only the chromium regression project and | |
| # writes its report to the app root, where the workflow's | |
| # upload-artifact steps actually look. | |
| enable-playwright: true | |
| playwright-test-path: tests/e2e | |
| # Keepiq's nine workflow specs UNLOCK the vault with the development | |
| # master password seeded by lib/Repair/SeedDevelopmentData.php — and that | |
| # repair step returns immediately unless the `debug` system config is | |
| # true, which `occ maintenance:install` does not set. A stock CI install | |
| # therefore comes up with no dev vault at all and nothing exits non-zero. | |
| # The script turns debug on, re-runs the repair steps, imports the | |
| # register through OpenRegister's admin API, and fails loudly if the | |
| # suite / secrets / schemas still aren't there. | |
| # cwd for this step is the Nextcloud server root. | |
| playwright-seed-command: 'bash apps/keepiq/tests/e2e/ci-seed.sh' | |
| # ── Frontend Check legs ────────────────────────────────────────────── | |
| # `frontend-checks` defaults to `[]`, and an empty list means the shared | |
| # workflow emits NO "Frontend Check" job at all — so these two validators | |
| # ran nowhere while the run still looked complete. Both are self-contained | |
| # `node` scripts, which is what a leg has to be (each leg is a fresh job | |
| # with its own checkout + `npm ci`). | |
| # `test` / `test:unit` are NOT listed: the shared "Frontend Tests (unit)" | |
| # job already auto-detects and runs them. | |
| # | |
| # `format` (prettier --check) is listed because the shared workflow has NO | |
| # prettier job of its own — `quality.yml` runs eslint and stylelint and | |
| # mentions prettier ZERO times. This repo already carries | |
| # `@nextcloud/prettier-config` and a `format` script, so without this leg | |
| # `npm run format` never runs outside a developer's editor and the tree | |
| # drifts straight back out of format between merges — the same inert- | |
| # formatter failure mode that made the old `.prettierrc` worth deleting. | |
| # Centralising the config never stopped drift; the gate does. | |
| # Measured on this tree before enabling: PASSES, 294 of 310 tracked | |
| # frontend files in scope. This repo has TWO documentation trees and both | |
| # are excluded by .prettierignore — `docs/` and the separate `docusaurus/` | |
| # site, which has its own package.json and its own toolchain. | |
| # `check:l10n-js` regenerates l10n/<locale>.js from the JSON catalogue and | |
| # fails when the committed file is stale. Nextcloud serves ONLY the JS half | |
| # to a browser — raw JSON out of an app directory is a 404 — so a catalogue | |
| # that exists only as JSON renders English in the entire UI while every | |
| # server-rendered string is translated, with no error anywhere. | |
| # `check:schema-l10n` is a RATCHET, not a gate. Every string inside a form | |
| # comes from the schema and is a key in THIS app's catalogue; an absent key | |
| # renders the English source inside an otherwise translated form, silently. | |
| # The fleet had 30,459 such strings, so this records the current count and | |
| # fails only when it GROWS — burning it down stays an ordinary PR. | |
| frontend-checks: '["check:manifest", "test:l10n", "format", "check:l10n-js", "check:schema-l10n"]' | |
| # ── Coverage ratchet ───────────────────────────────────────────────── | |
| # `enable-coverage-guard` defaults to FALSE, which is why both | |
| # "Coverage Baseline Protection" (PR side) and "Coverage Baseline Check" | |
| # (push side) have only ever reported `skipped`. It needs two inputs this | |
| # repo did not have, both added in this commit: | |
| # `scripts/coverage-guard.php` (byte-identical to the copies in | |
| # openregister and procest) and `.coverage-baseline` = 55.78, this repo's | |
| # own measured coverage (6838 of 12258 statements) read from clover.xml | |
| # in the `coverage-report` artifact of run 30911329266. | |
| enable-coverage-guard: true | |
| # ── Hydra mechanical gates ─────────────────────────────────────────── | |
| # `enable-hydra-gates` defaults to FALSE, so this tier has never executed | |
| # here — the job reported `skipped`, which the Quality Report renders | |
| # identically to a pass. | |
| # `enable-axe` deliberately NOT set: a vanilla Nextcloud 34 already carries | |
| # serious/critical violations on core's OWN routes that DOM scoping does | |
| # not remove. Enabling axe is a separate decision. Note that gate-33 | |
| # (axe-core) reads tests/axe/report.json, which the Playwright job writes | |
| # ONLY when `enable-axe: true` — un-skipping Playwright is not the fix; | |
| # with axe off the gate declares itself not applicable. | |
| enable-hydra-gates: true | |
| # No `hydra-gates-ref` here on purpose. The shared workflow defaults it | |
| # to @main, and this workflow is itself consumed at @main, so the two | |
| # sides move together and a gate fix reaches this repo without a commit | |
| # in this repo. A pin is a silent expiry date: 22 repos sat on v1.0.1 and | |
| # 16 gates were dead fleet-wide while every one reported PASS (.github#159), | |
| # and a default flipped at @main later reached those old runners and made | |
| # them red on gates they had no subject matter for (.github#173). | |
| # To hold this repo still for a specific reason, set the input explicitly | |
| # and say why — it is still honoured. To roll back for everyone, revert on | |
| # ConductionNL/.github main. |