Compare commits

...

2 commits

Author SHA1 Message Date
Ana Hobden a8f56d609f Fixuip serde name 2023-06-26 12:43:54 -07:00
Ana Hobden 160347e788 Mac remote builder fix 2023-06-26 12:21:02 -07:00
4 changed files with 106 additions and 1 deletions

View file

@ -0,0 +1,97 @@
use std::path::{Path, PathBuf};
use tracing::{span, Span};
use crate::action::{
Action, ActionDescription, ActionError, ActionErrorKind, ActionTag, StatefulAction,
};
const NIX_STORE_SYMLINK_LOCATION: &str = "/usr/local/bin/nix-store";
const NIX_STORE_SYMLINK_TARGET: &str = "/nix/var/nix/profiles/default/bin/nix-store";
/**
Perform a remote builder fix for Mac which links `nix-store` into `/usr/local/bin`
*/
// Previously, the installer suggested users use a workaround: https://github.com/DeterminateSystems/nix-installer/blob/4bfd6c2547dab100cde1dbc60e3d623499ead2c4/README.md?plain=1#L377-L418
#[derive(Debug, serde::Deserialize, serde::Serialize, Clone)]
pub struct MacRemoteBuilderFix;
impl MacRemoteBuilderFix {
#[tracing::instrument(level = "debug", skip_all)]
pub async fn plan() -> Result<StatefulAction<Self>, ActionError> {
let nix_path = Path::new(NIX_STORE_SYMLINK_LOCATION);
if nix_path.exists() {
if !nix_path.is_symlink() {
return Err(Self::error(ActionErrorKind::PathWasNotSymlink(
nix_path.into(),
)));
}
let link_destination = std::fs::read_link(nix_path)
.map_err(|e| ActionErrorKind::ReadSymlink(nix_path.into(), e))
.map_err(Self::error)?;
if link_destination == Path::new("/nix/var/nix/profiles/default/bin/nix-store") {
return Ok(StatefulAction::completed(Self));
} else {
return Err(Self::error(ActionErrorKind::SymlinkExists(nix_path.into())));
}
}
Ok(StatefulAction::uncompleted(Self))
}
}
#[async_trait::async_trait]
#[typetag::serde(name = "mac_remote_builder_fix")]
impl Action for MacRemoteBuilderFix {
fn action_tag() -> ActionTag {
ActionTag("mac_remote_builder_fix")
}
fn tracing_synopsis(&self) -> String {
format!(
"Create symlink at `{NIX_STORE_SYMLINK_LOCATION}` to `{NIX_STORE_SYMLINK_TARGET}`",
)
}
fn tracing_span(&self) -> Span {
span!(tracing::Level::DEBUG, "mac_remote_builder_fix",)
}
fn execute_description(&self) -> Vec<ActionDescription> {
vec![ActionDescription::new(self.tracing_synopsis(), vec![
"In order to support acting as a remote builder (Mac populates the `PATH` environment differently than other environments)".to_string()
])]
}
#[tracing::instrument(level = "debug", skip_all)]
async fn execute(&mut self) -> Result<(), ActionError> {
tokio::fs::symlink(NIX_STORE_SYMLINK_TARGET, NIX_STORE_SYMLINK_LOCATION)
.await
.map_err(|e| {
ActionErrorKind::Symlink(
PathBuf::from(NIX_STORE_SYMLINK_LOCATION),
PathBuf::from(NIX_STORE_SYMLINK_TARGET),
e,
)
})
.map_err(Self::error)?;
Ok(())
}
fn revert_description(&self) -> Vec<ActionDescription> {
vec![ActionDescription::new(
format!("Remove symlink at `{NIX_STORE_SYMLINK_LOCATION}`",),
vec![],
)]
}
#[tracing::instrument(level = "debug", skip_all)]
async fn revert(&mut self) -> Result<(), ActionError> {
tokio::fs::remove_file(NIX_STORE_SYMLINK_LOCATION)
.await
.map_err(|e| ActionErrorKind::Remove(PathBuf::from(NIX_STORE_SYMLINK_LOCATION), e))
.map_err(Self::error)?;
Ok(())
}
}

View file

@ -10,6 +10,7 @@ pub(crate) mod create_volume_service;
pub(crate) mod enable_ownership; pub(crate) mod enable_ownership;
pub(crate) mod encrypt_apfs_volume; pub(crate) mod encrypt_apfs_volume;
pub(crate) mod kickstart_launchctl_service; pub(crate) mod kickstart_launchctl_service;
pub(crate) mod mac_remote_builder_fix;
pub(crate) mod set_tmutil_exclusion; pub(crate) mod set_tmutil_exclusion;
pub(crate) mod set_tmutil_exclusions; pub(crate) mod set_tmutil_exclusions;
pub(crate) mod unmount_apfs_volume; pub(crate) mod unmount_apfs_volume;
@ -22,6 +23,7 @@ pub use create_volume_service::CreateVolumeService;
pub use enable_ownership::{EnableOwnership, EnableOwnershipError}; pub use enable_ownership::{EnableOwnership, EnableOwnershipError};
pub use encrypt_apfs_volume::EncryptApfsVolume; pub use encrypt_apfs_volume::EncryptApfsVolume;
pub use kickstart_launchctl_service::KickstartLaunchctlService; pub use kickstart_launchctl_service::KickstartLaunchctlService;
pub use mac_remote_builder_fix::MacRemoteBuilderFix;
use serde::Deserialize; use serde::Deserialize;
pub use set_tmutil_exclusion::SetTmutilExclusion; pub use set_tmutil_exclusion::SetTmutilExclusion;
pub use set_tmutil_exclusions::SetTmutilExclusions; pub use set_tmutil_exclusions::SetTmutilExclusions;

View file

@ -409,6 +409,8 @@ pub enum ActionErrorKind {
PathModeMismatch(std::path::PathBuf, u32, u32), PathModeMismatch(std::path::PathBuf, u32, u32),
#[error("Path `{0}` exists, but is not a file, consider removing it with `rm {0}`")] #[error("Path `{0}` exists, but is not a file, consider removing it with `rm {0}`")]
PathWasNotFile(std::path::PathBuf), PathWasNotFile(std::path::PathBuf),
#[error("Path `{0}` exists, but is not a symlink, consider removing it with `rm {0}`")]
PathWasNotSymlink(std::path::PathBuf),
#[error("Path `{0}` exists, but is not a directory, consider removing it with `rm {0}`")] #[error("Path `{0}` exists, but is not a directory, consider removing it with `rm {0}`")]
PathWasNotDirectory(std::path::PathBuf), PathWasNotDirectory(std::path::PathBuf),
#[error("Getting metadata for {0}`")] #[error("Getting metadata for {0}`")]

View file

@ -10,7 +10,7 @@ use crate::{
action::{ action::{
base::RemoveDirectory, base::RemoveDirectory,
common::{ConfigureInitService, ConfigureNix, CreateUsersAndGroups, ProvisionNix}, common::{ConfigureInitService, ConfigureNix, CreateUsersAndGroups, ProvisionNix},
macos::{CreateNixVolume, SetTmutilExclusions}, macos::{CreateNixVolume, SetTmutilExclusions,MacRemoteBuilderFix},
StatefulAction, StatefulAction,
}, },
execute_command, execute_command,
@ -161,6 +161,10 @@ impl Planner for Macos {
.await .await
.map_err(PlannerError::Action)? .map_err(PlannerError::Action)?
.boxed(), .boxed(),
MacRemoteBuilderFix::plan()
.await
.map_err(PlannerError::Action)?
.boxed(),
RemoveDirectory::plan(crate::settings::SCRATCH_DIR) RemoveDirectory::plan(crate::settings::SCRATCH_DIR)
.await .await
.map_err(PlannerError::Action)? .map_err(PlannerError::Action)?