Skip to content

Instantly share code, notes, and snippets.

@paulo-ferraz-oliveira
Created September 9, 2023 11:54
Show Gist options
  • Save paulo-ferraz-oliveira/9a5d45f376a334fdad346288fc988e90 to your computer and use it in GitHub Desktop.
Save paulo-ferraz-oliveira/9a5d45f376a334fdad346288fc988e90 to your computer and use it in GitHub Desktop.
Bump a specific dep's version in mix.exs (via AST traversal)

Bump mix.exs dep. version

(from: jelly-beam/rebar3_ex_doc#67)

This little Gist shows how to achieve simple AST walk + update to change a module attribute, that defines a version (in the example), in mix.exs.

# up_version.exs
defmodule UpVersion do
  @mix_exs "mix.exs"
  @vsn_attr :dep_version

  def up(new_vsn) do
    content_up =
      @mix_exs
      |> File.read!()
      |> up(new_vsn)

    File.write!(@mix_exs, "#{content_up}\n")
  end

  defp up(mix_exs, new_vsn) do
    mix_exs
    |> Code.string_to_quoted!()
    |> Macro.prewalk(fn
      {:@, anno, [{@vsn_attr, anno, [_cur_vsn]}]} ->
        {:@, anno, [{@vsn_attr, anno, [new_vsn]}]}

      node ->
        node
    end)
    |> Macro.to_string()
  end
end

[new_vsn] = System.argv()
:ok = UpVersion.up(new_vsn)

Example

Here's an example from that reference (comments added for readibility, since the above script will strip them out).

defmodule Rebar3ExDoc.MixProject do
  use Mix.Project
  @ex_doc_version "0.30.5" # Here's the module attribute (:dep_version would become :ex_doc_version, above)
  def project do
    [
      app: :rebar3_ex_doc,
      version: "0.2.20",
      elixir: "~> 1.13",
      deps: [ex_doc: "~> #{@ex_doc_version}"],
      escript: [main_module: ExDoc.CLI, name: "ex_doc", path: "priv/ex_doc"],
      docs: [main: "readme", extras: ["README.md"]]
    ]
  end
end

After running elixir up_version.exs 0.30.6 the file's content would be updated to show @ex_doc_version "0.30.6", instead.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment