Skip to content

Commit

Permalink
Support filtering by dependents
Browse files Browse the repository at this point in the history
  • Loading branch information
pnezis committed Sep 30, 2024
1 parent c32910e commit a17d759
Show file tree
Hide file tree
Showing 7 changed files with 90 additions and 4 deletions.
15 changes: 14 additions & 1 deletion workspace/CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,20 @@ The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/).

## [Unreleased]

* `workspace.list`: support filtering by dependency
* `workspace.list`: support filtering by dependents through the `--dependent` flag. You
can now list all projects that are direct dependencies of a given project:

```bash
mix workspace.list --dependent my_project
```

* `workspace.list`: support filtering by dependencies through the `--dependency`. Using this
flag you can list only those projects that have the given direct dependency:

```bash
mix workspace.list --dependency a_project
```

* `workspace.list`: add `--maintainer` for filtering projects with the given maintainer

## [v0.1.1](https://github.com/sportradar/elixir-workspace/tree/workspace/v0.1.1) (2024-07-04)
Expand Down
6 changes: 6 additions & 0 deletions workspace/lib/mix/tasks/workspace.list.ex
Original file line number Diff line number Diff line change
Expand Up @@ -47,6 +47,7 @@ defmodule Mix.Tasks.Workspace.List do
:tags,
:excluded_tags,
:dependency,
:dependent,
:show_status
],
opts
Expand Down Expand Up @@ -88,6 +89,11 @@ defmodule Mix.Tasks.Workspace.List do
$ mix workspace.list --dependency foo
Additionally you can specify the `--dependent` flag to consider only dependencies of a
given project:
$ mix workspace.list --dependent foo
You can also filter by the project's maintainer. The search is case insensitive. The
maintainers are expected to be defined under `package`:
Expand Down
8 changes: 8 additions & 0 deletions workspace/lib/workspace/cli_options.ex
Original file line number Diff line number Diff line change
Expand Up @@ -37,6 +37,14 @@ defmodule Workspace.CliOptions do
""",
doc_section: :filtering
],
dependent: [
type: :string,
multiple: false,
doc: """
If set, only projects that are dependencies of the given project are considered.
""",
doc_section: :filtering
],
excluded_tags: [
type: :string,
multiple: true,
Expand Down
12 changes: 10 additions & 2 deletions workspace/lib/workspace/filtering.ex
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,7 @@ defmodule Workspace.Filtering do
considered. All projects that do not have at least one the specified tags will
be skipped.
* `:dependency` (`t:atom/0`) - keeps only projects that have the given dependency.
* `:dependent` (`t:atom/0`) - keeps only dependencies of the given project.
* `:affected` (`t:boolean/0`) - if set only the affected projects will be
included and everything else will be skipped. Defaults to `false`.
* `:modified` (`t:boolean/0`) - if set only the modified projects will be
Expand Down Expand Up @@ -77,7 +78,8 @@ defmodule Workspace.Filtering do
only_roots: opts[:only_roots] || false,
excluded_tags: opts[:excluded_tags] || [],
tags: Enum.map(opts[:tags] || [], &maybe_to_tag/1),
dependency: maybe_to_atom(opts[:dependency])
dependency: maybe_to_atom(opts[:dependency]),
dependent: maybe_to_atom(opts[:dependent])
]

Enum.map(workspace.projects, fn {_name, project} ->
Expand Down Expand Up @@ -118,7 +120,8 @@ defmodule Workspace.Filtering do
not_root?(project, opts[:only_roots]) or
not_affected?(project, opts[:affected]) or
not_modified?(project, opts[:modified]) or
not_dependency?(workspace, project, opts[:dependency])
not_dependency?(workspace, project, opts[:dependency]) or
not_dependent?(workspace, project, opts[:dependent])
end

defp excluded_project?(project, excluded), do: project.app in excluded
Expand Down Expand Up @@ -147,4 +150,9 @@ defmodule Workspace.Filtering do

defp not_dependency?(workspace, project, dependency),
do: dependency not in Workspace.Graph.dependencies(workspace, project.app)

defp not_dependent?(_workspace, _project, nil), do: false

defp not_dependent?(workspace, project, dependent),
do: project.app not in Workspace.Graph.dependencies(workspace, dependent)
end
36 changes: 36 additions & 0 deletions workspace/test/mix/tasks/workspace.list_test.exs
Original file line number Diff line number Diff line change
Expand Up @@ -139,6 +139,42 @@ defmodule Mix.Tasks.Workspace.ListTest do
end) == expected
end

test "filtering by --dependent" do
expected = """
Found 3 workspace projects matching the given options.
* :package_default_b package_default_b/mix.exs - a dummy project
* :package_default_c package_default_c/mix.exs
* :package_default_d package_default_d/mix.exs
"""

assert capture_io(fn ->
ListTask.run([
"--workspace-path",
@sample_workspace_default_path,
"--dependent",
"package_default_a"
])
end) == expected
end

test "filtering by both --dependency and --dependent" do
expected = """
Found 1 workspace projects matching the given options.
* :package_default_c package_default_c/mix.exs
"""

assert capture_io(fn ->
ListTask.run([
"--workspace-path",
@sample_workspace_default_path,
"--dependency",
"package_default_e",
"--dependent",
"package_default_a"
])
end) == expected
end

test "with --json option set" do
output = Path.join(@sample_workspace_changed_path, "workspace.json")

Expand Down
3 changes: 2 additions & 1 deletion workspace/test/workspace/cli_test.exs
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,8 @@ defmodule Workspace.CliTest do
:head,
:tags,
:excluded_tags,
:dependency
:dependency,
:dependent
]

test "valid options sanity check" do
Expand Down
14 changes: 14 additions & 0 deletions workspace/test/workspace/filtering_test.exs
Original file line number Diff line number Diff line change
Expand Up @@ -131,5 +131,19 @@ defmodule Workspace.FilteringTest do
assert Workspace.project!(workspace, :baz).skip
refute Workspace.project!(workspace, :foo).skip
end

test "with dependent set", %{workspace: workspace} do
workspace = Workspace.Filtering.run(workspace, dependent: :bar)

assert Workspace.project!(workspace, :bar).skip
assert Workspace.project!(workspace, :baz).skip
assert Workspace.project!(workspace, :foo).skip

workspace = Workspace.Filtering.run(workspace, dependent: :foo)

refute Workspace.project!(workspace, :bar).skip
assert Workspace.project!(workspace, :baz).skip
assert Workspace.project!(workspace, :foo).skip
end
end
end

0 comments on commit a17d759

Please sign in to comment.