diff --git a/.github/PULL_REQUEST_TEMPLATE.md b/.github/PULL_REQUEST_TEMPLATE.md index deca0aac..67d628eb 100644 --- a/.github/PULL_REQUEST_TEMPLATE.md +++ b/.github/PULL_REQUEST_TEMPLATE.md @@ -4,44 +4,64 @@ ## PR type - -- Bug fix -- Small maintenance improvement -- Docs fix -- Translation update -- Approved larger change (link approval below) + +- [ ] Reproducible bug fix +- [ ] UI glitch/bug fix +- [ ] Behavior bug/regression fix +- [ ] Small maintenance only, with no UI or behavior change +- [ ] Docs accuracy fix +- [ ] Translation/localization only +- [ ] Approved larger or directional change ## Why - + + +## Issue or approval + + + + +## UI / behavior impact + + +- [ ] No UI change +- [ ] No behavior change +- [ ] UI changed only to fix a documented glitch/bug +- [ ] Behavior changed only to fix a documented bug/regression +- [ ] UI change has explicit maintainer approval +- [ ] Behavior change has explicit maintainer approval ## Policy check -- [ ] This PR is not cosmetic-only, unless it is a translation PR. -- [ ] This PR does not add a new major feature without prior approval. -- [ ] This PR is small in scope and focused on one problem. -- [ ] If this is a larger or directional change, I linked the **approved** feature request issue below. +- [ ] I have read and understood `CONTRIBUTING.md`. +- [ ] This PR is small, focused, and limited to one problem. +- [ ] This PR is not cosmetic-only. +- [ ] Any UI change fixes a linked glitch/bug and includes visual proof, or this PR has no UI change. +- [ ] Any behavior change fixes a linked bug/regression or has explicit approval, or this PR has no behavior change. +- [ ] This PR does not bundle unrelated refactors, cleanups, formatting, or drive-by changes. +- [ ] This PR does not add dependencies, architecture changes, migrations, or product-direction changes without explicit approval. +- [ ] I listed the testing performed below. -> **Large PRs without a linked, approved feature request issue will be closed immediately without review. No exceptions.** +> UI polish, cosmetic-only changes, minor behavior tweaks, and unapproved product changes will be closed without review. -## Approved feature request (required for large/non-trivial PRs) +## Scope boundaries - - + ## Testing - + ## Screenshots / Video (UI changes only) - + ## Breaking changes - + ## Linked issues - + diff --git a/.github/workflows/pr-template-check.yml b/.github/workflows/pr-template-check.yml index a24b4709..fae2ab89 100644 --- a/.github/workflows/pr-template-check.yml +++ b/.github/workflows/pr-template-check.yml @@ -29,9 +29,44 @@ jobs: return (next === -1 ? rest : rest.slice(0, next)).trim(); } - const required = ["Summary", "Why", "Testing", "Breaking changes", "Linked issues"]; + function cleanedContent(title) { + const content = sectionContent(title); + if (content === null) return null; + return content + .replace(//g, "") + .replace(/`/g, "") + .replace(/\s+/g, " ") + .trim(); + } + + function checkedLines(content) { + return (content || "").match(/^\s*-\s+\[[xX]\]\s+.+$/gm) || []; + } + + function uncheckedLines(content) { + return (content || "").match(/^\s*-\s+\[\s\]\s+.+$/gm) || []; + } + + function hasIssueReference(content) { + return /(^|\s)(#\d+|https:\/\/github\.com\/\S+\/issues\/\d+)/i.test(content || ""); + } + + const required = [ + "Summary", + "PR type", + "Why", + "Issue or approval", + "UI / behavior impact", + "Policy check", + "Scope boundaries", + "Testing", + "Screenshots / Video", + "Breaking changes", + "Linked issues", + ]; const missing = []; const empty = []; + const failedRules = []; for (const name of required) { const content = sectionContent(name); @@ -40,34 +75,73 @@ jobs: continue; } - const cleaned = content - .replace(//g, "") - .replace(/`/g, "") - .replace(/\s+/g, " ") - .trim() - .toLowerCase(); + const cleaned = cleanedContent(name); + const normalized = cleaned.toLowerCase(); + const allowsNone = name === "Breaking changes" || name === "Screenshots / Video"; if ( cleaned.length < 4 || - cleaned === "none" || - cleaned.includes("what changed in this pr") || - cleaned.includes("why this change is needed") || - cleaned.includes("what you tested") || - cleaned.includes("example: fixes #123") + (!allowsNone && ["none", "n/a", "na", "not applicable"].includes(normalized)) || + normalized.includes("what changed in this pr") || + normalized.includes("why this change is needed") || + normalized.includes("what you tested") || + normalized.includes("example: fixes #123") ) { empty.push(name); } } - if (missing.length || empty.length) { + const prTypeContent = sectionContent("PR type") || ""; + const prTypeChecked = checkedLines(prTypeContent); + if (sectionContent("PR type") !== null && prTypeChecked.length !== 1) { + failedRules.push("Check exactly one PR type."); + } + + const impactContent = sectionContent("UI / behavior impact") || ""; + const impactChecked = checkedLines(impactContent); + if (sectionContent("UI / behavior impact") !== null && impactChecked.length === 0) { + failedRules.push("Check at least one UI / behavior impact box."); + } + + const policyContent = sectionContent("Policy check") || ""; + const policyChecked = checkedLines(policyContent); + const policyUnchecked = uncheckedLines(policyContent); + if (sectionContent("Policy check") !== null && policyChecked.length === 0) { + failedRules.push("Policy check must include checked boxes."); + } + if (policyUnchecked.length) { + failedRules.push("Every Policy check box must be checked."); + } + + const checkedTypeText = prTypeChecked.join(" "); + const issueRequired = + /bug fix|ui glitch|behavior bug|approved larger|approved directional/i.test(checkedTypeText); + const issueText = [ + cleanedContent("Issue or approval") || "", + cleanedContent("Linked issues") || "", + ].join(" "); + if (issueRequired && !hasIssueReference(issueText)) { + failedRules.push("Bug fixes, UI glitch fixes, behavior fixes, and approved changes must link an issue or approved request."); + } + + const uiChanged = checkedLines(impactContent).some((line) => + /UI changed only to fix a documented glitch\/bug|UI change has explicit maintainer approval/i.test(line) + ); + const screenshotText = (cleanedContent("Screenshots / Video") || "").toLowerCase(); + if (uiChanged && ["none", "n/a", "na", "not a ui change", "not applicable"].includes(screenshotText)) { + failedRules.push("UI changes must include before/after screenshots or video."); + } + + if (missing.length || empty.length || failedRules.length) { const lines = [ "PR description is missing required detail.", "", ]; if (missing.length) lines.push(`Missing sections: ${missing.join(", ")}`); if (empty.length) lines.push(`Incomplete sections: ${empty.join(", ")}`); + if (failedRules.length) lines.push(`Failed policy rules: ${failedRules.join(" ")}`); lines.push(""); - lines.push("Please fill the PR template before merging."); + lines.push("Please complete the PR template and make sure the PR fits CONTRIBUTING.md before review."); core.setFailed(lines.join("\n")); } else { core.info("PR template check passed."); diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md index 3eaf8ae3..4f2d48c8 100644 --- a/CONTRIBUTING.md +++ b/CONTRIBUTING.md @@ -2,33 +2,84 @@ Thanks for helping improve Nuvio. -## Strict rules — read before opening anything +## Strict rules - read before opening anything These rules are enforced strictly. Issues and PRs that do not follow them will be closed without review. --- -## PR policy +## What PRs are for -Pull requests are currently intended for: +Pull requests are accepted only when they fit one of these categories: -- Reproducible bug fixes -- Small stability improvements -- Minor maintenance work +- Reproducible bug fixes for documented issues +- UI glitch fixes for visible bugs or regressions, with before/after proof +- Behavior bug fixes that restore expected behavior without changing product direction +- Small maintenance work that does not change UI, UX, behavior, dependencies, architecture, or public contracts - Small documentation fixes that improve accuracy -- Translation updates +- Translation/localization updates -Pull requests are generally **not** accepted for: +Pull requests are not accepted for: - New major features - Product direction changes -- Large UX / UI redesigns -- Cosmetic-only changes -- Refactors without a clear user-facing or maintenance benefit +- UX/UI redesigns +- Cosmetic-only UI changes +- "Minor polish" changes to colors, spacing, typography, icons, copy, layout, animations, or visual style +- Behavior changes that are not tied to a reproducible bug or approved feature request +- Refactors without a clear maintenance need +- Dependency additions or architecture changes without prior approval Translation PRs are allowed, as long as they stay focused on translation/localization work and do not bundle unrelated feature or UI changes. -### Large PRs and large changes +--- + +## UI changes + +Do not open a pull request for a UI change just because it looks better, cleaner, more modern, or more consistent to you. + +UI PRs are accepted only when they fix a specific, documented glitch or bug, such as: + +- Broken layout +- Overlapping or clipped text +- Unreadable content +- Incorrect visual state +- Navigation, gesture, or focus glitches +- A visible regression from a previous version +- A crash, blank screen, or unusable screen caused by UI code + +Every UI PR must include: + +- A linked bug issue +- A short explanation of the exact glitch being fixed +- Before and after screenshots or a short video +- The smallest possible change that fixes the glitch + +Cosmetic-only UI PRs will be closed, even if the change is small. + +--- + +## Behavior changes + +Behavior includes, but is not limited to, playback, stream/source selection, resume state, watched state, search, sync, settings defaults, navigation, gestures, error handling, caching, networking, storage, downloads, offline behavior, and account-related flows. + +Do not open a PR that changes behavior unless one of these is true: + +- It fixes a linked, reproducible bug or regression and restores the intended behavior. +- It links an approved feature request where a maintainer explicitly approved implementation. + +Behavior PRs must explain: + +- The old behavior +- The broken or unwanted behavior +- The new behavior +- How the behavior was tested + +Minor behavior tweaks are still behavior changes. They need the same issue link or approval. + +--- + +## Large PRs and large changes **Any large PR or change that is not a simple bug fix must be discussed and approved via a feature request issue first.** @@ -38,7 +89,9 @@ Translation PRs are allowed, as long as they stay focused on translation/localiz PRs that introduce large changes without a linked, approved feature request **will not be reviewed at all** and will be closed immediately. No exceptions. -This applies to — but is not limited to — UI changes, new features, architecture changes, dependency additions, and large refactors. +This applies to UI changes, behavior changes, new features, architecture changes, dependency additions, large refactors, migrations, and changes that affect product direction. + +Approval means a maintainer has clearly said the implementation is approved. A feature request being open, popular, or labeled `enhancement` is not approval. --- @@ -100,14 +153,26 @@ Opening a feature request does **not** mean a pull request will be accepted for Please make sure your PR is all of the following: -- Small in scope -- Focused on one problem +- Allowed by this policy +- Small in scope and focused on one problem - Clearly aligned with the current direction of the project -- Not cosmetic-only, unless it is a translation PR -- Not a new major feature unless it was discussed and approved first -- **If large or non-trivial: linked to an approved feature request issue** +- Not cosmetic-only +- Not changing behavior unless it fixes a linked bug or has explicit approval +- Not changing UI unless it fixes a linked glitch/bug and includes visual proof +- Not bundling refactors, cleanups, or drive-by changes with a bug fix +- Tested manually and/or automatically in a way that matches the risk +- Linked to an approved feature request issue if large, directional, or non-trivial -PRs that do not fit this policy will be closed without merge so review time can stay focused on bugs, regressions, and small improvements. +PRs will be closed without review if they: + +- Are cosmetic-only UI changes +- Change behavior without a linked bug or approved feature request +- Change UI without screenshots/video +- Bundle unrelated changes +- Leave the PR template incomplete +- Add dependencies, architecture changes, or broad refactors without approval + +Review time is reserved for bugs, regressions, stability, translations, documentation accuracy, and approved work. --- diff --git a/iosApp/Configuration/Version.xcconfig b/iosApp/Configuration/Version.xcconfig index 0e642b56..b89cbc9c 100644 --- a/iosApp/Configuration/Version.xcconfig +++ b/iosApp/Configuration/Version.xcconfig @@ -1,3 +1,3 @@ -CURRENT_PROJECT_VERSION=59 +CURRENT_PROJECT_VERSION=61 MARKETING_VERSION=0.1.19