Skip to content

Commit 24ae367

Browse files
flatpak: Add explicit package-fallback opt-in for sandboxed source builds
The Flatpak sandbox compiles a full repository checkout but has no Pkl, so build.rs saw canonical sources present and demanded a SCE_CLI_GENERATED_INPUT_DIR handoff that the sandbox cannot produce. The staged cli/package-fallback payload was present but unreachable on that path. build.rs now honors SCE_CLI_PACKAGE_FALLBACK as an explicit opt-in that selects the packaged fallback even when repository sources exist. The value is parsed strictly ('1'/'true' vs '0'/'false'/empty) and anything else fails the build, so a stray environment value cannot silently downgrade a repository build. The missing-handoff error now names the opt-in as the sandboxed alternative. The Flatpak module sets the variable in build-options.env, and static-validate.sh asserts it alongside the existing fallback source entries so the manifest cannot regress to the unbuildable state. Co-authored-by: SCE <sce@crocoder.dev>
1 parent 0174112 commit 24ae367

8 files changed

Lines changed: 62 additions & 11 deletions

File tree

cli/build.rs

Lines changed: 52 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,7 @@ const PKL_OUTPUT_DIR: &str = "pkl-generated";
1212
const STATIC_OUTPUT_DIR: &str = "static";
1313
const MIGRATIONS_ROOT: &str = "migrations";
1414
const GENERATED_INPUT_ENV: &str = "SCE_CLI_GENERATED_INPUT_DIR";
15+
const PACKAGE_FALLBACK_ENV: &str = "SCE_CLI_PACKAGE_FALLBACK";
1516
const GENERATED_INPUT_INVENTORY: &str = "SHA256SUMS";
1617
const CANONICAL_INPUT_INVENTORY: &str = "INPUTS.SHA256SUMS";
1718
const PACKAGE_FALLBACK_DIR: &str = "package-fallback";
@@ -69,9 +70,17 @@ fn prepare_build_artifacts() -> io::Result<()> {
6970

7071
if repository_sources_available(repository_root) {
7172
println!("cargo:rerun-if-env-changed={GENERATED_INPUT_ENV}");
72-
let generated_input_root = generated_input_root(env::var_os(GENERATED_INPUT_ENV))?;
73-
stage_generated_input(repository_root, &generated_input_root, &out_dir)?;
74-
stage_static_inputs(repository_root, &manifest_dir, &out_dir)?;
73+
println!("cargo:rerun-if-env-changed={PACKAGE_FALLBACK_ENV}");
74+
// Sandboxed source builds (Flatpak) compile a full repository checkout
75+
// without Pkl, so they stage the packaging fallback and opt into it
76+
// explicitly. Every other repository build must supply the handoff.
77+
if package_fallback_requested(env::var_os(PACKAGE_FALLBACK_ENV))? {
78+
stage_packaged_fallback(&manifest_dir, &out_dir)?;
79+
} else {
80+
let generated_input_root = generated_input_root(env::var_os(GENERATED_INPUT_ENV))?;
81+
stage_generated_input(repository_root, &generated_input_root, &out_dir)?;
82+
stage_static_inputs(repository_root, &manifest_dir, &out_dir)?;
83+
}
7584
} else {
7685
stage_packaged_fallback(&manifest_dir, &out_dir)?;
7786
}
@@ -86,10 +95,26 @@ fn repository_sources_available(repository_root: &Path) -> bool {
8695
&& repository_root.join("config/lib").is_dir()
8796
}
8897

98+
fn package_fallback_requested(value: Option<OsString>) -> io::Result<bool> {
99+
let Some(value) = value else {
100+
return Ok(false);
101+
};
102+
let value = value
103+
.to_str()
104+
.ok_or_else(|| invalid_data(&format!("{PACKAGE_FALLBACK_ENV} must be valid UTF-8")))?;
105+
match value.trim().to_ascii_lowercase().as_str() {
106+
"" | "0" | "false" => Ok(false),
107+
"1" | "true" => Ok(true),
108+
other => Err(invalid_data(&format!(
109+
"{PACKAGE_FALLBACK_ENV} must be '1', 'true', '0', or 'false'; got '{other}'"
110+
))),
111+
}
112+
}
113+
89114
fn generated_input_root(value: Option<OsString>) -> io::Result<PathBuf> {
90115
let value = value.ok_or_else(|| {
91116
invalid_data(&format!(
92-
"repository builds require a pre-generated Pkl payload. Set {GENERATED_INPUT_ENV} to a generated-input directory containing {PKL_OUTPUT_DIR}/, {GENERATED_INPUT_INVENTORY}, and {CANONICAL_INPUT_INVENTORY}"
117+
"repository builds require a pre-generated Pkl payload. Set {GENERATED_INPUT_ENV} to a generated-input directory containing {PKL_OUTPUT_DIR}/, {GENERATED_INPUT_INVENTORY}, and {CANONICAL_INPUT_INVENTORY}, or set {PACKAGE_FALLBACK_ENV}=1 for Pkl-free sandboxed source builds that stage {PACKAGE_FALLBACK_DIR}/"
93118
))
94119
})?;
95120
if value.is_empty() {
@@ -740,9 +765,9 @@ mod tests {
740765
};
741766

742767
use super::{
743-
generated_input_root, inventory_for_paths, stage_generated_input,
744-
CANONICAL_GENERATOR_INPUTS, CANONICAL_INPUT_INVENTORY, GENERATED_INPUT_INVENTORY,
745-
PKL_OUTPUT_DIR,
768+
generated_input_root, inventory_for_paths, package_fallback_requested,
769+
stage_generated_input, CANONICAL_GENERATOR_INPUTS, CANONICAL_INPUT_INVENTORY,
770+
GENERATED_INPUT_INVENTORY, PKL_OUTPUT_DIR,
746771
};
747772

748773
static NEXT_TEMP_ID: AtomicU64 = AtomicU64::new(0);
@@ -839,9 +864,29 @@ mod tests {
839864
assert!(error
840865
.to_string()
841866
.contains("repository builds require a pre-generated Pkl payload"));
867+
assert!(error.to_string().contains("SCE_CLI_PACKAGE_FALLBACK=1"));
842868
assert!(generated_input_root(Some(OsString::from(""))).is_err());
843869
}
844870

871+
#[test]
872+
fn package_fallback_opt_in_is_explicit() {
873+
assert!(!package_fallback_requested(None).expect("absent value is not an opt-in"));
874+
for unset in ["", "0", "false", "FALSE"] {
875+
assert!(!package_fallback_requested(Some(OsString::from(unset)))
876+
.expect("negative value is not an opt-in"));
877+
}
878+
for set in ["1", "true", "True"] {
879+
assert!(package_fallback_requested(Some(OsString::from(set)))
880+
.expect("positive value is an opt-in"));
881+
}
882+
883+
let error = package_fallback_requested(Some(OsString::from("yes")))
884+
.expect_err("unrecognized value must fail");
885+
assert!(error
886+
.to_string()
887+
.contains("SCE_CLI_PACKAGE_FALLBACK must be"));
888+
}
889+
845890
#[test]
846891
fn missing_generated_input_directory_is_rejected() {
847892
let temp = TempDir::new("missing-handoff");

context/architecture.md

Lines changed: 1 addition & 1 deletion
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

context/glossary.md

Lines changed: 1 addition & 1 deletion
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

context/patterns.md

Lines changed: 1 addition & 1 deletion
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

context/sce/flatpak-distribution-patterns.md

Lines changed: 1 addition & 1 deletion
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

nix/flatpak/manifest.nix

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -49,6 +49,10 @@ let
4949
build-args = [ "--share=network" ];
5050
env = {
5151
CARGO_HOME = "/run/build/sce/cargo";
52+
# The sandbox compiles a full repository checkout without Pkl, so
53+
# build.rs must consume the staged cli/package-fallback payload
54+
# instead of demanding a pre-generated handoff directory.
55+
SCE_CLI_PACKAGE_FALLBACK = "1";
5256
};
5357
};
5458
build-commands = [

nix/flatpak/static-validate.sh

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -60,6 +60,7 @@ require_contains "command: sce" "manifest command is not sce"
6060
require_contains "org.freedesktop.Sdk.Extension.rust-stable" "Rust SDK extension is missing"
6161
require_contains "path: cli-package-fallback" "ephemeral package-fallback source is missing"
6262
require_contains "dest: cli/package-fallback" "package-fallback source destination is missing"
63+
require_contains "SCE_CLI_PACKAGE_FALLBACK" "package-fallback build-mode opt-in is missing"
6364
require_contains "cargo --offline build --release --manifest-path cli/Cargo.toml --bin sce" "offline Cargo source-build command is missing"
6465

6566
if [[ "$manifest" == *"prepare-cli-generated-assets.sh"* ]]; then

packaging/flatpak/dev.crocoder.sce.yml

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,7 @@ modules:
1717
- --share=network
1818
env:
1919
CARGO_HOME: /run/build/sce/cargo
20+
SCE_CLI_PACKAGE_FALLBACK: '1'
2021
buildsystem: simple
2122
name: sce
2223
sources:

0 commit comments

Comments
 (0)