fix ios codesign on device (#4339)
* fix ios codesign on device * switch to tmpfile
This commit is contained in:
1 parent
ac9b1fc519
commit
7d24a47c22
1 file changed
+38
-48
@@ -513,7 +513,14 @@ impl AppBuilder {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
Platform::Ios => self.open_ios_sim(envs).await?,
|
Platform::Ios => {
|
||||||
|
if self.build.device {
|
||||||
|
self.codesign_ios().await?;
|
||||||
|
self.open_ios_device().await?
|
||||||
|
} else {
|
||||||
|
self.open_ios_sim(envs).await?
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
Platform::Android => {
|
Platform::Android => {
|
||||||
self.open_android_sim(false, devserver_ip, envs).await?;
|
self.open_android_sim(false, devserver_ip, envs).await?;
|
||||||
@@ -853,54 +860,35 @@ impl AppBuilder {
|
|||||||
///
|
///
|
||||||
/// Converting these commands shouldn't be too hard, but device support would imply we need
|
/// Converting these commands shouldn't be too hard, but device support would imply we need
|
||||||
/// better support for codesigning and entitlements.
|
/// better support for codesigning and entitlements.
|
||||||
#[allow(unused)]
|
|
||||||
async fn open_ios_device(&self) -> Result<()> {
|
async fn open_ios_device(&self) -> Result<()> {
|
||||||
use serde_json::Value;
|
use serde_json::Value;
|
||||||
let app_path = self.build.root_dir();
|
|
||||||
|
|
||||||
install_app(&app_path).await?;
|
// 1. Find an active device
|
||||||
|
|
||||||
// 2. Determine which device the app was installed to
|
|
||||||
let device_uuid = get_device_uuid().await?;
|
let device_uuid = get_device_uuid().await?;
|
||||||
|
|
||||||
// 3. Get the installation URL of the app
|
// 2. Get the installation URL of the app
|
||||||
let installation_url = get_installation_url(&device_uuid, &app_path).await?;
|
let installation_url = get_installation_url(&device_uuid, &self.build.root_dir()).await?;
|
||||||
|
|
||||||
// 4. Launch the app into the background, paused
|
// 3. Launch the app into the background, paused
|
||||||
launch_app_paused(&device_uuid, &installation_url).await?;
|
launch_app_paused(&device_uuid, &installation_url).await?;
|
||||||
|
|
||||||
// 5. Pick up the paused app and resume it
|
|
||||||
resume_app(&device_uuid).await?;
|
|
||||||
|
|
||||||
async fn install_app(app_path: &PathBuf) -> Result<()> {
|
|
||||||
let output = Command::new("xcrun")
|
|
||||||
.args(["simctl", "install", "booted"])
|
|
||||||
.arg(app_path)
|
|
||||||
.output()
|
|
||||||
.await?;
|
|
||||||
|
|
||||||
if !output.status.success() {
|
|
||||||
return Err(format!("Failed to install app: {:?}", output).into());
|
|
||||||
}
|
|
||||||
|
|
||||||
Ok(())
|
|
||||||
}
|
|
||||||
|
|
||||||
async fn get_device_uuid() -> Result<String> {
|
async fn get_device_uuid() -> Result<String> {
|
||||||
let output = Command::new("xcrun")
|
let tmpfile = tempfile::NamedTempFile::new()
|
||||||
|
.context("Failed to create temporary file for device list")?;
|
||||||
|
|
||||||
|
Command::new("xcrun")
|
||||||
.args([
|
.args([
|
||||||
"devicectl",
|
"devicectl".to_string(),
|
||||||
"list",
|
"list".to_string(),
|
||||||
"devices",
|
"devices".to_string(),
|
||||||
"--json-output",
|
"--json-output".to_string(),
|
||||||
"target/deviceid.json",
|
tmpfile.path().to_str().unwrap().to_string(),
|
||||||
])
|
])
|
||||||
.output()
|
.output()
|
||||||
.await?;
|
.await?;
|
||||||
|
|
||||||
let json: Value =
|
let json: Value = serde_json::from_str(&std::fs::read_to_string(tmpfile.path())?)
|
||||||
serde_json::from_str(&std::fs::read_to_string("target/deviceid.json")?)
|
.context("Failed to parse xcrun output")?;
|
||||||
.context("Failed to parse xcrun output")?;
|
|
||||||
let device_uuid = json["result"]["devices"][0]["identifier"]
|
let device_uuid = json["result"]["devices"][0]["identifier"]
|
||||||
.as_str()
|
.as_str()
|
||||||
.ok_or("Failed to extract device UUID")?
|
.ok_or("Failed to extract device UUID")?
|
||||||
@@ -910,6 +898,9 @@ impl AppBuilder {
|
|||||||
}
|
}
|
||||||
|
|
||||||
async fn get_installation_url(device_uuid: &str, app_path: &Path) -> Result<String> {
|
async fn get_installation_url(device_uuid: &str, app_path: &Path) -> Result<String> {
|
||||||
|
let tmpfile = tempfile::NamedTempFile::new()
|
||||||
|
.context("Failed to create temporary file for device list")?;
|
||||||
|
|
||||||
// xcrun devicectl device install app --device <uuid> --path <path> --json-output
|
// xcrun devicectl device install app --device <uuid> --path <path> --json-output
|
||||||
let output = Command::new("xcrun")
|
let output = Command::new("xcrun")
|
||||||
.args([
|
.args([
|
||||||
@@ -921,8 +912,8 @@ impl AppBuilder {
|
|||||||
device_uuid,
|
device_uuid,
|
||||||
&app_path.display().to_string(),
|
&app_path.display().to_string(),
|
||||||
"--json-output",
|
"--json-output",
|
||||||
"target/xcrun.json",
|
|
||||||
])
|
])
|
||||||
|
.arg(tmpfile.path())
|
||||||
.output()
|
.output()
|
||||||
.await?;
|
.await?;
|
||||||
|
|
||||||
@@ -930,7 +921,7 @@ impl AppBuilder {
|
|||||||
return Err(format!("Failed to install app: {:?}", output).into());
|
return Err(format!("Failed to install app: {:?}", output).into());
|
||||||
}
|
}
|
||||||
|
|
||||||
let json: Value = serde_json::from_str(&std::fs::read_to_string("target/xcrun.json")?)
|
let json: Value = serde_json::from_str(&std::fs::read_to_string(tmpfile.path())?)
|
||||||
.context("Failed to parse xcrun output")?;
|
.context("Failed to parse xcrun output")?;
|
||||||
let installation_url = json["result"]["installedApplications"][0]["installationURL"]
|
let installation_url = json["result"]["installedApplications"][0]["installationURL"]
|
||||||
.as_str()
|
.as_str()
|
||||||
@@ -941,6 +932,9 @@ impl AppBuilder {
|
|||||||
}
|
}
|
||||||
|
|
||||||
async fn launch_app_paused(device_uuid: &str, installation_url: &str) -> Result<()> {
|
async fn launch_app_paused(device_uuid: &str, installation_url: &str) -> Result<()> {
|
||||||
|
let tmpfile = tempfile::NamedTempFile::new()
|
||||||
|
.context("Failed to create temporary file for device list")?;
|
||||||
|
|
||||||
let output = Command::new("xcrun")
|
let output = Command::new("xcrun")
|
||||||
.args([
|
.args([
|
||||||
"devicectl",
|
"devicectl",
|
||||||
@@ -953,8 +947,8 @@ impl AppBuilder {
|
|||||||
device_uuid,
|
device_uuid,
|
||||||
installation_url,
|
installation_url,
|
||||||
"--json-output",
|
"--json-output",
|
||||||
"target/launch.json",
|
|
||||||
])
|
])
|
||||||
|
.arg(tmpfile.path())
|
||||||
.output()
|
.output()
|
||||||
.await?;
|
.await?;
|
||||||
|
|
||||||
@@ -962,11 +956,7 @@ impl AppBuilder {
|
|||||||
return Err(format!("Failed to launch app: {:?}", output).into());
|
return Err(format!("Failed to launch app: {:?}", output).into());
|
||||||
}
|
}
|
||||||
|
|
||||||
Ok(())
|
let json: Value = serde_json::from_str(&std::fs::read_to_string(tmpfile.path())?)
|
||||||
}
|
|
||||||
|
|
||||||
async fn resume_app(device_uuid: &str) -> Result<()> {
|
|
||||||
let json: Value = serde_json::from_str(&std::fs::read_to_string("target/launch.json")?)
|
|
||||||
.context("Failed to parse xcrun output")?;
|
.context("Failed to parse xcrun output")?;
|
||||||
|
|
||||||
let status_pid = json["result"]["process"]["processIdentifier"]
|
let status_pid = json["result"]["process"]["processIdentifier"]
|
||||||
@@ -994,10 +984,9 @@ impl AppBuilder {
|
|||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
unimplemented!("dioxus-cli doesn't support ios devices yet.")
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
#[allow(unused)]
|
|
||||||
async fn codesign_ios(&self) -> Result<()> {
|
async fn codesign_ios(&self) -> Result<()> {
|
||||||
const CODESIGN_ERROR: &str = r#"This is likely because you haven't
|
const CODESIGN_ERROR: &str = r#"This is likely because you haven't
|
||||||
- Created a provisioning profile before
|
- Created a provisioning profile before
|
||||||
@@ -1011,7 +1000,7 @@ https://developer.apple.com/documentation/xcode/sharing-your-teams-signing-certi
|
|||||||
|
|
||||||
let profiles_folder = dirs::home_dir()
|
let profiles_folder = dirs::home_dir()
|
||||||
.context("Your machine has no home-dir")?
|
.context("Your machine has no home-dir")?
|
||||||
.join("Library/MobileDevice/Provisioning Profiles");
|
.join("Library/Developer/Xcode/UserData/Provisioning Profiles");
|
||||||
|
|
||||||
if !profiles_folder.exists() || profiles_folder.read_dir()?.next().is_none() {
|
if !profiles_folder.exists() || profiles_folder.read_dir()?.next().is_none() {
|
||||||
tracing::error!(
|
tracing::error!(
|
||||||
@@ -1080,10 +1069,11 @@ We checked the folder: {}
|
|||||||
struct ProvisioningProfile {
|
struct ProvisioningProfile {
|
||||||
#[serde(rename = "TeamIdentifier")]
|
#[serde(rename = "TeamIdentifier")]
|
||||||
team_identifier: Vec<String>,
|
team_identifier: Vec<String>,
|
||||||
#[serde(rename = "ApplicationIdentifierPrefix")]
|
|
||||||
application_identifier_prefix: Vec<String>,
|
|
||||||
#[serde(rename = "Entitlements")]
|
#[serde(rename = "Entitlements")]
|
||||||
entitlements: Entitlements,
|
entitlements: Entitlements,
|
||||||
|
#[allow(dead_code)]
|
||||||
|
#[serde(rename = "ApplicationIdentifierPrefix")]
|
||||||
|
application_identifier_prefix: Vec<String>,
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(serde::Deserialize, Debug)]
|
#[derive(serde::Deserialize, Debug)]
|
||||||
|
|||||||
Reference in new issue
Block a user