mirror of
https://github.com/OrcaSlicer/OrcaSlicer.git
synced 2026-09-27 10:51:22 +00:00
feat: add CI to generate OPC for OTA workflow (#15624)
# Description Adds the CI half of the profile OTA pipeline: a push-triggered workflow that rebuilds a vendor's binary preset cache (`<vendor>.opc`) whenever its profile changes on `main` / `release/*`, and publishes it as a versioned release asset for OrcaCloud's OTA Manager to pick up. ### `.github/workflows/post_merge_profiles.yml` (new) Push-triggered counterpart to `check_profiles.yml` (which only gates PRs): - Diffs the push to find which vendors under `resources/profiles/**` changed. - Reads the Orca version from `version.inc` and each vendor's 4-part `version` from `resources/profiles/<vendor>.json` (fails the run if it isn't `A.B.C.D`). - Downloads the prebuilt `generate_system_cache` from this repo's `nightly-builds` release and builds one `<vendor>.opc` per changed vendor. - Packages each as `<orca_ver>_<vendor>_<profile_version>_<UTCyyyymmddHHMM>.zip` (zip root `<vendor>.opc`) — the asset-name contract OrcaCloud's release scanner expects. - Uploads them to a per-Orca-version release on the profiles repo via a scoped GitHub App token. It stops there: no changelog, no R2, no OTA webhook — a maintainer still publishes from the OTA Manager. Job is guarded to `OrcaSlicer/OrcaSlicer`; workflow permissions are `contents: read` (the cross-repo write uses the App token only). ### `.github/workflows/build_orca.yml` Two steps on the Linux leg: upload `generate_system_cache` as a CI artifact, and (on `main`) deploy it to the `nightly-builds` release as `generate_system_cache_Linux_Ubuntu2404_nightly` so the workflow above has a tool to download. `.opc` is 64-bit little-endian and platform-independent, so only the Linux binary is shipped. ### `src/dev-utils/generate_system_cache.cpp` New `-v` / `--vendor` option to generate the cache for a single vendor (plus the always-loaded Orca filament library) instead of all vendors, and an error if the named vendor produced no `.opc` (catches typos). Reuses `PresetBundle::set_vendor_to_validate()` from #14217. ## Operational prerequisites - Repo secrets `PROFILES_APP_ID` / `PROFILES_APP_PRIVATE_KEY` for a GitHub App with `contents: write` on the target profiles repo. - `env.PROFILES_OWNER` / `env.PROFILES_REPO` in `post_merge_profiles.yml` must point at the production profiles repo OrcaCloud reads. - `generate_system_cache_Linux_Ubuntu2404_nightly` only appears after the first post-merge nightly `build_orca` run; a profile-only push before then fails at the download step. ## Screenshots/Recordings/Graphs n/a — CI only. ## Tests Exercised end-to-end in a staging environment: per-vendor `.opc` zips published in the expected `<orca_ver>_<vendor>_<profile_version>_<timestamp>.zip` layout, and `generate_system_cache -v <vendor>` confirmed to emit only that vendor's `.opc`. [How to Download Pull Requests Artifacts for Testing](https://www.orcaslicer.com/wiki/how_to_download_pr_artifacts)
This commit is contained in:
@@ -23,7 +23,8 @@ int main(int argc, char* argv[])
|
||||
#else
|
||||
("path,p", po::value<std::string>()->default_value("../../../resources/profiles"), "Path to profiles directory")
|
||||
#endif
|
||||
("log_level,l", po::value<int>()->default_value(2), "Log level (0=trace, 2=info, 4=error)");
|
||||
("log_level,l", po::value<int>()->default_value(2), "Log level (0=trace, 2=info, 4=error)")
|
||||
("vendor,v", po::value<std::string>()->default_value(""), "Vendor name. Optional; generate the cache for this vendor only (the Orca filament library is always included as the inheritance base). All vendors if not specified.");
|
||||
// clang-format on
|
||||
|
||||
po::variables_map vm;
|
||||
@@ -38,6 +39,7 @@ int main(int argc, char* argv[])
|
||||
|
||||
const std::string profiles_path = vm["path"].as<std::string>();
|
||||
const int log_level = vm["log_level"].as<int>();
|
||||
const std::string vendor = vm["vendor"].as<std::string>();
|
||||
|
||||
if (!fs::exists(profiles_path) || !fs::is_directory(profiles_path)) {
|
||||
std::cerr << "Error: '" << profiles_path << "' is not a valid directory\n";
|
||||
@@ -59,8 +61,12 @@ int main(int argc, char* argv[])
|
||||
preset_bundle->set_is_validation_mode(true);
|
||||
preset_bundle->set_default_suppressed(true);
|
||||
preset_bundle->set_generate_vendor_caches(true);
|
||||
// Empty == every vendor. Otherwise only this vendor (plus the always-loaded
|
||||
// Orca filament library) is parsed, so only its <vendor>.opc is written.
|
||||
preset_bundle->set_vendor_to_validate(vendor);
|
||||
|
||||
std::cout << "Loading system presets from: " << profiles_path << "\n";
|
||||
std::cout << "Loading system presets from: " << profiles_path
|
||||
<< (vendor.empty() ? "" : " (vendor: " + vendor + ")") << "\n";
|
||||
|
||||
try {
|
||||
// In validation mode data_dir() is the profiles directory set above, so the
|
||||
@@ -71,6 +77,14 @@ int main(int argc, char* argv[])
|
||||
return 1;
|
||||
}
|
||||
|
||||
// A specific vendor must have produced its own cache; the always-loaded
|
||||
// filament library alone would otherwise mask a misspelt or removed name.
|
||||
if (!vendor.empty() && !fs::exists(fs::path(profiles_path) / (vendor + ".opc"))) {
|
||||
std::cerr << "No cache was generated for vendor '" << vendor << "' under " << profiles_path
|
||||
<< " - check the vendor name.\n";
|
||||
return 1;
|
||||
}
|
||||
|
||||
size_t cache_count = 0;
|
||||
for (auto& entry : fs::directory_iterator(profiles_path))
|
||||
if (boost::iends_with(entry.path().string(), ".opc"))
|
||||
|
||||
Reference in New Issue
Block a user