Rename release outputs and managed project to OME
Some checks failed
Some checks failed
This commit is contained in:
@@ -69,17 +69,17 @@ jobs:
|
|||||||
- name: Stage verified workflow artifact
|
- name: Stage verified workflow artifact
|
||||||
run: |
|
run: |
|
||||||
mkdir -p build/workflow-artifact
|
mkdir -p build/workflow-artifact
|
||||||
cp build/package/OpenMaidEngine-Himegari-linux-x64.tar.gz build/workflow-artifact/
|
cp build/package/OME-linux-x64.tar.gz build/workflow-artifact/
|
||||||
cp build/package/staging/OpenMaidEngine-Himegari-linux-x64/BUILD-INFO.json build/workflow-artifact/
|
cp build/package/staging/OME-linux-x64/BUILD-INFO.json build/workflow-artifact/
|
||||||
cp build/package/staging/OpenMaidEngine-Himegari-linux-x64/SHA256SUMS build/workflow-artifact/
|
cp build/package/staging/OME-linux-x64/SHA256SUMS build/workflow-artifact/
|
||||||
cp build/package/package-smoke.log build/workflow-artifact/
|
cp build/package/package-smoke.log build/workflow-artifact/
|
||||||
cd build/workflow-artifact
|
cd build/workflow-artifact
|
||||||
sha256sum OpenMaidEngine-Himegari-linux-x64.tar.gz > OpenMaidEngine-Himegari-linux-x64.tar.gz.sha256
|
sha256sum OME-linux-x64.tar.gz > OME-linux-x64.tar.gz.sha256
|
||||||
|
|
||||||
- name: Upload verified Linux package
|
- name: Upload verified Linux package
|
||||||
uses: christopherhx/gitea-upload-artifact@v4
|
uses: christopherhx/gitea-upload-artifact@v4
|
||||||
with:
|
with:
|
||||||
name: OpenMaidEngine-Himegari-linux-x64-${{ gitea.sha }}
|
name: OME-linux-x64-${{ gitea.sha }}
|
||||||
path: build/workflow-artifact/*
|
path: build/workflow-artifact/*
|
||||||
if-no-files-found: error
|
if-no-files-found: error
|
||||||
retention-days: 30
|
retention-days: 30
|
||||||
@@ -155,17 +155,17 @@ jobs:
|
|||||||
- name: Stage verified workflow artifact
|
- name: Stage verified workflow artifact
|
||||||
run: |
|
run: |
|
||||||
mkdir -p build/workflow-artifact-windows
|
mkdir -p build/workflow-artifact-windows
|
||||||
cp build/package/windows-x64/OpenMaidEngine-Himegari-windows-x64.zip build/workflow-artifact-windows/
|
cp build/package/windows-x64/OME-windows-x64.zip build/workflow-artifact-windows/
|
||||||
cp build/package/windows-x64/staging/OpenMaidEngine-Himegari-windows-x64/BUILD-INFO.json build/workflow-artifact-windows/
|
cp build/package/windows-x64/staging/OME-windows-x64/BUILD-INFO.json build/workflow-artifact-windows/
|
||||||
cp build/package/windows-x64/staging/OpenMaidEngine-Himegari-windows-x64/SHA256SUMS build/workflow-artifact-windows/
|
cp build/package/windows-x64/staging/OME-windows-x64/SHA256SUMS build/workflow-artifact-windows/
|
||||||
cp build/package/windows-x64/staging/OpenMaidEngine-Himegari-windows-x64/WINDOWS-VERIFICATION.json build/workflow-artifact-windows/
|
cp build/package/windows-x64/staging/OME-windows-x64/WINDOWS-VERIFICATION.json build/workflow-artifact-windows/
|
||||||
cd build/workflow-artifact-windows
|
cd build/workflow-artifact-windows
|
||||||
sha256sum OpenMaidEngine-Himegari-windows-x64.zip > OpenMaidEngine-Himegari-windows-x64.zip.sha256
|
sha256sum OME-windows-x64.zip > OME-windows-x64.zip.sha256
|
||||||
|
|
||||||
- name: Upload verified Windows package
|
- name: Upload verified Windows package
|
||||||
uses: christopherhx/gitea-upload-artifact@v4
|
uses: christopherhx/gitea-upload-artifact@v4
|
||||||
with:
|
with:
|
||||||
name: OpenMaidEngine-Himegari-windows-x64-${{ gitea.sha }}
|
name: OME-windows-x64-${{ gitea.sha }}
|
||||||
path: build/workflow-artifact-windows/*
|
path: build/workflow-artifact-windows/*
|
||||||
if-no-files-found: error
|
if-no-files-found: error
|
||||||
retention-days: 30
|
retention-days: 30
|
||||||
@@ -177,7 +177,7 @@ jobs:
|
|||||||
name: windows-release-failure-${{ gitea.run_id }}-${{ gitea.run_attempt }}
|
name: windows-release-failure-${{ gitea.run_id }}-${{ gitea.run_attempt }}
|
||||||
path: |
|
path: |
|
||||||
build/native/win-x64/verification.json
|
build/native/win-x64/verification.json
|
||||||
build/package/windows-x64/staging/OpenMaidEngine-Himegari-windows-x64/WINDOWS-VERIFICATION.json
|
build/package/windows-x64/staging/OME-windows-x64/WINDOWS-VERIFICATION.json
|
||||||
build/validation/**
|
build/validation/**
|
||||||
if-no-files-found: ignore
|
if-no-files-found: ignore
|
||||||
retention-days: 7
|
retention-days: 7
|
||||||
@@ -209,13 +209,13 @@ jobs:
|
|||||||
- name: Download verified Linux artifact
|
- name: Download verified Linux artifact
|
||||||
uses: christopherhx/gitea-download-artifact@v4
|
uses: christopherhx/gitea-download-artifact@v4
|
||||||
with:
|
with:
|
||||||
name: OpenMaidEngine-Himegari-linux-x64-${{ gitea.sha }}
|
name: OME-linux-x64-${{ gitea.sha }}
|
||||||
path: build/release-assets/linux
|
path: build/release-assets/linux
|
||||||
|
|
||||||
- name: Download verified Windows artifact
|
- name: Download verified Windows artifact
|
||||||
uses: christopherhx/gitea-download-artifact@v4
|
uses: christopherhx/gitea-download-artifact@v4
|
||||||
with:
|
with:
|
||||||
name: OpenMaidEngine-Himegari-windows-x64-${{ gitea.sha }}
|
name: OME-windows-x64-${{ gitea.sha }}
|
||||||
path: build/release-assets/windows
|
path: build/release-assets/windows
|
||||||
|
|
||||||
- name: Create or resume Gitea release
|
- name: Create or resume Gitea release
|
||||||
|
|||||||
@@ -158,13 +158,13 @@ S:\Game Hacking\Eushully\Himegari\ ← workspace root (three siblings)
|
|||||||
├── tools/frida/ runtime-capture + engine-dump scripts (see tools/frida/README.md)
|
├── tools/frida/ runtime-capture + engine-dump scripts (see tools/frida/README.md)
|
||||||
└── godot/ DELIVERABLE — the Godot/C# ADV front-end (references Age.Engine
|
└── godot/ DELIVERABLE — the Godot/C# ADV front-end (references Age.Engine
|
||||||
plus the optional exact Windows text adapter). Its assembly embeds
|
plus the optional exact Windows text adapter). Its assembly embeds
|
||||||
generated build/opcodes.json through HimegariRuntimeMetadata, so
|
generated build/opcodes.json through OmeRuntimeMetadata, so
|
||||||
exports do not need repository discovery. Also contains the portable
|
exports do not need repository discovery. Also contains the portable
|
||||||
TextServer glyph adapter, per-profile font-substitution configuration,
|
TextServer glyph adapter, per-profile font-substitution configuration,
|
||||||
and TITLE-only F4 debug scene launcher
|
and TITLE-only F4 debug scene launcher
|
||||||
```
|
```
|
||||||
|
|
||||||
The Godot deliverable includes `Himegari.sln` because Godot's .NET exporter requires a solution,
|
The Godot deliverable includes `OME.sln` because Godot's .NET exporter requires a solution,
|
||||||
`export_presets.cfg` for Linux and Windows x86_64, and `build/.gdignore` so disposable capture frames below
|
`export_presets.cfg` for Linux and Windows x86_64, and `build/.gdignore` so disposable capture frames below
|
||||||
the project do not enter its import or export scan. `tools/build-linux-x64.sh` and
|
the project do not enter its import or export scan. `tools/build-linux-x64.sh` and
|
||||||
`tools/build-windows-x64.sh` produce their complete disposable artifacts under `build/export/`; the older
|
`tools/build-windows-x64.sh` produce their complete disposable artifacts under `build/export/`; the older
|
||||||
@@ -181,7 +181,7 @@ Godot input routing, locator/debug hotkeys, debug-scene dispatch, cursor control
|
|||||||
full-width text entry.
|
full-width text entry.
|
||||||
|
|
||||||
`engine/Age.Engine.Frontend/` is the production owner of frontend helpers that do not depend on Godot types.
|
`engine/Age.Engine.Frontend/` is the production owner of frontend helpers that do not depend on Godot types.
|
||||||
Both `engine/AgeEngine.sln` and `godot/Himegari.sln` include the project; Godot and `Age.Engine.Tests` consume it
|
Both `engine/AgeEngine.sln` and `godot/OME.sln` include the project; Godot and `Age.Engine.Tests` consume it
|
||||||
through project references rather than compiling duplicate linked sources. The first owned cluster contains
|
through project references rather than compiling duplicate linked sources. The first owned cluster contains
|
||||||
`PageLocatorState`, `GodotTimelineLog`, `GodotTraceSink`, `StepLimitDiagnosticFormatter`, `GodotVmOptions`,
|
`PageLocatorState`, `GodotTimelineLog`, `GodotTraceSink`, `StepLimitDiagnosticFormatter`, `GodotVmOptions`,
|
||||||
`PerformanceFrameLog`, and `WindowLaunchOptions`. It also owns the internal movie decoder boundary/runtime,
|
`PerformanceFrameLog`, and `WindowLaunchOptions`. It also owns the internal movie decoder boundary/runtime,
|
||||||
|
|||||||
@@ -758,7 +758,7 @@ decodes at most one frame ahead, waits against a monotonic `Stopwatch` clock for
|
|||||||
newest-frame-wins handoff, and reports EOF only after the larger of declared stop time or the final frame interval.
|
newest-frame-wins handoff, and reports EOF only after the larger of declared stop time or the final frame interval.
|
||||||
Disposal interrupts a far-future frame wait and joins the worker; asynchronous decode failure records a diagnostic
|
Disposal interrupts a far-future frame wait and joins the worker; asynchronous decode failure records a diagnostic
|
||||||
and completes the decoder so AGE cannot remain blocked. `Main` now selects `FfmpegMovieDecoderFactory`, while the
|
and completes the decoder so AGE cannot remain blocked. `Main` now selects `FfmpegMovieDecoderFactory`, while the
|
||||||
Godot build stages the shim and its five local shared-library dependencies beside `Himegari.dll`. DirectShow stays
|
Godot build stages the shim and its five local shared-library dependencies beside `OME.dll`. DirectShow stays
|
||||||
in-tree but is no longer selected; delete it only after the corpus and live acceptance gates. Deterministic fake-
|
in-tree but is no longer selected; delete it only after the corpus and live acceptance gates. Deterministic fake-
|
||||||
clock tests cover due-frame publication, final completion, cancellation, and failure. Real paced probes cover
|
clock tests cover due-frame publication, final completion, cancellation, and failure. Real paced probes cover
|
||||||
formerly failing 280x352 `MVB961` and aligned `MVB908`. A natural headless SYSTEM4 smoke played and released
|
formerly failing 280x352 `MVB961` and aligned `MVB908`. A natural headless SYSTEM4 smoke played and released
|
||||||
|
|||||||
@@ -149,7 +149,7 @@ both external archive hashes, exact clean tag-commit metadata and target RID, ma
|
|||||||
ledgers inside each archive, Linux's accepted dynamic package smoke, and Windows's complete static AMD64/ABI/
|
ledgers inside each archive, Linux's accepted dynamic package smoke, and Windows's complete static AMD64/ABI/
|
||||||
import report. It creates or resumes only a matching release, rejects unexpected or colliding assets, and exposes
|
import report. It creates or resumes only a matching release, rejects unexpected or colliding assets, and exposes
|
||||||
exactly two distributable archives:
|
exactly two distributable archives:
|
||||||
`OpenMaidEngine-Himegari-linux-x64.tar.gz` and `OpenMaidEngine-Himegari-windows-x64.zip`. A third small
|
`OME-linux-x64.tar.gz` and `OME-windows-x64.zip`. A third small
|
||||||
`RELEASE-SHA256SUMS` attachment will authenticate both archives while keeping the release below Gitea's observed
|
`RELEASE-SHA256SUMS` attachment will authenticate both archives while keeping the release below Gitea's observed
|
||||||
five-attachment boundary; detailed build metadata, payload ledgers, and logs remain inside each archive and in
|
five-attachment boundary; detailed build metadata, payload ledgers, and logs remain inside each archive and in
|
||||||
the retained workflow artifacts. The release notes will state that Linux received the dynamic package smoke and
|
the retained workflow artifacts. The release notes will state that Linux received the dynamic package smoke and
|
||||||
@@ -158,8 +158,10 @@ pass. The hosted develop run at `d657c63` completed both platform builds and cor
|
|||||||
2026-08-03, accepting the paired non-tag path. Its core job initially failed before checkout on a transient
|
2026-08-03, accepting the paired non-tag path. Its core job initially failed before checkout on a transient
|
||||||
runner DNS lookup for GitHub, then passed unchanged on retry; this was infrastructure availability rather than a
|
runner DNS lookup for GitHub, then passed unchanged on retry; this was infrastructure availability rather than a
|
||||||
validation failure. The lightweight `v0.2.0` tag at `93d8236` then completed both platform jobs and promotion on
|
validation failure. The lightweight `v0.2.0` tag at `93d8236` then completed both platform jobs and promotion on
|
||||||
2026-08-03. The resulting Gitea release exposes exactly the Linux archive, Windows archive, and
|
2026-08-03. That historical release retains its then-current `OpenMaidEngine-Himegari-*` archive names; future
|
||||||
`RELEASE-SHA256SUMS`, accepting the dual-platform CI/CD path end to end; `v0.1.0` remains unchanged.
|
builds and releases use the `OME-*` names above. The resulting Gitea release exposes exactly the Linux archive,
|
||||||
|
Windows archive, and `RELEASE-SHA256SUMS`, accepting the dual-platform CI/CD path end to end; `v0.1.0` remains
|
||||||
|
unchanged.
|
||||||
|
|
||||||
Code signing, an installer, Windows-on-Linux execution, and retroactively modifying the accepted Linux-only
|
Code signing, an installer, Windows-on-Linux execution, and retroactively modifying the accepted Linux-only
|
||||||
`v0.1.0` release are outside this effort. A future signing slice can use `osslsigncode` and protected credentials
|
`v0.1.0` release are outside this effort. A future signing slice can use `osslsigncode` and protected credentials
|
||||||
@@ -191,7 +193,7 @@ entry. The system-font-only policy remains supported until the bundled-font opti
|
|||||||
| ADV font discovery/raster fidelity | `Age.Engine.Text` remains OS-neutral. On compatible ACP-932 Windows, `auto` selects the separate exact-to-request `Age.Engine.Text.Windows` GDI gray-4 backend. Otherwise Godot TextServer supplies Unicode masks and metrics from ordered system-font substitutions in `godot/config/himegari-text-rendering.json`; this policy is explicitly not GDI pixel-exact. Immediate `0x204`/`0x205`, live ADV, retained History, and the wait atlas all enter ordinary RGBA surfaces/retained handles | Three Mincho/Gothic regular/bold samples byte-match an independent Unicode GDI oracle. A live `SC0000@0x869` trace proves that the `AGE Patch.exe`/`jprun.dll` wrapper overrides authored Mincho to MS Gothic: 13 captured masks match Gothic byte-for-byte and Mincho 0/13. This is wrapper behavior, not the true-native default, and reproducing it is outside the compatibility target. Forced exact and forced portable self-tests cover immediate, live, and History rasterization, bounded caching, complete-line materialization, retained ordering, alpha/tint/fade, transforms, clipping, capture, HIDEWIN suspension, partial erase/republication, reset, and teardown. Gameplay `Label` pools and overlay projection are gone | Select and smoke-test a redistributable Linux font-bundling policy or retain the explicit system-font prerequisite; add macOS runtime coverage and keep the GDI project out of non-Windows deliverables |
|
| ADV font discovery/raster fidelity | `Age.Engine.Text` remains OS-neutral. On compatible ACP-932 Windows, `auto` selects the separate exact-to-request `Age.Engine.Text.Windows` GDI gray-4 backend. Otherwise Godot TextServer supplies Unicode masks and metrics from ordered system-font substitutions in `godot/config/himegari-text-rendering.json`; this policy is explicitly not GDI pixel-exact. Immediate `0x204`/`0x205`, live ADV, retained History, and the wait atlas all enter ordinary RGBA surfaces/retained handles | Three Mincho/Gothic regular/bold samples byte-match an independent Unicode GDI oracle. A live `SC0000@0x869` trace proves that the `AGE Patch.exe`/`jprun.dll` wrapper overrides authored Mincho to MS Gothic: 13 captured masks match Gothic byte-for-byte and Mincho 0/13. This is wrapper behavior, not the true-native default, and reproducing it is outside the compatibility target. Forced exact and forced portable self-tests cover immediate, live, and History rasterization, bounded caching, complete-line materialization, retained ordering, alpha/tint/fade, transforms, clipping, capture, HIDEWIN suspension, partial erase/republication, reset, and teardown. Gameplay `Label` pools and overlay projection are gone | Select and smoke-test a redistributable Linux font-bundling policy or retain the explicit system-font prerequisite; add macOS runtime coverage and keep the GDI project out of non-Windows deliverables |
|
||||||
| Filesystem semantics | Several filename and containment comparisons use `OrdinalIgnoreCase`; installed assets are conventionally uppercase | Needs validation on case-sensitive filesystems; may hide casing or containment mistakes | Add Linux/macOS tests with mixed-case synthetic roots and use filesystem-appropriate containment rules |
|
| Filesystem semantics | Several filename and containment comparisons use `OrdinalIgnoreCase`; installed assets are conventionally uppercase | Needs validation on case-sensitive filesystems; may hide casing or containment mistakes | Add Linux/macOS tests with mixed-case synthetic roots and use filesystem-appropriate containment rules |
|
||||||
| Save/profile/settings storage | `Sys4PersistencePaths` models AGE's independent `SAVEPATH` and `REGFILEPATH` resolutions. Godot replaces Himegari's related profile directory with `user://`, yielding `user://SAVE` for native S3SD/S4SD/S3RT files and thumbnails plus `user://SYS4REG.INI` for the BOM-less CP932 options file; the preserving writer changes only its nine `[sound]` keys | Save payloads and engine options are isolated together without changing either native format. Native/drop-in resolution remains available through `USEAPPDATAFOLDER` plus both SYS4INI paths. A single-root override is rejected when `SAVEPATH` is not beneath `REGFILEPATH`, preventing cross-profile guesses | Expose explicit profile/native selection through the future launcher and allow independent overrides for profiles whose two native paths are unrelated. Validate CP932 availability, replace/flush, case, permissions, and interrupted-write behavior on each export target |
|
| Save/profile/settings storage | `Sys4PersistencePaths` models AGE's independent `SAVEPATH` and `REGFILEPATH` resolutions. Godot replaces Himegari's related profile directory with `user://`, yielding `user://SAVE` for native S3SD/S4SD/S3RT files and thumbnails plus `user://SYS4REG.INI` for the BOM-less CP932 options file; the preserving writer changes only its nine `[sound]` keys | Save payloads and engine options are isolated together without changing either native format. Native/drop-in resolution remains available through `USEAPPDATAFOLDER` plus both SYS4INI paths. A single-root override is rejected when `SAVEPATH` is not beneath `REGFILEPATH`, preventing cross-profile guesses | Expose explicit profile/native selection through the future launcher and allow independent overrides for profiles whose two native paths are unrelated. Validate CP932 availability, replace/flush, case, permissions, and interrupted-write behavior on each export target |
|
||||||
| Game-install, runtime metadata, and repository discovery | `GameRootSelection` accepts `--game-root`, then probes the executable directory and current working directory for `SYS4INI.BIN`; on Unix the frontend prefers inherited shell `PWD` because Godot may change the process directory during project startup. Godot injects the selected root into its catalog and loose-first ALF store. `Himegari.csproj` embeds generated `build/opcodes.json`, and the frontend loads that assembly resource rather than `Paths.OpcodesJson`. Development/test `Paths.cs` finds the repository by tracked `global.json`, solution, and opcode-map markers rather than a checkout-directory name | Installed game data and packaged VM metadata no longer depend on the workspace sibling layout. The Linux export passed an explicit absolute game root outside the repository and read the installed archives; a source-only core proof also passes from an arbitrary repository directory name. Exported automatic page maps use `user://diagnostics/page-maps`; editor/development runs preserve `build/page-map-<SCENE>.jsonl` | Let the future profile launcher pass `--game-root`, and run executable-directory/CWD plus case/permission smoke gates on Linux and macOS |
|
| Game-install, runtime metadata, and repository discovery | `GameRootSelection` accepts `--game-root`, then probes the executable directory and current working directory for `SYS4INI.BIN`; on Unix the frontend prefers inherited shell `PWD` because Godot may change the process directory during project startup. Godot injects the selected root into its catalog and loose-first ALF store. `OME.csproj` embeds generated `build/opcodes.json`, and the frontend loads that assembly resource rather than `Paths.OpcodesJson`. Development/test `Paths.cs` finds the repository by tracked `global.json`, solution, and opcode-map markers rather than a checkout-directory name | Installed game data and packaged VM metadata no longer depend on the workspace sibling layout. The Linux export passed an explicit absolute game root outside the repository and read the installed archives; a source-only core proof also passes from an arbitrary repository directory name. Exported automatic page maps use `user://diagnostics/page-maps`; editor/development runs preserve `build/page-map-<SCENE>.jsonl` | Let the future profile launcher pass `--game-root`, and run executable-directory/CWD plus case/permission smoke gates on Linux and macOS |
|
||||||
| Archive parity oracle | One integration test can launch a machine-local `bin/BinExtractALF.exe`; the binary and matching DLL are ignored and have unverified redistribution terms | Windows-only installed-data helper, not a shipped runtime dependency | Keep it in an explicit private workspace gate; runtime ALF/AAI readers do not depend on it |
|
| Archive parity oracle | One integration test can launch a machine-local `bin/BinExtractALF.exe`; the binary and matching DLL are ignored and have unverified redistribution terms | Windows-only installed-data helper, not a shipped runtime dependency | Keep it in an explicit private workspace gate; runtime ALF/AAI readers do not depend on it |
|
||||||
| Native RE tools | Frida/Ghidra helpers target the original `AGE.EXE`; PE-sieve was tried and replaced by the Frida import-map workflow | Development/research only; no native RE executable is tracked | Keep separate from export requirements; document platform prerequisites per tool |
|
| Native RE tools | Frida/Ghidra helpers target the original `AGE.EXE`; PE-sieve was tried and replaced by the Frida import-map workflow | Development/research only; no native RE executable is tracked | Keep separate from export requirements; document platform prerequisites per tool |
|
||||||
| Python workflow and core CI | The operating guide uses Windows `py -3.11`; `validate.py` launches child tools through `sys.executable` and has POSIX process-group cleanup plus `ps`-based leak auditing | The 590 engine cases are explicitly split into 502 source-only core cases and 88 `Workspace` installed-data/native-oracle cases; both selections pass with zero skips. The opcode-bootstrap unit injects synthetic observations while production bootstrap retains real-corpus scanning. `.gitea/workflows/core-validation.yml` uses the target server's demonstrated `ubuntu-latest`, checkout/setup-dotnet v4, setup-python v6, and Gitea artifact action baseline. A standalone arbitrary-name, corpus-free repository passes the complete core driver. The sanitized history is published on the private remote's default `develop` branch; the first hosted Linux core run succeeded on 2026-08-03 before sanitation at the tree now represented by `524ea74`, and the hosted gate succeeded again on the sanitized lineage at `d673652` | Retain Windows-native GDI parity and private installed-game/runtime checks as separate trusted gates; keep the hosted core gate required for future integration policy |
|
| Python workflow and core CI | The operating guide uses Windows `py -3.11`; `validate.py` launches child tools through `sys.executable` and has POSIX process-group cleanup plus `ps`-based leak auditing | The 590 engine cases are explicitly split into 502 source-only core cases and 88 `Workspace` installed-data/native-oracle cases; both selections pass with zero skips. The opcode-bootstrap unit injects synthetic observations while production bootstrap retains real-corpus scanning. `.gitea/workflows/core-validation.yml` uses the target server's demonstrated `ubuntu-latest`, checkout/setup-dotnet v4, setup-python v6, and Gitea artifact action baseline. A standalone arbitrary-name, corpus-free repository passes the complete core driver. The sanitized history is published on the private remote's default `develop` branch; the first hosted Linux core run succeeded on 2026-08-03 before sanitation at the tree now represented by `524ea74`, and the hosted gate succeeded again on the sanitized lineage at `d673652` | Retain Windows-native GDI parity and private installed-game/runtime checks as separate trusted gates; keep the hosted core gate required for future integration policy |
|
||||||
@@ -336,7 +338,7 @@ PE/bundle verifier. The managed resolver accepts
|
|||||||
280x352/866 ms, `MVB908` 400x400/333 ms, and `CHAPTER` 800x600/12016 ms, all with changing frames and
|
280x352/866 ms, `MVB908` 400x400/333 ms, and `CHAPTER` 800x600/12016 ms, all with changing frames and
|
||||||
nondecreasing timestamps. Malformed input and repeated teardown are covered. This is not yet distributable
|
nondecreasing timestamps. Malformed input and repeated teardown are covered. This is not yet distributable
|
||||||
packaging. `FfmpegMovieDecoder` now adds cancellable timestamp pacing and is the live selection. The Godot build
|
packaging. `FfmpegMovieDecoder` now adds cancellable timestamp pacing and is the live selection. The Godot build
|
||||||
copies the shim, five required shared libraries, and FFmpeg license beside `Himegari.dll`; a natural SYSTEM4
|
copies the shim, five required shared libraries, and FFmpeg license beside `OME.dll`; a natural SYSTEM4
|
||||||
smoke completed 7288 ms `LOGO.AGF`, opened 106919 ms `OP.AGF`, and published frames from both without loading
|
smoke completed 7288 ms `LOGO.AGF`, opened 106919 ms `OP.AGF`, and published frames from both without loading
|
||||||
DirectShow; the user subsequently confirmed both opening movies work in normal windowed playback. DirectShow
|
DirectShow; the user subsequently confirmed both opening movies work in normal windowed playback. DirectShow
|
||||||
was deleted after the later synchronized-audio gate. Full export/source-offer packaging, Linux Godot runtime
|
was deleted after the later synchronized-audio gate. Full export/source-offer packaging, Linux Godot runtime
|
||||||
@@ -348,11 +350,11 @@ five required SONAME libraries and license under disposable `build/native/linux-
|
|||||||
`RUNPATH=$ORIGIN`, every FFmpeg dependency resolves beside it, and the bundle's newest required glibc symbol is
|
`RUNPATH=$ORIGIN`, every FFmpeg dependency resolves beside it, and the bundle's newest required glibc symbol is
|
||||||
2.28, matching the provider baseline enforced by the build script. A self-contained Linux corpus-gate executable
|
2.28, matching the provider baseline enforced by the build script. A self-contained Linux corpus-gate executable
|
||||||
under Ubuntu 20.04 decoded all 213 installed payloads with 0 failures in 10.696 seconds. A zero-warning
|
under Ubuntu 20.04 decoded all 213 installed payloads with 0 failures in 10.696 seconds. A zero-warning
|
||||||
`ExportRelease` Linux-target assembly build staged the shim, five libraries, and license beside `Himegari.dll`
|
`ExportRelease` Linux-target assembly build staged the shim, five libraries, and license beside `OME.dll`
|
||||||
without the Windows GDI assembly or DLLs.
|
without the Windows GDI assembly or DLLs.
|
||||||
|
|
||||||
The Godot Linux-x64 artifact pipeline landed the same day. `godot/export_presets.cfg` and the .NET-export-required
|
The Godot Linux-x64 artifact pipeline landed the same day. `godot/export_presets.cfg` and the .NET-export-required
|
||||||
`godot/Himegari.sln` are committed; `tools/export-linux-x64.ps1` replaces only its exact disposable output,
|
`godot/OME.sln` are committed; `tools/export-linux-x64.ps1` replaces only its exact disposable output,
|
||||||
performs a bounded Godot shutdown, verifies the complete artifact, and rejects Windows-only runtime files.
|
performs a bounded Godot shutdown, verifies the complete artifact, and rejects Windows-only runtime files.
|
||||||
`godot/build/.gdignore` prevents historical capture frames from being imported and packed. The exported ELF64
|
`godot/build/.gdignore` prevents historical capture frames from being imported and packed. The exported ELF64
|
||||||
x86-64 executable, PCK, self-contained .NET runtime, and local FFmpeg bundle passed `--selftest` under Ubuntu/WSL
|
x86-64 executable, PCK, self-contained .NET runtime, and local FFmpeg bundle passed `--selftest` under Ubuntu/WSL
|
||||||
|
|||||||
@@ -307,8 +307,8 @@ Windows target, a native C compiler/binutils for Linux, and the ordinary archive
|
|||||||
|
|
||||||
The managed isolated probes load from `AGE_FFMPEG_NATIVE_DIR` when set, then application-local and
|
The managed isolated probes load from `AGE_FFMPEG_NATIVE_DIR` when set, then application-local and
|
||||||
`runtimes/<rid>/native` locations. Build the target shim before running the `FfmpegShim*` tests; no original-game
|
`runtimes/<rid>/native` locations. Build the target shim before running the `FfmpegShim*` tests; no original-game
|
||||||
movie is copied into the repository or native output. A target-aware `dotnet build godot/Himegari.csproj`
|
movie is copied into the repository or native output. A target-aware `dotnet build godot/OME.csproj`
|
||||||
stages the matching shim, five shared-library dependencies, and `FFmpeg-LICENSE.txt` beside `Himegari.dll`
|
stages the matching shim, five shared-library dependencies, and `FFmpeg-LICENSE.txt` beside `OME.dll`
|
||||||
when the corresponding `build/native/win-x64/` or `build/native/linux-x64/` bundle exists.
|
when the corresponding `build/native/win-x64/` or `build/native/linux-x64/` bundle exists.
|
||||||
|
|
||||||
The current native movie ABI is version 3. In addition to sequential video/audio decode, it exposes a
|
The current native movie ABI is version 3. In addition to sequential video/audio decode, it exposes a
|
||||||
@@ -382,7 +382,7 @@ at 2.5M lines). All observe-only → parity preserved; all on `run`/`play`/`swee
|
|||||||
`godot --path godot -- --scene SC0000 --boot --shot out/p1.png --trace-histogram out/hist.txt`.
|
`godot --path godot -- --scene SC0000 --boot --shot out/p1.png --trace-histogram out/hist.txt`.
|
||||||
|
|
||||||
**Godot frontend** (Godot 4.7 .NET; project = `godot/`). Toolchain: `godot --headless --path godot
|
**Godot frontend** (Godot 4.7 .NET; project = `godot/`). Toolchain: `godot --headless --path godot
|
||||||
--import` → `dotnet build godot/Himegari.csproj` → `godot [--headless] --path godot [-- <userargs>]`.
|
--import` → `dotnet build godot/OME.csproj` → `godot [--headless] --path godot [-- <userargs>]`.
|
||||||
Plays the real bytecode with call-script execution on (subroutines run live). The game root is selected
|
Plays the real bytecode with call-script execution on (subroutines run live). The game root is selected
|
||||||
before catalog loading: `--game-root <directory>` wins, otherwise the directory containing the running
|
before catalog loading: `--game-root <directory>` wins, otherwise the directory containing the running
|
||||||
executable is tried, then the current working directory. A candidate must contain `SYS4INI.BIN`; invalid
|
executable is tried, then the current working directory. A candidate must contain `SYS4INI.BIN`; invalid
|
||||||
@@ -391,7 +391,7 @@ resolved against the current working directory, and repeated overrides use the l
|
|||||||
Godot preserves the shell launch directory through inherited `PWD` because editor/project startup may
|
Godot preserves the shell launch directory through inherited `PWD` because editor/project startup may
|
||||||
change the process directory before managed code runs.
|
change the process directory before managed code runs.
|
||||||
|
|
||||||
**Linux x64 export** uses the committed `godot/export_presets.cfg` preset and `godot/Himegari.sln`:
|
**Linux x64 export** uses the committed `godot/export_presets.cfg` preset and `godot/OME.sln`:
|
||||||
|
|
||||||
For the complete Linux-native release path, run from `age-reimpl/`:
|
For the complete Linux-native release path, run from `age-reimpl/`:
|
||||||
|
|
||||||
@@ -419,10 +419,10 @@ The packager adds `LICENSE`, `README.md`, `THIRD_PARTY_NOTICES.md`, a source/dep
|
|||||||
`BUILD-INFO.json`, and per-file `SHA256SUMS` to a stable top-level directory. It normalizes archive ownership,
|
`BUILD-INFO.json`, and per-file `SHA256SUMS` to a stable top-level directory. It normalizes archive ownership,
|
||||||
modes, ordering, and timestamps using `SOURCE_DATE_EPOCH` or the source commit time. Outputs are the loose
|
modes, ordering, and timestamps using `SOURCE_DATE_EPOCH` or the source commit time. Outputs are the loose
|
||||||
export under `build/export/linux-x64/`, the staged installation and `package-smoke.log` under
|
export under `build/export/linux-x64/`, the staged installation and `package-smoke.log` under
|
||||||
`build/package/`, and `build/package/OpenMaidEngine-Himegari-linux-x64.tar.gz`.
|
`build/package/`, and `build/package/OME-linux-x64.tar.gz`.
|
||||||
|
|
||||||
Before reporting success, the command launches the staged executable as
|
Before reporting success, the command launches the staged executable as
|
||||||
`Himegari.x86_64 --headless -- --package-smoke`. This asset-independent mode runs before game-root discovery
|
`OME --headless -- --package-smoke`. This asset-independent mode runs before game-root discovery
|
||||||
and proves that the packaged managed assembly can read all 548 embedded opcode records and dynamically load
|
and proves that the packaged managed assembly can read all 548 embedded opcode records and dynamically load
|
||||||
the bundled native movie shim plus its local FFmpeg dependencies at ABI version 3. It does not exercise game
|
the bundled native movie shim plus its local FFmpeg dependencies at ABI version 3. It does not exercise game
|
||||||
archives, fonts, rendering, audio output, or a desktop window; retain the installed-game self-test below as a
|
archives, fonts, rendering, audio output, or a desktop window; retain the installed-game self-test below as a
|
||||||
@@ -452,9 +452,10 @@ It regenerates runtime metadata, builds and statically verifies the pinned Windo
|
|||||||
exact self-contained `ExportRelease/win-x64` managed runtime, and performs the real Godot `Windows x86_64`
|
exact self-contained `ExportRelease/win-x64` managed runtime, and performs the real Godot `Windows x86_64`
|
||||||
release export. No produced Windows program is executed. `package_windows_x64.py` requires the Godot AMD64 EXE,
|
release export. No produced Windows program is executed. `package_windows_x64.py` requires the Godot AMD64 EXE,
|
||||||
PCK, self-contained runtime, project assemblies including `Age.Engine.Text.Windows.dll`, and FFmpeg DLL/license
|
PCK, self-contained runtime, project assemblies including `Age.Engine.Text.Windows.dll`, and FFmpeg DLL/license
|
||||||
set; it rejects Linux shared objects and embeds `BUILD-INFO.json`, `WINDOWS-VERIFICATION.json`, notices, and a
|
set; it rejects Linux shared objects and the legacy `Himegari.dll` name, and embeds `BUILD-INFO.json`,
|
||||||
|
`WINDOWS-VERIFICATION.json`, notices, and a
|
||||||
complete `SHA256SUMS`. The normalized output is
|
complete `SHA256SUMS`. The normalized output is
|
||||||
`build/package/windows-x64/OpenMaidEngine-Himegari-windows-x64.zip`.
|
`build/package/windows-x64/OME-windows-x64.zip`.
|
||||||
|
|
||||||
Focused commands are:
|
Focused commands are:
|
||||||
|
|
||||||
@@ -469,7 +470,7 @@ The package verifier needs `x86_64-w64-mingw32-objdump` unless `--objdump` names
|
|||||||
Windows host, an extracted package can optionally run the same asset-independent dynamic gate as Linux:
|
Windows host, an extracted package can optionally run the same asset-independent dynamic gate as Linux:
|
||||||
|
|
||||||
```powershell
|
```powershell
|
||||||
.\Himegari.exe --headless -- --package-smoke
|
.\OME.exe --headless -- --package-smoke
|
||||||
```
|
```
|
||||||
|
|
||||||
That command proves the embedded 548-opcode table and local FFmpeg ABI 3 load. It is a manual acceptance aid,
|
That command proves the embedded 548-opcode table and local FFmpeg ABI 3 load. It is a manual acceptance aid,
|
||||||
@@ -486,8 +487,8 @@ Install the Godot 4.7 .NET export templates first and build the pinned native bu
|
|||||||
only `build/export/linux-x64`, invokes the release preset with a bounded headless shutdown, then calls the
|
only `build/export/linux-x64`, invokes the release preset with a bounded headless shutdown, then calls the
|
||||||
same Python payload verifier used by the Linux pipeline. The verifier checks the executable/PCK/self-contained
|
same Python payload verifier used by the Linux pipeline. The verifier checks the executable/PCK/self-contained
|
||||||
managed payload plus all six project-owned FFmpeg files and rejects the Windows GDI adapter and Windows FFmpeg
|
managed payload plus all six project-owned FFmpeg files and rejects the Windows GDI adapter and Windows FFmpeg
|
||||||
DLLs. Output is `build/export/linux-x64/Himegari.x86_64` with its
|
DLLs as well as the legacy `Himegari.dll` name. Output is `build/export/linux-x64/OME` with `OME.pck` and the
|
||||||
PCK and `data_Himegari_linuxbsd_x86_64/` runtime directory. Do not relocate only the executable; the three
|
`data_OME_linuxbsd_x86_64/` runtime directory. Do not relocate only the executable; the three
|
||||||
items are one artifact.
|
items are one artifact.
|
||||||
|
|
||||||
The portable font policy requires a Japanese-capable system font. A minimal Ubuntu install needs, for
|
The portable font policy requires a Japanese-capable system font. A minimal Ubuntu install needs, for
|
||||||
@@ -495,7 +496,7 @@ example, `sudo apt install fonts-noto-cjk`; absence is a startup failure rather
|
|||||||
output. The exported headless smoke command is:
|
output. The exported headless smoke command is:
|
||||||
|
|
||||||
```bash
|
```bash
|
||||||
./build/export/linux-x64/Himegari.x86_64 --headless -- \
|
./build/export/linux-x64/OME --headless -- \
|
||||||
--selftest --game-root "/absolute/path/to/Himegari_Game" --text-backend portable
|
--selftest --game-root "/absolute/path/to/Himegari_Game" --text-backend portable
|
||||||
```
|
```
|
||||||
|
|
||||||
|
|||||||
@@ -2,4 +2,4 @@ using System.Runtime.CompilerServices;
|
|||||||
|
|
||||||
[assembly: InternalsVisibleTo("Age.Engine.Tests")]
|
[assembly: InternalsVisibleTo("Age.Engine.Tests")]
|
||||||
[assembly: InternalsVisibleTo("Age.MovieCorpusGate")]
|
[assembly: InternalsVisibleTo("Age.MovieCorpusGate")]
|
||||||
[assembly: InternalsVisibleTo("Himegari")]
|
[assembly: InternalsVisibleTo("OME")]
|
||||||
|
|||||||
@@ -10,7 +10,7 @@ public partial class Main
|
|||||||
if (!OS.HasFeature("linux") && !OS.HasFeature("windows"))
|
if (!OS.HasFeature("linux") && !OS.HasFeature("windows"))
|
||||||
throw new PlatformNotSupportedException(
|
throw new PlatformNotSupportedException(
|
||||||
"the packaged-runtime smoke gate supports Linux and Windows x64");
|
"the packaged-runtime smoke gate supports Linux and Windows x64");
|
||||||
var table = HimegariRuntimeMetadata.LoadOpcodeTable();
|
var table = OmeRuntimeMetadata.LoadOpcodeTable();
|
||||||
if (table.Count != 548)
|
if (table.Count != 548)
|
||||||
throw new InvalidOperationException(
|
throw new InvalidOperationException(
|
||||||
$"embedded opcode table has {table.Count} entries; expected 548");
|
$"embedded opcode table has {table.Count} entries; expected 548");
|
||||||
|
|||||||
@@ -16,7 +16,7 @@ public partial class Main
|
|||||||
// and deferred main-thread calls) drives the VM identically to a headless run.
|
// and deferred main-thread calls) drives the VM identically to a headless run.
|
||||||
private void RunSelfTest()
|
private void RunSelfTest()
|
||||||
{
|
{
|
||||||
var table = HimegariRuntimeMetadata.LoadOpcodeTable();
|
var table = OmeRuntimeMetadata.LoadOpcodeTable();
|
||||||
var (script, provider) = BuildSelfTestScene(table);
|
var (script, provider) = BuildSelfTestScene(table);
|
||||||
var headless = new VirtualMachine(script, table, new CaptureHost(), null, provider);
|
var headless = new VirtualMachine(script, table, new CaptureHost(), null, provider);
|
||||||
headless.Run();
|
headless.Run();
|
||||||
|
|||||||
@@ -240,7 +240,7 @@ public partial class Main : Godot.Control
|
|||||||
_clock.Speed = System.Math.Clamp(speed, 0.05, 8.0);
|
_clock.Speed = System.Math.Clamp(speed, 0.05, 8.0);
|
||||||
GD.Print($"[renderer] retained backend={(_useGpuBackend ? "gpu" : "software")}");
|
GD.Print($"[renderer] retained backend={(_useGpuBackend ? "gpu" : "software")}");
|
||||||
|
|
||||||
var table = HimegariRuntimeMetadata.LoadOpcodeTable();
|
var table = OmeRuntimeMetadata.LoadOpcodeTable();
|
||||||
// Persistence retains AGE's native filenames and formats, but the port owns one profile-root
|
// Persistence retains AGE's native filenames and formats, but the port owns one profile-root
|
||||||
// interception point. Himegari's SYS4INI makes SAVEPATH the SAVE child of REGFILEPATH, so both
|
// interception point. Himegari's SYS4INI makes SAVEPATH the SAVE child of REGFILEPATH, so both
|
||||||
// save payloads and SYS4REG.INI remain isolated together under Godot's user directory.
|
// save payloads and SYS4REG.INI remain isolated together under Godot's user directory.
|
||||||
|
|||||||
@@ -15,7 +15,7 @@
|
|||||||
<ProjectReference Include="..\engine\Age.Engine\Age.Engine.csproj" />
|
<ProjectReference Include="..\engine\Age.Engine\Age.Engine.csproj" />
|
||||||
<ProjectReference Include="..\engine\Age.Engine.Frontend\Age.Engine.Frontend.csproj" />
|
<ProjectReference Include="..\engine\Age.Engine.Frontend\Age.Engine.Frontend.csproj" />
|
||||||
<EmbeddedResource Include="..\build\opcodes.json"
|
<EmbeddedResource Include="..\build\opcodes.json"
|
||||||
LogicalName="Himegari.Runtime.opcodes.json" />
|
LogicalName="OME.Runtime.opcodes.json" />
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
<ItemGroup Condition="'$(GodotTargetPlatform)' == 'windows'">
|
<ItemGroup Condition="'$(GodotTargetPlatform)' == 'windows'">
|
||||||
<ProjectReference Include="..\engine\Age.Engine.Text.Windows\Age.Engine.Text.Windows.csproj" />
|
<ProjectReference Include="..\engine\Age.Engine.Text.Windows\Age.Engine.Text.Windows.csproj" />
|
||||||
@@ -3,7 +3,7 @@ Microsoft Visual Studio Solution File, Format Version 12.00
|
|||||||
# Visual Studio Version 17
|
# Visual Studio Version 17
|
||||||
VisualStudioVersion = 17.0.31903.59
|
VisualStudioVersion = 17.0.31903.59
|
||||||
MinimumVisualStudioVersion = 10.0.40219.1
|
MinimumVisualStudioVersion = 10.0.40219.1
|
||||||
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Himegari", "Himegari.csproj", "{5821B505-EBD3-4B50-A83A-7AFE22AA1528}"
|
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "OME", "OME.csproj", "{5821B505-EBD3-4B50-A83A-7AFE22AA1528}"
|
||||||
EndProject
|
EndProject
|
||||||
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Age.Engine.Frontend", "..\engine\Age.Engine.Frontend\Age.Engine.Frontend.csproj", "{2B018D3E-4057-465E-89CB-4CC77FDD60E2}"
|
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Age.Engine.Frontend", "..\engine\Age.Engine.Frontend\Age.Engine.Frontend.csproj", "{2B018D3E-4057-465E-89CB-4CC77FDD60E2}"
|
||||||
EndProject
|
EndProject
|
||||||
@@ -5,16 +5,16 @@ using Age.Engine.Model;
|
|||||||
using Age.Engine.Sys4;
|
using Age.Engine.Sys4;
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Himegari profile metadata that must travel with every Godot build. Repository discovery belongs to
|
/// OME profile metadata that must travel with every Godot build. Repository discovery belongs to
|
||||||
/// development tooling; exported runtimes read the generator output embedded into this assembly.
|
/// development tooling; exported runtimes read the generator output embedded into this assembly.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
internal static class HimegariRuntimeMetadata
|
internal static class OmeRuntimeMetadata
|
||||||
{
|
{
|
||||||
internal const string OpcodeTableResourceName = "Himegari.Runtime.opcodes.json";
|
internal const string OpcodeTableResourceName = "OME.Runtime.opcodes.json";
|
||||||
|
|
||||||
internal static OpcodeTable LoadOpcodeTable()
|
internal static OpcodeTable LoadOpcodeTable()
|
||||||
{
|
{
|
||||||
Assembly assembly = typeof(HimegariRuntimeMetadata).Assembly;
|
Assembly assembly = typeof(OmeRuntimeMetadata).Assembly;
|
||||||
using Stream stream = assembly.GetManifestResourceStream(OpcodeTableResourceName)
|
using Stream stream = assembly.GetManifestResourceStream(OpcodeTableResourceName)
|
||||||
?? throw new InvalidDataException(
|
?? throw new InvalidDataException(
|
||||||
$"Embedded runtime metadata '{OpcodeTableResourceName}' is missing from " +
|
$"Embedded runtime metadata '{OpcodeTableResourceName}' is missing from " +
|
||||||
@@ -8,7 +8,7 @@ custom_features=""
|
|||||||
export_filter="all_resources"
|
export_filter="all_resources"
|
||||||
include_filter=""
|
include_filter=""
|
||||||
exclude_filter=""
|
exclude_filter=""
|
||||||
export_path="../build/export/linux-x64/Himegari.x86_64"
|
export_path="../build/export/linux-x64/OME"
|
||||||
patches=PackedStringArray()
|
patches=PackedStringArray()
|
||||||
encryption_include_filters=""
|
encryption_include_filters=""
|
||||||
encryption_exclude_filters=""
|
encryption_exclude_filters=""
|
||||||
@@ -41,7 +41,7 @@ custom_features=""
|
|||||||
export_filter="all_resources"
|
export_filter="all_resources"
|
||||||
include_filter=""
|
include_filter=""
|
||||||
exclude_filter=""
|
exclude_filter=""
|
||||||
export_path="../build/export/windows-x64/Himegari.exe"
|
export_path="../build/export/windows-x64/OME.exe"
|
||||||
patches=PackedStringArray()
|
patches=PackedStringArray()
|
||||||
encryption_include_filters=""
|
encryption_include_filters=""
|
||||||
encryption_exclude_filters=""
|
encryption_exclude_filters=""
|
||||||
|
|||||||
@@ -9,7 +9,7 @@ window/size/viewport_width=640
|
|||||||
window/size/viewport_height=480
|
window/size/viewport_height=480
|
||||||
|
|
||||||
[dotnet]
|
[dotnet]
|
||||||
project/assembly_name="Himegari"
|
project/assembly_name="OME"
|
||||||
|
|
||||||
[rendering]
|
[rendering]
|
||||||
environment/defaults/default_clear_color=Color(0, 0, 0, 1)
|
environment/defaults/default_clear_color=Color(0, 0, 0, 1)
|
||||||
|
|||||||
@@ -28,7 +28,7 @@ param(
|
|||||||
$ErrorActionPreference = 'Stop'
|
$ErrorActionPreference = 'Stop'
|
||||||
$repo = $PSScriptRoot # age-reimpl/
|
$repo = $PSScriptRoot # age-reimpl/
|
||||||
$project = Join-Path $repo 'godot'
|
$project = Join-Path $repo 'godot'
|
||||||
$csproj = Join-Path $project 'Himegari.csproj'
|
$csproj = Join-Path $project 'OME.csproj'
|
||||||
|
|
||||||
function Resolve-ConfiguredFile {
|
function Resolve-ConfiguredFile {
|
||||||
param(
|
param(
|
||||||
|
|||||||
@@ -39,7 +39,7 @@ DOTNET_CLI_USE_MSBUILD_SERVER=0 \
|
|||||||
MSBUILDDISABLENODEREUSE=1 \
|
MSBUILDDISABLENODEREUSE=1 \
|
||||||
DOTNET_gcServer=0 \
|
DOTNET_gcServer=0 \
|
||||||
DOTNET_GCConserveMemory=9 \
|
DOTNET_GCConserveMemory=9 \
|
||||||
dotnet publish "$project_root/Himegari.csproj" \
|
dotnet publish "$project_root/OME.csproj" \
|
||||||
--configuration ExportRelease \
|
--configuration ExportRelease \
|
||||||
--runtime linux-x64 \
|
--runtime linux-x64 \
|
||||||
--self-contained true \
|
--self-contained true \
|
||||||
@@ -61,7 +61,7 @@ if [[ "$managed_proxy_directory" != "$expected_managed_proxy_directory" || "$man
|
|||||||
fi
|
fi
|
||||||
rm -rf -- "$managed_proxy_directory"
|
rm -rf -- "$managed_proxy_directory"
|
||||||
mkdir -p -- "$managed_proxy_directory"
|
mkdir -p -- "$managed_proxy_directory"
|
||||||
cp -- "$managed_publish_directory/Himegari.dll" "$managed_proxy_directory/Himegari.dll"
|
cp -- "$managed_publish_directory/OME.dll" "$managed_proxy_directory/OME.dll"
|
||||||
|
|
||||||
real_dotnet="$(command -v dotnet)"
|
real_dotnet="$(command -v dotnet)"
|
||||||
expected_dotnet_proxy_directory="$repo_root/build/dotnet-export-proxy"
|
expected_dotnet_proxy_directory="$repo_root/build/dotnet-export-proxy"
|
||||||
@@ -90,15 +90,15 @@ RestoreDisableParallel=true \
|
|||||||
DOTNET_gcServer=0 \
|
DOTNET_gcServer=0 \
|
||||||
DOTNET_GCConserveMemory=9 \
|
DOTNET_GCConserveMemory=9 \
|
||||||
AGE_REAL_DOTNET="$real_dotnet" \
|
AGE_REAL_DOTNET="$real_dotnet" \
|
||||||
AGE_PUBLISH_PROJECT="$project_root/Himegari.csproj" \
|
AGE_PUBLISH_PROJECT="$project_root/OME.csproj" \
|
||||||
AGE_PREPUBLISHED_OUTPUT="$managed_proxy_directory" \
|
AGE_PREPUBLISHED_OUTPUT="$managed_proxy_directory" \
|
||||||
AGE_PUBLISH_OUTPUT_ROOT="${TMPDIR:-/tmp}/godot-publish-dotnet" \
|
AGE_PUBLISH_OUTPUT_ROOT="${TMPDIR:-/tmp}/godot-publish-dotnet" \
|
||||||
AGE_PUBLISH_ASSEMBLY="Himegari.dll" \
|
AGE_PUBLISH_ASSEMBLY="OME.dll" \
|
||||||
AGE_PUBLISH_RUNTIME="linux-x64" \
|
AGE_PUBLISH_RUNTIME="linux-x64" \
|
||||||
PATH="$dotnet_proxy_directory:$PATH" \
|
PATH="$dotnet_proxy_directory:$PATH" \
|
||||||
XDG_DATA_HOME="$xdg_data_home" "$godot_console" \
|
XDG_DATA_HOME="$xdg_data_home" "$godot_console" \
|
||||||
--headless --quit-after 120 --path "$project_root" \
|
--headless --quit-after 120 --path "$project_root" \
|
||||||
--export-release "Linux x86_64" "$export_directory/Himegari.x86_64"
|
--export-release "Linux x86_64" "$export_directory/OME"
|
||||||
export_status=$?
|
export_status=$?
|
||||||
set -e
|
set -e
|
||||||
if [[ $export_status -ne 0 ]]; then
|
if [[ $export_status -ne 0 ]]; then
|
||||||
@@ -108,8 +108,8 @@ if [[ $export_status -ne 0 ]]; then
|
|||||||
exit "$export_status"
|
exit "$export_status"
|
||||||
fi
|
fi
|
||||||
|
|
||||||
managed_export_directory="$export_directory/data_Himegari_linuxbsd_x86_64"
|
managed_export_directory="$export_directory/data_OME_linuxbsd_x86_64"
|
||||||
expected_managed_export_directory="$repo_root/build/export/linux-x64/data_Himegari_linuxbsd_x86_64"
|
expected_managed_export_directory="$repo_root/build/export/linux-x64/data_OME_linuxbsd_x86_64"
|
||||||
if [[ "$managed_export_directory" != "$expected_managed_export_directory" || "$managed_export_directory" == "/" ]]; then
|
if [[ "$managed_export_directory" != "$expected_managed_export_directory" || "$managed_export_directory" == "/" ]]; then
|
||||||
echo "refusing to replace unexpected managed export directory: $managed_export_directory" >&2
|
echo "refusing to replace unexpected managed export directory: $managed_export_directory" >&2
|
||||||
exit 1
|
exit 1
|
||||||
@@ -131,7 +131,7 @@ package_root="${package_outputs[0]}"
|
|||||||
archive_path="${package_outputs[1]}"
|
archive_path="${package_outputs[1]}"
|
||||||
smoke_log="$package_directory/package-smoke.log"
|
smoke_log="$package_directory/package-smoke.log"
|
||||||
set +e
|
set +e
|
||||||
"$package_root/Himegari.x86_64" --headless -- --package-smoke >"$smoke_log" 2>&1
|
"$package_root/OME" --headless -- --package-smoke >"$smoke_log" 2>&1
|
||||||
smoke_status=$?
|
smoke_status=$?
|
||||||
set -e
|
set -e
|
||||||
cat "$smoke_log"
|
cat "$smoke_log"
|
||||||
|
|||||||
@@ -39,7 +39,7 @@ DOTNET_CLI_USE_MSBUILD_SERVER=0 \
|
|||||||
MSBUILDDISABLENODEREUSE=1 \
|
MSBUILDDISABLENODEREUSE=1 \
|
||||||
DOTNET_gcServer=0 \
|
DOTNET_gcServer=0 \
|
||||||
DOTNET_GCConserveMemory=9 \
|
DOTNET_GCConserveMemory=9 \
|
||||||
dotnet publish "$project_root/Himegari.csproj" \
|
dotnet publish "$project_root/OME.csproj" \
|
||||||
--configuration ExportRelease \
|
--configuration ExportRelease \
|
||||||
--runtime win-x64 \
|
--runtime win-x64 \
|
||||||
--self-contained true \
|
--self-contained true \
|
||||||
@@ -58,7 +58,7 @@ if [[ "$managed_proxy_directory" != "$expected_managed_proxy_directory" || "$man
|
|||||||
fi
|
fi
|
||||||
rm -rf -- "$managed_proxy_directory"
|
rm -rf -- "$managed_proxy_directory"
|
||||||
mkdir -p -- "$managed_proxy_directory"
|
mkdir -p -- "$managed_proxy_directory"
|
||||||
cp -- "$managed_publish_directory/Himegari.dll" "$managed_proxy_directory/Himegari.dll"
|
cp -- "$managed_publish_directory/OME.dll" "$managed_proxy_directory/OME.dll"
|
||||||
|
|
||||||
real_dotnet="$(command -v dotnet)"
|
real_dotnet="$(command -v dotnet)"
|
||||||
expected_dotnet_proxy_directory="$repo_root/build/dotnet-export-proxy"
|
expected_dotnet_proxy_directory="$repo_root/build/dotnet-export-proxy"
|
||||||
@@ -87,15 +87,15 @@ RestoreDisableParallel=true \
|
|||||||
DOTNET_gcServer=0 \
|
DOTNET_gcServer=0 \
|
||||||
DOTNET_GCConserveMemory=9 \
|
DOTNET_GCConserveMemory=9 \
|
||||||
AGE_REAL_DOTNET="$real_dotnet" \
|
AGE_REAL_DOTNET="$real_dotnet" \
|
||||||
AGE_PUBLISH_PROJECT="$project_root/Himegari.csproj" \
|
AGE_PUBLISH_PROJECT="$project_root/OME.csproj" \
|
||||||
AGE_PREPUBLISHED_OUTPUT="$managed_proxy_directory" \
|
AGE_PREPUBLISHED_OUTPUT="$managed_proxy_directory" \
|
||||||
AGE_PUBLISH_OUTPUT_ROOT="${TMPDIR:-/tmp}/godot-publish-dotnet" \
|
AGE_PUBLISH_OUTPUT_ROOT="${TMPDIR:-/tmp}/godot-publish-dotnet" \
|
||||||
AGE_PUBLISH_ASSEMBLY="Himegari.dll" \
|
AGE_PUBLISH_ASSEMBLY="OME.dll" \
|
||||||
AGE_PUBLISH_RUNTIME="win-x64" \
|
AGE_PUBLISH_RUNTIME="win-x64" \
|
||||||
PATH="$dotnet_proxy_directory:$PATH" \
|
PATH="$dotnet_proxy_directory:$PATH" \
|
||||||
XDG_DATA_HOME="$xdg_data_home" "$godot_console" \
|
XDG_DATA_HOME="$xdg_data_home" "$godot_console" \
|
||||||
--headless --quit-after 120 --path "$project_root" \
|
--headless --quit-after 120 --path "$project_root" \
|
||||||
--export-release "Windows x86_64" "$export_directory/Himegari.exe"
|
--export-release "Windows x86_64" "$export_directory/OME.exe"
|
||||||
export_status=$?
|
export_status=$?
|
||||||
set -e
|
set -e
|
||||||
if [[ $export_status -ne 0 ]]; then
|
if [[ $export_status -ne 0 ]]; then
|
||||||
@@ -105,8 +105,8 @@ if [[ $export_status -ne 0 ]]; then
|
|||||||
exit "$export_status"
|
exit "$export_status"
|
||||||
fi
|
fi
|
||||||
|
|
||||||
managed_export_directory="$export_directory/data_Himegari_windows_x86_64"
|
managed_export_directory="$export_directory/data_OME_windows_x86_64"
|
||||||
expected_managed_export_directory="$repo_root/build/export/windows-x64/data_Himegari_windows_x86_64"
|
expected_managed_export_directory="$repo_root/build/export/windows-x64/data_OME_windows_x86_64"
|
||||||
if [[ "$managed_export_directory" != "$expected_managed_export_directory" || "$managed_export_directory" == "/" ]]; then
|
if [[ "$managed_export_directory" != "$expected_managed_export_directory" || "$managed_export_directory" == "/" ]]; then
|
||||||
echo "refusing to replace unexpected managed export directory: $managed_export_directory" >&2
|
echo "refusing to replace unexpected managed export directory: $managed_export_directory" >&2
|
||||||
exit 1
|
exit 1
|
||||||
|
|||||||
@@ -9,13 +9,13 @@ $projectRoot = Join-Path $repoRoot 'godot'
|
|||||||
$godotConsolePath = (Resolve-Path -LiteralPath $GodotConsole).Path
|
$godotConsolePath = (Resolve-Path -LiteralPath $GodotConsole).Path
|
||||||
$outputDirectory = [System.IO.Path]::GetFullPath((Join-Path $repoRoot 'build\export\linux-x64'))
|
$outputDirectory = [System.IO.Path]::GetFullPath((Join-Path $repoRoot 'build\export\linux-x64'))
|
||||||
$expectedOutputDirectory = [System.IO.Path]::GetFullPath((Join-Path $repoRoot 'build\export\linux-x64'))
|
$expectedOutputDirectory = [System.IO.Path]::GetFullPath((Join-Path $repoRoot 'build\export\linux-x64'))
|
||||||
$executable = Join-Path $outputDirectory 'Himegari.x86_64'
|
$executable = Join-Path $outputDirectory 'OME'
|
||||||
|
|
||||||
if (-not (Test-Path -LiteralPath $godotConsolePath -PathType Leaf)) {
|
if (-not (Test-Path -LiteralPath $godotConsolePath -PathType Leaf)) {
|
||||||
throw "Godot console executable was not found: $godotConsolePath"
|
throw "Godot console executable was not found: $godotConsolePath"
|
||||||
}
|
}
|
||||||
foreach ($required in @(
|
foreach ($required in @(
|
||||||
(Join-Path $projectRoot 'Himegari.sln'),
|
(Join-Path $projectRoot 'OME.sln'),
|
||||||
(Join-Path $projectRoot 'export_presets.cfg'),
|
(Join-Path $projectRoot 'export_presets.cfg'),
|
||||||
(Join-Path $repoRoot 'build\native\linux-x64\libage_movie_ffmpeg.so')
|
(Join-Path $repoRoot 'build\native\linux-x64\libage_movie_ffmpeg.so')
|
||||||
)) {
|
)) {
|
||||||
|
|||||||
@@ -15,12 +15,12 @@ from pathlib import Path
|
|||||||
|
|
||||||
HERE = Path(__file__).resolve().parent
|
HERE = Path(__file__).resolve().parent
|
||||||
REPO = HERE.parent
|
REPO = HERE.parent
|
||||||
MANAGED_DIRECTORY = "data_Himegari_linuxbsd_x86_64"
|
MANAGED_DIRECTORY = "data_OME_linuxbsd_x86_64"
|
||||||
PACKAGE_NAME = "OpenMaidEngine-Himegari-linux-x64"
|
PACKAGE_NAME = "OME-linux-x64"
|
||||||
REQUIRED_FILES = (
|
REQUIRED_FILES = (
|
||||||
"Himegari.x86_64",
|
"OME",
|
||||||
"Himegari.pck",
|
"OME.pck",
|
||||||
f"{MANAGED_DIRECTORY}/Himegari.dll",
|
f"{MANAGED_DIRECTORY}/OME.dll",
|
||||||
f"{MANAGED_DIRECTORY}/Age.Engine.dll",
|
f"{MANAGED_DIRECTORY}/Age.Engine.dll",
|
||||||
f"{MANAGED_DIRECTORY}/Age.Engine.Frontend.dll",
|
f"{MANAGED_DIRECTORY}/Age.Engine.Frontend.dll",
|
||||||
f"{MANAGED_DIRECTORY}/libage_movie_ffmpeg.so",
|
f"{MANAGED_DIRECTORY}/libage_movie_ffmpeg.so",
|
||||||
@@ -36,6 +36,7 @@ FORBIDDEN_FILES = (
|
|||||||
f"{MANAGED_DIRECTORY}/age_movie_ffmpeg.dll",
|
f"{MANAGED_DIRECTORY}/age_movie_ffmpeg.dll",
|
||||||
f"{MANAGED_DIRECTORY}/avformat-62.dll",
|
f"{MANAGED_DIRECTORY}/avformat-62.dll",
|
||||||
)
|
)
|
||||||
|
LEGACY_FILES = (f"{MANAGED_DIRECTORY}/Himegari.dll",)
|
||||||
PROJECT_FILES = ("LICENSE", "README.md", "THIRD_PARTY_NOTICES.md")
|
PROJECT_FILES = ("LICENSE", "README.md", "THIRD_PARTY_NOTICES.md")
|
||||||
|
|
||||||
|
|
||||||
@@ -54,7 +55,10 @@ def verify_export(export_directory: Path) -> Path:
|
|||||||
forbidden = [name for name in FORBIDDEN_FILES if (export_directory / name).exists()]
|
forbidden = [name for name in FORBIDDEN_FILES if (export_directory / name).exists()]
|
||||||
if forbidden:
|
if forbidden:
|
||||||
raise ValueError("Linux export contains Windows-only files: " + ", ".join(forbidden))
|
raise ValueError("Linux export contains Windows-only files: " + ", ".join(forbidden))
|
||||||
executable = export_directory / "Himegari.x86_64"
|
legacy = [name for name in LEGACY_FILES if (export_directory / name).exists()]
|
||||||
|
if legacy:
|
||||||
|
raise ValueError("Linux export contains legacy-branded files: " + ", ".join(legacy))
|
||||||
|
executable = export_directory / "OME"
|
||||||
if os.name != "nt" and not os.access(executable, os.X_OK):
|
if os.name != "nt" and not os.access(executable, os.X_OK):
|
||||||
raise ValueError(f"Linux export executable bit is not set: {executable}")
|
raise ValueError(f"Linux export executable bit is not set: {executable}")
|
||||||
return export_directory
|
return export_directory
|
||||||
@@ -89,7 +93,7 @@ def build_metadata(epoch: int) -> dict[str, object]:
|
|||||||
dirty = bool(_git("status", "--porcelain", "--untracked-files=normal"))
|
dirty = bool(_git("status", "--porcelain", "--untracked-files=normal"))
|
||||||
return {
|
return {
|
||||||
"schema_version": 1,
|
"schema_version": 1,
|
||||||
"project": "OpenMaidEngine Himegari profile",
|
"project": "Open Maid Engine",
|
||||||
"target": "linux-x64",
|
"target": "linux-x64",
|
||||||
"source_commit": _git("rev-parse", "HEAD"),
|
"source_commit": _git("rev-parse", "HEAD"),
|
||||||
"source_dirty": dirty,
|
"source_dirty": dirty,
|
||||||
|
|||||||
@@ -18,12 +18,12 @@ import verify_windows_native
|
|||||||
|
|
||||||
HERE = Path(__file__).resolve().parent
|
HERE = Path(__file__).resolve().parent
|
||||||
REPO = HERE.parent
|
REPO = HERE.parent
|
||||||
MANAGED_DIRECTORY = "data_Himegari_windows_x86_64"
|
MANAGED_DIRECTORY = "data_OME_windows_x86_64"
|
||||||
PACKAGE_NAME = "OpenMaidEngine-Himegari-windows-x64"
|
PACKAGE_NAME = "OME-windows-x64"
|
||||||
REQUIRED_FILES = (
|
REQUIRED_FILES = (
|
||||||
"Himegari.exe",
|
"OME.exe",
|
||||||
"Himegari.pck",
|
"OME.pck",
|
||||||
f"{MANAGED_DIRECTORY}/Himegari.dll",
|
f"{MANAGED_DIRECTORY}/OME.dll",
|
||||||
f"{MANAGED_DIRECTORY}/Age.Engine.dll",
|
f"{MANAGED_DIRECTORY}/Age.Engine.dll",
|
||||||
f"{MANAGED_DIRECTORY}/Age.Engine.Frontend.dll",
|
f"{MANAGED_DIRECTORY}/Age.Engine.Frontend.dll",
|
||||||
f"{MANAGED_DIRECTORY}/Age.Engine.Text.Windows.dll",
|
f"{MANAGED_DIRECTORY}/Age.Engine.Text.Windows.dll",
|
||||||
@@ -34,10 +34,11 @@ REQUIRED_FILES = (
|
|||||||
*(f"{MANAGED_DIRECTORY}/{name}" for name in verify_windows_native.REQUIRED_FILES),
|
*(f"{MANAGED_DIRECTORY}/{name}" for name in verify_windows_native.REQUIRED_FILES),
|
||||||
)
|
)
|
||||||
FORBIDDEN_FILES = (
|
FORBIDDEN_FILES = (
|
||||||
"Himegari.x86_64",
|
"OME",
|
||||||
f"{MANAGED_DIRECTORY}/libage_movie_ffmpeg.so",
|
f"{MANAGED_DIRECTORY}/libage_movie_ffmpeg.so",
|
||||||
f"{MANAGED_DIRECTORY}/libavformat.so.62",
|
f"{MANAGED_DIRECTORY}/libavformat.so.62",
|
||||||
)
|
)
|
||||||
|
LEGACY_FILES = (f"{MANAGED_DIRECTORY}/Himegari.dll",)
|
||||||
PROJECT_FILES = ("LICENSE", "README.md", "THIRD_PARTY_NOTICES.md")
|
PROJECT_FILES = ("LICENSE", "README.md", "THIRD_PARTY_NOTICES.md")
|
||||||
|
|
||||||
|
|
||||||
@@ -61,10 +62,13 @@ def verify_export(export_directory: Path, objdump: str) -> tuple[Path, dict[str,
|
|||||||
)
|
)
|
||||||
if forbidden:
|
if forbidden:
|
||||||
raise ValueError("Windows export contains Linux-only files: " + ", ".join(sorted(set(forbidden))))
|
raise ValueError("Windows export contains Linux-only files: " + ", ".join(sorted(set(forbidden))))
|
||||||
executable_machine = verify_windows_native.pe_machine(export_directory / "Himegari.exe")
|
legacy = [name for name in LEGACY_FILES if (export_directory / name).exists()]
|
||||||
|
if legacy:
|
||||||
|
raise ValueError("Windows export contains legacy-branded files: " + ", ".join(legacy))
|
||||||
|
executable_machine = verify_windows_native.pe_machine(export_directory / "OME.exe")
|
||||||
if executable_machine != verify_windows_native.PE_MACHINE_AMD64:
|
if executable_machine != verify_windows_native.PE_MACHINE_AMD64:
|
||||||
raise ValueError(
|
raise ValueError(
|
||||||
f"Windows executable is not AMD64 PE (0x{executable_machine:04x}): Himegari.exe"
|
f"Windows executable is not AMD64 PE (0x{executable_machine:04x}): OME.exe"
|
||||||
)
|
)
|
||||||
native_report = verify_windows_native.verify_bundle(
|
native_report = verify_windows_native.verify_bundle(
|
||||||
export_directory / MANAGED_DIRECTORY,
|
export_directory / MANAGED_DIRECTORY,
|
||||||
@@ -113,7 +117,7 @@ def build_metadata(epoch: int) -> dict[str, object]:
|
|||||||
ffmpeg = json.load(stream)
|
ffmpeg = json.load(stream)
|
||||||
return {
|
return {
|
||||||
"schema_version": 1,
|
"schema_version": 1,
|
||||||
"project": "OpenMaidEngine Himegari profile",
|
"project": "Open Maid Engine",
|
||||||
"target": "win-x64",
|
"target": "win-x64",
|
||||||
"source_commit": _git("rev-parse", "HEAD"),
|
"source_commit": _git("rev-parse", "HEAD"),
|
||||||
"source_dirty": bool(_git("status", "--porcelain", "--untracked-files=normal")),
|
"source_dirty": bool(_git("status", "--porcelain", "--untracked-files=normal")),
|
||||||
|
|||||||
@@ -20,8 +20,8 @@ from typing import Any, Callable, Protocol
|
|||||||
import verify_windows_native
|
import verify_windows_native
|
||||||
|
|
||||||
|
|
||||||
LINUX_ARCHIVE = "OpenMaidEngine-Himegari-linux-x64.tar.gz"
|
LINUX_ARCHIVE = "OME-linux-x64.tar.gz"
|
||||||
WINDOWS_ARCHIVE = "OpenMaidEngine-Himegari-windows-x64.zip"
|
WINDOWS_ARCHIVE = "OME-windows-x64.zip"
|
||||||
RELEASE_CHECKSUMS = "RELEASE-SHA256SUMS"
|
RELEASE_CHECKSUMS = "RELEASE-SHA256SUMS"
|
||||||
LINUX_ARTIFACT_FILES = frozenset({
|
LINUX_ARTIFACT_FILES = frozenset({
|
||||||
LINUX_ARCHIVE,
|
LINUX_ARCHIVE,
|
||||||
@@ -38,8 +38,8 @@ WINDOWS_ARTIFACT_FILES = frozenset({
|
|||||||
"WINDOWS-VERIFICATION.json",
|
"WINDOWS-VERIFICATION.json",
|
||||||
})
|
})
|
||||||
EXPECTED_RELEASE_ASSETS = frozenset({LINUX_ARCHIVE, WINDOWS_ARCHIVE, RELEASE_CHECKSUMS})
|
EXPECTED_RELEASE_ASSETS = frozenset({LINUX_ARCHIVE, WINDOWS_ARCHIVE, RELEASE_CHECKSUMS})
|
||||||
LINUX_PACKAGE_ROOT = "OpenMaidEngine-Himegari-linux-x64"
|
LINUX_PACKAGE_ROOT = "OME-linux-x64"
|
||||||
WINDOWS_PACKAGE_ROOT = "OpenMaidEngine-Himegari-windows-x64"
|
WINDOWS_PACKAGE_ROOT = "OME-windows-x64"
|
||||||
SMOKE_MARKER = "PACKAGE SMOKE OK: opcodes=548 ffmpeg-abi=3"
|
SMOKE_MARKER = "PACKAGE SMOKE OK: opcodes=548 ffmpeg-abi=3"
|
||||||
TAG_PATTERN = re.compile(r"v[0-9][0-9A-Za-z.+-]*\Z")
|
TAG_PATTERN = re.compile(r"v[0-9][0-9A-Za-z.+-]*\Z")
|
||||||
COMMIT_PATTERN = re.compile(r"[0-9a-f]{40}\Z")
|
COMMIT_PATTERN = re.compile(r"[0-9a-f]{40}\Z")
|
||||||
@@ -279,8 +279,8 @@ def _validate_windows_verification(data: bytes) -> None:
|
|||||||
}
|
}
|
||||||
if native.get("schema_version") != 1 or native.get("target") != "win-x64":
|
if native.get("schema_version") != 1 or native.get("target") != "win-x64":
|
||||||
mismatches["native"] = ((native.get("schema_version"), native.get("target")), (1, "win-x64"))
|
mismatches["native"] = ((native.get("schema_version"), native.get("target")), (1, "win-x64"))
|
||||||
if native.get("bundle") != "data_Himegari_windows_x86_64":
|
if native.get("bundle") != "data_OME_windows_x86_64":
|
||||||
mismatches["bundle"] = (native.get("bundle"), "data_Himegari_windows_x86_64")
|
mismatches["bundle"] = (native.get("bundle"), "data_OME_windows_x86_64")
|
||||||
if machines != expected_machines:
|
if machines != expected_machines:
|
||||||
mismatches["machines"] = (machines, expected_machines)
|
mismatches["machines"] = (machines, expected_machines)
|
||||||
exports_value = native.get("shim_exports")
|
exports_value = native.get("shim_exports")
|
||||||
@@ -361,9 +361,9 @@ def prepare_release_assets(
|
|||||||
if external != internal:
|
if external != internal:
|
||||||
raise ValueError(f"external and packaged {label} do not match")
|
raise ValueError(f"external and packaged {label} do not match")
|
||||||
|
|
||||||
if b" Himegari.x86_64\n" not in linux_ledger:
|
if b" OME\n" not in linux_ledger:
|
||||||
raise ValueError("Linux SHA256SUMS does not contain the packaged executable")
|
raise ValueError("Linux SHA256SUMS does not contain the packaged executable")
|
||||||
if b" Himegari.exe\n" not in windows_ledger:
|
if b" OME.exe\n" not in windows_ledger:
|
||||||
raise ValueError("Windows SHA256SUMS does not contain the packaged executable")
|
raise ValueError("Windows SHA256SUMS does not contain the packaged executable")
|
||||||
|
|
||||||
output_directory = output_directory.resolve()
|
output_directory = output_directory.resolve()
|
||||||
@@ -410,7 +410,7 @@ def promote_release(
|
|||||||
)
|
)
|
||||||
if {asset.name for asset in assets} != EXPECTED_RELEASE_ASSETS:
|
if {asset.name for asset in assets} != EXPECTED_RELEASE_ASSETS:
|
||||||
raise RuntimeError("prepared release asset set is invalid")
|
raise RuntimeError("prepared release asset set is invalid")
|
||||||
title = f"OpenMaidEngine Himegari {tag}"
|
title = f"Open Maid Engine {tag}"
|
||||||
release = api.get_release(tag)
|
release = api.get_release(tag)
|
||||||
if release is None:
|
if release is None:
|
||||||
release = api.create_release({
|
release = api.create_release({
|
||||||
|
|||||||
@@ -12,11 +12,11 @@ class DotnetPublishProxyTests(unittest.TestCase):
|
|||||||
def test_stages_exact_expected_publish(self) -> None:
|
def test_stages_exact_expected_publish(self) -> None:
|
||||||
with tempfile.TemporaryDirectory() as temporary:
|
with tempfile.TemporaryDirectory() as temporary:
|
||||||
root = Path(temporary)
|
root = Path(temporary)
|
||||||
project = root / "Himegari.csproj"
|
project = root / "OME.csproj"
|
||||||
project.write_text("<Project />", encoding="utf-8")
|
project.write_text("<Project />", encoding="utf-8")
|
||||||
source = root / "prepublished"
|
source = root / "prepublished"
|
||||||
source.mkdir()
|
source.mkdir()
|
||||||
(source / "Himegari.dll").write_bytes(b"managed")
|
(source / "OME.dll").write_bytes(b"managed")
|
||||||
(source / "libhostfxr.so").write_bytes(b"runtime")
|
(source / "libhostfxr.so").write_bytes(b"runtime")
|
||||||
output_root = root / "godot-publish-dotnet"
|
output_root = root / "godot-publish-dotnet"
|
||||||
output = output_root / "123-ExportRelease-linux-x64"
|
output = output_root / "123-ExportRelease-linux-x64"
|
||||||
@@ -29,26 +29,26 @@ class DotnetPublishProxyTests(unittest.TestCase):
|
|||||||
"AGE_PUBLISH_PROJECT": str(project),
|
"AGE_PUBLISH_PROJECT": str(project),
|
||||||
"AGE_PREPUBLISHED_OUTPUT": str(source),
|
"AGE_PREPUBLISHED_OUTPUT": str(source),
|
||||||
"AGE_PUBLISH_OUTPUT_ROOT": str(output_root),
|
"AGE_PUBLISH_OUTPUT_ROOT": str(output_root),
|
||||||
"AGE_PUBLISH_ASSEMBLY": "Himegari.dll",
|
"AGE_PUBLISH_ASSEMBLY": "OME.dll",
|
||||||
"AGE_PUBLISH_RUNTIME": "linux-x64",
|
"AGE_PUBLISH_RUNTIME": "linux-x64",
|
||||||
})
|
})
|
||||||
self.assertEqual(output.resolve(), staged)
|
self.assertEqual(output.resolve(), staged)
|
||||||
self.assertEqual(b"managed", (staged / "Himegari.dll").read_bytes())
|
self.assertEqual(b"managed", (staged / "OME.dll").read_bytes())
|
||||||
self.assertEqual(b"runtime", (staged / "libhostfxr.so").read_bytes())
|
self.assertEqual(b"runtime", (staged / "libhostfxr.so").read_bytes())
|
||||||
|
|
||||||
def test_rejects_drift_and_output_escape(self) -> None:
|
def test_rejects_drift_and_output_escape(self) -> None:
|
||||||
with tempfile.TemporaryDirectory() as temporary:
|
with tempfile.TemporaryDirectory() as temporary:
|
||||||
root = Path(temporary)
|
root = Path(temporary)
|
||||||
project = root / "Himegari.csproj"
|
project = root / "OME.csproj"
|
||||||
project.write_text("<Project />", encoding="utf-8")
|
project.write_text("<Project />", encoding="utf-8")
|
||||||
source = root / "prepublished"
|
source = root / "prepublished"
|
||||||
source.mkdir()
|
source.mkdir()
|
||||||
(source / "Himegari.dll").write_bytes(b"managed")
|
(source / "OME.dll").write_bytes(b"managed")
|
||||||
environment = {
|
environment = {
|
||||||
"AGE_PUBLISH_PROJECT": str(project),
|
"AGE_PUBLISH_PROJECT": str(project),
|
||||||
"AGE_PREPUBLISHED_OUTPUT": str(source),
|
"AGE_PREPUBLISHED_OUTPUT": str(source),
|
||||||
"AGE_PUBLISH_OUTPUT_ROOT": str(root / "reserved"),
|
"AGE_PUBLISH_OUTPUT_ROOT": str(root / "reserved"),
|
||||||
"AGE_PUBLISH_ASSEMBLY": "Himegari.dll",
|
"AGE_PUBLISH_ASSEMBLY": "OME.dll",
|
||||||
"AGE_PUBLISH_RUNTIME": "linux-x64",
|
"AGE_PUBLISH_RUNTIME": "linux-x64",
|
||||||
}
|
}
|
||||||
wrong_runtime = dotnet_publish_proxy.PublishRequest(
|
wrong_runtime = dotnet_publish_proxy.PublishRequest(
|
||||||
@@ -65,11 +65,11 @@ class DotnetPublishProxyTests(unittest.TestCase):
|
|||||||
def test_stages_windows_publish_when_explicitly_selected(self) -> None:
|
def test_stages_windows_publish_when_explicitly_selected(self) -> None:
|
||||||
with tempfile.TemporaryDirectory() as temporary:
|
with tempfile.TemporaryDirectory() as temporary:
|
||||||
root = Path(temporary)
|
root = Path(temporary)
|
||||||
project = root / "Himegari.csproj"
|
project = root / "OME.csproj"
|
||||||
project.write_text("<Project />", encoding="utf-8")
|
project.write_text("<Project />", encoding="utf-8")
|
||||||
source = root / "prepublished"
|
source = root / "prepublished"
|
||||||
source.mkdir()
|
source.mkdir()
|
||||||
(source / "Himegari.dll").write_bytes(b"managed")
|
(source / "OME.dll").write_bytes(b"managed")
|
||||||
output = root / "reserved/123-ExportRelease-win-x64"
|
output = root / "reserved/123-ExportRelease-win-x64"
|
||||||
request = dotnet_publish_proxy.PublishRequest(
|
request = dotnet_publish_proxy.PublishRequest(
|
||||||
project, "ExportRelease", "win-x64", "true", output
|
project, "ExportRelease", "win-x64", "true", output
|
||||||
@@ -78,7 +78,7 @@ class DotnetPublishProxyTests(unittest.TestCase):
|
|||||||
"AGE_PUBLISH_PROJECT": str(project),
|
"AGE_PUBLISH_PROJECT": str(project),
|
||||||
"AGE_PREPUBLISHED_OUTPUT": str(source),
|
"AGE_PREPUBLISHED_OUTPUT": str(source),
|
||||||
"AGE_PUBLISH_OUTPUT_ROOT": str(root / "reserved"),
|
"AGE_PUBLISH_OUTPUT_ROOT": str(root / "reserved"),
|
||||||
"AGE_PUBLISH_ASSEMBLY": "Himegari.dll",
|
"AGE_PUBLISH_ASSEMBLY": "OME.dll",
|
||||||
"AGE_PUBLISH_RUNTIME": "win-x64",
|
"AGE_PUBLISH_RUNTIME": "win-x64",
|
||||||
})
|
})
|
||||||
self.assertEqual(output.resolve(), staged)
|
self.assertEqual(output.resolve(), staged)
|
||||||
|
|||||||
@@ -16,11 +16,24 @@ def make_export(root: Path) -> Path:
|
|||||||
path = export / relative
|
path = export / relative
|
||||||
path.parent.mkdir(parents=True, exist_ok=True)
|
path.parent.mkdir(parents=True, exist_ok=True)
|
||||||
path.write_bytes(f"fixture:{relative}".encode())
|
path.write_bytes(f"fixture:{relative}".encode())
|
||||||
(export / "Himegari.x86_64").chmod(0o755)
|
(export / "OME").chmod(0o755)
|
||||||
return export
|
return export
|
||||||
|
|
||||||
|
|
||||||
class PackageLinuxX64Tests(unittest.TestCase):
|
class PackageLinuxX64Tests(unittest.TestCase):
|
||||||
|
def test_public_output_names_use_ome_branding(self) -> None:
|
||||||
|
self.assertEqual("OME-linux-x64", package_linux_x64.PACKAGE_NAME)
|
||||||
|
self.assertIn("OME", package_linux_x64.REQUIRED_FILES)
|
||||||
|
self.assertIn("OME.pck", package_linux_x64.REQUIRED_FILES)
|
||||||
|
self.assertIn(
|
||||||
|
f"{package_linux_x64.MANAGED_DIRECTORY}/OME.dll",
|
||||||
|
package_linux_x64.REQUIRED_FILES,
|
||||||
|
)
|
||||||
|
self.assertIn(
|
||||||
|
f"{package_linux_x64.MANAGED_DIRECTORY}/Himegari.dll",
|
||||||
|
package_linux_x64.LEGACY_FILES,
|
||||||
|
)
|
||||||
|
|
||||||
def test_verify_rejects_missing_and_windows_files(self) -> None:
|
def test_verify_rejects_missing_and_windows_files(self) -> None:
|
||||||
with tempfile.TemporaryDirectory() as temporary:
|
with tempfile.TemporaryDirectory() as temporary:
|
||||||
export = make_export(Path(temporary))
|
export = make_export(Path(temporary))
|
||||||
@@ -33,12 +46,17 @@ class PackageLinuxX64Tests(unittest.TestCase):
|
|||||||
forbidden.write_bytes(b"windows")
|
forbidden.write_bytes(b"windows")
|
||||||
with self.assertRaisesRegex(ValueError, "Windows-only"):
|
with self.assertRaisesRegex(ValueError, "Windows-only"):
|
||||||
package_linux_x64.verify_export(export)
|
package_linux_x64.verify_export(export)
|
||||||
|
forbidden.unlink()
|
||||||
|
legacy = export / package_linux_x64.LEGACY_FILES[0]
|
||||||
|
legacy.write_bytes(b"legacy")
|
||||||
|
with self.assertRaisesRegex(ValueError, "legacy-branded"):
|
||||||
|
package_linux_x64.verify_export(export)
|
||||||
|
|
||||||
@unittest.skipIf(package_linux_x64.os.name == "nt", "executable-bit gate is POSIX-only")
|
@unittest.skipIf(package_linux_x64.os.name == "nt", "executable-bit gate is POSIX-only")
|
||||||
def test_verify_requires_executable_bit_on_posix(self) -> None:
|
def test_verify_requires_executable_bit_on_posix(self) -> None:
|
||||||
with tempfile.TemporaryDirectory() as temporary:
|
with tempfile.TemporaryDirectory() as temporary:
|
||||||
export = make_export(Path(temporary))
|
export = make_export(Path(temporary))
|
||||||
(export / "Himegari.x86_64").chmod(0o644)
|
(export / "OME").chmod(0o644)
|
||||||
with self.assertRaisesRegex(ValueError, "executable bit"):
|
with self.assertRaisesRegex(ValueError, "executable bit"):
|
||||||
package_linux_x64.verify_export(export)
|
package_linux_x64.verify_export(export)
|
||||||
|
|
||||||
@@ -65,7 +83,7 @@ class PackageLinuxX64Tests(unittest.TestCase):
|
|||||||
self.assertTrue((package_root / "LICENSE").is_file())
|
self.assertTrue((package_root / "LICENSE").is_file())
|
||||||
self.assertTrue((package_root / "BUILD-INFO.json").is_file())
|
self.assertTrue((package_root / "BUILD-INFO.json").is_file())
|
||||||
checksums = (package_root / "SHA256SUMS").read_text(encoding="utf-8")
|
checksums = (package_root / "SHA256SUMS").read_text(encoding="utf-8")
|
||||||
self.assertIn("Himegari.x86_64", checksums)
|
self.assertIn("OME", checksums)
|
||||||
self.assertIn("THIRD_PARTY_NOTICES.md", checksums)
|
self.assertIn("THIRD_PARTY_NOTICES.md", checksums)
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
@@ -33,7 +33,7 @@ def make_export(root: Path) -> Path:
|
|||||||
path = export / relative
|
path = export / relative
|
||||||
path.parent.mkdir(parents=True, exist_ok=True)
|
path.parent.mkdir(parents=True, exist_ok=True)
|
||||||
path.write_bytes(f"fixture:{relative}".encode())
|
path.write_bytes(f"fixture:{relative}".encode())
|
||||||
write_pe(export / "Himegari.exe")
|
write_pe(export / "OME.exe")
|
||||||
managed = export / package_windows_x64.MANAGED_DIRECTORY
|
managed = export / package_windows_x64.MANAGED_DIRECTORY
|
||||||
for name in (verify_windows_native.SHIM, *verify_windows_native.RUNTIME_DLLS):
|
for name in (verify_windows_native.SHIM, *verify_windows_native.RUNTIME_DLLS):
|
||||||
write_pe(managed / name)
|
write_pe(managed / name)
|
||||||
@@ -41,6 +41,19 @@ def make_export(root: Path) -> Path:
|
|||||||
|
|
||||||
|
|
||||||
class PackageWindowsX64Tests(unittest.TestCase):
|
class PackageWindowsX64Tests(unittest.TestCase):
|
||||||
|
def test_public_output_names_use_ome_branding(self) -> None:
|
||||||
|
self.assertEqual("OME-windows-x64", package_windows_x64.PACKAGE_NAME)
|
||||||
|
self.assertIn("OME.exe", package_windows_x64.REQUIRED_FILES)
|
||||||
|
self.assertIn("OME.pck", package_windows_x64.REQUIRED_FILES)
|
||||||
|
self.assertIn(
|
||||||
|
f"{package_windows_x64.MANAGED_DIRECTORY}/OME.dll",
|
||||||
|
package_windows_x64.REQUIRED_FILES,
|
||||||
|
)
|
||||||
|
self.assertIn(
|
||||||
|
f"{package_windows_x64.MANAGED_DIRECTORY}/Himegari.dll",
|
||||||
|
package_windows_x64.LEGACY_FILES,
|
||||||
|
)
|
||||||
|
|
||||||
def test_verify_rejects_missing_linux_and_wrong_machine_files(self) -> None:
|
def test_verify_rejects_missing_linux_and_wrong_machine_files(self) -> None:
|
||||||
with tempfile.TemporaryDirectory() as temporary:
|
with tempfile.TemporaryDirectory() as temporary:
|
||||||
export = make_export(Path(temporary))
|
export = make_export(Path(temporary))
|
||||||
@@ -56,7 +69,12 @@ class PackageWindowsX64Tests(unittest.TestCase):
|
|||||||
with self.assertRaisesRegex(ValueError, "Linux-only"):
|
with self.assertRaisesRegex(ValueError, "Linux-only"):
|
||||||
package_windows_x64.verify_export(export, "objdump")
|
package_windows_x64.verify_export(export, "objdump")
|
||||||
linux.unlink()
|
linux.unlink()
|
||||||
write_pe(export / "Himegari.exe", machine=0x014C)
|
legacy = export / package_windows_x64.LEGACY_FILES[0]
|
||||||
|
legacy.write_bytes(b"legacy")
|
||||||
|
with self.assertRaisesRegex(ValueError, "legacy-branded"):
|
||||||
|
package_windows_x64.verify_export(export, "objdump")
|
||||||
|
legacy.unlink()
|
||||||
|
write_pe(export / "OME.exe", machine=0x014C)
|
||||||
with self.assertRaisesRegex(ValueError, "not AMD64"):
|
with self.assertRaisesRegex(ValueError, "not AMD64"):
|
||||||
package_windows_x64.verify_export(export, "objdump")
|
package_windows_x64.verify_export(export, "objdump")
|
||||||
|
|
||||||
@@ -88,7 +106,7 @@ class PackageWindowsX64Tests(unittest.TestCase):
|
|||||||
self.assertTrue((package_root / "BUILD-INFO.json").is_file())
|
self.assertTrue((package_root / "BUILD-INFO.json").is_file())
|
||||||
self.assertTrue((package_root / "WINDOWS-VERIFICATION.json").is_file())
|
self.assertTrue((package_root / "WINDOWS-VERIFICATION.json").is_file())
|
||||||
checksums = (package_root / "SHA256SUMS").read_text(encoding="utf-8")
|
checksums = (package_root / "SHA256SUMS").read_text(encoding="utf-8")
|
||||||
self.assertIn("Himegari.exe", checksums)
|
self.assertIn("OME.exe", checksums)
|
||||||
self.assertIn("THIRD_PARTY_NOTICES.md", checksums)
|
self.assertIn("THIRD_PARTY_NOTICES.md", checksums)
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
@@ -49,7 +49,7 @@ def matching_release() -> dict[str, Any]:
|
|||||||
"id": 17,
|
"id": 17,
|
||||||
"tag_name": TAG,
|
"tag_name": TAG,
|
||||||
"target_commitish": TARGET,
|
"target_commitish": TARGET,
|
||||||
"name": f"OpenMaidEngine Himegari {TAG}",
|
"name": f"Open Maid Engine {TAG}",
|
||||||
"draft": False,
|
"draft": False,
|
||||||
"prerelease": False,
|
"prerelease": False,
|
||||||
"html_url": "https://gitea.invalid/releases/tag/v0.2.0",
|
"html_url": "https://gitea.invalid/releases/tag/v0.2.0",
|
||||||
@@ -77,7 +77,7 @@ def windows_verification() -> bytes:
|
|||||||
"native": {
|
"native": {
|
||||||
"schema_version": 1,
|
"schema_version": 1,
|
||||||
"target": "win-x64",
|
"target": "win-x64",
|
||||||
"bundle": "data_Himegari_windows_x86_64",
|
"bundle": "data_OME_windows_x86_64",
|
||||||
"machines": {
|
"machines": {
|
||||||
name: "AMD64"
|
name: "AMD64"
|
||||||
for name in (verify_windows_native.SHIM, *verify_windows_native.RUNTIME_DLLS)
|
for name in (verify_windows_native.SHIM, *verify_windows_native.RUNTIME_DLLS)
|
||||||
@@ -109,7 +109,7 @@ def create_artifacts(root: Path) -> tuple[Path, Path, Path]:
|
|||||||
windows.mkdir()
|
windows.mkdir()
|
||||||
|
|
||||||
linux_info = build_info("linux-x64")
|
linux_info = build_info("linux-x64")
|
||||||
linux_ledger = f"{'0' * 64} Himegari.x86_64\n".encode()
|
linux_ledger = f"{'0' * 64} OME\n".encode()
|
||||||
linux_archive = linux / publish_gitea_release.LINUX_ARCHIVE
|
linux_archive = linux / publish_gitea_release.LINUX_ARCHIVE
|
||||||
with tarfile.open(linux_archive, "w:gz") as archive:
|
with tarfile.open(linux_archive, "w:gz") as archive:
|
||||||
add_tar_bytes(
|
add_tar_bytes(
|
||||||
@@ -130,7 +130,7 @@ def create_artifacts(root: Path) -> tuple[Path, Path, Path]:
|
|||||||
write_checksum(linux, linux_archive)
|
write_checksum(linux, linux_archive)
|
||||||
|
|
||||||
windows_info = build_info("win-x64")
|
windows_info = build_info("win-x64")
|
||||||
windows_ledger = f"{'1' * 64} Himegari.exe\n".encode()
|
windows_ledger = f"{'1' * 64} OME.exe\n".encode()
|
||||||
verification = windows_verification()
|
verification = windows_verification()
|
||||||
windows_archive = windows / publish_gitea_release.WINDOWS_ARCHIVE
|
windows_archive = windows / publish_gitea_release.WINDOWS_ARCHIVE
|
||||||
with zipfile.ZipFile(windows_archive, "w", compression=zipfile.ZIP_DEFLATED) as archive:
|
with zipfile.ZipFile(windows_archive, "w", compression=zipfile.ZIP_DEFLATED) as archive:
|
||||||
@@ -156,6 +156,7 @@ class PublishGiteaReleaseTests(unittest.TestCase):
|
|||||||
self.assertEqual(17, result["id"])
|
self.assertEqual(17, result["id"])
|
||||||
self.assertEqual(TAG, api.created_payload["tag_name"])
|
self.assertEqual(TAG, api.created_payload["tag_name"])
|
||||||
self.assertEqual(TARGET, api.created_payload["target_commitish"])
|
self.assertEqual(TARGET, api.created_payload["target_commitish"])
|
||||||
|
self.assertEqual(f"Open Maid Engine {TAG}", api.created_payload["name"])
|
||||||
self.assertIn("Windows archive", api.created_payload["body"])
|
self.assertIn("Windows archive", api.created_payload["body"])
|
||||||
self.assertEqual(
|
self.assertEqual(
|
||||||
publish_gitea_release.EXPECTED_RELEASE_ASSETS,
|
publish_gitea_release.EXPECTED_RELEASE_ASSETS,
|
||||||
|
|||||||
@@ -8,6 +8,13 @@ from pathlib import Path
|
|||||||
|
|
||||||
REPO = Path(__file__).resolve().parent.parent
|
REPO = Path(__file__).resolve().parent.parent
|
||||||
WORKFLOW = REPO / ".gitea/workflows/linux-release-build.yml"
|
WORKFLOW = REPO / ".gitea/workflows/linux-release-build.yml"
|
||||||
|
EXPORT_PRESETS = REPO / "godot/export_presets.cfg"
|
||||||
|
GODOT_PROJECT = REPO / "godot/project.godot"
|
||||||
|
MANAGED_PROJECT = REPO / "godot/OME.csproj"
|
||||||
|
MANAGED_SOLUTION = REPO / "godot/OME.sln"
|
||||||
|
LINUX_BUILD = REPO / "tools/build-linux-x64.sh"
|
||||||
|
WINDOWS_BUILD = REPO / "tools/build-windows-x64.sh"
|
||||||
|
WINDOWS_HOSTED_EXPORT = REPO / "tools/export-linux-x64.ps1"
|
||||||
|
|
||||||
|
|
||||||
def job(text: str, name: str, next_name: str | None) -> str:
|
def job(text: str, name: str, next_name: str | None) -> str:
|
||||||
@@ -23,6 +30,42 @@ class ReleaseWorkflowTests(unittest.TestCase):
|
|||||||
cls.linux = job(cls.text, "linux-release", "windows-release")
|
cls.linux = job(cls.text, "linux-release", "windows-release")
|
||||||
cls.windows = job(cls.text, "windows-release", "publish-release")
|
cls.windows = job(cls.text, "windows-release", "publish-release")
|
||||||
cls.publish = job(cls.text, "publish-release", None)
|
cls.publish = job(cls.text, "publish-release", None)
|
||||||
|
cls.export_presets = EXPORT_PRESETS.read_text(encoding="utf-8")
|
||||||
|
cls.godot_project = GODOT_PROJECT.read_text(encoding="utf-8")
|
||||||
|
cls.managed_project = MANAGED_PROJECT.read_text(encoding="utf-8")
|
||||||
|
cls.managed_solution = MANAGED_SOLUTION.read_text(encoding="utf-8")
|
||||||
|
cls.linux_build = LINUX_BUILD.read_text(encoding="utf-8")
|
||||||
|
cls.windows_build = WINDOWS_BUILD.read_text(encoding="utf-8")
|
||||||
|
cls.windows_hosted_export = WINDOWS_HOSTED_EXPORT.read_text(encoding="utf-8")
|
||||||
|
|
||||||
|
def test_public_build_outputs_use_ome_branding(self) -> None:
|
||||||
|
self.assertIn('export_path="../build/export/linux-x64/OME"', self.export_presets)
|
||||||
|
self.assertIn('export_path="../build/export/windows-x64/OME.exe"', self.export_presets)
|
||||||
|
self.assertIn('project/assembly_name="OME"', self.godot_project)
|
||||||
|
self.assertIn('LogicalName="OME.Runtime.opcodes.json"', self.managed_project)
|
||||||
|
self.assertIn('= "OME", "OME.csproj"', self.managed_solution)
|
||||||
|
self.assertIn("'OME.sln'", self.windows_hosted_export)
|
||||||
|
self.assertFalse((REPO / "godot/Himegari.csproj").exists())
|
||||||
|
self.assertFalse((REPO / "godot/Himegari.sln").exists())
|
||||||
|
active_surfaces = "\n".join(
|
||||||
|
(
|
||||||
|
self.text,
|
||||||
|
self.export_presets,
|
||||||
|
self.godot_project,
|
||||||
|
self.linux_build,
|
||||||
|
self.windows_build,
|
||||||
|
self.windows_hosted_export,
|
||||||
|
)
|
||||||
|
)
|
||||||
|
for legacy_name in (
|
||||||
|
"Himegari.exe",
|
||||||
|
"Himegari.x86_64",
|
||||||
|
"Himegari.dll",
|
||||||
|
"Himegari.csproj",
|
||||||
|
"Himegari.sln",
|
||||||
|
"OpenMaidEngine-Himegari",
|
||||||
|
):
|
||||||
|
self.assertNotIn(legacy_name, active_surfaces)
|
||||||
|
|
||||||
def test_build_jobs_are_linux_hosted_read_only_and_target_separate(self) -> None:
|
def test_build_jobs_are_linux_hosted_read_only_and_target_separate(self) -> None:
|
||||||
self.assertRegex(self.text, r"(?m)^permissions:\n contents: read$")
|
self.assertRegex(self.text, r"(?m)^permissions:\n contents: read$")
|
||||||
@@ -49,8 +92,8 @@ class ReleaseWorkflowTests(unittest.TestCase):
|
|||||||
|
|
||||||
def test_windows_artifact_is_archive_plus_structural_evidence(self) -> None:
|
def test_windows_artifact_is_archive_plus_structural_evidence(self) -> None:
|
||||||
for name in (
|
for name in (
|
||||||
"OpenMaidEngine-Himegari-windows-x64.zip",
|
"OME-windows-x64.zip",
|
||||||
"OpenMaidEngine-Himegari-windows-x64.zip.sha256",
|
"OME-windows-x64.zip.sha256",
|
||||||
"BUILD-INFO.json",
|
"BUILD-INFO.json",
|
||||||
"SHA256SUMS",
|
"SHA256SUMS",
|
||||||
"WINDOWS-VERIFICATION.json",
|
"WINDOWS-VERIFICATION.json",
|
||||||
@@ -66,8 +109,8 @@ class ReleaseWorkflowTests(unittest.TestCase):
|
|||||||
r"(?m)^ needs:\n - linux-release\n - windows-release$",
|
r"(?m)^ needs:\n - linux-release\n - windows-release$",
|
||||||
)
|
)
|
||||||
self.assertIn("releases: write", self.publish)
|
self.assertIn("releases: write", self.publish)
|
||||||
self.assertIn("OpenMaidEngine-Himegari-linux-x64-${{ gitea.sha }}", self.publish)
|
self.assertIn("OME-linux-x64-${{ gitea.sha }}", self.publish)
|
||||||
self.assertIn("OpenMaidEngine-Himegari-windows-x64-${{ gitea.sha }}", self.publish)
|
self.assertIn("OME-windows-x64-${{ gitea.sha }}", self.publish)
|
||||||
self.assertIn("path: build/release-assets/linux", self.publish)
|
self.assertIn("path: build/release-assets/linux", self.publish)
|
||||||
self.assertIn("path: build/release-assets/windows", self.publish)
|
self.assertIn("path: build/release-assets/windows", self.publish)
|
||||||
self.assertIn("--linux-artifact-directory build/release-assets/linux", self.publish)
|
self.assertIn("--linux-artifact-directory build/release-assets/linux", self.publish)
|
||||||
|
|||||||
@@ -216,7 +216,7 @@ def build_gate_plan(
|
|||||||
Gate(
|
Gate(
|
||||||
"godot-build",
|
"godot-build",
|
||||||
"Godot C# build",
|
"Godot C# build",
|
||||||
("dotnet", "build", "godot/Himegari.csproj", "--nologo", "--verbosity", "minimal"),
|
("dotnet", "build", "godot/OME.csproj", "--nologo", "--verbosity", "minimal"),
|
||||||
300,
|
300,
|
||||||
),
|
),
|
||||||
Gate(
|
Gate(
|
||||||
|
|||||||
Reference in New Issue
Block a user