There are two kinds of projects in Polylith: development and deployable.
  1. 1.
    The development project:
    • This is where we work with the code, often from a REPL.
    • It contains all libraries, components and bases in the workspace, which is specified in ./deps.edn.
    • If we have any profiles then they are defined in ./deps.edn.
    • Any extra code, that is not part of a component or base, lives under the development directory.
  2. 2.
    Any deployable project:
    • Used to build deployable artifacts, e.g.: lambda functions, REST API's, libraries, tools, ...and more.
    • Lives under the projects directory where each project has its own directory.
    • Has a deps.edn config file that specifies which libraries, component and bases that are included.
    • Can optionally have a resources directory.
    • If the base (we normally have only one per project) and the components that belong to it, contain any tests, then they will be run when we execute the test command.
    • If it has any tests of its own, they will live in the test directory, e.g. projects/my-project/test.
    • It's discouraged to have a src directory since all production code should normally only live in components and bases.
The :project key in ./workspace.edn configures which alias each project has and whether any tests should be excluded.
Let's create a project, by executing the create project command:
poly create project name:command-line
Our workspace should now look like this:
├── bases
│ └── cli
│ ├── deps.edn
│ ├── resources
│ │ └── cli
│ ├── src
│ │ └── se
│ │ └── example
│ │ └── cli
│ │ └── core.clj
│ └── test
│ └── se
│ └── example
│ └── cli
│ └── core_test.clj
├── components
│ └── user
│ ├── deps.edn
│ ├── resources
│ │ └── user
│ ├── src
│ │ └── se
│ │ └── example
│ │ └── user
│ │ ├── core.clj
│ │ └── interface.clj
│ └── test
│ └── se
│ └── example
│ └── user
│ └── interface_test.clj
├── deps.edn
├── development
│ └── src
│ └── dev
│ └── lisa.clj
├── logo.png
├── projects
│ └── command-line
│ └── deps.edn
├── readme.md
└── workspace.edn
The tool also reminds us of this:
It's recommended to add an alias to :projects in ./workspace.edn for the command-line project.
If we don't add the alias to workspace.edn, the project heading will show up as ? when we execute the info command, so let's add it:
:projects {"development" {:alias "dev"}
"command-line" {:alias "cl"}}}
Now add user and cli to projects/command-line/deps.edn:
{:deps {poly/user {:local/root "../../components/user"}
poly/cli {:local/root "../../bases/cli"}
All keys must be unique, and a good pattern is to prefix them with poly/ followed by the brick name, e.g. poly/user or poly/cli as in this case. The reason all paths begin with "../../" is that components and bases live two levels up compared to projects/command-line and not at the root as with the development project.
The test command will figure out what tests need to be executed. If you have reasons to run the tests for each project separately using tools.deps, then you also have to specify the test paths.
Note: All the project deps.edn config files under the projects directory specifies what bricks to include by giving a list of :local/root mappings. The poly test command uses this information to figure out what bricks and library dependencies that should be included when executing the tests, by looking into each brick's deps.edn file. tools.deps does not "inherit" test dependencies from :local/root mappings, which is the reason we have to add our dependencis as separate paths in /deps.edn to allow IDE's and other tooling to work properly.
Let's summarise where the paths/dependencies to bricks are located:
  • The dev project: ./deps.edn > :aliases > :dev > :extra-paths
  • Other projects: projects/PROJECT-DIR > deps.edn > :deps