Skip to content

bug: openshell.spec %build does not compile OpenShell from source #4244

Closed

Description

@politerealism

Part of: #3510

User Story

I'm investigating Fedora packaging for OpenShell (see #3510) and need the
root openshell.spec's %build section to actually compile OpenShell from
source, so the package can build in Koji's network-isolated mock chroot
instead of depending on externally prebuilt binaries.

Problem Statement

openshell.spec's %build section does not build anything. It only asserts
that prebuilt binaries already exist:

%build
test -x "${OPENSHELL_PREBUILT_BINARIES_DIR}/openshell"
test -x "${OPENSHELL_PREBUILT_BINARIES_DIR}/openshell-gateway"
test -x "${OPENSHELL_PREBUILT_BINARIES_DIR}/openshell-prover"

%install then copies those binaries from $OPENSHELL_PREBUILT_BINARIES_DIR
into the build root. Compilation happens entirely outside the spec, in
whatever external CI step populates that directory. %prep does correctly
vendor dependencies (%cargo_prep -v vendor) and patch the workspace version,
so the groundwork for a real build is already there — %build just never
invokes cargo build.

Impact / Why This Matters

This is disqualifying for Fedora: Koji builds run in a mock chroot with no
network access after %prep, and cannot consume an externally built artifact
the way $OPENSHELL_PREBUILT_BINARIES_DIR requires. The current workaround
(populate that directory from an external CI pipeline before invoking
rpmbuild) has no Fedora equivalent and blocks every other item in #3510 —
there's no point auditing licenses or bundling policy for a spec that can't
pass Fedora's own build requirement.

A working internal reference exists: Red Hat's internal RHEL9 spec (Brew task
72003056, maintained by Robby Callicotte) runs real
cargo build --release --offline --locked --target <triple> --package <pkg>
invocations per binary — static-PIE for CLI/supervisor/sandbox
(RUSTFLAGS="-C target-feature=+crt-static", BuildRequires: glibc-static,
%undefine _auto_set_build_flags so redhat-rpm-config's hardened LDFLAGS
don't break the static link), dynamic linking for the gateway. This is a
usable template regardless of the one-spec-vs-two-spec question still open
on #3510.

Acceptance Criteria

  • %build runs cargo build --release --offline --locked for
    openshell, openshell-gateway, and openshell-prover against the
    %cargo_prep-vendored sources
  • Builds successfully in a mock chroot with networking disabled
  • No remaining dependency on OPENSHELL_PREBUILT_BINARIES_DIR or any
    externally populated build artifact
  • %global debug_package %{nil} is either resolved (debuginfo generated
    properly) or explicitly justified in a spec comment — this is a known
    Fedora review flag reviewers ask about directly

Reproduction Steps

  1. Check out openshell.spec at the repo root without setting
    OPENSHELL_PREBUILT_BINARIES_DIR or pre-populating it with built binaries.
  2. Run rpmbuild -ba openshell.spec (or an equivalent mock build) with
    networking disabled after %prep.
  3. Observe %build fails at the first test -x assertion — no compilation
    is attempted, and there is no path to produce the binaries %install
    expects without an external, network-dependent build step.

Environment

Suggested UX

Not user-facing — this is a packaging/build-system change. Notional %build
shape (CLI/supervisor/sandbox static-PIE, gateway dynamic), following the
internal RHEL9 spec's approach:

%build
export RUSTFLAGS="-C target-feature=+crt-static"
cargo build --release --offline --locked --target %{rust_target} --package openshell
cargo build --release --offline --locked --target %{rust_target} --package openshell-prover
unset RUSTFLAGS
cargo build --release --offline --locked --package openshell-gateway

Logs

N/A — the failure is a missing build step, not a captured error.

Activity

  1. politerealism commented on Oct 6, 2026

    @politerealism
    ContributorAuthor

    @andre-motta flagged a real risk worth calling out explicitly here: if the %build fix for this issue is designed and maintained only in an out-of-tree/downstream spec rather than landing in this repo's own openshell.spec, packaging changes there could diverge from what upstream expects without anyone here noticing — especially since hermetic, fully-vendored builds are already easy to get subtly wrong. A silent divergence would mean breaking changes to how OpenShell actually builds could ship without this repo's own CI or reviewers ever seeing them.

    Whoever picks this up: the fix should land in this repo's openshell.spec directly (or a Fedora-targeted sibling spec per the open one-spec-vs-two-spec question above), not only in a separate downstream copy — so build correctness stays visible and testable upstream.

  2. politerealism commented on Oct 6, 2026

    @politerealism
    ContributorAuthor

    Follow-up from the same thread:

    Andre's proposed resolution to the divergence risk above: run the out-of-tree/internal CI build as its own thing, but keep the actual spec changes living in this repo. A bot/hook watches for changes to the relevant files upstream and triggers an out-of-tree build when they change — so normal upstream CI isn't slowed down, but the out-of-tree build can't silently drift from what's actually in this repo.

    Clarification on why %build is prebuilt-binary today: this is by design, not an oversight — it avoids compiling OpenShell twice in the existing pipeline (once for normal release artifacts, again for the RPM). The implication for this issue: the fix likely isn't converting this spec to build from source in place (which would reintroduce that double-build cost), but standing up the separate Fedora-targeted from-source spec per the still-open one-spec-vs-two-spec question on #3510, with this spec staying prebuilt-binary for its existing purpose. Worth settling that question before implementing a fix here.

  3. olivercalder commented on Oct 6, 2026

    @olivercalder
    Contributor

    My quick two cents:

    1. I wouldn't expect to be able to use the upstream OpenShell repo's RPM build spec to build the RPM for Fedora. Distro packaging for repositories is almost always different from building a package directly from the upstream. So it seems reasonable to me to have a different RPM packaging spec for upstream OpenShell, one for the Fedora repos, probably a different one for RHEL/Rocky/Alma, one for OpenSuse, etc.
    2. Ignoring my thoughts on (1), think it would be reasonable for the upstream OpenShell project to have two separate RPM packaging specs and jobs: for each PR, build the RPM using the prebuilt binaries from CI and do the usual smoke testing, then when a prerelease or proper release is cut, trigger a separate CI workflow which builds the "real" RPM from source intended for the Fedora repos, and does more rigorous testing of it.
      1. This would be useful for other packaging formats like the snap as well, where latest/edge would be built from prebuilt binaries and published after each merge to master, and whenever a prerelease is tagged, that would build from source and publish to the latest/beta or latest/candidate channel, and then when a proper release is cut, it would use that same snapcraft.yaml to build from source and publish to the latest/stable channel. Though for the snap building from source doesn't matter as much, we just prefer it for reproducibility and to be able to build the package locally and in network-restricted environments like Launchpad builders.
  4. politerealism commented on Oct 7, 2026

    @politerealism
    ContributorAuthor

    @olivercalder I like how you thought about that. The reason I created an issue and brought it up was for the idea that this will be repeatable hopefully. So when you mention other packaging formats, it makes sense to make this a bit less arduous. The way you laid it out might work.. what are your thoughts @SDAChess ?

  5. olivercalder commented on Oct 7, 2026

    @olivercalder
    Contributor

    For some more context, the snap originally built binaries directly, and only later switched to consuming prebuilt binaries from CI. The reverse of this change is probably something like what you need for the Fedora RPM packaging. Here's the PR which made that change: #1651

    Bear in mind that things have likely changed since then. For example, there's a separate prover binary now, and the zig/z3 configuration stuff may have changed. AFAIK the snap didn't originally build for musl or use the special zig stuff which is (was?) part of the binary build process in CI. If you're building from source though it's probably okay to avoid some of that complexity and just build the binaries directly, like the snap used to, since you know your target is Fedora, which has compatible glibc, etc.

  6. olivercalder commented on Oct 7, 2026

    @olivercalder
    Contributor

    Oh, one more thing: another benefit of building from source is that it's easier to build for other architectures (e.g. arm64, riscv64, s390x, powerpc/ppc64el). For snaps, we can use launchpad remote builders to build snaps for all architectures we support. I'm not sure what the build systems are for Fedora (the page mentions "koji"?) but it seems the builds at least must succeed on amd64 and arm64, with those other architectures I listed as alternatives which should be supported as well: https://fedoraproject.org/wiki/Architectures#Primary_Architectures So worth ensuring the package can be built on all those architectures as well.

  7. politerealism commented on Oct 8, 2026

    @politerealism
    ContributorAuthor

    Resolving this: We will separate Fedora targeted spec maintained out of tree per @olivercalder 's point that distro packaging is normally separate fro upstream builds tooling anyway. Plus input from @SDAChess that we would want to build out the RPM first then revisit.

  8. olivercalder commented on Oct 8, 2026

    @olivercalder
    Contributor

    As discussed with @politerealism offline, I think it's important that distro packaging for officially supported distros such as Fedora, Ubuntu, ... remain officially maintained and tested just like other supported platforms. Whether that's in the core repo vs in another repo within the official org doesn't matter that much, the challenge is keeping build flags and dependencies, rust toolchain versions, etc. synchronized across all the relevant repos, which is harder than if they're all in one repo.

    IMO if the reason to do so is just CI times, then I would focus on reducing the complexity of CI and trying to speed it up, rather than splitting up the repo to compensate. For example:

    • Cache as much as possible toolchains, dependencies, build/test tooling, container/VM images within a given CI run
    • If nested tooling (nix, mise, ...) causes things to be re-fetched multiple times, try to find a way to avoid doing so
    • Allow jobs to run in parallel (e.g. if package builds don't require prebuilt binaries, start the package builds from source alongside the jobs to build the prebuilt binaries)

    I see stronger reason for the qualification CI for releases to live in a separate repo, as that can pin a particular commit/tag/release from the core repo and then do qualification there. But for packaging, things need to change in lockstep as dependencies/toolchains and the shape of the application changes. If distro packages are only built/tested for pre-release and releases... releases, then perhaps this is okay. But if we want regular testing of official packaging for distros as development happens (I think we do, perhaps not on every PR but maybe nightly instead, with ability to trigger it for relevant PRs which e.g. touch packaging), having distro packaging in the core repo would I think make it much easier to keep everything in sync.

    CC @SDAChess, this is just my opinion, hopefully it's helpful, I'm happy to discuss more of course if you'd like.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    state:triage-neededOpened without agent diagnostics and needs triage

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions