Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat: add build check to ManagedEnvironment::{push,push_new} #832

Merged
merged 10 commits into from
Jan 25, 2024
12 changes: 6 additions & 6 deletions Justfile
Original file line number Diff line number Diff line change
Expand Up @@ -34,20 +34,20 @@ cargo_test_invocation := "PKGDB_BIN=${PKGDB_BIN} cargo test --workspace"

# Build the compilation database
build-cdb:
@make -C pkgdb -j -s cdb
@make -C pkgdb -j 8 -s cdb

# Build only pkgdb
@build-pkgdb:
make -C pkgdb -j;
make -C pkgdb -j 8;

# Build pkgdb with debug symbols
@build-pkgdb-debug:
# Note that you need to clean pkgdb first
make -C pkgdb -j -s DEBUG=1
make -C pkgdb -j 8 -s DEBUG=1

# Clean the pkgdb build cache
@clean-pkgdb:
make -C pkgdb -j -s clean
make -C pkgdb -j 8 -s clean

# Build only flox
@build-cli: build-pkgdb
Expand All @@ -61,7 +61,7 @@ build: build-cli

# Run the pkgdb tests
@test-pkgdb: build-pkgdb
make -C pkgdb -j tests;
make -C pkgdb -j 8 tests;
make -C pkgdb check;

# Run the end-to-end test suite
Expand Down Expand Up @@ -94,7 +94,7 @@ build: build-cli
test-cli: impure-tests integ-tests functional-tests

# Run the entire test suite, including impure unit tests
test-all: test-pkgdb impure-tests integ-tests functional-tests
test-all: test-pkgdb impure-tests integ-tests functional-tests


# ---------------------------------------------------------------------------- #
Expand Down
36 changes: 29 additions & 7 deletions cli/flox-rust-sdk/src/models/environment/managed_environment.rs
Original file line number Diff line number Diff line change
Expand Up @@ -127,6 +127,9 @@ pub enum ManagedEnvironmentError {
#[error("could not link environment")]
Link(#[source] CoreEnvironmentError),

#[error("could not build environment")]
Build(#[source] CoreEnvironmentError),

#[error("could not read manifest")]
ReadManifest(#[source] GenerationsError),

Expand Down Expand Up @@ -877,8 +880,17 @@ impl ManagedEnvironment {
) -> Result<Self, ManagedEnvironmentError> {
// path of the original .flox directory
let dot_flox_path = path_environment.path.clone();
let path_pointer = path_environment.pointer.clone();
let name = path_environment.name();

let mut core_environment = path_environment.into_core_environment();

// Ensure the environment builds before we push it
core_environment
.build(flox)
.map_err(ManagedEnvironmentError::Build)?;

let pointer = ManagedPointer::new(owner, path_environment.name(), &flox.floxhub);
let pointer = ManagedPointer::new(owner, name, &flox.floxhub);

let checkedout_floxmeta_path = tempfile::tempdir_in(&flox.temp_dir).unwrap().into_path();
let temp_floxmeta_path = tempfile::tempdir_in(&flox.temp_dir).unwrap().into_path();
Expand All @@ -898,7 +910,7 @@ impl ManagedEnvironment {
checkedout_floxmeta_path,
temp_floxmeta_path,
remote_branch_name(&pointer),
&path_environment.pointer,
&path_pointer,
)
.map_err(ManagedEnvironmentError::InitializeFloxmeta)?;

Expand All @@ -909,10 +921,7 @@ impl ManagedEnvironment {
.map_err(ManagedEnvironmentError::CreateFloxmetaDir)?;

generations
.add_generation(
&mut path_environment.into_core_environment(),
"Add first generation".to_string(),
)
.add_generation(&mut core_environment, "Add first generation".to_string())
.map_err(ManagedEnvironmentError::CommitGeneration)?;

temp_floxmeta_git
Expand Down Expand Up @@ -949,10 +958,23 @@ impl ManagedEnvironment {
Ok(env)
}

pub fn push(&mut self, force: bool) -> Result<(), ManagedEnvironmentError> {
pub fn push(&mut self, flox: &Flox, force: bool) -> Result<(), ManagedEnvironmentError> {
let project_branch = branch_name(&self.pointer, &self.path);
let sync_branch = remote_branch_name(&self.pointer);

// Ensure the environment builds before we push it
// Usually we don't create generations unless they build,
// but that is not always the case.
// If a user pulls an environment that is broken on their system, we may
// create a "broken" generation.
// That generation could have a divergent manifest and lock,
// or it could fail to build.
// So we have to verify we don't have a "broken" generation before pushing.
{
let mut env = self.get_current_generation(flox)?;
env.build(flox).map_err(ManagedEnvironmentError::Build)?;
}

// Fetch the remote branch into sync branch
self.floxmeta
.git
Expand Down
10 changes: 5 additions & 5 deletions cli/flox-rust-sdk/src/models/environment/remote_environment.rs
Original file line number Diff line number Diff line change
Expand Up @@ -133,7 +133,7 @@ impl Environment for RemoteEnvironment {
) -> Result<InstallationAttempt, EnvironmentError2> {
let result = self.inner.install(packages, flox)?;
self.inner
.push(false)
.push(flox, false)
.map_err(RemoteEnvironmentError::UpdateUpstream)?;
// TODO: clean up git branch for temporary environment
Ok(result)
Expand All @@ -147,7 +147,7 @@ impl Environment for RemoteEnvironment {
) -> Result<String, EnvironmentError2> {
let result = self.inner.uninstall(packages, flox)?;
self.inner
.push(false)
.push(flox, false)
.map_err(RemoteEnvironmentError::UpdateUpstream)?;
Ok(result)
}
Expand All @@ -159,7 +159,7 @@ impl Environment for RemoteEnvironment {
return Ok(result);
}
self.inner
.push(false)
.push(flox, false)
.map_err(RemoteEnvironmentError::UpdateUpstream)?;
Ok(result)
}
Expand All @@ -172,7 +172,7 @@ impl Environment for RemoteEnvironment {
) -> Result<UpdateResult, EnvironmentError2> {
let result = self.inner.update(flox, inputs)?;
self.inner
.push(false)
.push(flox, false)
.map_err(RemoteEnvironmentError::UpdateUpstream)?;
Ok(result)
}
Expand All @@ -185,7 +185,7 @@ impl Environment for RemoteEnvironment {
) -> Result<UpgradeResult, EnvironmentError2> {
let result = self.inner.upgrade(flox, groups_or_iids)?;
self.inner
.push(false)
.push(flox, false)
.map_err(RemoteEnvironmentError::UpdateUpstream)?;
Ok(result)
}
Expand Down
20 changes: 19 additions & 1 deletion cli/flox/src/commands/environment.rs
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
use std::borrow::Cow;
use std::error::Error;
use std::fmt::Display;
use std::fs::{self, File};
use std::io::{stdin, stdout, Write};
Expand Down Expand Up @@ -1131,7 +1132,7 @@ impl Push {
) -> Result<()> {
let mut env = ManagedEnvironment::open(flox, managed_pointer.clone(), dir.join(DOT_FLOX))
.context("Could not open environment")?;
env.push(force)
env.push(flox, force)
.map_err(|err| Self::convert_error(err, managed_pointer, false))?;

Ok(())
Expand Down Expand Up @@ -1165,6 +1166,15 @@ impl Push {
let owner = &pointer.owner;
let name = &pointer.name;

fn error_chain(mut e: &dyn Error) -> String {
let mut msg = e.to_string();
while let Some(source) = e.source() {
e = source;
msg.push_str(&format!(": {}", e));
}
msg
}

let message = match err {
ManagedEnvironmentError::AccessDenied => formatdoc! {"
❌ You do not have permission to write to {owner}/{name}
Expand All @@ -1175,6 +1185,14 @@ impl Push {
To rename your environment: 'flox edit --name <new name>'
To pull and manually re-apply your changes: 'flox delete && flox pull -r {owner}/{name}'
"}.into(),
ManagedEnvironmentError::Build(ref err) => formatdoc! {"
{err}
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The actual error still isn't getting printed:

ERROR: ❌  Unable to push environment with compatibility errors on your system (aarch64-darwin).

    could not build environment

    Use 'flox edit' to resolve errors, test with 'flox activate', and 'flox push' again.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Well it is just not the helpful bits...
Fixing this tomorrow
Just wondering if we should display the entire chain or not just the root cause (esp. for these pkgdb ones).
Leaning towards the latter

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I bet we'll come back and change it anyways when we rework errors, so either's probably fine for now


❌ Unable to push environment with build errors.

Use 'flox edit' to resolve errors, test with 'flox activate', and 'flox push' again.",
err = error_chain(err)
}.into(),
_ => None
};

Expand Down
9 changes: 7 additions & 2 deletions cli/flox/src/utils/openers.rs
Original file line number Diff line number Diff line change
Expand Up @@ -34,7 +34,12 @@ impl Browser {
"linux" => {
let path_var =
env::var("PATH").map_err(|_| "Could not read PATH variable".to_string())?;
let Some((path, _)) = first_in_path([OPENERS, BROWSER_OPENERS].concat(), env::split_paths(&path_var)) else { return Err("No opener found in PATH".to_string()) };
let Some((path, _)) = first_in_path(
[OPENERS, BROWSER_OPENERS].concat(),
env::split_paths(&path_var),
) else {
return Err("No opener found in PATH".to_string());
};
Self(path)
},
"macos" => Self(PathBuf::from("/usr/bin/open")),
Expand Down Expand Up @@ -75,6 +80,6 @@ where
I::IntoIter: Clone,
{
path.into_iter()
.cartesian_product(candidates.into_iter())
.cartesian_product(candidates)
.find(|(path, editor)| path.join(editor).exists())
}
1 change: 1 addition & 0 deletions cli/tests/environment-managed.bats
Original file line number Diff line number Diff line change
Expand Up @@ -319,6 +319,7 @@ EOF
}

@test "sanity check upgrade works for managed environments" {
_PKGDB_GA_REGISTRY_REF_OR_REV="${PKGDB_NIXPKGS_REV_OLD?}" \
make_empty_remote_env

_PKGDB_GA_REGISTRY_REF_OR_REV="${PKGDB_NIXPKGS_REV_OLD?}" \
Expand Down
24 changes: 24 additions & 0 deletions cli/tests/environment-push.bats
Original file line number Diff line number Diff line change
Expand Up @@ -180,3 +180,27 @@ function update_dummy_env() {
assert_line "emacs"
popd > /dev/null || return
}

# bats test_tags=push:broken
@test "push: broken: if you attempt to flox push an environment that fails to build then the push should fail with a message." {
make_dummy_floxmeta "owner"

run "$FLOX_BIN" init

init_system=
# replace linux with darwin or darwin with linux
if [ -z "${NIX_SYSTEM##*-linux}" ]; then
init_system="${NIX_SYSTEM%%-linux}-darwin"
elif [ -z "${NIX_SYSTEM#*-darwin}" ]; then
init_system="${NIX_SYSTEM%%-darwin}-linux"
else
echo "unknown system: '$NIX_SYSTEM'"
exit 1
fi

tomlq --in-place -t ".options.systems=[\"$init_system\"]" .flox/env/manifest.toml

run "$FLOX_BIN" push --owner owner # dummy owner
assert_failure
assert_output --partial "Unable to push environment with build errors:"
mkenigs marked this conversation as resolved.
Show resolved Hide resolved
}
1 change: 1 addition & 0 deletions cli/tests/environment-remote.bats
Original file line number Diff line number Diff line change
Expand Up @@ -222,6 +222,7 @@ EOF
# ---------------------------------------------------------------------------- #

@test "sanity check upgrade works for remote environments" {
_PKGDB_GA_REGISTRY_REF_OR_REV="${PKGDB_NIXPKGS_REV_OLD?}" \
make_empty_remote_env

_PKGDB_GA_REGISTRY_REF_OR_REV="${PKGDB_NIXPKGS_REV_OLD?}" \
Expand Down
Loading