Repository: railwayapp/nixpacks
Pull request #463 (2022-08-29 13:54:16)

add zlib nix libraries if pandas is detected
Previously we were just adding the `zlib` library if `numpy` was detected. This PR changes it so we also add them if only `pandas` is detected.

Fixes https://github.com/railwayapp/nixpacks/issues/462


Patch:
diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml
index 15c99f1..4ca399b 100644
--- a/.github/workflows/release.yml
+++ b/.github/workflows/release.yml
@@ -137,6 +137,21 @@ jobs:
         tag_name: ${{ needs.create-release.outputs.nixpacks_version }}
         files: nixpacks-${{ needs.create-release.outputs.nixpacks_version }}-${{ matrix.target }}*
 
+    - name: Install cargo-deb
+      if: matrix.target == 'x86_64-unknown-linux-musl'
+      run: cargo install cargo-deb
+
+    - name: Generate .deb package file
+      if: matrix.target == 'x86_64-unknown-linux-musl'
+      run: cargo deb --target x86_64-unknown-linux-musl --output nixpacks-${{ needs.create-release.outputs.nixpacks_version }}-amd64.deb
+
+    - name: Upload .deb package file
+      if: matrix.target == 'x86_64-unknown-linux-musl'
+      uses: svenstaro/upload-release-action@v2
+      with:
+        tag: ${{ needs.create-release.outputs.nixpacks_version }}
+        file: nixpacks-${{ needs.create-release.outputs.nixpacks_version }}-amd64.deb
+
     - name: Set SHA
       if: matrix.config.os == 'macos-latest'
       id: shasum
diff --git a/Cargo.toml b/Cargo.toml
index e6d8bf2..79ff3bf 100644
--- a/Cargo.toml
+++ b/Cargo.toml
@@ -52,3 +52,8 @@ path-slash = "0.2.1"
 dotenv-parser = "0.1.3"
 insta = { version = "1.18.2", features = ["redactions", "json"] }
 test-helper = { path = "./test-helper" }
+
+[package.metadata.deb]
+# https://packages.debian.org/stretch
+section = "devel"
+
diff --git a/docs/pages/docs/install.md b/docs/pages/docs/install.md
index f29b60b..f89b29d 100644
--- a/docs/pages/docs/install.md
+++ b/docs/pages/docs/install.md
@@ -20,6 +20,16 @@ Download Nixpacks from GH releases and install automatically
 curl -sSL https://nixpacks.com/install.sh | bash
 ```
 
+## Debian (and derivatives like Ubuntu)
+
+Nixpacks provides a `.deb` file provided in each [release](https://github.com/railwayapp/nixpacks/releases).
+
+```sh
+# Replace {VERSION} with the version that you want to install
+curl -LO https://github.com/railwayapp/nixpacks/releases/download/v{VERSION}/nixpacks-v{VERSION}-amd64.deb
+sudo dpkg -i nixpacks-v{VERSION}-amd64.deb
+```
+
 ## Scoop
 
 Install Nixpacks from Scoop using the [official bucket](https://github.com/ScoopInstaller/Main/blob/master/bucket/nixpacks.json) (Windows Only)
diff --git a/src/nixpacks/environment.rs b/src/nixpacks/environment.rs
index 5499e03..701144b 100644
--- a/src/nixpacks/environment.rs
+++ b/src/nixpacks/environment.rs
@@ -1,4 +1,5 @@
-use anyhow::{bail, Result};
+use anyhow::Result;
+use regex::Regex;
 use std::{collections::BTreeMap, env};
 
 pub type EnvironmentVariables = BTreeMap<String, String>;
@@ -16,19 +17,22 @@ impl Environment {
     pub fn from_envs(envs: Vec<&str>) -> Result<Environment> {
         let mut environment = Environment::default();
         for env in envs {
-            let v: Vec<&str> = env.split('=').collect();
-            if v.len() == 1 {
-                // Pull the variable from the current environment
-                let name = v[0];
+            let matches = Regex::new(r"([A-Za-z0-9_-]*)(?:=?)([\s\S]*)")
+                .unwrap()
+                .captures(env)
+                .unwrap();
+            if matches.get(2).unwrap().as_str() == "" {
+                // No value, pull from the current environment
+                let name = matches.get(1).unwrap().as_str();
                 if let Ok(value) = env::var(name) {
-                    // Variable is set
                     environment.set_variable(name.to_string(), value);
                 }
-            } else if v.len() > 2 {
-                bail!("Unable to parse variable string");
             } else {
                 // Use provided name, value pair
-                environment.set_variable(v[0].to_string(), v[1].to_string());
+                environment.set_variable(
+                    matches.get(1).unwrap().as_str().to_string(),
+                    matches.get(2).unwrap().as_str().to_string(),
+                );
             }
         }
 
@@ -87,8 +91,9 @@ mod tests {
     }
 
     #[test]
-    fn test_create_invalid_environment() {
-        assert!(Environment::from_envs(vec!["INVALID=ENV=CONFIG"]).is_err());
+    fn test_create_equals_sign_parsing() {
+        let environment = Environment::from_envs(vec!["INVALID=ENV=CONFIG"]).unwrap();
+        assert_eq!(environment.get_variable("INVALID"), Some("ENV=CONFIG"));
     }
 
     #[test]
diff --git a/src/nixpacks/plan/generator.rs b/src/nixpacks/plan/generator.rs
index 7dd7157..b68fb56 100644
--- a/src/nixpacks/plan/generator.rs
+++ b/src/nixpacks/plan/generator.rs
@@ -7,9 +7,9 @@ use anyhow::{Context, Ok, Result};
 use std::collections::HashMap;
 
 // This line is automatically updated.
-// Last Modified: 2022-08-22 17:06:26 UTC+0000
-// https://github.com/NixOS/nixpkgs/commit/54060e816971276da05970a983487a25810c38a7
-pub const NIXPKGS_ARCHIVE: &str = "54060e816971276da05970a983487a25810c38a7";
+// Last Modified: 2022-08-29 17:07:50 UTC+0000
+// https://github.com/NixOS/nixpkgs/commit/0e304ff0d9db453a4b230e9386418fd974d5804a
+pub const NIXPKGS_ARCHIVE: &str = "0e304ff0d9db453a4b230e9386418fd974d5804a";
 
 #[derive(Clone, Default, Debug)]
 pub struct GeneratePlanOptions {
diff --git a/src/providers/go.rs b/src/providers/go.rs
index 5213aca..08e8760 100644
--- a/src/providers/go.rs
+++ b/src/providers/go.rs
@@ -35,7 +35,7 @@ impl Provider for GolangProvider {
         plan.add_phase(Phase::setup(Some(vec![Pkg::new(&nix_pkg)])));
 
         if app.includes_file("go.mod") {
-            let mut install = Phase::install(Some("go get".to_string()));
+            let mut install = Phase::install(Some("go mod download".to_string()));
             install.add_cache_directory(GO_BUILD_CACHE_DIR.to_string());
             plan.add_phase(install);
         }
diff --git a/src/providers/python.rs b/src/providers/python.rs
index 3c63907..ae8e4e5 100644
--- a/src/providers/python.rs
+++ b/src/providers/python.rs
@@ -104,7 +104,7 @@ impl PythonProvider {
 
         // Numpy needs some C headers to be available
         // stdenv.cc.cc.lib -> https://discourse.nixos.org/t/nixos-with-poetry-installed-pandas-libstdc-so-6-cannot-open-shared-object-file/8442/3
-        if PythonProvider::uses_numpy(app)? {
+        if PythonProvider::uses_dep(app, "numpy")? || PythonProvider::uses_dep(app, "pandas")? {
             setup_phase.add_pkgs_libs(vec!["zlib".to_string(), "stdenv.cc.cc.lib".to_string()]);
         }
 
@@ -327,20 +327,20 @@ impl PythonProvider {
         ))
     }
 
-    fn uses_numpy(app: &App) -> Result<bool> {
-        let requirements_numpy = app.includes_file("requirements.txt")
+    fn uses_dep(app: &App, dep: &str) -> Result<bool> {
+        let requirements_usage = app.includes_file("requirements.txt")
             && app
                 .read_file("requirements.txt")?
                 .to_lowercase()
-                .contains("numpy");
+                .contains(dep);
 
-        let project_numpy = app.includes_file("pyproject.toml")
+        let pyproject_usage = app.includes_file("pyproject.toml")
             && app
                 .read_file("pyproject.toml")?
                 .to_lowercase()
-                .contains("numpy");
+                .contains(dep);
 
-        Ok(requirements_numpy || project_numpy)
+        Ok(requirements_usage || pyproject_usage)
     }
 }
 
@@ -407,12 +407,14 @@ mod test {
 
     #[test]
     fn test_numpy_detection() -> Result<()> {
-        assert!(!PythonProvider::uses_numpy(&App::new(
-            "./examples/python"
-        )?)?,);
-        assert!(PythonProvider::uses_numpy(&App::new(
-            "./examples/python-numpy"
-        )?)?,);
+        assert!(!PythonProvider::uses_dep(
+            &App::new("./examples/python",)?,
+            "numpy"
+        )?,);
+        assert!(PythonProvider::uses_dep(
+            &App::new("./examples/python-numpy",)?,
+            "numpy"
+        )?,);
         Ok(())
     }
 }


Test patch:
diff --git a/tests/snapshots/generate_plan_tests__go_custom_version.snap b/tests/snapshots/generate_plan_tests__go_custom_version.snap
index ab2caa4..2bbdbb4 100644
--- a/tests/snapshots/generate_plan_tests__go_custom_version.snap
+++ b/tests/snapshots/generate_plan_tests__go_custom_version.snap
@@ -15,7 +15,7 @@ expression: plan
         "setup"
       ],
       "commands": [
-        "go get"
+        "go mod download"
       ],
       "cacheDirectories": [
         "/root/.cache/go-build"
diff --git a/tests/snapshots/generate_plan_tests__go_gin.snap b/tests/snapshots/generate_plan_tests__go_gin.snap
index ab2caa4..2bbdbb4 100644
--- a/tests/snapshots/generate_plan_tests__go_gin.snap
+++ b/tests/snapshots/generate_plan_tests__go_gin.snap
@@ -15,7 +15,7 @@ expression: plan
         "setup"
       ],
       "commands": [
-        "go get"
+        "go mod download"
       ],
       "cacheDirectories": [
         "/root/.cache/go-build"
diff --git a/tests/snapshots/generate_plan_tests__go_mod.snap b/tests/snapshots/generate_plan_tests__go_mod.snap
index bfd52c6..1e3511e 100644
--- a/tests/snapshots/generate_plan_tests__go_mod.snap
+++ b/tests/snapshots/generate_plan_tests__go_mod.snap
@@ -15,7 +15,7 @@ expression: plan
         "setup"
       ],
       "commands": [
-        "go get"
+        "go mod download"
       ],
       "cacheDirectories": [
         "/root/.cache/go-build"