Sending Message to Mattermost With PHP and Github Actions
Today I show you how you can send notifications to Mattermost with PHP and Github Actions. There are some implementations on Github Marketplace but nothing was made with PHP, there was Javascript, Go, or Python. But PHP can be used to create command-line utilities and it's very easy. Don't trust me? Come I'll show you.
Creating new project
First of all, create a new folder for your project, mine is action-mattermost-notify
. You can do this with the command as follows.
mkdir action-mattermost-notify
Now initializae new repository
# cd action-mattermost-notify
composer init
The composer will ask you for some information such as project name, author name, and email. When you are done you will have a folder structure like this one:
action-mattermost-notify
├── composer.json
├── composer.lock
├── src
└── vendor
Now You need to add some dependencies. (Here are two of them). The first one is the HTTP client and the second one is Console.
# cd action-mattermost-notify
composer require symfony/http-client
composer require symfony/console
After this step, 1st part is done. Go to next step.
Creating Console application
With the Console
component is creating a new console application easy. When you finish this part your folder structure will look like follows
action-mattermost-notify
├── app.php # Added this one
├── composer.json
├── composer.lock
├── src
│ └── SendCommand.php # Added this one
└── vendor
First create app.php
, which is the main file that launches your console application, and put there following content.
# app.php
require __DIR__ . '/vendor/autoload.php';
use Symfony\Component\Console\Application;
# Load version information from the composer file
# You will need to add a version tag to your composer.json
$version = json_decode(file_get_contents(__DIR__ . '/composer.json'), true);
$app = new Application('Action Mattermost Notify', $version['version']);
$app->run();
Good job! Now try to run it
php app.php
Action Mattermost Notify 1.0.0
Usage:
command [options] [arguments]
Options:
-h, --help Display help for the given command. When no command is given display help for the list command
-q, --quiet Do not output any message
-V, --version Display this application version
--ansi|--no-ansi Force (or disable --no-ansi) ANSI output
-n, --no-interaction Do not ask any interactive question
-v|vv|vvv, --verbose Increase the verbosity of messages: 1 for normal output, 2 for more verbose output and 3 for debug
Available commands:
completion Dump the shell completion script
help Display help for a command
list List commands
Next, you need to create a new command that will communicate with Mattermost. Go into the src
folder and create SendCommand.php
# cd src
touch SendCommand.php
...and put there following content
<?php
declare(strict_types=1);
# Change namespace to your project's namespace
namespace Maymeow\ActionMattermostNotify;
use Symfony\Component\Console\Command\Command;
use Symfony\Component\Console\Input\InputArgument;
use Symfony\Component\Console\Input\InputInterface;
use Symfony\Component\Console\Input\InputOption;
use Symfony\Component\Console\Output\OutputInterface;
use Symfony\Component\HttpClient\HttpClient;
class SendCommand extends Command
{
protected static $defaultName = 'send';
/**
* Configure method
*
* @return void
*/
public function configure(): void
{
$this
->setDescription('Send a message to Mattermost')
->setHelp('This command allows you to send a message to Mattermost');
$this
->addArgument('message', InputArgument::REQUIRED, 'The message to send')
->addOption('channel', null, InputOption::VALUE_OPTIONAL, 'The channel to send the message to')
->addOption('username', null, InputOption::VALUE_OPTIONAL, 'The username to send the message as')
->addOption('icon', null, InputOption::VALUE_OPTIONAL, 'The icon to send the message with')
->addOption('url', null, InputOption::VALUE_OPTIONAL, 'The URL to send the message with');
}
/**
* Execute method
*
* @param \Symfony\Component\Console\Input\InputInterface $input Input interface
* @param \Symfony\Component\Console\Output\OutputInterface $output Output interface
* @return int
*/
public function execute(InputInterface $input, OutputInterface $output): int
{
$message = $input->getArgument('message');
$channel = $input->getOption('channel');
$username = $input->getOption('username');
$icon = $input->getOption('icon');
$url = $input->getOption('url');
$client = HttpClient::create();
$response = $client->request('POST', $url, [
'body' => json_encode([
'channel' => $channel,
'text' => $message,
'username' => $username,
'icon_url' => $icon,
]),
'headers' => [
'Content-Type' => 'application/json',
],
]);
$output->writeln($response->getContent());
return Command::SUCCESS;
}
}
Let me show you what are parts of this file doing
public function configure(): void
The function above, as the name says, is used to configure your command. It tells your application what argument or options this command needs, its name, and description or you can modify the handler (how you call it from command line).
public function execute(InputInterface $input, OutputInterface $output): int
Function execute is the one where all magic happens. It is used to execute your actions.
The part below is HTTP Client that calls your webhook with the POST method and sends there required information.
// SendCommand::execute()
//...
$client = HttpClient::create();
$response = $client->request('POST', $url, [
'body' => json_encode([
'channel' => $channel,
'text' => $message,
'username' => $username,
'icon_url' => $icon,
]),
'headers' => [
'Content-Type' => 'application/json',
],
]);
// ...
Ok, Now register your Command to your application with $app->add(new SendCommand());
. Add this to your app.php
file. After this step, your file will look like this one
<?php
require __DIR__ . '/vendor/autoload.php';
use Maymeow\ActionMattermostNotify\SendCommand;
use Symfony\Component\Console\Application;
$c = json_decode(file_get_contents(__DIR__ . '/composer.json'), true);
$app = new Application('Action Mattermost Notify', $c['version']);
$app->add(new SendCommand());
$app->run();
Try to run your app again php app.php
. In your response another action has been added:
Action Mattermost Notify 1.0.0
# // ...
Available commands:
completion Dump the shell completion script
help Display help for a command
list List commands # <--- This one as beed added
To see information about any command append --help
behind that command. For example send command
php app.php send --help
Required are the message
and url
of your webhook.
You can obtain the webhook URL on your mattermost instance in integrations, then click on Incoming webhook then add new and provide requested information.
Sending message
When you have all you need (created webhook), you can send a meesage to the server as follows
php app.php send "Hello World from PHP commandline!" --url "https://your-mattermost.url/webhook-id"
Cool isn't it? But, I like it if I can call the application without php
word as follows
`./action-mattermost-notify send "Hello World from PHP commandline!" --url "https://your-mattermost.url/webhook-id"`
Ok, Let's do this.
Packing your application to single file
In this step, you will learn how to pack your PHP application into phar. You have 2 options, read the PHP manual and do it your way, or IMO a more elegant way to use phar-composer.
First of all, you need to install it.
wget https://github.com/clue/phar-composer/releases/download/v1.4.0/phar-composer-1.4.0.phar \
&& chmod +x phar-composer-1.4.0.phar \
&& mv phar-composer-1.4.0.phar /usr/local/bin/phar-composer
To check the current version go to the releases page.
Before you can pack your app you need to make small changes in your composer file. Add "bin": ["app.php"],
somewhere in composer file. This tells to phar-composer which file needs to call when execute.
Ok build it and make it executable.
phar-composer build
chmod +x action-mattermost-notify.phar
After this you can call it like follows
./action-mattermost-notify.phar
Ok, the console application is finished and now you can create a GitHub action
Creating Action
The folder structure after this part is finished will look like follows
action-mattermost-notify
├── action.yml # Added this one
├── app.php
├── composer.json
├── composer.lock
├── Dockerfile # Added this one
├── entrypoint.sh # Added this one
├── src
│ └── SendCommand.php
└── vendor
First of all, you need to automate the steps above like building phar and making it executable. You don't want to have bin files in your git repository. To do this, we use Docker in this tutorial. Create Dockerfile
and put there following content:
# Dockerfile
# Folloing image has composer-phar preinstaled in it
FROM ghcr.io/maymeow/php-ci-cd/php-ci-cd:8.1.6-cs-git-psalm AS build-env
WORKDIR /app
COPY . /app
RUN composer install --no-ansi --no-dev --no-interaction --no-plugins --no-progress --optimize-autoloader --no-scripts
RUN phar-composer build && chmod +x action-mattermost-notify.phar
# Use smallest php image
FROM php:8.1.6-cli-alpine
COPY --from=build-env /app/action-mattermost-notify.phar /usr/local/bin/action-mattermost-notify
COPY --from=build-env /app/entrypoint.sh /entrypoint.sh
RUN action-mattermost-notify list
ENTRYPOINT ["/entrypoint.sh"]
The example above is a multistep build. In the production image, you will only have phar without source codes.
The second file you need to add is entrypoint.sh
which runs when the image starts. Create it with the following content
#entrypoint.sh
#!/bin/sh
action-mattermost-notify send "$1" --url "$2" --channel "$3" --username "$5" --icon "$4"
At last, you need to create an action configuration file that tells Github all the required information about the action that you creating. It is called action.yml
and has to be in the root directory. Create it with the following content:
# action.yml
name: 'Action Name' #change this to your action name
author: 'Action Author' # Change this to your
description: 'Action Description' # change this
branding:
icon: 'command'
color: 'purple'
inputs: # following are all inputs that can be used in this action
message:
description: 'Enter the message to send to Mattermost'
required: true
url:
description: 'The URL to send the message to'
required: true
channel:
description: 'Enter the channel to send the message to'
required: false
icon:
description: 'Enter the icon to use for the message'
required: false
username:
description: 'Enter the username to use for the message'
required: false
runs: # How this action start?
using: 'docker'
image: 'Dockerfile'
args:
- ${{ inputs.message }}
- ${{ inputs.url }}
- ${{ inputs.channel }}
- ${{ inputs.icon }}
- ${{ inputs.username }}
Good job! Congratulation, You are reading this to the finish. You now have your own Github action and you learned how to
- create a PHP console application
- how to pack it in a single Phar file
- how to create Github Action with PHP
How to run it
At the very end, ill show you how you can use it. There are more options on how to call it.
- Register it in the marketplace (via new release)
- Call it with branch name or commit hash
If you have published it you can call it as follows
- name: Action Mattermost Notify
uses: MayMeow/action-mattermost-notify@v1 # Change this to your action
with:
url: ${{ secrets.MATTERMOST_WEBHOOK }}
message: "Hello world from ${{ github.repository }}"
Your action has name your-github-username/your-action-repository@version
or your-github-username/your-action-repository@branch-name
or your-github-username/your-action-repository@commit-hash
. The last two options don't require to have action registered in the marketplace.
In the end
All source code is available on my Github: Action Mattermost notify and Mattermost Action example.
Thank you for reading this post and I hope you enjoy it.
- GitHub: github.com/MayMeow
- DEV: dev.to/maymeow
- Hashnode: hashnode.com/@maymeow
- Ko-fi: ko-fi.com/maymeow
Originally published at My Blog