mirror of
https://github.com/Abdess/retroarch_system.git
synced 2026-11-06 01:53:56 -06:00
chore: drop the scheduled campaign job
This commit is contained in:
1 parent
6876fe7ec3
commit
442d49e4e1
5 files changed
+13
-81
No files matched your search
@@ -94,35 +94,6 @@ jobs:
|
|||||||
stdout: tmp/autorun/bios-integrity.json
|
stdout: tmp/autorun/bios-integrity.json
|
||||||
report: tmp/autorun/bios-integrity.json
|
report: tmp/autorun/bios-integrity.json
|
||||||
|
|
||||||
campaign:
|
|
||||||
schedule: "*-*-* 06:00"
|
|
||||||
network: true
|
|
||||||
max_load_wait: 7200
|
|
||||||
timeout: 12600
|
|
||||||
steps:
|
|
||||||
- run: [python, scripts/campaign.py, run, --budget, 150m]
|
|
||||||
ok_codes: [0, 75]
|
|
||||||
stdout: tmp/autorun/campaign.json
|
|
||||||
env: [RETROBIOS_ROMFETCH, RETROBIOS_AUTO_LOCK, ROMFETCH_CONTENT_DIR, ROMFETCH_CACHE_DIR,
|
|
||||||
ROMFETCH_DATS_DIR, ROMFETCH_RETOOL_DIR, ROMFETCH_MIN_INTERVAL, ROMFETCH_MAX_SIZE,
|
|
||||||
ROMFETCH_DISABLED_SOURCES, XDG_CONFIG_HOME]
|
|
||||||
gate:
|
|
||||||
- [python, scripts/campaign.py, gate]
|
|
||||||
commits:
|
|
||||||
- subject: "chore: add campaign measurements"
|
|
||||||
body: >-
|
|
||||||
Core probe records, findings and the pass summary written by
|
|
||||||
campaign.py, behind the measurement tests and the schemas.
|
|
||||||
paths: [measurements/*.jsonl]
|
|
||||||
- subject: "chore: apply fields the campaign proved"
|
|
||||||
body: >-
|
|
||||||
Fields the campaign's rule table settled from real runs, each with
|
|
||||||
the record ids in evidence:, behind verify and an emulator pack of
|
|
||||||
every changed profile.
|
|
||||||
paths: [emulators/*.yml]
|
|
||||||
report: tmp/autorun/campaign.json
|
|
||||||
scratch: [tmp/autorun, tmp/core_probe]
|
|
||||||
|
|
||||||
assets:
|
assets:
|
||||||
schedule: "*-*-* 04:30"
|
schedule: "*-*-* 04:30"
|
||||||
network: true
|
network: true
|
||||||
|
|||||||
+2
-11
@@ -53,11 +53,9 @@ Usage:
|
|||||||
python scripts/campaign.py findings [--all] [--json]
|
python scripts/campaign.py findings [--all] [--json]
|
||||||
python scripts/campaign.py review KEY --status applied|rejected --reason TEXT [--set FIELD=YAML]
|
python scripts/campaign.py review KEY --status applied|rejected --reason TEXT [--set FIELD=YAML]
|
||||||
python scripts/campaign.py gate
|
python scripts/campaign.py gate
|
||||||
python scripts/campaign.py install-timer [--enable]
|
|
||||||
|
|
||||||
install-timer is opt-in: a contributor who wants a schedule on their own
|
A maintainer starts each pass for a question that names its profiles: no
|
||||||
machine installs the timer. It writes the units and enables nothing unless
|
job runs it on a schedule.
|
||||||
--enable is passed.
|
|
||||||
"""
|
"""
|
||||||
|
|
||||||
from __future__ import annotations
|
from __future__ import annotations
|
||||||
@@ -1941,18 +1939,11 @@ def main(argv: Sequence[str] | None = None) -> int:
|
|||||||
help="with --status applied, a field to write into the entry")
|
help="with --status applied, a field to write into the entry")
|
||||||
review_p.add_argument("--index", type=int, help="the entry's position when several share its name")
|
review_p.add_argument("--index", type=int, help="the entry's position when several share its name")
|
||||||
sub.add_parser("gate", help="tests, schemas, verify and pack of the changed profiles")
|
sub.add_parser("gate", help="tests, schemas, verify and pack of the changed profiles")
|
||||||
timer_p = sub.add_parser("install-timer",
|
|
||||||
help="opt-in: write the autorun units, the campaign job's timer among them")
|
|
||||||
timer_p.add_argument("--enable", action="store_true",
|
|
||||||
help="also reload systemd and enable the timers (never by default)")
|
|
||||||
args = parser.parse_args(argv)
|
args = parser.parse_args(argv)
|
||||||
|
|
||||||
paths = Paths.default()
|
paths = Paths.default()
|
||||||
if args.command == "gate":
|
if args.command == "gate":
|
||||||
return gate(paths.root, changed_profiles(paths.root))
|
return gate(paths.root, changed_profiles(paths.root))
|
||||||
if args.command == "install-timer":
|
|
||||||
command = [sys.executable, str(ROOT / "scripts" / "autorun.py"), "install-timers"]
|
|
||||||
return subprocess.run(command + (["--enable"] if args.enable else []), check=False).returncode
|
|
||||||
if args.command == "review":
|
if args.command == "review":
|
||||||
updates: dict[str, object] = {}
|
updates: dict[str, object] = {}
|
||||||
for item in args.set:
|
for item in args.set:
|
||||||
|
|||||||
@@ -275,7 +275,6 @@ class GithubTokenPerStep(Scratch):
|
|||||||
def test_the_committed_registry(self):
|
def test_the_committed_registry(self):
|
||||||
jobs = ar.load_jobs()
|
jobs = ar.load_jobs()
|
||||||
self.assertTrue(all(step.github_token for step in jobs["nightly"].steps))
|
self.assertTrue(all(step.github_token for step in jobs["nightly"].steps))
|
||||||
self.assertFalse(any(step.github_token for step in jobs["campaign"].steps + jobs["campaign"].gate))
|
|
||||||
|
|
||||||
|
|
||||||
class ReportAlert(Scratch):
|
class ReportAlert(Scratch):
|
||||||
|
|||||||
+7
-30
@@ -1019,24 +1019,6 @@ class ContentFile(Workspace):
|
|||||||
self.assertIn("Other Game (Japan)", out.getvalue())
|
self.assertIn("Other Game (Japan)", out.getvalue())
|
||||||
|
|
||||||
|
|
||||||
class InstallTimer(unittest.TestCase):
|
|
||||||
def test_writes_the_units_and_enables_only_when_asked(self) -> None:
|
|
||||||
calls = []
|
|
||||||
real_run = subprocess.run
|
|
||||||
|
|
||||||
def fake_run(argv: list[str], **kwargs: object) -> subprocess.CompletedProcess:
|
|
||||||
if "install-timers" not in argv:
|
|
||||||
return real_run(argv, **kwargs)
|
|
||||||
calls.append(argv)
|
|
||||||
return subprocess.CompletedProcess(argv, 0)
|
|
||||||
with unittest.mock.patch.object(campaign.subprocess, "run", fake_run):
|
|
||||||
self.assertEqual(campaign.main(["install-timer"]), 0)
|
|
||||||
self.assertEqual(campaign.main(["install-timer", "--enable"]), 0)
|
|
||||||
self.assertEqual([argv[2:] for argv in calls],
|
|
||||||
[["install-timers"], ["install-timers", "--enable"]])
|
|
||||||
self.assertTrue(calls[0][1].endswith("scripts/autorun.py"))
|
|
||||||
|
|
||||||
|
|
||||||
class Registry(unittest.TestCase):
|
class Registry(unittest.TestCase):
|
||||||
def test_no_profile_takes_a_campaign_file_name(self) -> None:
|
def test_no_profile_takes_a_campaign_file_name(self) -> None:
|
||||||
stems = {p.stem for p in (REPO_ROOT / "emulators").glob("*.yml")}
|
stems = {p.stem for p in (REPO_ROOT / "emulators").glob("*.yml")}
|
||||||
@@ -1054,18 +1036,13 @@ class Registry(unittest.TestCase):
|
|||||||
self.assertGreater(len(item.reason), 40)
|
self.assertGreater(len(item.reason), 40)
|
||||||
self.assertGreater(item.frames, item.frame_hash_every)
|
self.assertGreater(item.frames, item.frame_hash_every)
|
||||||
|
|
||||||
def test_the_autorun_job(self) -> None:
|
def test_no_job_runs_a_standing_campaign(self) -> None:
|
||||||
jobs = campaign.autorun.load_jobs()
|
"""A daily pass over every profile contradicted the rule that probes
|
||||||
job = jobs["campaign"]
|
run on demand, for a question that names its profiles."""
|
||||||
self.assertTrue(job.lock and job.worktree and job.schedule)
|
for name, job in campaign.autorun.load_jobs().items():
|
||||||
self.assertEqual(job.gate[0].argv, ("python", "scripts/campaign.py", "gate"))
|
for step in [*job.steps, *job.gate]:
|
||||||
self.assertEqual({p for rule in job.commits for p in rule.paths},
|
with self.subTest(job=name):
|
||||||
{"measurements/*.jsonl", "emulators/*.yml"})
|
self.assertNotIn("scripts/campaign.py", step.argv)
|
||||||
self.assertGreater(job.schedule, jobs["nightly"].schedule)
|
|
||||||
|
|
||||||
def test_autorun_tells_its_steps_the_lock_is_held(self) -> None:
|
|
||||||
job = campaign.autorun.load_jobs()["campaign"]
|
|
||||||
self.assertEqual(campaign.autorun.job_env(job)[campaign.LOCK_HELD_ENV], "1")
|
|
||||||
|
|
||||||
|
|
||||||
@unittest.skipUnless(shutil.which("cc") and shutil.which("strace"), "no C compiler or no strace")
|
@unittest.skipUnless(shutil.which("cc") and shutil.which("strace"), "no C compiler or no strace")
|
||||||
|
|||||||
+4
-10
@@ -772,7 +772,6 @@ until a report without one. Exit codes: 0 for `ok`,
|
|||||||
|-----|----------|--------------|
|
|-----|----------|--------------|
|
||||||
| `nightly` | 02:00 | `check_freshness.py --json` saved to a file, `refresh_stale.py --findings` on its `data` and `catalogs` rows, the MAME and FBNeo hash scrapers, then `pipeline.py --offline` as the gate. `database.json` and `install/*.json` are computed a second time and compared. Commits the hash profiles, the recipes and the regenerated records |
|
| `nightly` | 02:00 | `check_freshness.py --json` saved to a file, `refresh_stale.py --findings` on its `data` and `catalogs` rows, the MAME and FBNeo hash scrapers, then `pipeline.py --offline` as the gate. `database.json` and `install/*.json` are computed a second time and compared. Commits the hash profiles, the recipes and the regenerated records |
|
||||||
| `assets` | 04:30 | `sync_release_assets.py`, as a dry run |
|
| `assets` | 04:30 | `sync_release_assets.py`, as a dry run |
|
||||||
| `campaign` | 06:00 | `campaign.py run --budget 150m` once the host is idle (up to two hours of waiting), gated by `campaign.py gate`. Commits the records, findings and pass line, then the profile fields the runs proved |
|
|
||||||
| `bios-integrity` | Sunday 08:30 | `bios_integrity.py --apply --json` in the main checkout, once the host is idle (up to four hours of waiting). Its report is kept in the job's status |
|
| `bios-integrity` | Sunday 08:30 | `bios_integrity.py --apply --json` in the main checkout, once the host is idle (up to four hours of waiting). Its report is kept in the job's status |
|
||||||
| `cleanup` | 05:30 | `cleanup_disk.py --apply --hours 72` in the main checkout |
|
| `cleanup` | 05:30 | `cleanup_disk.py --apply --hours 72` in the main checkout |
|
||||||
| `disk-check` | hourly | `cleanup_disk.py --check`, without the lock |
|
| `disk-check` | hourly | `cleanup_disk.py --check`, without the lock |
|
||||||
@@ -1052,7 +1051,6 @@ python scripts/campaign.py findings # what waits for review
|
|||||||
python scripts/campaign.py review beetle_psx/sony-playstation/scph5501.bin/validation \
|
python scripts/campaign.py review beetle_psx/sony-playstation/scph5501.bin/validation \
|
||||||
--status applied --set on_mismatch=warn --reason "logs the SHA1 and loads (libretro.c:853-860)"
|
--status applied --set on_mismatch=warn --reason "logs the SHA1 and loads (libretro.c:853-860)"
|
||||||
python scripts/campaign.py gate # the checks behind a commit
|
python scripts/campaign.py gate # the checks behind a commit
|
||||||
python scripts/campaign.py install-timer # opt-in: writes the autorun units, enables nothing
|
|
||||||
```
|
```
|
||||||
|
|
||||||
| Step | What happens |
|
| Step | What happens |
|
||||||
@@ -1108,10 +1106,10 @@ checks. The campaign's own `evidence:` writes do not count as a profile change.
|
|||||||
|
|
||||||
| Guard | Rule |
|
| Guard | Rule |
|
||||||
|-------|------|
|
|-------|------|
|
||||||
| Lock | The host-wide autorun lock. Under the `campaign` job, autorun holds it and says so with `RETROBIOS_AUTO_LOCK_HELD` |
|
| Lock | The host-wide autorun lock. When a caller already holds it, `RETROBIOS_AUTO_LOCK_HELD` says so |
|
||||||
| Probe lock | Not held by the pass: each core_probe it starts takes the host probe lock for its own run, so the pass and other measurements (pack_probe, a core_probe loop) interleave. Two campaign passes still exclude each other through the automation lock, since they share `.cache/campaign/state.json`. Do not wrap `campaign.py run` in `flock` |
|
| Probe lock | Not held by the pass: each core_probe it starts takes the host probe lock for its own run, so the pass and other measurements (pack_probe, a core_probe loop) interleave. Two campaign passes still exclude each other through the automation lock, since they share `.cache/campaign/state.json`. Do not wrap `campaign.py run` in `flock` |
|
||||||
| Environment | `core_probe.py`, git and `make` get autorun's allowlist, romfetch the same plus its `ROMFETCH_*` settings. None sees a token or a password |
|
| Environment | `core_probe.py`, git and `make` get autorun's allowlist, romfetch the same plus its `ROMFETCH_*` settings. None sees a token or a password |
|
||||||
| Sandbox | Fails closed: without a working bubblewrap the pass is `refused` (exit 3) and nothing third-party runs, every probe is started with `--require-sandbox`, and a build is refused. `--allow-unsandboxed` overrides. Under autorun the refusal raises the `job:campaign` alert |
|
| Sandbox | Fails closed: without a working bubblewrap the pass is `refused` (exit 3) and nothing third-party runs, every probe is started with `--require-sandbox`, and a build is refused. `--allow-unsandboxed` overrides |
|
||||||
| Load | Before each run, waits while the 1-minute load is above a quarter of the CPUs, up to `--max-load-wait` seconds, then the pass stops as `paused` |
|
| Load | Before each run, waits while the 1-minute load is above a quarter of the CPUs, up to `--max-load-wait` seconds, then the pass stops as `paused` |
|
||||||
| Disk | Below `--min-free-gb` (default 30) the pass stops as `paused` |
|
| Disk | Below `--min-free-gb` (default 30) the pass stops as `paused` |
|
||||||
| Budget | No check starts after `--budget` |
|
| Budget | No check starts after `--budget` |
|
||||||
@@ -1129,12 +1127,8 @@ and campaign tests, `validate_schemas.py --source-only`, then `verify.py
|
|||||||
--emulator` and `generate_pack.py --emulator` for each changed profile. A file
|
--emulator` and `generate_pack.py --emulator` for each changed profile. A file
|
||||||
that had uncommitted changes before the pass is left alone.
|
that had uncommitted changes before the pass is left alone.
|
||||||
|
|
||||||
A maintainer starts each pass. Scheduling is opt-in: a contributor who wants a
|
A maintainer starts each pass, for a question that names its profiles. No
|
||||||
schedule on their own machine installs the timer with `campaign.py
|
autorun job runs it on a schedule.
|
||||||
install-timer`, which writes the autorun units and enables nothing unless
|
|
||||||
`--enable` is passed. The `campaign` autorun job then runs a 150-minute pass
|
|
||||||
in the automation worktree, gates it with `campaign.py gate` and commits with
|
|
||||||
its own rules, pushing only with `--push`.
|
|
||||||
|
|
||||||
`review` closes an open finding once someone has read the core's code at the
|
`review` closes an open finding once someone has read the core's code at the
|
||||||
profile's pin. `--status applied` writes each `--set FIELD=YAML` into the
|
profile's pin. `--status applied` writes each `--set FIELD=YAML` into the
|
||||||
|
|||||||
Reference in new issue
Block a user