Skip to content

fenv-org/d

Repository files navigation

d

codecov

d is a CLI tool to help manage multi-packages workspace - mostly flutter workspace. d is written typescript and powered by deno. We decided deno as the language for d carefully. The main reason is not to has any dependency on dart and flutter.

melos is a very powerful tool to help manage multi-packages workspace.

The biggest weak point of melos is that it depends on dart and dart's third-party libraries even though melos is a tool to manage dart/flutter projects. Therefore, sometimes, melos users might run into problems regarding to dart/flutter pub get or melos bootstrap.

This project is under developing actively.

Table of contents

Supported OS and architectures

MacOS

  • x86_64
  • arm64

Linux

How to install

Install the latest version

$ curl -fsSL https://d-install.jerry.company | bash

If you are a bash or a zsh user, you may need to add the following to the end of your ~/.bashrc or ~/.zshrc:

export D_HOME="$HOME/.d"
export PATH="$D_HOME/bin:$PATH"

If you are a fish user, please execute the following:

$ mkdir -p $HOME/.config/fish/conf.d
$ echo "set -gx D_HOME $HOME/.d" \
  > $HOME/.config/fish/conf.d/d.fish
$ exec $SHELL -l
$ fish_add_path $D_HOME/bin

Install the specific version

You can install the specific version of d like:

$ curl -fsSL https://d-install.jerry.company | bash -s vX.Y.Z

Please find the released versions at https://github.com/fenv-org/d/releases.

To install d to the specific directory

The install script installs d to $HOME/.d directory by default. However, you also specify another location like:

$ curl -fsSL https://d-install.jerry.company \
    | D_INSTALL_DIR=[other_directory] bash

To put any other name instead of d

If there already exists any other CLI command d in your shell environment, you can install d as any other name instead of d. For example, oh-my-zsh has a pre-defined zsh function d to show directory history. In this case, the feature will be useful.

To give any other name to d, sets D_CLI environment variable.

echo 'export D_CLI=other_command` >> ~/.bashrc

The above is an example for bash users. Please add D_CLI according to your favorite shell.

And then, install d according to above installation instructions. d installer will install d with the name you gave instead of d.

How to use d

Let's assume the workspace's directory structure is:

workspace
  ├> app
  │  └> pubspec.yaml
  └> packages
     ├> package-a
     │  └> pubspec.yaml
     ├> package-b
     │  └> pubspec.yaml
     ├> package-c
     │  └> pubspec.yaml
     └> package-d
        ├> pubspec.yaml
        └> example
           ├> ios
           ├> android
           └> pubspec.yaml

And the dependency relations are:

  • app requires package-b and package-c
  • package-b requires package-a and package-d
  • package-c requires package-d

Make d.yaml

d CLI needs a configuration file d.yaml. You can place the file any where in the repository.

If you place d.yaml under app, the d.yaml should look like:

version: v1

name: "Workspace name here"

packages:
  include:
    - .
    - ../packages/**
  exclude:
    - "*example*"

Or if you place d.yaml file under workspace, the d.yaml should look like, instead:

version: v1

name: "Workspace name here"

packages:
  include:
    - app
    - packages/**
  exclude:
    - "*example*"

Specify dependencies in pubspec.yaml

Then, we need to specify dependency relations among packages in pubspec.yaml of each packages. Just leave the dependent package names.

  • workspace/app/pubspec.yaml

    ...
    dependencies:
      ...
      package-b: # No need to specify "path". `d` will take care on behalf of you.
      package-c:
      ...
    ...
  • workspace/packages/package-b/pubspec.yaml

    name: package-b
    ...
    dependencies:
      ...
      package-a:
      package-d:
      ...
    ...
  • workspace/packages/package-c/pubspec.yaml

    name: package-c
    ...
    dependencies:
      ...
      package-d:
      ...
    ...

Run d bootstrap

To analyze the dependencies among linked packages, you should run d bootstrap when you initially make a workspace and whenever the dependencies among managed packages are changed. d bootstrap does 1. analyzing the dependencies among packages, 2. generating pubspec_overrides.yaml when needed, and 3. running flutter pub get.

You can run it on any child directory of the directory that has d.yaml file. d will find the nearest d.yaml file from the current working directory to upward.

workspace/app>$ d bs # bs is an alias of `bootstrap`.

Then, d will generate .d directory on the workspace root and pubspec_overrides.yaml files on some directories. Hence, we recommend to list up .d/ and pubspec_overrides.yaml to .gitignore file.

How to define functions in d.yaml

d supports to define functions in d.yaml and execute them with d func command.

version: v1
name: ...
packages: ...

functions:
  <function_name>:
    description: "Describe what this function is" # Optional
    exec: "Write bash scripts here" # Mandatory
    options: # Optional
      earlyExit: true/false # Defaults to `true`.
      concurrency: positive integer # Defaults to `5`.
      # Package filters
      includeHasFile: string array
      excludeHasFile: string array
      includeHasDir: string array
      excludeHasDir: string array
      # Dependency filters
      includeDependency: string array
      excludeDependency: string array
      includeDirectDependency: string array
      excludeDirectDependency: string array
      includeDevDependency: string array
      excludeDevDependency: string array

The function in d supports patterns and arguments as well.

functions:
  echo:{abcd}:{efgh}:
    description: echo strings
    exec: |
      echo "abcd=$abcd"
      echo "efgh=$efgh"
      echo '$1='$1
      echo '$2='$2
      echo "package_name=$PACKAGE_NAME"
    options:
      includeHasFile:
        - pubspec.yaml
      excludeHasFile:
        - pubspec_overrides.yaml
      includeDependency:
        - flutter

For example, assuming we have the above sample function, we can run d func echo:hello:world -- good night. In that case, $abcd and $efgh will be replaced with hello and world respectively. And, $1 and $2 will be replaced with good and night respectively.

This feature will enable to write the following function:

functions:
  build:{platform}:{phase}:{flavor}:
    exec: flutter build $platform --$phase --flavor=$flavor $@
    options:
      includeDependency:
        - flutter
$ d func build:ipa:release:store -- --no-codesign

Commands

bootstrap

bootstrap is a command to find and link packages specified in d.yaml. After bootstrapping, d can run various commands for each linked packages considering their dependency relationship.

bootstrap supports package filters.

Usage examples

$ d bootstrap [--config <PATH-TO-d.yaml>]
# or
$ d bs [--config <PATH-TO-d.yaml>]

pub

pub is a command to run flutter pub <subcommand> [args...] command in each bootstrapped packages. You can run any arbitrary flutter pub's subcommand with this command.

pub supports package filters and dependency filters.

Usage examples

$ d pub [--config <PATH-TO-d.yaml>] get
$ d pub [--config <PATH-TO-d.yaml>] upgrade

build_runner

build_runner is a command to run dart run build_runner build/run/clean command in every bootstrapped package where has a dev dependency on the build_runner package. br is an alias of build_runner.

build_runner supports package filters and dependency filters.

Usage examples

  • build_runner build

    $ d build_runner build --delete-conflicting-outputs
    # or shortly
    $ d br b -d
  • build_runner run

    $ d build_runner run --delete-conflicting-outputs \
        '$WORKSPACE_PATH'/target.dart -- \
        [script args...]
    # or shortly
    $ d br r -d \
        '$WORKSPACE_PATH'/target.dart -- \
        [script args...]
  • build_runner clean

    $ d build_runner clean
    # or shortly
    $ d br c

run

run is a command to run any arbitrary command in every bootstrapped package. run supports package filters and dependency filters.

Usage examples

$ d run -- 'pwd'
$ d run --no-early-exit \
    --id "ios" \
    --if "ios/Podfile" \
    -- \
    'cd ios
    pod install || pod install --repo-update'
$ d run \
    -- \
    '
    set -x
    echo $WORKSPACE_PATH
    echo $PACKAGE_PATH
    echo $PACKAGE_NAME
    '

func

func is a command that run a pre-defined function in d.yaml. func supports package filters and dependency filters.

Refer to the How to define functions in d.yaml section for more information.

test

test is a command to run flutter test [args...] command in every bootstrapped package that has any file matching test/**/*_test.dart.

test supports package filters and dependency filters.

Usage examples

$ d test --no-early-exit \
    --reporter expanded \
    --file-reporter \
    json:'$WORKSPACE_PATH'/reports/tests_'$PACKAGE_NAME'.json

graph

graph is a command to describe the dependency relationship among linked packages. graph command can be executed even if not bootstrapped yet.

Usage examples

$ d graph

clean

clean is a command to remove files that are automatically generated by d such as a bootstrap cache directory .d/ and pubspec_overrides.yaml files.

In addition, By specifying -f or --flutter, d can run flutter clean for each package.

# Remove auto-generated files. You need to run `d bootstrap` again.
$ d clean 
# or
# Run `flutter clean` as well as removing auto-generated files.
$ d clean [--flutter]

update

update is a command to self-update the d CLI or to list the available versions.

# Updates `d` to the latest version.
$ d update

# Updates `d` to the specific version `X.Y.Z`.
# Downgrade as well as upgrade is supported.
$ d update vX.Y.Z
# Show all available versions.
$ d update [--show-list | -l]

Common options

Early exit

  • [--early-exit]:
    • Exit as soon as possible when any failure happens on any package.
    • By default, enabled.
  • [--no-early-exit]:
    • Unlikely --early-exit, execute the given command in all packages even though runs into any kind of failure in a package.

Concurrency

  • [-c|--concurrency] <parallelism>:
    • Specifies the maximum parallelism. Defaults to 5.

Package filters

  • [--include-has-file|--if] <fileOrGlob>:
    • Includes only packages where have any file that specifies the given pattern. The pattern can be a relative file path from the package root directory or a relative glob pattern from the package root directory.
    • Can be repeated.
    • Prioritize --exclude-has-file option.
  • [--exclude-has-file|--ef] <fileOrGlob>:
    • Excludes packages where have any file that specifies the given pattern. The pattern can be a relative file path from the package root directory or a relative glob pattern from the package root directory.
    • Can be repeated.
  • [--include-has-dir|--id] <dirOrGlob>:
    • --id is an alias.
    • Includes only packages where have any directory that specifies the given pattern. The pattern can be a relative directory path from the package root directory or a relative glob pattern from the package root directory.
    • Can be repeated.
    • Prioritize --exclude-has-dir option.
  • [--exclude-has-dir|--ed] <dirOrGlob>:
    • Excludes packages where have any directory that specifies the given pattern. The pattern can be a relative directory path from the package root directory or a relative glob pattern from the package root directory.
    • Can be repeated.

Dependency filters

  • --include-dependency:
    • Includes only packages where have a dependency on the given package.
    • Can be repeated.
    • Prioritize --exclude-dependency option.
  • --exclude-dependency:
    • Excludes packages where have a dependency on the given package.
    • Can be repeated.
  • --include-direct-dependency:
    • Includes only packages where have a "direct" dependency on the given package.
    • Can be repeated.
    • Prioritize --exclude-direct-dependency option.
  • --exclude-direct-dependency:
    • Excludes packages where have a "direct" dependency on the given package.
    • Can be repeated.
  • --include-dev-dependency:
    • Includes only packages where have a "dev" dependency on the given package.
    • Can be repeated.
    • Prioritize --exclude-dev-dependency option.
  • --exclude-dev-dependency:
    • Excludes packages where have a "dev" dependency on the given package.
    • Can be repeated.

Pre-defined environment variables

d provides some pre-defined environment variables. These environment variables can be used in any command.

  • $WORKSPACE_PATH: The absolute path of the directory where d.yaml file is located.
  • $PACKAGE_PATH: The absolute path of the package root where a command is running on at the moment.
  • $PACKAGE_NAME: The name of the package where a command is running on at the moment.

About

Dart multi-package project manager

Topics

Resources

License

Stars

Watchers

Forks

Packages

 
 
 

Contributors