mirror of
https://github.com/Gathin23/cleanyourtv.git
synced 2026-11-07 02:36:02 -10:00
CI on every PR, issue forms, PR template, code of conduct, examples validator
The workflow builds the launcher with its unit tests and a 400 KB size guard, and runs the tools tests plus a new tests/test_examples.py that checks every list's format and that both TV tables index every folder. Issue forms for TV reports and bugs, a PR checklist from CONTRIBUTING, and a short plain-language code of conduct.
This commit is contained in:
1 parent
1636b9ec42
commit
97a1b24cb2
7 files changed
+291
No files matched your search
@@ -0,0 +1,43 @@
|
||||
name: Bug
|
||||
description: The launcher, a script or the prompt did something wrong
|
||||
labels: [bug]
|
||||
body:
|
||||
- type: dropdown
|
||||
id: part
|
||||
attributes:
|
||||
label: Which part
|
||||
options:
|
||||
- Launcher (the home screen)
|
||||
- Install script (build-and-install)
|
||||
- Debloat or restore scripts
|
||||
- tools/tv.py or b64push.py
|
||||
- The prompt (PROMPT.md)
|
||||
- Website (cleanyour.tv)
|
||||
validations:
|
||||
required: true
|
||||
- type: input
|
||||
id: tv
|
||||
attributes:
|
||||
label: TV model and Android version
|
||||
placeholder: Xiaomi MiTV-MOOQ1, Android TV 10
|
||||
validations:
|
||||
required: true
|
||||
- type: textarea
|
||||
id: what
|
||||
attributes:
|
||||
label: What happened, and what you expected
|
||||
validations:
|
||||
required: true
|
||||
- type: textarea
|
||||
id: steps
|
||||
attributes:
|
||||
label: Steps to reproduce
|
||||
placeholder: |
|
||||
1. Press Down twice from the dock
|
||||
2. Press Home
|
||||
- type: textarea
|
||||
id: logs
|
||||
attributes:
|
||||
label: Output or screenshot
|
||||
description: Script output, a `logcat` excerpt, or a screenshot pulled from the TV.
|
||||
render: shell
|
||||
@@ -0,0 +1,11 @@
|
||||
blank_issues_enabled: true
|
||||
contact_links:
|
||||
- name: Question or "does it work on my TV?"
|
||||
url: https://github.com/Gathin23/cleanyourtv/discussions/categories/q-a
|
||||
about: Ask in Discussions. Issues are for bugs and TV lists.
|
||||
- name: Show what you built
|
||||
url: https://github.com/Gathin23/cleanyourtv/discussions/categories/show-and-tell
|
||||
about: Screenshots, themes, forks. Launchers and ports also go in SHOWCASE.md by pull request.
|
||||
- name: cleanyour.tv
|
||||
url: https://cleanyour.tv
|
||||
about: The site, with the prompt and the story.
|
||||
@@ -0,0 +1,48 @@
|
||||
name: My TV
|
||||
description: A TV that is not in examples/ yet, or a list that needs a change
|
||||
title: "[TV] Brand Model (Android version)"
|
||||
labels: [tv-list]
|
||||
body:
|
||||
- type: markdown
|
||||
attributes:
|
||||
value: |
|
||||
Lists people have tested live in [`examples/`](../tree/main/examples). If you already have a working list, a pull request is even better: see [CONTRIBUTING.md](../blob/main/CONTRIBUTING.md).
|
||||
- type: input
|
||||
id: model
|
||||
attributes:
|
||||
label: TV model
|
||||
description: "`tools/tv.py --probe` prints the model, device codename, Android version and build."
|
||||
placeholder: Sony BRAVIA KD-55X8509C (SVP-DTV15)
|
||||
validations:
|
||||
required: true
|
||||
- type: input
|
||||
id: android
|
||||
attributes:
|
||||
label: Android version and firmware build
|
||||
placeholder: Android TV 11, build RTT1.230922.001
|
||||
validations:
|
||||
required: true
|
||||
- type: dropdown
|
||||
id: stage
|
||||
attributes:
|
||||
label: How far did you get?
|
||||
options:
|
||||
- Could not connect over ADB
|
||||
- Debloat worked, launcher did not
|
||||
- Both worked, here is my list
|
||||
- Something broke after the debloat
|
||||
validations:
|
||||
required: true
|
||||
- type: textarea
|
||||
id: details
|
||||
attributes:
|
||||
label: What happened
|
||||
description: What you ran, what the TV did, what you expected. Paste the packages you disabled if you have them.
|
||||
render: shell
|
||||
validations:
|
||||
required: true
|
||||
- type: textarea
|
||||
id: screenshot
|
||||
attributes:
|
||||
label: Screenshot
|
||||
description: "Optional. `tools/tv.py 'screencap -p /sdcard/s.png'` then `tools/tv.py --pull /sdcard/s.png s.png`, and drop the file here."
|
||||
@@ -0,0 +1,16 @@
|
||||
<!-- Thanks. One or two sentences on what this changes and the TV it was tried on is plenty. -->
|
||||
|
||||
**Tested on:** <!-- model, Android version -->
|
||||
|
||||
### If this adds or changes a TV list
|
||||
- [ ] `examples/<brand>-<model>/debloat.txt`, header with model, Android version and firmware build
|
||||
- [ ] Only packages I actually disabled and lived with; anything I had to re-enable is noted
|
||||
- [ ] A row in `examples/README.md` and one in the README's TV table
|
||||
- [ ] Nothing in the list uninstalls
|
||||
|
||||
### If this touches the launcher
|
||||
- [ ] Verified on a real TV, screenshot attached
|
||||
- [ ] D-pad checked from every edge (Up, Down, Left, Right)
|
||||
- [ ] No network, no background service, no new permission
|
||||
- [ ] New strings in `values/strings.xml` and the other `values-*` folders
|
||||
- [ ] Anything TV-specific is in `config.xml` or a theme, not in code
|
||||
@@ -0,0 +1,49 @@
|
||||
name: CI
|
||||
|
||||
on:
|
||||
push:
|
||||
branches: [main]
|
||||
pull_request:
|
||||
|
||||
permissions:
|
||||
contents: read
|
||||
|
||||
jobs:
|
||||
lists-and-tools:
|
||||
name: Lists, tools and docs
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- uses: actions/checkout@v4
|
||||
- uses: actions/setup-python@v5
|
||||
with:
|
||||
python-version: "3.12"
|
||||
- name: Tools virtualenv
|
||||
run: |
|
||||
python3 -m venv tools/venv
|
||||
tools/venv/bin/pip install -q -r tools/requirements.txt
|
||||
- name: Example lists, README tables, shell helpers
|
||||
run: python3 -m unittest discover -s tests -v
|
||||
|
||||
launcher:
|
||||
name: Launcher build and unit tests
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- uses: actions/checkout@v4
|
||||
- uses: actions/setup-java@v4
|
||||
with:
|
||||
distribution: temurin
|
||||
java-version: "17"
|
||||
- uses: android-actions/setup-android@v3
|
||||
with:
|
||||
packages: platforms;android-34 build-tools;34.0.0
|
||||
- uses: gradle/actions/setup-gradle@v4
|
||||
- name: Unit tests and release build
|
||||
working-directory: launcher
|
||||
run: |
|
||||
chmod +x gradlew
|
||||
./gradlew --no-daemon testReleaseUnitTest assembleRelease
|
||||
- name: The launcher stays small
|
||||
run: |
|
||||
size=$(stat -c %s launcher/app/build/outputs/apk/release/app-release.apk)
|
||||
echo "release APK: $((size / 1024)) KB"
|
||||
test "$size" -lt 409600 || { echo "APK is over 400 KB; the launcher targets 1 GB TVs, keep it small"; exit 1; }
|
||||
@@ -0,0 +1,36 @@
|
||||
# Code of conduct
|
||||
|
||||
This project exists because a few thousand people helped each other fix their TVs in the replies
|
||||
to a tweet. Keep it like that.
|
||||
|
||||
## Expected
|
||||
|
||||
- Be kind. Many contributors are doing this on a parent's or grandparent's TV, in a second
|
||||
language, on their first pull request.
|
||||
- Assume good faith. A list that breaks something was tested on different firmware, not written to
|
||||
hurt anyone.
|
||||
- Say what you tested on. Specifics ("Android TV 11, build RTT1, Hisense A4") help; verdicts
|
||||
("doesn't work") do not.
|
||||
- Respect the maintainers' decisions on scope. The launcher stays small, offline and without
|
||||
prebuilt binaries; if your idea does not fit, a fork with a SHOWCASE row is a good outcome, not a
|
||||
rejection of you.
|
||||
|
||||
## Not accepted
|
||||
|
||||
- Insults, harassment, slurs, sexualised language or imagery, or personal attacks, in issues,
|
||||
pull requests, Discussions or the showcase.
|
||||
- Publishing other people's private information: device identifiers, Wi-Fi names, IP addresses,
|
||||
ADB keys or anything that could identify a TV or a home.
|
||||
- Lists or instructions that uninstall, root, or intentionally damage a TV, or that target a
|
||||
specific person's device.
|
||||
- Spam, affiliate links, or passing off someone else's work as your own.
|
||||
|
||||
## Enforcement
|
||||
|
||||
Maintainers may edit, hide or remove content and block accounts that break these rules, with a
|
||||
short explanation. To report something, open an issue, or if it is private, message
|
||||
[@gathint on X](https://x.com/gathint). Reports are read by the maintainer and handled within a
|
||||
few days.
|
||||
|
||||
This is a short, plain-language code adapted in spirit from the
|
||||
[Contributor Covenant](https://www.contributor-covenant.org/version/2/1/code_of_conduct/).
|
||||
@@ -0,0 +1,88 @@
|
||||
"""Checks every TV list in examples/ and the two tables that index them.
|
||||
|
||||
Run from the repository root: python3 -m unittest discover -s tests -v
|
||||
"""
|
||||
import re
|
||||
from pathlib import Path
|
||||
import unittest
|
||||
|
||||
|
||||
ROOT = Path(__file__).resolve().parents[1]
|
||||
EXAMPLES = ROOT / "examples"
|
||||
PACKAGE = re.compile(r"^[A-Za-z_][A-Za-z0-9_]*(\.[A-Za-z0-9_]+)+$")
|
||||
|
||||
|
||||
def folders():
|
||||
return sorted(p for p in EXAMPLES.iterdir() if p.is_dir())
|
||||
|
||||
|
||||
def table_rows(path, header_prefix):
|
||||
"""Rows of the first markdown table whose header starts with header_prefix."""
|
||||
lines = path.read_text(encoding="utf-8").split("\n")
|
||||
start = next(i for i, l in enumerate(lines) if l.startswith(header_prefix))
|
||||
rows = []
|
||||
for line in lines[start + 2:]:
|
||||
if not line.startswith("|"):
|
||||
break
|
||||
rows.append(line)
|
||||
return rows
|
||||
|
||||
|
||||
class ExampleListsTest(unittest.TestCase):
|
||||
def test_every_folder_has_a_list(self):
|
||||
for folder in folders():
|
||||
with self.subTest(folder=folder.name):
|
||||
self.assertTrue((folder / "debloat.txt").is_file(), "no debloat.txt")
|
||||
|
||||
def test_list_format(self):
|
||||
for folder in folders():
|
||||
path = folder / "debloat.txt"
|
||||
if not path.is_file():
|
||||
continue
|
||||
with self.subTest(folder=folder.name):
|
||||
lines = path.read_text(encoding="utf-8").split("\n")
|
||||
self.assertTrue(lines and lines[0].startswith("#"),
|
||||
"first line should be a comment naming the TV, Android version and build")
|
||||
packages = []
|
||||
for n, line in enumerate(lines, 1):
|
||||
body = line.split("#", 1)[0].strip()
|
||||
if not body:
|
||||
continue
|
||||
self.assertRegex(body, PACKAGE, f"line {n}: not a package name: {line!r}")
|
||||
packages.append(body)
|
||||
self.assertTrue(packages, "no packages: notes without a list belong in docs/devices/")
|
||||
dupes = sorted({p for p in packages if packages.count(p) > 1})
|
||||
self.assertFalse(dupes, f"listed twice: {dupes}")
|
||||
text = path.read_text(encoding="utf-8")
|
||||
self.assertNotIn("pm uninstall", text, "lists disable, they never uninstall")
|
||||
|
||||
def test_examples_table_matches_folders(self):
|
||||
rows = table_rows(EXAMPLES / "README.md", "| Folder |")
|
||||
listed = []
|
||||
for row in rows:
|
||||
m = re.match(r"\|\s*`([^`/]+)/`\s*\|", row)
|
||||
self.assertIsNotNone(m, f"row does not start with a `folder/` cell: {row[:60]}")
|
||||
listed.append(m.group(1))
|
||||
names = [f.name for f in folders()]
|
||||
self.assertEqual(sorted(listed), sorted(names),
|
||||
"examples/README.md rows and examples/ folders differ")
|
||||
self.assertEqual(len(listed), len(set(listed)), "a folder is listed twice")
|
||||
|
||||
def test_readme_table_has_one_row_per_list(self):
|
||||
readme_rows = table_rows(ROOT / "README.md", "| TV | OS |")
|
||||
example_rows = table_rows(EXAMPLES / "README.md", "| Folder |")
|
||||
self.assertEqual(len(readme_rows), len(example_rows),
|
||||
"README.md TV table and examples/README.md have a different number of rows")
|
||||
readme_tvs = sorted(r.split("|")[1].strip() for r in readme_rows)
|
||||
example_tvs = sorted(r.split("|")[2].strip() for r in example_rows)
|
||||
self.assertEqual(readme_tvs, example_tvs, "the TV column differs between the two tables")
|
||||
|
||||
def test_readme_counts(self):
|
||||
text = (ROOT / "README.md").read_text(encoding="utf-8")
|
||||
n = len(folders())
|
||||
self.assertIn(f"{n} TV lists", text, "nav link count is stale")
|
||||
self.assertIn(f"{n} TVs with tested lists", text, "numbers line is stale")
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
unittest.main()
|
||||
Reference in new issue
Block a user