Skip to content

test(e2e): say WHICH link breaks when the pin badge is absent #259

test(e2e): say WHICH link breaks when the pin badge is absent

test(e2e): say WHICH link breaks when the pin badge is absent #259

Workflow file for this run

name: Code Quality
on:
push:
branches: [main, development, feature/**, bugfix/**, hotfix/**]
pull_request:
branches: [main, master, development, beta]
workflow_dispatch:
jobs:
quality:
uses: ConductionNL/.github/.github/workflows/quality.yml@main
with:
# app_versions with an UNDERSCORE, matching <id>app_versions</id> in
# appinfo/info.xml — NOT the repository name, which is hyphenated.
#
# Nextcloud requires the app DIRECTORY name to equal the app id. Checked
# out as `apps/app-versions`, `occ app:enable` fails with
#
# App "app-versions" cannot be installed because appinfo file cannot be read.
#
# which reads like a malformed or missing info.xml and is nothing of the
# sort — the file is valid and simply not where that id says to look. All
# six PHPUnit legs and the E2E job died on this at the install step, so
# not one of them ever ran a test.
app-name: app_versions
php-version: "8.3"
php-test-versions: '["8.3", "8.4"]'
# 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. The previous list ran stable31 — below the floor even before this
# change raised it — and had no stable34 leg at all, so the one major this
# app most needed to prove was the one nothing touched.
# 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"]'
# This repo's PHP toolchain is the upstream Nextcloud app-template one:
# php-cs-fixer + psalm (+ rector, phpunit). It has no phpcs.xml, no
# phpmd.xml and no phpstan.neon, and correspondingly no `phpcs`, `phpmd`,
# `phpstan` or `phpmetrics` composer script.
#
# Those four legs were nevertheless switched on, so quality.yml ran
# `composer <tool>` and got `Command "<tool>" is not defined.` — i.e. the
# phpmd / phpstan / phpmetrics jobs have been failing on every run for
# months for the absence of a tool, not for a finding, and the phpcs job
# passed VACUOUSLY (quality.yml maps composer's exit 1 to "warnings only →
# pass"). Turning them off makes CI say what is true. Adopting them for
# real is tracked as a follow-up issue; flip these back when the configs
# and scripts land.
enable-psalm: true
enable-phpstan: false
enable-phpcs: false
enable-phpmd: false
enable-phpmetrics: false
enable-frontend: true
enable-eslint: true
enable-phpunit: true
# ── Integration tests: OFF, and this is a correction ──────────────────
# This was `true`, but there is no `tests/integration/` directory in this
# repository and no *.postman_collection.json anywhere in it. The shared
# workflow's "Validate Newman collections" step hard-fails on exactly
# that ("collection directory 'tests/integration' does not exist"), so
# the input could only ever have produced a guaranteed red that measures
# nothing. It has never actually surfaced, because the Newman job also
# carries `needs.security.result != 'failure'` and Security (npm) has
# been failing here — so a broken input has been hiding behind an
# unrelated failure.
# This is not a gate being switched off because it failed. It is a gate
# being switched off because the repository has nothing for it to run.
# Flip it back to `true` in the same commit that adds a collection.
enable-newman: false
# ── notifications, because four e2e specs assert on its table ─────────
#
# jobs.spec.ts reads and clears `oc_notifications` to prove the
# auto-update job tells the admin what it did. That table is created by
# the `notifications` app, which is bundled into Nextcloud RELEASES but
# is a separate repo and is NOT present in a server GIT checkout — which
# is what this workflow installs.
#
# So those assertions failed with
# SQLSTATE[42P01] relation "oc_notifications" does not exist
# i.e. the app under test was blamed for the absence of an integration
# that was never installed. Checking it out at the same stable branch the
# server runs makes the assertion measure what it claims to.
# `notes` is here for the same reason, found the same way. versions.spec
# picks it as a representative App Store app and failed with
# waiting for locator('article').filter({ has: getByText('notes') })
# i.e. the app card was simply not in the list, because Notes is another
# separate repo absent from a server git checkout. It has no stableXX
# branches, so `main` is the only ref there is.
# `notes` was here and is deliberately gone. It is a separate repo whose
# info.xml declares min-version="33", while this matrix includes
# stable32 — so on two of the six PHPUnit cells it could never enable:
# App "Notes" cannot be installed because it is not compatible with
# this version of the server.
# That looked harmless only because a failed enable is currently a
# ::warning:: and the job carries on; ConductionNL/.github#355 makes it
# fail, which is correct — a suite running without the app it was told to
# install reports the absence as this repository's own failures.
#
# It was added so versions.spec had an installed App Store app to walk.
# `dashboard` serves that purpose with no compatibility floor at all,
# because Nextcloud bundles it — see the note at the top of that spec.
additional-apps: '[{"repo":"nextcloud/notifications","app":"notifications","ref":"stable34"}]'
enable-sbom: true
# ── E2E browser tests ────────────────────────────────────────────────
# `enable-playwright` defaults to FALSE and this caller never set it, so
# the 15 spec files under tests/e2e had never run in CI while the job
# reported `skipped`.
# No CI-scoped config is needed here, unlike most of the fleet: this
# repo's ROOT playwright.config.ts declares only `setup` and `chromium`
# — no `docs-capture` project (which would re-shoot documentation
# screenshots on every PR) and no `visual` project (whose committed PNG
# baselines are host-font/GPU specific and cannot byte-match a CI
# runner). The run step's fallback to the root config is therefore the
# correct behaviour here rather than an accident.
# Honest expectation: this job will keep reporting `skipped` until
# Security (npm) goes green, because the playwright job carries
# `needs.security.result != 'failure'`. Enabling the input removes the
# first of the two reasons it was dark; the second is a real failure in
# this repo that this change does not touch.
enable-playwright: true
# ── The forge fixture, without which two thirds of the suite skips ────
#
# Ten spec files open with
#
# test.skip(!(await fixtureAvailable(page)), 'forge fixture not running')
#
# and nothing in CI ever started it. On the first run in which this job
# executed at all (2026-08-19) the tally was
#
# 7 failed · 3 flaky · 66 skipped · 22 passed
#
# and "22 passed" is what a reader takes away. The 66 are the CLI
# commands, downgrade migration drift, the artifact cache, TOFU digest
# recording, install faults and rate-limited forges — most of what this
# app does. A skip whose reason has quietly stopped being true reads as a
# considered decision and is an unnoticed hole.
#
# `bootstrap.sh` cannot serve here: it assumes Nextcloud in a container
# named `av-e2e` joined to the fixture by a Docker network, and this job
# runs the PHP built-in server on the runner. `bootstrap-ci.sh` is the
# same wiring without Docker, and it EXITS NON-ZERO if the fixture does
# not come up — the seed step fails the job on that, which is the point.
# A fixture that silently fails to start would put those 66 tests back to
# skipping for a reason that is no longer true.
playwright-seed-command: "bash apps/app_versions/tests/e2e/fixtures/forge/bootstrap-ci.sh"
# ── 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. Unlike the two jobs above, this one is NOT gated
# on the security job, so it reaches a verdict on this PR.
#
# 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.
#
# Whole-tree debt on this repo (inherited, not created here): gates 38
# skip-link, 40 form-label-association, 43 table-headers and 45
# prefers-reduced-motion fail on the full tree. Diff scoping keeps them
# out of unrelated PRs.
# `enable-axe` deliberately NOT set: a vanilla Nextcloud 34 already carries
# serious/critical violations from core's own UI.
enable-hydra-gates: true