Composer plugin that provides a way for packages to expose scripts to the root project
Switch branches/tags
Nothing to show
Clone or download
Fetching latest commit…
Cannot retrieve the latest commit at this time.
Permalink
Failed to load latest commit information.
src
tests
.gitattributes
.gitignore
.travis.yml
CHANGELOG.rst
LICENSE
README.rst
composer.json
phpunit.xml.dist

README.rst

Composer package scripts

Composer plugin that provides a way for packages to expose custom scripts to the root project. These scripts work similarly to the root-only scripts option.

https://travis-ci.com/kuria/composer-pkg-scripts.svg?branch=master

Requirements

  • PHP 7.1+
  • Composer 1.6+

Terminology

root package
the main package (project)
root script
a script defined in the root package's scripts option
package script
a script defined in a package's extra.package-scripts option

Installation

Specify kuria/composer-pkg-scripts as a dependency in your composer.json.

This can be done either in the root package or in one of the required packages (perhaps a metapackage?). That depends entirely on your use case.

{
    // ...
    "require": {
        "kuria/composer-pkg-scripts": "^1.0"
    }
}

Defining package scripts

Package scripts can be defined in the composer.json's extra option.

The syntax is identical to the root-only scripts option. See Composer docs - defining scripts.

{
    "name": "acme/example",
    // ...
    "extra": {
        "package-scripts": {
            "hello-world": "echo Hello world!",
            "php-version": "php -v"
        }
    }
}

The final script names are automatically prefixed by the package name.

The example above will define the following scripts:

  • acme:example:hello-world
  • acme:example:php-version

To define shorter aliases, see Specifying aliases and help.

Note

Package scripts will not override root scripts with the same name.

Note

Package scripts defined in the root package will not be loaded. Use scripts instead.

Referencing other scripts

In addition to the root scripts, package scripts may reference other package scripts defined in the same file.

See Composer docs - referencing scripts.

{
    "name": "acme/example",
    // ...
    "extra": {
        "package-scripts": {
            "all": ["@first", "@second", "@third"],
            "first": "echo first",
            "second": "echo second",
            "third": "echo third"
        }
    }
}

Package scripts of other packages may be referenced using their full name or alias (if it exists). Using the full name should be preferred.

{
    "name": "acme/example",
    // ...
    "extra": {
        "package-scripts": {
            "another-foo": "@acme:another:foo"
        }
    }
}

Specifying aliases and help

Package script aliases and help can be defined in the composer.json's extra option.

{
    "name": "acme/example",
    // ...
    "extra": {
        "package-scripts": {
            "hello-world": "echo Hello world!",
            "php-version": "php -v"
        },
        "package-scripts-meta": {
            "hello-world": {"aliases": "hello", "help": "An example command"},
            "php-version": {"aliases": ["phpv", "pv"], "help": "Show PHP version"}
        }
    }
}

Unlike script names, aliases are not automatically prefixed by the package name.

The example above will define the following scripts:

  • acme:example:hello-world
  • acme:example:php-version
  • hello
  • phpv
  • pv

Note

Package script aliases will not override root scripts or other aliases with the same name.

Specifying aliases in the root package

If a package doesn't provide suitable aliases, the root package may define them in its scripts option.

{
    "name": "acme/project",
    // ...
    "scripts": {
        "acme-hello": "@acme:example:hello-world"
    }
}

Using variables

Unlike root scripts, package scripts may use variable placeholders.

The syntax of the placeholder is:

{$variable-name}
  • variable name can consist of any characters other than "}"
  • nonexistent variables resolve to an empty string
  • the final value is escaped by escapeshellarg()
  • array variables will be imploded and separated by spaces, with each value escaped by escapeshellarg()

Composer configuration

All Composer configuration directives are available through variables.

See Composer docs - config.

{
    "name": "acme/example",
    // ...
    "extra": {
        "package-scripts": {
            "list-vendors": "ls {$vendor-dir}"
        }
    }
}

Package variables

Packages may define their own variables in the composer.json's extra option.

{
    "name": "acme/example",
    // ...
    "extra": {
        "package-scripts": {
            "hello": "echo {$name}"
        },
        "package-scripts-vars": {
            "name": "Bob"
        }
    }
}

These defaults may then be overriden in the root package, if needed:

{
    "name": "acme/project",
    // ...
    "extra": {
        "package-scripts-vars": {
            "acme/example": {
                "name": "John"
            }
        }
    }
}
Referencing other variables

Package variables may reference composer configuration directives or other package variables belonging to the same package.

{
    "name": "acme/example",
    // ...
    "extra": {
        "package-scripts": {
            "hello": "echo Hello {$names}",
            "show-paths": "echo {$paths}"
        },
        "package-scripts-vars": {
            "names": ["Bob", "{$other-names}"],
            "other-names": ["John", "Nick"],
            "paths": ["{$vendor-dir}", "{$bin-dir}"]
        }
    }
}
composer acme:example:hello
> echo Hello "Bob" "John" "Nick"
Hello Bob John Nick
composer acme:example:show-paths
> echo "/project/vendor" "/project/vendor/bin"
/project/vendor /project/vendor/bin

Note

Array variables must be referenced directly, e.g. "{$array-var}", not embedded in the middle of a string.

Nested array variable references are flattened into a simple list, as seen in the examples above.

Running package scripts

Package scripts can be invoked the same way root scripts can:

  1. composer run-script acme:example:hello-world
  2. composer acme:example:hello-world

See Composer docs - running scripts manually.

Using package scripts in events

Package scripts may be used in event scripts (provided the plugin is loaded at that point).

{
    "name": "acme/project",
    // ...
    "scripts": {
        "post-install-cmd": "@acme:example:hello-world"
    }
}

Listing package scripts

This plugin provides a command called package-scripts:list, which lists both active and inactive package scripts and aliases.

composer package-scripts:list
Available package scripts:
  acme:example:hello-world (hello)    An example command
  acme:example:php-version (phpv, pv) Show PHP version

Enabling verbose mode will show additonal information:

composer package-scripts:list -v
Available package scripts:
  acme:example:hello-world Run the "hello-world" script from acme/example
   - package: acme/example
   - definition: "echo Hello world!"
   - aliases:
  acme:example:php-version Run the "php-version" script from acme/example
   - package: acme/example
   - definition: "php -v"
   - aliases:

You may use the psl alias instead of the full command name.

Debugging package scripts and variables

This plugin provides a command called package-scripts:dump, which dumps compiled scripts (including root scripts) or package script variables.

composer package-scripts:dump

Specifying the --vars flag will dump compiled package script variables instead:

composer package-scripts:dump --vars

You may use the psd alias instead of the full command name.