diff --git a/README.md b/README.md index 9bc2b5d..7b1b303 100644 --- a/README.md +++ b/README.md @@ -87,6 +87,7 @@ jobs: | `source-revision` | The revision of `flakehub-push` to use. Conflicts with all other `source-*` options. | string | | | | `source-tag` | The tag of `flakehub-push` to use. Conflicts with all other `source-*` options. | string | | | | `source-url` | A URL pointing to a `flakehub-push` binary. Overrides all other `source-*` options. | string | | | +| `impure` | Allow the use of impure operations (e.g. `builtins.fetchGit`). | boolean | | `false` | ## Developing `flakehub-push` diff --git a/src/cli/mod.rs b/src/cli/mod.rs index a91a2ae..679580f 100644 --- a/src/cli/mod.rs +++ b/src/cli/mod.rs @@ -53,6 +53,9 @@ pub(crate) struct FlakeHubPushCli { #[clap(long, env = "FLAKEHUB_PUSH_MIRROR", default_value_t = false)] pub(crate) mirror: bool, + #[clap(long, env = "FLAKEHUB_PUSH_IMPURE", value_parser = EmptyBoolParser, default_value_t = false)] + pub(crate) impure: bool, + /// URL of a JWT mock server (like https://github.com/spectare/fakeidp) which can issue tokens. #[clap(long)] pub(crate) jwt_issuer_uri: Option, diff --git a/src/flake_info.rs b/src/flake_info.rs index bd74f9f..b751407 100644 --- a/src/flake_info.rs +++ b/src/flake_info.rs @@ -19,6 +19,7 @@ pub struct FlakeMetadata { pub(crate) source_dir: std::path::PathBuf, pub(crate) flake_locked_url: String, pub(crate) metadata_json: serde_json::Value, + pub(crate) impure: bool, my_flake_is_too_big: bool, } @@ -26,21 +27,29 @@ pub struct FlakeMetadata { pub struct FlakeOutputs(pub serde_json::Value); impl FlakeMetadata { - pub async fn from_dir(directory: &Path, my_flake_is_too_big: bool) -> Result { - let output = tokio::process::Command::new("nix") - .arg("flake") - .arg("metadata") - .arg("--json") - .arg("--no-write-lock-file") - .arg(directory) - .output() - .await - .wrap_err_with(|| { - eyre!( - "Failed to execute `nix flake metadata --json {}`", - directory.display() - ) - })?; + pub async fn from_dir( + directory: &Path, + my_flake_is_too_big: bool, + impure: bool, + ) -> Result { + let mut command = tokio::process::Command::new("nix"); + command.arg("flake"); + command.arg("metadata"); + command.arg("--json"); + command.arg("--no-write-lock-file"); + + if impure { + command.arg("--impure"); + } + + command.arg(directory); + + let output = command.output().await.wrap_err_with(|| { + eyre!( + "Failed to execute `nix flake metadata --json {}`", + directory.display() + ) + })?; let metadata_json: serde_json::Value = serde_json::from_slice(&output.stdout) .wrap_err_with(|| { @@ -79,6 +88,7 @@ impl FlakeMetadata { flake_locked_url: flake_locked_url.to_string(), metadata_json, my_flake_is_too_big, + impure, }) } @@ -93,6 +103,10 @@ impl FlakeMetadata { command.arg("--all-systems"); } + if self.impure { + command.arg("--impure"); + } + command.arg("--json"); command.arg("--no-write-lock-file"); command.arg(&self.source_dir); @@ -135,20 +149,24 @@ impl FlakeMetadata { /// this does not ensure anything about the recentness of the locked revs. pub async fn check_lock_if_exists(&self) -> Result<()> { if self.source_dir.join("flake.lock").exists() { - let output = tokio::process::Command::new("nix") - .arg("flake") - .arg("metadata") - .arg("--json") - .arg("--no-update-lock-file") - .arg(&self.source_dir) - .output() - .await - .wrap_err_with(|| { - eyre!( - "Failed to execute `nix flake metadata --json --no-update-lock-file {}`", - self.source_dir.display() - ) - })?; + let mut command = tokio::process::Command::new("nix"); + command.arg("flake"); + command.arg("metadata"); + command.arg("--json"); + command.arg("--no-update-lock-file"); + + if self.impure { + command.arg("--impure"); + } + + command.arg(&self.source_dir); + + let output = command.output().await.wrap_err_with(|| { + eyre!( + "Failed to execute `nix flake metadata --json --no-update-lock-file {}`", + self.source_dir.display() + ) + })?; if !output.status.success() { let command = format!( @@ -278,6 +296,11 @@ impl FlakeMetadata { cmd.arg("eval"); cmd.arg("--json"); cmd.arg("--no-write-lock-file"); + + if self.impure { + cmd.arg("--impure"); + } + cmd.arg(format!("{}#contents", tempdir_path.display())); let output = cmd.output().await.wrap_err_with(|| { eyre!( diff --git a/src/release_metadata.rs b/src/release_metadata.rs index af0d757..7b47495 100644 --- a/src/release_metadata.rs +++ b/src/release_metadata.rs @@ -46,9 +46,10 @@ impl ReleaseMetadata { // flake_dir is an absolute path of flake_root(aka git_root)/subdir let flake_dir = local_git_root.join(&subdir); - let flake_metadata = FlakeMetadata::from_dir(&flake_dir, cli.my_flake_is_too_big) - .await - .wrap_err("Getting flake metadata")?; + let flake_metadata = + FlakeMetadata::from_dir(&flake_dir, cli.my_flake_is_too_big, cli.impure) + .await + .wrap_err("Getting flake metadata")?; tracing::debug!("Got flake metadata: {:?}", flake_metadata); // sanity checks diff --git a/ts/index.ts b/ts/index.ts index 50dc295..cc7cce4 100644 --- a/ts/index.ts +++ b/ts/index.ts @@ -23,6 +23,7 @@ type ExecutionEnvironment = { FLAKEHUB_PUSH_ROLLING?: string; FLAKEHUB_PUSH_MIRROR?: string; FLAKEHUB_PUSH_ROLLING_MINOR?: string; + FLAKEHUB_PUSH_IMPURE?: string; }; class FlakeHubPushAction extends DetSysAction { @@ -44,6 +45,7 @@ class FlakeHubPushAction extends DetSysAction { private mirror: boolean; private name: string | null; private rollingMinor: number | null; + private impure: boolean; constructor() { super({ @@ -72,6 +74,7 @@ class FlakeHubPushAction extends DetSysAction { this.mirror = inputs.getBool("mirror"); this.name = inputs.getStringOrNull("name"); this.rollingMinor = inputs.getNumberOrNull("rolling-minor"); + this.impure = inputs.getBool("impure"); } async main(): Promise { @@ -125,6 +128,7 @@ class FlakeHubPushAction extends DetSysAction { env.FLAKEHUB_PUSH_INCLUDE_OUTPUT_PATHS = this.includeOutputPaths.toString(); env.FLAKEHUB_PUSH_ROLLING = this.rolling.toString(); env.FLAKEHUB_PUSH_MIRROR = this.mirror.toString(); + env.FLAKEHUB_PUSH_IMPURE = this.impure.toString(); if (this.name !== null) { env.FLAKEHUB_PUSH_NAME = this.name;