-
Notifications
You must be signed in to change notification settings - Fork 0
227 lines (220 loc) · 13.6 KB
/
Copy pathcode-quality.yml
File metadata and controls
227 lines (220 loc) · 13.6 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
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:
jobs:
quality:
uses: ConductionNL/.github/.github/workflows/quality.yml@main
with:
app-name: decidesk
php-version: "8.3"
php-test-versions: '["8.3", "8.4"]'
# stable31 is REMOVED because it tested an impossible configuration, not
# because we are trimming coverage. `additional-apps` below installs
# openregister, which declares min-version="32" (ConductionNL/openregister#2384),
# so on NC31 `occ app:enable openregister` refuses with "not compatible with
# this version of the server". The shared workflow runs that as
# `php occ app:enable "$name" || echo "::warning::Failed to enable $name"`,
# so the failure is a WARNING and the job continues without its data layer,
# then dies ~70s later on missing schemas — which reads like an app fault.
#
# Order mattered as much as membership: the newman, playwright and
# journeydoc-capture jobs each check out the server at
# `fromJSON(inputs.nextcloud-test-refs)[0]`, so stable31 sitting FIRST put
# all three on the one version openregister cannot load.
#
# THE LIST IS THE WHOLE DECLARED RANGE. An earlier revision of this comment
# said "stable33 is deliberately NOT added: this removes an impossible leg,
# it does not widen the matrix" — but the same change also dropped stable32,
# which was NOT impossible, it was the declared floor. appinfo/info.xml
# declares <nextcloud min-version="32" max-version="34"/>, so 32, 33 and 34
# each get a leg; anything narrower advertises a range to the App Store that
# no job touches.
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
# Every Newman collection seeds its own fixtures through OpenRegister's
# object API (`/apps/openregister/api/objects/decidesk/<schema>`) — ADR-022
# keeps plain CRUD there rather than in decidesk controllers. Without
# OpenRegister checked out the seed POSTs answer 404, every downstream id
# interpolates to the empty string, and the collections fail wholesale on
# a cause that has nothing to do with the code under test (measured:
# 206 of 282 assertions failed in run 30899265429).
#
# `ref: development` matches the rest of the fleet (opencatalogi,
# openconnector, procest, softwarecatalog, scholiq, pipelinq). It is not
# interchangeable with `main`: decidesk's appinfo/routes.php builds on
# `\OCA\OpenRegister\AppHost\Routes`, which does not exist on OpenRegister
# `main` (0.2.19) at all — only on `development`.
additional-apps: '[{"repo":"ConductionNL/openregister","app":"openregister","ref":"development"}]'
# Two collections (decidesk-meeting-agenda, decidesk-user-settings) carry
# no collection-level `baseUrl`/`noAuthBase`/`adminUser`/`adminPass`, and
# the workflow's ad-hoc fallback defines `base_url`-style names instead.
# Every request in those two therefore left `{{baseUrl}}` unresolved and
# errored before it was sent — 42 assertions failing with no server
# involved. The committed environment file supplies all four to every
# collection uniformly.
newman-environment-path: tests/integration/decidesk-environment.json
enable-sbom: true
# ── E2E browser tests ────────────────────────────────────────────────
# `enable-playwright` defaults to FALSE and was never set here, so the
# "E2E Tests (Playwright)" job has reported `skipped` on every run this
# repo has ever produced — while the tree ships a root
# `playwright.config.ts` and 28 gating spec files under `tests/e2e/`
# (spec-coverage/, workflows/, integration-registry.spec.ts). A skipped
# job renders in the Quality Report exactly like a passing one, so the
# whole browser tier was invisible rather than absent.
#
# `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 all
# three of its projects — including `visual` (pixel baselines whose own
# header states a CI Linux runner cannot byte-match a dev-container
# baseline) and `docs-capture` (journeydoc screenshot re-shoots, which
# have their own dedicated job). The tests/e2e config declares only the
# `chromium` regression project, and writes its report/output to the app
# root, where the workflow's upload steps actually look.
#
# OpenRegister is already checked out for Newman above (`additional-apps`)
# and the Playwright job honours the same input — which it must: the specs
# read and seed fixtures through `/apps/openregister/api/objects/decidesk/
# <schema>` and assert on `window.OCA.OpenRegister.integrations`.
enable-playwright: true
playwright-test-path: tests/e2e
# OpenRegister being INSTALLED is not the same as decidesk's register
# being IMPORTED, and the difference is silent. `occ app:enable decidesk`
# runs a repair step that is supposed to import
# `lib/Settings/decidesk_register.json` + the 24 `register.d/` fragments,
# but an IRepairStep has no user session, OpenRegister's RBAC denies the
# write as 'Anonymous', and the step catches \Throwable and downgrades it
# to a warning — so `occ app:enable` exits 0 with no register at all.
# In that state every UI spec times out on an empty list and every
# `expect(resp.ok()).toBe(true)` against
# /apps/openregister/api/objects/decidesk/<schema> fails with a message
# that accuses the selector, never the missing import.
#
# ci-seed.sh does the import explicitly over the admin HTTP API (which
# has a real session), forced, then VERIFIES the register slug, 18 schema
# slugs, four object collections, and that the SPA bundle actually serves
# as JavaScript. A bad provision becomes ONE loud step failure instead of
# two dozen misleading spec failures.
#
# It also sets and reads back `htaccess.IgnoreFrontController`. Without
# it, `occ maintenance:install` leaves that flag FALSE, JS `generateUrl`
# therefore prefixes `/index.php`, and decidesk's
# `createWebHistory(generateUrl('/apps/decidesk'))` router base becomes
# `/index.php/apps/decidesk` while every spec navigates to
# `/apps/decidesk/...`. vue-router only strips a base the path starts
# with, so nothing matched and the catch-all `redirect: '/'` landed EVERY
# deep link on the dashboard.
#
# cwd for this step is the Nextcloud server root.
playwright-seed-command: 'bash apps/decidesk/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:unit` is NOT listed: the shared "Frontend Tests (unit)" job
# already falls back to it when there is no `test` script, and this repo
# has none — its 282 vitest tests are already covered there.
# `test:l10n:parity` is NOT listed either: measured on this tree it is
# short 289+ translations across the required locales. That is a
# translation backlog, and a permanently-red leg is one that gets
# switched off again.
#
# `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, 197 of 203 tracked
# frontend files in scope (docs/ excluded via .prettierignore; build
# output via .gitignore, which prettier 3 also reads).
# `check:nav-ceiling` (added with the nav-ceiling-gate change) enforces
# ADR-004's six-item top-level navigation ceiling: it rebuilds the
# effective menu the same way src/main.js's buildManifest pipeline
# does (base manifest + every manifest.d/*.json fragment + menu-
# layout.json) and fails on a primary-nav count over 6, or on any
# fragment top-level menu entry menu-layout.json never explicitly
# placed (relocation / removal / settingsSection lift). Without this,
# ADR-004's ceiling had no mechanical enforcement — 22 independent
# fragments each added their own top-level entry and the nav grew
# back to 44 items with no single commit that visibly broke the rule.
frontend-checks: '["check:manifest", "check:nav-ceiling", "test:l10n", "format"]'
# ── 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` = 57.66, this repo's
# own measured coverage (8687 of 15065 statements) read from clover.xml
# in the `coverage-report` artifact of run 30911223203.
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. .github#149 is what made this viable: gate-7
# (no-admin-idor) now follows delegation, so the 11 MinutesController-style
# methods whose guards are reached through `staffAction()` → `requireStaff()`
# are no longer flagged.
# `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.
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.