PHPackages                             typo3/tailor - PHPackages - PHPackages  [Skip to content](#main-content)[PHPackages](/)[Directory](/)[Categories](/categories)[Trending](/trending)[Leaderboard](/leaderboard)[Changelog](/changelog)[Analyze](/analyze)[Collections](/collections)[Log in](/login)[Sign up](/register)

1. [Directory](/)
2. /
3. [CLI &amp; Console](/categories/cli)
4. /
5. typo3/tailor

ActiveLibrary[CLI &amp; Console](/categories/cli)

typo3/tailor
============

A CLI tool to make TYPO3 extension handling easier

1.7.0(1y ago)32111.5k↑76%12[5 issues](https://github.com/TYPO3/tailor/issues)[2 PRs](https://github.com/TYPO3/tailor/pulls)20MITPHPPHP ^7.2 || ^8.0CI passing

Since Dec 2Pushed 9mo ago3 watchersCompare

[ Source](https://github.com/TYPO3/tailor)[ Packagist](https://packagist.org/packages/typo3/tailor)[ RSS](/packages/typo3-tailor/feed)WikiDiscussions main Synced 1mo ago

READMEChangelog (10)Dependencies (6)Versions (13)Used By (20)

Tailor
======

[](#tailor)

[![Tests](https://github.com/TYPO3/tailor/workflows/tests/badge.svg)](https://github.com/TYPO3/tailor/workflows/tests/badge.svg)

Tailor is a CLI application to help you maintain your extensions. Tailor talks with the [TER REST API](https://extensions.typo3.org/faq/rest-api/) and enables you to register new keys, update extension information and publish new versions to the [extension repository](https://extensions.typo3.org).

Contents
--------

[](#contents)

- [Prerequisites](#prerequisites)
- [Installation](#installation)
- [Usage](#usage)
    - [Manage your personal access token](#manage-your-personal-access-token)
    - [Register a new extension key](#register-a-new-extension-key)
    - [Update the version in your extension files](#update-the-version-in-your-extension-files)
    - [Publish a new version of an extension to TER](#publish-a-new-version-of-an-extension-to-ter)
    - [Create a local artefact of an extension](#create-a-local-artefact-of-an-extension)
    - [Update extension meta information](#update-extension-meta-information)
    - [Transfer ownership of an extension to another user](#transfer-ownership-of-an-extension-to-another-user)
    - [Delete / abandon an extension](#delete--abandon-an-extension)
    - [Find and filter extensions on TER](#find-and-filter-extensions-on-ter)
        - [Specific extension details](#specific-extension-details)
        - [Specific extension version details](#specific-extension-version-details)
        - [Details for all versions of an extension](#details-for-all-versions-of-an-extension)
- [Publish a new version using tailor locally](#publish-a-new-version-using-tailor-locally)
- [Publish a new version using your CI](#publish-a-new-version-using-your-ci)
    - [Github actions workflow](#github-actions-workflow)
    - [GitLab pipeline](#gitlab-pipeline)
- [Exclude paths from packaging](#exclude-paths-from-packaging)
- [Overview of all available commands](#overview-of-all-available-commands)
    - [General options for all commands](#general-options-for-all-commands)
- [Author &amp; License](#author--license)

Prerequisites
-------------

[](#prerequisites)

The [TER REST API](https://extensions.typo3.org/faq/rest-api/) can be accessed providing a personal access token. You can create such token either on [https://extensions.typo3.org/](https://extensions.typo3.org) after you've logged in, or directly using Tailor.

Important

To create, refresh or revoke an access token with Tailor, you have to add your TYPO3.org credentials (see below). Even if it is possible to execute all commands using the TYPO3.org credentials for authentication, it is highly discouraged. That's why we have built token based authentication for the [TER](https://extensions.typo3.org).

Provide your credentials by either creating a `.env` file in the project root folder or setting environment variables through your system to this PHP script:

```
TYPO3_API_TOKEN=
TYPO3_API_USERNAME=
TYPO3_API_PASSWORD=
```

Note

For an overview of all available environment variables, have a look at the `.env.dist` file.

Tip

You can also add environment variables directly on executing a command. This overrides any variable, defined in the `.env` file.

Example:

```
TYPO3_API_TOKEN="someToken" TYPO3_EXTENSION_KEY="ext_key" bin/tailor ter:details
```

This will display the extension details for extension `ext_key` if `someToken` is valid (not expired/revoked and having at least the `extension:read` scope assigned).

Installation
------------

[](#installation)

Use Tailor as a dev dependency via composer of your extensions:

```
composer req --dev typo3/tailor
```

Usage
-----

[](#usage)

All commands, requesting the TER API, provide the `-r, --raw`option. If set, the raw result will be returned. This can be used for further processing e.g. by using some JSON processor.

Most of the commands require an extension key to work with. There are multiple possibilities to provide an extension key. These are - in the order in which they are checked:

- As argument, e.g. `./vendor/bin/tailor ter:details my_key`
- As environment variable, `TYPO3_EXTENSION_KEY=my_key`
- In your `composer.json`, `[extra][typo3/cms][extension-key] = 'my_key'`

This means, even if you have an extension key defined globally, either as environment variable or in your `composer.json`, you can still run all commands for different extensions by adding the desired extension key as argument to the command.

Note

If no extension key is defined, neither as an argument, as environment variable, nor in your `composer.json`, commands which require an extension key to be set, will throw an exception.

### Manage your personal access token

[](#manage-your-personal-access-token)

Use the `ter:token:create` command to create a new token:

```
./vendor/bin/tailor ter:token:create --name="token for my_extension" --extensions=my_extension
```

The result will look like this:

```
Token type: bearer
Access token: eyJ0eXAOiEJKV1QiLCJhb
Refresh token: eyJ0eXMRxHRaF4hIVrEtu
Expires in: 604800
Scope: extension:read,extension:write
Extensions: my_extension

```

As you can see, this will create an access token which is only valid for the extension `my_extension`. The scopes are set to `extension:read,extension:write` since this is the default if option `--scope` is not provided. The same applies to the expiration date which can be set with the option `--expires`.

If the token threatens to expire, refresh it with `ter:token:refresh`:

```
./vendor/bin/tailor ter:token:refresh eyJ0eXMRxHRaF4hIVrEtu
```

This will generate new access and refresh tokens with the same options, initially set on creation.

To revoke an access token irretrievably, use `ter:token:revoke`:

```
./vendor/bin/tailor ter:token:revoke eyJ0eXAOiEJKV1QiLCJhb
```

### Register a new extension key

[](#register-a-new-extension-key)

To register a new extension, use `ter:register` by providing your desired extension key as argument:

```
./vendor/bin/tailor ter:register my_extension
```

This registers the key `my_extension` and returns following confirmation:

```
Key: my_extension
Owner: your_username
```

### Update the version in your extension files

[](#update-the-version-in-your-extension-files)

Prior to publishing a new version, you have to update the version in your extensions `ext_emconf.php` file. This can be done using the `set-version` command.

```
./vendor/bin/tailor set-version 1.2.0
```

If your extension also contains a `Documentation/guides.xml`or `Documentation/Settings.cfg` file, the command will also update the `release` and `version` information in it. You can disable this feature by either using `--no-docs` or by setting the environment variable `TYPO3_DISABLE_DOCS_VERSION_UPDATE=1`.

Tip

It's also possible to use the `--path` option to specify the location of your extension. If not given, your current working directory is search for the `ext_emconf.php`file.

Note

The version will only be updated if already present in your `ext_emconf.php`. It won't be added by this command.

### Publish a new version of an extension to TER

[](#publish-a-new-version-of-an-extension-to-ter)

You can publish a new version of your extension using the `ter:publish` command. Therefore, provide the extension key and version number as arguments followed by the path to the extension directory or an artefact (a zipped version of your extension). The latter can be either local or a remote file.

Using `--path`:

```
./vendor/bin/tailor ter:publish 1.2.0 my_extension --path=/path/to/my_extension
```

Using a local `--artefact`:

```
./vendor/bin/tailor ter:publish 1.2.0 my_extension --artefact=/path/to/any-zip-file/my_extension.zip
```

Using a remote `--artefact`:

```
./vendor/bin/tailor ter:publish 1.2.0 my_extension --artefact=https://github.com/my-name/my_extension/archive/1.2.0.zip
```

Using the root direcotry:

```
./vendor/bin/tailor ter:publish 1.2.0 my_extension
```

If the extension key is defined as environment variable or in your `composer.json`, it can also be skipped. So using the current root directory the whole command simplifies to:

```
./vendor/bin/tailor ter:publish 1.2.0
```

Important

A couple of directories and files are excluded from packaging by default. Read more about [excluding paths from packaging](#exclude-paths-from-packaging)below.

Note

The REST API, just like the the [TER](https://extensions.typo3.org), requires an upload comment to be set. This can be achieved using the `--comment` option. If not set, Tailor will automatically use `Updated extension to ` as comment.

### Create a local artefact of an extension

[](#create-a-local-artefact-of-an-extension)

You can generate a local artefact of your extension using the `create-artefact` command. This will generate a zip archive ready to be uploaded to TER (which is not covered by this command, have a look at the [`ter:publish`](#publish-a-new-version-of-an-extension-to-ter)command instead).

Provide the version number and extension key as arguments followed by the path to the extension directory or an artefact (a zipped version of your extension). The latter can be either local or a remote file.

Using `--path`:

```
./vendor/bin/tailor create-artefact 1.2.0 my_extension --path=/path/to/my_extension
```

Using a local `--artefact`:

```
./vendor/bin/tailor create-artefact 1.2.0 my_extension --artefact=/path/to/any-zip-file/my_extension.zip
```

Using a remote `--artefact`:

```
./vendor/bin/tailor create-artefact 1.2.0 my_extension --artefact=https://github.com/my-name/my_extension/archive/1.2.0.zip
```

Using the root directory:

```
./vendor/bin/tailor create-artefact 1.2.0 my_extension
```

If the extension key is defined as environment variable or in your `composer.json`, it can also be skipped. So using the current root directory the whole command simplifies to:

```
./vendor/bin/tailor create-artefact 1.2.0
```

Important

A couple of directories and files are excluded from packaging by default. Read more about [excluding paths from packaging](#exclude-paths-from-packaging)below.

### Update extension meta information

[](#update-extension-meta-information)

You can update the extension meta information, such as the composer name, or the associated tags with the `ter:update`command.

To update the composer name:

```
./vendor/bin/tailor ter:update my_extension --composer=vender/my_extension
```

To update the tags:

```
./vendor/bin/tailor ter:update my_extension --tags=some-tag,another-tag
```

Please use `./vendor/bin/tailor ter:update -h` to see the full list of available options.

Important

All options set with this command will overwrite the existing data. Therefore, if you, for example, just want to add another tag, you have to add the current ones along with the new one. You can use `ter:details` to get the current state.

### Transfer ownership of an extension to another user

[](#transfer-ownership-of-an-extension-to-another-user)

It's possible to transfer one of your extensions to another user. Therefore, use the `ter:transfer` command providing the extension key to be transferred and the TYPO3.org username of the recipient.

Since you won't have any access to the extension afterwards, the command asks for your confirmation before sending the order to the REST API.

```
./vendor/bin/tailor ter:transfer some_user my_extension
```

This transfers the extension `my_extension` to the user `some_user` and returns following confirmation:

```
Key: my_extension
Owner: some_user
```

Tip

For automated workflows the confirmation can be skipped with the `-n, --no-interaction` option.

### Delete / abandon an extension

[](#delete--abandon-an-extension)

You can easily delete / abandon extensions with Tailor using the `ter:delete` command. This either removes the extension entirely or just abandons it if the extension still has public versions.

Since you won't have any access to the extension afterwards, the command asks for your confirmation before sending the order to the REST API.

```
./vendor/bin/tailor ter:delete my_extension
```

This will delete / abandon the extension `my_extension`.

Tip

For automated workflows the confirmation can be skipped with the `-n, --no-interaction` option.

### Find and filter extensions on TER

[](#find-and-filter-extensions-on-ter)

Tailor can't only be used for managing your extensions but also to find others. Therefore, use `ter:find` by adding some filters:

```
./vendor/bin/tailor ter:find
./vendor/bin/tailor ter:find --typo3-version=9
./vendor/bin/tailor ter:find --typo3-author=some_user
```

First command will find all public extensions. The second and third one will only return extensions which match the filter. In this case being compatible with TYPO3 version `9` or owned by `some_user`.

To limit / paginate the result, you can use the options `--page` and `--per_page`:

```
./vendor/bin/tailor ter:find --page=3 --per_page=20
```

#### Specific extension details

[](#specific-extension-details)

You can also request more details about a specific extension using the `ter:details` command:

```
./vendor/bin/tailor ter:details my_extension
```

This will return details about the extension `my_extension`like the current version, the author, some meta information and more. Similar to the extension detail page on [extension.typo3.org](https://extensions.typo3.org).

#### Specific extension version details

[](#specific-extension-version-details)

If you like to get details about a specific version of an extension, `ter:version` can be used:

```
./vendor/bin/tailor ter:version 1.0.0 my_extension
```

This will return details about version `1.0.0` of extension `my_extension`.

#### Details for all versions of an extension

[](#details-for-all-versions-of-an-extension)

You can also get the details for all versions of an extension with `ter:versions`:

```
./vendor/bin/tailor ter:versions my_extension
```

This will return the details for all version of the extension `my_extension`.

Publish a new version using tailor locally
------------------------------------------

[](#publish-a-new-version-using-tailor-locally)

**Step 1: Update the version in your extension files**

```
./vendor/bin/tailor set-version 1.5.0
```

**Step 2: Commit the changes and add a tag**

```
git commit -am "[RELEASE] A new version was published"
git tag -a 1.5.0
```

**Step 3: Push this to your remote repository**

```
git push origin --tags
```

**Step 4: Push this version to TER**

```
./vendor/bin/tailor ter:publish 1.5.0
```

Note

Both `set-version` and `ter:publish` provide options to specify the location of your extension. If, like in the example above, non is set, Tailor automatically uses your current working directory.

Publish a new version using your CI
-----------------------------------

[](#publish-a-new-version-using-your-ci)

You can also integrate tailor into you GitHub workflow respectively your GitLab pipeline. Therefore, **Step 1**, **Step 2** and **Step 3**from the above example are the same. **Step 4** could then be done by your integration.

Please have a look at the following examples describing how such integration could look like for GitHub workflows and GitLab pipelines.

### Github actions workflow

[](#github-actions-workflow)

The workflow will only be executed when pushing a new tag. This can either be done using **Step 3** from above example or by creating a new GitHub release which will also add a new tag.

The workflow furthermore requires the GitHub secrets `TYPO3_EXTENSION_KEY`and `TYPO3_API_TOKEN` to be set. Add them at "Settings -&gt; Secrets -&gt; New repository secret".

Note

If your `composer.json` file contains the extension key at `[extra][typo3/cms][extension-key] = 'my_key'` (this is good practice anyway), the `TYPO3_EXTENSION_KEY` secret and assignment in the below GitHub action example is not needed, tailor will pick it up.

The version is automatically fetched from the tag and validated to match the required pattern.

The commit message from **Step 2** is used as the release comment. If it's empty, a static text will be used.

To see the following workflow in action, please have a look at the [tailor\_ext](https://github.com/o-ba/tailor_ext) example extension.

```
name: publish
on:
  push:
    tags:
      - '*'
jobs:
  publish:
    name: Publish new version to TER
    # use folliwing if tags begins with `v`
    # if: startsWith(github.ref, 'refs/tags/v')
    if: startsWith(github.ref, 'refs/tags/')
    runs-on: ubuntu-20.04
    env:
      TYPO3_EXTENSION_KEY: ${{ secrets.TYPO3_EXTENSION_KEY }}
      TYPO3_API_TOKEN: ${{ secrets.TYPO3_API_TOKEN }}
    steps:
      - name: Checkout repository
        uses: actions/checkout@v3

      - name: Check tag
        run: |
          # use ^refs/tags/v[0-9]{1,3}.[0-9]{1,3}.[0-9]{1,3}$ when tag is prefixed with v
          if ! [[ ${{ github.ref }} =~ ^refs/tags/[0-9]{1,3}.[0-9]{1,3}.[0-9]{1,3}$ ]]; then
            exit 1
          fi

      - name: Get version
        id: get-version
        run: echo "version=${GITHUB_REF/refs\/tags\//}" >> $GITHUB_ENV

      - name: Get comment
        id: get-comment
        run: |
          # If tag begins with `v` use:
          # readonly local comment=$(git tag -l v${{ env.version }} --format '%(contents))
          readonly local comment=$(git tag -l ${{ env.version }} --format '%(contents))

          if [[ -z "${comment// }" ]]; then
            echo "comment=Released version ${{ env.version }} of ${{ env.TYPO3_EXTENSION_KEY }}" >> $GITHUB_ENV
          else
            {
              echo 'comment
