ci(release): publish Conan binaries for Linux, macOS, and Windows#108
Merged
Conversation
The release job ran only on ubuntu-22.04, so Cloudsmith carried a single Linux/gcc binary. macOS and Windows consumers therefore had to build plotjuggler_core from source via --build=missing — slow, and on macOS brittle: from-source builds depend on the recipe's exported sources being intact in the cache, which breaks (e.g. after a version is re-published under a new recipe revision) with "exports_sources but sources not found in local cache". Restructure into prepare -> build (matrix) -> github-release: - prepare resolves the version/tag once and verifies it matches conanfile.py - build fans out over [ubuntu-22.04, macos-15-intel, windows-latest], each running conan create + conan upload with the same Release/cppstd=20 settings consumers use, so the published package_id matches downstream - github-release cuts the GitHub Release once, gated on all platforms With a binary per platform, downstream macOS/Windows CI downloads instead of compiling, eliminating the from-source fragility entirely. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Add a prepare-job guard that refuses to publish plotjuggler_core/<version> when it is already on Cloudsmith under a *different* recipe revision — the exact footgun that broke macOS CI (v0.5.0 was published twice from two different commits, replacing the recipe revision mid-resolve). It compares the recipe revision this release would publish against the remote: - not published -> proceed (first release) - same revision present -> proceed (idempotent re-run after a partial upload) - a different revision -> fail Override with the workflow_dispatch `allow_republish` input to repair a botched release. Also force an LF checkout in the build matrix: with no .gitattributes, Windows would otherwise check out CRLF and compute a different recipe revision than Linux/macOS, splitting one version across two revisions and defeating the matrix. LF everywhere keeps the revision identical across all legs and matching the one the guard validates on Linux. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Problem
The
Releaseworkflow ran on a singleubuntu-22.04job, so Cloudsmith only ever received a Linux/gcc binary ofplotjuggler_core. macOS and Windows consumers were therefore forced to build core from source via--build=missing.That is slow, and on macOS it is brittle: a from-source build depends on the recipe's exported sources being intact in the local cache. After a version is re-published under a new recipe revision (or a cache is restored from a superseded one), the build dies with:
This is exactly what broke the downstream pj-official-plugins macOS CI on
main. (Earlier, pre-fast_float, the from-source macOS build also failed to compile because libc++ lacksstd::from_charsfor floating-point — now fixed innumber_parse.hpp, but the from-source path remains an avoidable liability.)Fix
Restructure the workflow into three jobs:
prepare— resolve the version/tag once and verify it matchesconanfile.py(unchanged logic, now exposed as job outputs).build— matrix over[ubuntu-22.04, macos-15-intel, windows-latest], each runningconan create+conan uploadwith the same-s build_type=Release -s compiler.cppstd=20settings consumers use, so the publishedpackage_idmatches what downstreamconan installresolves on each platform.github-release— cut the GitHub Release once, gated on all platform binaries publishing successfully.With a binary per platform, downstream macOS/Windows CI downloads core instead of compiling it — eliminating the from-source fragility entirely (and speeding those jobs up).
Notes
fail-fast: falseso a flaky upload on one OS still publishes the others; re-run the failed leg viaworkflow_dispatch. The GitHub Release stays gated on every leg succeeding, so an incomplete release is never advertised.package_idmatching assumes the release runner and the consumer runner share a compiler version (e.g. bothmacos-15-intel). If a runner image bumps Xcode/MSVC between release and consumption, consumers harmlessly fall back to today's from-source behavior.Follow-up (not in this PR)
The original incident's trigger was a moved tag (
v0.5.0published twice from two different commits). This PR makes consumers robust to that, but does not prevent it. A guard inpreparethat refuses to publish over an existing-but-different recipe revision could be added separately — happy to include it if wanted.🤖 Generated with Claude Code