mirror of
https://github.com/RetroPortingToolKit/psxrecomp
synced 2026-10-26 02:11:36 -04:00
874df9b5bb
Retire the setup-host release model (CI wiped generated/ and shipped
emitters + sources + a wizard so every player regenerated and rebuilt the
title). Titles now commit generated/ and CI ships the compiled game.
- docs/ci/templates/game-release.yml replaces setup-release.yml: gate on
committed game C (tools/ci/check_generated.sh), emit the OpenBIOS backend
in CI (tools/ci/generate_openbios.sh), configure with
PSXRECOMP_REQUIRE_GAME_C=ON and assert the full path was taken, package
with tools/package_game_release.sh, verify the zip is a game not a kit.
- tools/package_game_release.sh: exe, assets, bundled OpenBIOS, configs, mod
catalog + overlay toolchain via release_stage.py, notices; refuses sources,
emitters, generated C, BIOS dumps. clear_generated.sh removed;
package_setup_host.sh marked retired.
- Scaffold: gitignore templates track generated/, package_release.sh.in
wrapper, setup_project.{sh,ps1} commit generated/ after Generate.
- Project Studio: audit flags ignored/untracked generated/, retail BIOS C
and setup-host workflows; merge_gitignore un-ignores generated/; ops emit
the bundled packager + workflow; generate_ci uses the new template.
- Docs: docs/ci/BUNDLED_RELEASES.md replaces HOST_ONLY_RELEASES.md.
- Tests: tools/tests/test_bundled_release_layout.py; fix pre-existing
false positives in the packager-surface and overlay-static tests.
Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
124 lines
5.2 KiB
Python
Executable File
124 lines
5.2 KiB
Python
Executable File
#!/usr/bin/env python3
|
|
"""generate_ci.py -- write the bundled release workflow into an EXISTING PSX
|
|
project. Nothing else: no commit, no push, no migration plan.
|
|
|
|
The workflow builds the title's COMMITTED generated/ game C and ships the
|
|
compiled game (docs/ci/BUNDLED_RELEASES.md).
|
|
|
|
python3 psxrecomp/tools/generate_ci.py # cwd is the project
|
|
python3 psxrecomp/tools/generate_ci.py ~/src/MyGameRecomp
|
|
python3 psxrecomp/tools/generate_ci.py --check # stale? (exit 1)
|
|
python3 psxrecomp/tools/generate_ci.py --force # overwrite
|
|
|
|
This is the thin, single-purpose face of Project Studio's emit_ci_workflow
|
|
operation (tools/new_project_layout/project_studio/ops.py), which is also
|
|
what `migrate_project.py apply` and `git install-ci` run. The template is
|
|
docs/ci/templates/game-release.yml from the project's own psxrecomp
|
|
submodule when it has one, so the workflow matches the framework the project
|
|
pins; this checkout is the fallback.
|
|
|
|
Where the values come from:
|
|
ZIP_PREFIX scripts/package_release.sh --zip-prefix <x> (the packager's
|
|
prefix, so the zips CI uploads are the zips it built), else
|
|
derived from the project name, else --zip-prefix
|
|
GAME_TITLE CMakeLists.txt / game.toml window_title, else --title
|
|
|
|
An existing, filled release.yml is not overwritten silently: its step names
|
|
are compared with the template's, and a step the template defines that the
|
|
file lacks means the file predates a framework change (reported as stale).
|
|
--force overwrites; a customised workflow is replaced wholesale, so diff it.
|
|
"""
|
|
|
|
from __future__ import annotations
|
|
|
|
import argparse
|
|
import pathlib
|
|
import re
|
|
import sys
|
|
|
|
HERE = pathlib.Path(__file__).resolve().parent
|
|
sys.path.insert(0, str(HERE / "new_project_layout"))
|
|
|
|
WORKFLOW_REL = pathlib.Path(".github") / "workflows" / "release.yml"
|
|
|
|
|
|
def zip_prefix_from_packager(root: pathlib.Path) -> str:
|
|
# package_setup_release.sh is the retired setup-host wrapper; its prefix is
|
|
# still the right one for a title that has not re-emitted the packager.
|
|
for name in ("package_release.sh", "package_setup_release.sh"):
|
|
try:
|
|
text = (root / "scripts" / name).read_text(encoding="utf-8", errors="replace")
|
|
except OSError:
|
|
continue
|
|
m = re.search(r"--zip-prefix\s+([^\s\\'\"]+)", text)
|
|
if m:
|
|
return m.group(1)
|
|
return ""
|
|
|
|
|
|
def main() -> int:
|
|
ap = argparse.ArgumentParser(description=__doc__.split("\n\n")[0],
|
|
formatter_class=argparse.RawDescriptionHelpFormatter,
|
|
epilog="\n".join(__doc__.split("\n\n")[1:]))
|
|
ap.add_argument("root", nargs="?", default=".", help="project root (default: cwd)")
|
|
ap.add_argument("--zip-prefix", default="", help="override the release zip prefix")
|
|
ap.add_argument("--title", default="", help="override the game title in release names")
|
|
ap.add_argument("--force", action="store_true", help="overwrite an existing release.yml")
|
|
ap.add_argument("--check", action="store_true",
|
|
help="report whether release.yml is present and current; exit 1 if not")
|
|
ap.add_argument("--dry-run", action="store_true", help="resolve and report, write nothing")
|
|
args = ap.parse_args()
|
|
|
|
root = pathlib.Path(args.root).resolve()
|
|
if not (root / "CMakeLists.txt").is_file():
|
|
print(f"generate_ci: {root} has no CMakeLists.txt -- not a project root", file=sys.stderr)
|
|
return 2
|
|
|
|
try:
|
|
from project_studio.models import MigrateOptions
|
|
from project_studio.ops import op_emit_ci_workflow, _ci_steps_missing_from
|
|
from project_studio.paths import ci_release_template
|
|
except ImportError as exc:
|
|
print(f"generate_ci: cannot import Project Studio from {HERE / 'new_project_layout'}: {exc}",
|
|
file=sys.stderr)
|
|
return 2
|
|
|
|
template = ci_release_template(root)
|
|
if template is None:
|
|
print("generate_ci: no docs/ci/templates/game-release.yml found (neither the "
|
|
"project's psxrecomp submodule nor this checkout -- a submodule pinned "
|
|
"before bundled releases must be bumped first)", file=sys.stderr)
|
|
return 2
|
|
|
|
dst = root / WORKFLOW_REL
|
|
if args.check:
|
|
if not dst.is_file():
|
|
print(f"{WORKFLOW_REL}: missing")
|
|
return 1
|
|
text = dst.read_text(encoding="utf-8", errors="replace")
|
|
if "YOUR_ZIP_PREFIX" in text or "YOUR_GAME_TITLE" in text:
|
|
print(f"{WORKFLOW_REL}: still has YOUR_* placeholders")
|
|
return 1
|
|
stale = _ci_steps_missing_from(dst, template)
|
|
if stale:
|
|
print(f"{WORKFLOW_REL}: stale -- missing step(s): {', '.join(stale)}")
|
|
return 1
|
|
print(f"{WORKFLOW_REL}: present and current")
|
|
return 0
|
|
|
|
options = MigrateOptions(
|
|
zip_prefix=args.zip_prefix or zip_prefix_from_packager(root) or None,
|
|
window_title=args.title or None,
|
|
force=args.force,
|
|
dry_run=args.dry_run,
|
|
)
|
|
result = op_emit_ci_workflow(root, options)
|
|
print(f"template: {template}")
|
|
print(f"zip prefix: {options.zip_prefix or '(derived from the project name)'}")
|
|
print(result.message)
|
|
return 0 if result.ok else 1
|
|
|
|
|
|
if __name__ == "__main__":
|
|
raise SystemExit(main())
|