- Notifications
You must be signed in to change notification settings - Fork0
CLI Tool for maintaining public TYPO3 Extensions
License
eliashaeussler/tailor
Folders and files
Name | Name | Last commit message | Last commit date | |
---|---|---|---|---|
Repository files navigation
Tailor is a CLI application to help you maintain your extensions.Tailor talks with theTER REST API and enables you toregister new keys, update extension information and publish newversions to theextension repository.
- Prerequisites
- Installation
- Usage
- Manage your personal access token
- Register a new extension key
- Update the version in your extension files
- Publish a new version of an extension to TER
- Create a local artefact of an extension
- Update extension meta information
- Transfer ownership of an extension to another user
- Delete / abandon an extension
- Find and filter extensions on TER
- Publish a new version using tailor locally
- Publish a new version using your CI
- Exclude paths from packaging
- Overview of all available commands
- Author & License
TheTER REST API can be accessed providing a personalaccess token. You can create such token either onhttps://extensions.typo3.org/ after you've logged in, ordirectly 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 itis possible to execute all commands using the TYPO3.org credentialsfor authentication, it is highly discouraged. That's why we havebuilt token based authentication for theTER.
Provide your credentials by either creating a.env
file in theproject root folder or setting environment variables through yoursystem to this PHP script:
TYPO3_API_TOKEN=<your-token>TYPO3_API_USERNAME=<your-t3o-username>TYPO3_API_PASSWORD=<your-t3o-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 onexecuting a command. This overrides any variable, defined inthe.env
file.
Example:
TYPO3_API_TOKEN="someToken" TYPO3_EXTENSION_KEY="ext_key" bin/tailor ter:details
This will display the extension details for extensionext_key
ifsomeToken
is valid (not expired/revoked and having at least theextension:read
scope assigned).
Use Tailor as a dev dependency via composer of your extensions:
composer req --dev typo3/tailor
All commands, requesting the TER API, provide the-r, --raw
option. If set, the raw result will be returned. This can beused 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 yourcomposer.json
, youcan still run all commands for different extensions by addingthe desired extension key as argument to the command.
Note
If no extension key is defined, neither as an argument,as environment variable, nor in yourcomposer.json
, commandswhich require an extension key to be set, will throw an exception.
Use theter: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: bearerAccess token: eyJ0eXAOiEJKV1QiLCJhbRefresh token: eyJ0eXMRxHRaF4hIVrEtuExpires in: 604800Scope: extension:read,extension:writeExtensions: my_extension
As you can see, this will create an access token which is onlyvalid for the extensionmy_extension
. The scopes are set toextension:read,extension:write
since this is the default ifoption--scope
is not provided. The same applies to theexpiration date which can be set with the option--expires
.
If the token threatens to expire, refresh it withter:token:refresh
:
./vendor/bin/tailor ter:token:refresh eyJ0eXMRxHRaF4hIVrEtu
This will generate new access and refresh tokens with the sameoptions, initially set on creation.
To revoke an access token irretrievably, useter:token:revoke
:
./vendor/bin/tailor ter:token:revoke eyJ0eXAOiEJKV1QiLCJhb
To register a new extension, useter:register
by providingyour desired extension key as argument:
./vendor/bin/tailor ter:register my_extension
This registers the keymy_extension
and returns followingconfirmation:
Key: my_extensionOwner: your_username
Prior to publishing a new version, you have to update theversion in your extensionsext_emconf.php
file. This canbe done using theset-version
command.
./vendor/bin/tailor set-version 1.2.0
If your extension also contains aDocumentation/Settings.cfg
file, the command will also update therelease
andversion
information in it. You can disable this feature by eitherusing--no-docs
or by setting the environment variableTYPO3_DISABLE_DOCS_VERSION_UPDATE=1
.
Tip
It's also possible to use the--path
option tospecify the location of your extension. If not given, yourcurrent working directory is search for theext_emconf.php
file.
Note
The version will only be updated if already presentin yourext_emconf.php
. It won't be added by this command.
You can publish a new version of your extension using theter:publish
command. Therefore, provide the extension keyand version number as arguments followed by the path to theextension directory or an artefact (a zipped version of yourextension). 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 orin yourcomposer.json
, it can also be skipped. So using thecurrent 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 packagingby default. Read more aboutexcluding paths from packagingbelow.
Note
The REST API, just like the theTER, requiresan upload comment to be set. This can be achieved using the--comment
option. If not set, Tailor will automatically useUpdated extension to <version>
as comment.
You can generate a local artefact of your extension using thecreate-artefact
command. This will generate a zip archiveready to be uploaded to TER (which is not covered by thiscommand, have a look at theter:publish
command instead).
Provide the version number and extension key as argumentsfollowed by the path to the extension directory or an artefact(a zipped version of your extension). The latter can be eitherlocal 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 orin yourcomposer.json
, it can also be skipped. So using thecurrent 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 packagingby default. Read more aboutexcluding paths from packagingbelow.
You can update the extension meta information, such as thecomposer name, or the associated tags with theter: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 fulllist of available options.
Important
All options set with this command will overwrite theexisting data. Therefore, if you, for example, just want to addanother tag, you have to add the current ones along with the newone. You can useter:details
to get the current state.
It's possible to transfer one of your extensions to another user.Therefore, use theter:transfer
command providing the extensionkey to be transferred and the TYPO3.org username of the recipient.
Since you won't have any access to the extension afterwards, thecommand asks for your confirmation before sending the order tothe REST API.
./vendor/bin/tailor ter:transfer some_user my_extension
This transfers the extensionmy_extension
to the usersome_user
and returns following confirmation:
Key: my_extensionOwner: some_user
Tip
For automated workflows the confirmation can beskipped with the-n, --no-interaction
option.
You can easily delete / abandon extensions with Tailor usingtheter:delete
command. This either removes the extensionentirely or just abandons it if the extension still has publicversions.
Since you won't have any access to the extension afterwards,the command asks for your confirmation before sending the orderto the REST API.
./vendor/bin/tailor ter:delete my_extension
This will delete / abandon the extensionmy_extension
.
Tip
For automated workflows the confirmation can beskipped with the-n, --no-interaction
option.
Tailor can't only be used for managing your extensions butalso to find others. Therefore, useter:find
by adding somefilters:
./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 secondand third one will only return extensions which match thefilter. In this case being compatible with TYPO3 version9
or owned bysome_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
You can also request more details about a specific extensionusing theter:details
command:
./vendor/bin/tailor ter:details my_extension
This will return details about the extensionmy_extension
like the current version, the author, some meta informationand more. Similar to the extension detail page onextension.typo3.org.
If you like to get details about a specific version of anextension,ter:version
can be used:
./vendor/bin/tailor ter:version 1.0.0 my_extension
This will return details about version1.0.0
of extensionmy_extension
.
You can also get the details for all versions of an extensionwithter:versions
:
./vendor/bin/tailor ter:versions my_extension
This will return the details for all version of the extensionmy_extension
.
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
Bothset-version
andter:publish
provide optionsto specify the location of your extension. If, like in the exampleabove, non is set, Tailor automatically uses your current workingdirectory.
You can also integrate tailor into you GitHub workflow respectivelyyour GitLab pipeline. Therefore,Step 1,Step 2 andStep 3from the above example are the same.Step 4 could then bedone by your integration.
Please have a look at the following examples describing howsuch integration could look like for GitHub workflows andGitLab pipelines.
The workflow will only be executed when pushing a new tag.This can either be done usingStep 3 from above exampleor by creating a new GitHub release which will also add anew tag.
The workflow furthermore requires the GitHub secretsTYPO3_EXTENSION_KEY
andTYPO3_API_TOKEN
to be set. Add them at "Settings -> Secrets -> Newrepository secret".
Note
If yourcomposer.json
file contains the extension key at[extra][typo3/cms][extension-key] = 'my_key'
(this is good practice anyway),theTYPO3_EXTENSION_KEY
secret and assignment in the below GitHub actionexample is not needed, tailor will pick it up.
The version is automatically fetched from the tag andvalidated to match the required pattern.
The commit message fromStep 2 is used as the releasecomment. If it's empty, a static text will be used.
To see the following workflow in action, please have alook at thetailor_ext example extension.
name:publishon:push:tags: -'*'jobs:publish:name:Publish new version to TERif:startsWith(github.ref, 'refs/tags/')runs-on:ubuntu-20.04env:TYPO3_EXTENSION_KEY:${{ secrets.TYPO3_EXTENSION_KEY }}TYPO3_API_TOKEN:${{ secrets.TYPO3_API_TOKEN }}steps: -name:Checkout repositoryuses:actions/checkout@v3 -name:Check tagrun:| if ! [[ ${{ github.ref }} =~ ^refs/tags/[0-9]{1,3}.[0-9]{1,3}.[0-9]{1,3}$ ]]; then exit 1 fi -name:Get versionid:get-versionrun:echo "version=${GITHUB_REF/refs\/tags\//}" >> $GITHUB_ENV -name:Get commentid:get-commentrun:| readonly local comment=$(git tag -n10 -l ${{ env.version }} | sed "s/^[0-9.]*[ ]*//g") if [[ -z "${comment// }" ]]; then echo "comment=Released version ${{ env.version }} of ${{ env.TYPO3_EXTENSION_KEY }}" >> $GITHUB_ENV else { echo 'comment<<EOF' echo "$comment" echo EOF } >> "$GITHUB_ENV" fi -name:Setup PHPuses:shivammathur/setup-php@v2with:php-version:7.4extensions:intl, mbstring, json, zip, curltools:composer:v2 -name:Install tailorrun:composer global require typo3/tailor --prefer-dist --no-progress --no-suggest -name:Publish to TERrun:php ~/.composer/vendor/bin/tailor ter:publish --comment "${{ env.comment }}" ${{ env.version }}
Important
If you're using tags with a leadingv
the above example needs to be adjusted.
- The regular expression in stepCheck tag should be:
^refs/tags/v[0-9]{1,3}.[0-9]{1,3}.[0-9]{1,3}$
- The output format in stepGet version should be:
${GITHUB_REF#refs/tags/v}
- The variable declaration in stepGet comment should be:
$(git tag -n10 -l v${{ env.version }}| sed"s/^v[0-9.]*[ ]*//g")
Additionally, to further simplify your workflow, you can also use thetypo3-uploader-ter GitHub action from TYPO3 communitymember Tomas Norre. For more information about the usage, please refer to thecorrespondingREADME.
The job will only be executed when pushing a new tag.The upload comment is taken from the message in the tag.
The job furthermore requires the GitLab variablesTYPO3_EXTENSION_KEY
andTYPO3_API_TOKEN
to be set.
Note
If yourcomposer.json
file contains your extensionkey, you can remove theTYPO3_EXTENSION_KEY
variable, thecheck and the assignment in the GitLab pipeline, since Tailorautomatically fetches this key then.
The variableCI_COMMIT_TAG
is set by GitLab automatically.
"Publish new version to TER":stage:releaseimage:composer:2only: -tagsbefore_script: -composer global require typo3/tailorscript: -> if [ -n "$CI_COMMIT_TAG" ] && [ -n "$TYPO3_API_TOKEN" ] && [ -n "$TYPO3_EXTENSION_KEY" ]; then echo -e "Preparing upload of release ${CI_COMMIT_TAG} to TER\n" # Cleanup before we upload git reset --hard HEAD && git clean -fx # Upload TAG_MESSAGE=`git tag -n10 -l $CI_COMMIT_TAG | sed 's/^[0-9.]*[ ]*//g'` echo "Uploading release ${CI_COMMIT_TAG} to TER" /tmp/vendor/bin/tailor ter:publish --comment "$TAG_MESSAGE" "$CI_COMMIT_TAG" "$TYPO3_EXTENSION_KEY" fi;
A couple of directories and files are excludedfrom packaging by default. You can find the configuration inconf/ExcludeFromPackaging.php
.
If you like, you can also use a custom configuration. Just add thepath to your custom configuration file to the environment variableTYPO3_EXCLUDE_FROM_PACKAGING
. This file must return anarray
with the keysdirectories
andfiles
on root level.
Commands | Arguments | Options | Description |
---|---|---|---|
set-version | version | --path --no-docs | Update the version in extension files |
ter:delete | extensionkey | Delete an extension. | |
ter:details | extensionkey | Fetch details about an extension. | |
ter:find | --page --per-page --author --typo3-version | Fetch a list of extensions from TER. | |
ter:publish | version extensionkey | --path --artefact --comment | Publishes a new version of an extension to TER. |
create-artefact | version extensionkey | --path --artefact | Create an artefact file (zip archive) of an extension. |
ter:register | extensionkey | Register a new extension key in TER. | |
ter:token:create | --name --expires --scope --extensions | Request an access token for the TER. | |
ter:token:refresh | token | Refresh an access token for the TER. | |
ter:token:revoke | token | Revoke an access token for the TER. | |
ter:transfer | username extensionkey | Transfer ownership of an extension key. | |
ter:update | extensionkey | --composer --issues --repository --manual --paypal --tags | Update extension meta information. |
ter:version | version extensionkey | Fetch details about an extension version. | |
ter:versions | extensionkey | Fetch details for all versions of an extension. |
-r, --raw
Return result as raw object (e.g. json) - Only for commands,requesting the TER API-h, --help
Display help message-q, --quiet
Do not output any message-v, --version
Display the CLI applications' version-n, --no-interaction
Do not ask any interactive question-v|vv|vvv, --verbose
Increase the verbosity of messages: 1 for normal output, 2for more verbose output and 3 for debug--ansi
Force ANSI output--no-ansi
Disable ANSI output
Created by Benni Mack and Oliver Bartsch.
MIT License, see LICENSE