Pass arguments to Mix aliases with anonymous functions

almirsarajcic

almirsarajcic

4 hours ago

Need to pass command-line arguments to your Mix aliases? Use anonymous functions instead of strings to capture and forward arguments.

# In mix.exs
defp aliases do
  [
    "test.features": [
      "assets.deploy",
      fn args ->
        cmd_args = Enum.join(args, " ")
        Mix.shell().cmd("mix test --only feature #{cmd_args}")
      end
    ]
  ]
end

Now you can run:

mix test.features path/to/file

This runs assets.deploy first, then executes mix test --only feature path/to/file.

How it works

Mix aliases can be either strings (for simple task sequences) or anonymous functions (for dynamic behavior). When you use a function, Mix passes any additional command-line arguments as a list to your function.

The key is using Enum.join(args, " ") to convert the argument list back into a space-separated string for shell commands. You can mix strings and functions in the same alias to run multiple tasks sequentially.

Bonus: Advanced server management

Here’s a more sophisticated example that stops existing servers and runs feature tests with proper cleanup:

"test.features": [
  "assets.deploy",
  fn args ->
    cmd_args = Enum.join(args, " ")
    Mix.shell().cmd("./scripts/feature_test.sh #{cmd_args}")
  end
]

This approach lets you build complex development workflows while maintaining the flexibility to pass different arguments for different test runs. The external script handles proper signal trapping so you can stop tests cleanly with Ctrl+C.

Here’s the scripts/feature_test.sh script:

#!/bin/bash

export FEATURE_TESTS=true
export PW_TIMEOUT=2000

# Clean up test server on exit
cleanup() {
    echo "🧹 Cleaning up test server..."
    lsof -ti tcp:4205 | xargs kill -9 2>/dev/null || true
}

trap cleanup EXIT INT

# Kill any existing test server
if lsof -ti tcp:4205 > /dev/null 2>&1; then
    echo "🧹 Cleaning up existing test server..."
    lsof -ti tcp:4205 | xargs kill -9 2>/dev/null || true
fi

# Run mix test with passed arguments
echo "🚀 Starting feature tests..."
mix test --color --only feature "$@"