ci: run workflows on main instead of dormant master/develop - #118
Conversation
The project moved from master to main between v10 and v11, but the branch filters were never updated. As a result Artifact, ESLint, Lint-php and Lint-phpcs have not run since 2026-05-21 and never run for a main-targeted PR, leaving DCO as the only check. Point them at main plus stable* for maintenance lines. Verified locally on main: php -l clean across 51 files, phpcs clean across 48 files, stylelint clean. create-tag.yml is deliberately left on master — it has never run, and enabling it on main would auto-tag every push and cascade into release.yml. Note: ESLint will fail until src/ is cleaned up (18 semi in listener.js, 7 stale '_' globals). Assisted-by: ClaudeCode:claude-opus-5 Signed-off-by: Christoph Schaefer <christoph.schaefer@nextcloud.com>
npm 10 (node 20) cannot npm ci this lockfile: it tries to materialise fdir's optional picomatch peer and demands picomatch@4.0.5, which is not in the lock file. npm 11 honours the optional peer and installs cleanly. @nextcloud/files@4 also requires node ^24.0.0, and appstore-build-publish.yml already falls back to node ^24 / npm ^11.3. Assisted-by: ClaudeCode:claude-opus-5 Signed-off-by: Christoph Schaefer <christoph.schaefer@nextcloud.com>
listener.js was written with semicolons while the shared config sets semi: ['error', 'never']; eslint --fix removes the 18 offenders. Seven files also declared '_' in /* global */ comments for Nextcloud's retired Underscore.js — _( ) appears nowhere in any of them, so the declaration is dropped (and the comment removed where _ was its only entry). No behavioural change. Verified: npx eslint *.js exits 0 (0 errors, 65 pre-existing @nextcloud/no-deprecations warnings) and npx stylelint on the tracked css files exits 0. Assisted-by: ClaudeCode:claude-opus-5 Signed-off-by: Christoph Schaefer <christoph.schaefer@nextcloud.com>
|
@chrip — reviewed, approve. Every factual claim in the description checks out against source; details at the bottom. Four things worth knowing before/after merge, none of them blockers. TL;DR
1 —
|
| branch | files declaring an unused _ |
|---|---|
stable10 |
7 |
stable11 |
8 |
Backporting the filter without the cleanup turns stable CI red on arrival. The workflow-audit table currently reads as though stable is covered — it will be, just not yet. Might be worth a line in the description saying so.
3 — release/stable11 doesn't match stable*
The glob matches stable10 and stable11 but not release/stable11, which also exists as a remote branch. If that's a branch release PRs actually target, it stays uncovered. Flagging with low confidence since I don't know whether it's live — either widen the glob or confirm it's vestigial.
4 — Merge conflict incoming with #70
Commit 3 de-semicolons exactly the getLinkWithPicker block that #70 rewrites (src/listener.js ~120–140). Whichever lands second needs a rebase. Trivial resolution — #70 already writes those lines semicolon-free — just don't be surprised by it.
Silver lining: once this merges, #70 gets real ESLint/artifact coverage for the first time, which is rather the point.
Verification — what I re-derived rather than took on trust
The description is AI-assisted (Assisted-by:), so I checked the claims against source instead of the prose. All of them hold:
| Claim | Result |
|---|---|
| Not run since 2026-05-21 | ✅ last ESLint run was push → master, 2026-05-21 |
create-tag.yml never ran |
✅ 0 runs ever |
| picomatch/fdir optional-peer diagnosis | ✅ npm-shrinkwrap.json:9990-10006 — rollup-plugin-license/node_modules/fdir@6.5.0 declares picomatch: ^3 || ^4 with optional: true and no nested entry. Run history confirms it empirically: two failures on node 20, success on 24 |
listener.js is semicolons only |
✅ strip trailing ; from both revisions and the sole remaining diff is the /* global */ line |
_ unused in all 7 files |
✅ no bare _ token remains in any of them; /* global */ is eslint-only, zero runtime effect |
| All 8 checks green | ✅ |
settings.js:162 correctly keeps /* global _ */ — it genuinely uses _.debounce. Though that does undercut the "Underscore is retired" framing: either _ is still provided by the server, or that path is already broken. It sits behind if (typeof window.$ !== 'function') return (settings.js:154), so it's jQuery/select2-era dead code on NC 33+ anyway (info.xml min-version 33). Pre-existing, out of scope here, but a decent companion to the deprecation-warning cleanup you've already listed.
And of your stated follow-ups, npm install vs npm ci in artifact.yml is the one that matters — it sailed green straight through the exact breakage ESLint caught, which is the textbook definition of a check that isn't a gate.
Reviewed with Claude Code (claude-opus-5).
|
Follow-up for finding 1 filed as #121 — |
|
@chrip — corrections to my review above. I put it through an adversarial re-check and finding 2 had real errors in it. Most consequential: the stable-branch table is wrong, and the "stable CI goes red" warning does not apply to What was wrong1.
My error: I counted 2. 3. "Run history confirms it: two failures on node 20, success on 24" — wrong, there was one. Per-SHA:
The conclusion stands; the corroboration was half what I said. 4. 5. What standsFindings 1, 3 and 4 as posted. Plus, verified more rigorously than I originally managed:
Follow-ups filed#125 (backport, with the corrected per-branch detail) · #126 ( Worth noting the merge already earned its keep: Renovate rebased and several dependency PRs got their first real CI run, three of them red. Reviewed with Claude Code (claude-opus-5); corrections after an adversarial second pass. |
Summary
The project moved from
mastertomainbetween v10 and v11 (v10.0.0is onmaster/stable10;v11.0.0andv11.0.1are onmain), but the workflow branch filters were never updated. As a result Artifact, ESLint, Lint-php and Lint-phpcs had not run since 2026-05-21 and never ran for amain-targeted PR — leavingDCOas the only check on every PR.This re-points them at
main(plusstable*for maintenance lines) and fixes the two things that stopped them passing once enabled.Found while reviewing #117, whose CI verification turned out to be unverifiable for exactly this reason.
Commits
ci: run workflows on main instead of dormant master/develop— branch filters[master, develop]/[master]→[main, 'stable*']inartifact.yml,lint-eslint.yml,lint-php.yml,lint-phpcs.yml.ci(eslint): build on node 24 to match the release pipeline—NODE_VERSION: 20→24.fix(lint): clear eslint errors blocking CI on main— the 25 pre-existing eslint errors.Why node 24 (commit 2)
With the filters fixed, ESLint failed at
npm ci:The lockfile is not corrupt.
fdir@6.5.0declarespicomatch: ^3 || ^4as an optional peer (peerDependenciesMeta.picomatch.optional: true). npm 10 — bundled with node 20 — tries to materialise that optional peer, resolves it to the newest match (picomatch@4.0.5, published recently), finds no lockfile entry and aborts. npm 11 honours the optionality and installs cleanly.Nothing in this repo changed to cause it; it started failing when picomatch shipped 4.0.5.
Node 20 was the wrong pin regardless:
@nextcloud/files@4.0.0— a direct dependency — declaresengines.node: ^24.0.0. Node 20 violates it (theEBADENGINEline in the failing log).appstore-build-publish.ymlalready builds releases on node^24/ npm^11.3, so release and lint CI were on different major toolchains.Why the lint cleanup (commit 3)
Two mechanical, pre-existing problems, both surfaced only because CI finally ran:
semi, all insrc/listener.js. The shared config setssemi: ['error', 'never']; that one file was written with semicolons. Fixed byeslint --fix.no-unused-vars—desktop.js,directeditor.js,editor.js,listener.js,main.js,share.js,template.jseach declared_in a/* global */comment for Nextcloud's retired Underscore.js._(appears nowhere in any of them, so the declaration is dropped (and the comment removed entirely where_was its only entry).No behavioural change: 6 files are comment-only, and
listener.jsis 18 trailing-semicolon removals plus its comment — verified line by line.Workflow audit
Since these workflows were inherited, I checked whether each still makes sense here rather than only renaming branches:
lint-phpphp -lclean across 51 fileslint-phpcsruleset.xmllint-eslintartifactcreate-tagmasterreleaseappstore-build-publishcreate-tag.ymlis intentionally not migrated. It has never run (0 runs ever — the v11 tags were created by hand). Pointing it atmainis not a rename but a behaviour change: it would auto-tag every non-docs push tomain, cascading intorelease.yml→ a published GitHub release. That is a release-process decision and belongs in its own PR. Either delete it as vestigial or enable it deliberately.appstore-build-publish.ymlshowing "skipped" is correct, not a bug: it is guarded byif: github.repository_owner == 'nextcloud-releases'and only runs in the mirror.release.ymlhandles the Euro-Office side, as its inline comment explains.The two remaining
masterreferences inappstore-build-publish.ymlpoint at nextcloud/server's branch and theapp-certificate-requestsrepo — deliberately untouched.Verification
All 8 checks green: Artifact, ESLint, Lint-php (8.1–8.4), Lint-phpcs, DCO.
Confirmed locally against the exact CI commands before pushing, with results matching CI character-for-character (
✖ 90 problems (25 errors, 65 warnings)before the cleanup,0 errorsafter).Known follow-ups (not in this PR)
@nextcloud/no-deprecationswarnings remain (OC.generateUrl,OCP.Toast,OC.filePath,OC.linkToOCS). Non-blocking, pre-existing. Worth a separate cleanup — and note that if--max-warnings 0is ever added, they become failures.artifact.ymlrunsnpm install, notnpm ci, so it re-resolves and silently ignores the lockfile. It stayed green through the npm-10 breakage that ESLint caught. Switching it tonpm ciwould make it a real lockfile gate.enginesinpackage.json. Declaringnode/npmwould make the release pipeline's^24/^11.3fallback explicit instead of accidental, and give Renovate a constraint for lockfile regeneration.create-tag.ymlneeds the decision described above.Assisted-by: ClaudeCode:claude-opus-5