Compare commits

...

31 commits

Author SHA1 Message Date
31b3b9fd24 flake: bump version to v0.4.0
All checks were successful
ci/woodpecker/push/check Pipeline was successful
2024-01-03 15:55:45 +00:00
37491e91e6 matrix-notifier: fix link to pipeline 2024-01-03 15:55:45 +00:00
48dad0c962 ci: use more explicit step name
All checks were successful
ci/woodpecker/push/check Pipeline was successful
2023-11-18 20:22:30 +00:00
a57f1cfa71 ci: add package check 2023-11-18 20:22:30 +00:00
d30a2d7366 ci: remove deprecated syntax 2023-11-18 20:22:30 +00:00
436483aac7 ci: remove Drone CI
All checks were successful
ci/woodpecker/push/check Pipeline was successful
ci/woodpecker/manual/check Pipeline was successful
2023-04-14 16:07:37 +00:00
cb62f179a3 ci: add Woodpecker CI workflow 2023-04-14 16:07:37 +00:00
04758f81f2 flake: bump version to v0.3.0
All checks were successful
continuous-integration/drone/push Build is passing
2023-03-18 12:48:28 +00:00
eebe509b02 matrix-notifier: add woodpecker integration
All checks were successful
continuous-integration/drone/push Build is passing
2023-03-18 12:46:36 +00:00
0bc11d85d5 nix: fix flake description 2023-03-18 12:42:02 +00:00
007994e0a2 nix: migrate from deprecated attributes
All checks were successful
continuous-integration/drone/push Build is passing
2022-06-03 16:30:12 +02:00
b6a9c7e6a4 nix: use 'inputsFrom'
All checks were successful
continuous-integration/drone/push Build is passing
2021-10-08 15:49:05 +02:00
5f1fb1c1a4 flake: bump version to v0.2.0
All checks were successful
continuous-integration/drone/push Build is passing
2021-06-16 21:14:22 +02:00
05ab9425dd doc: mention pandoc formatting 2021-06-16 21:14:22 +02:00
d2b019f29d matrix-notifier: use link formatting when enabled
Make the link formatted to provide a shorter, more good-looking message.
2021-06-16 21:10:06 +02:00
fe0de738b0 matrix-notifier: add option to disable mardown 2021-06-16 20:59:21 +02:00
758e4599ed matrix-notifier: add markdown rendering w/ pandoc 2021-06-16 20:42:17 +02:00
75d482cd6b flake: bump version to v0.1.2
All checks were successful
continuous-integration/drone/push Build is passing
2021-06-15 18:39:19 +02:00
261f3b27ec matrix-notifier: prefer tag in Drone message 2021-06-15 18:38:26 +02:00
11ed9e71d0 flake: bump version to v0.1.1
All checks were successful
continuous-integration/drone/push Build is passing
2021-06-15 18:29:07 +02:00
74b5d9b48c matrix-notifier: use full URL to Drone build 2021-06-15 18:28:20 +02:00
feb8639213 flake: add meta to package derivation 2021-06-12 21:44:09 +02:00
bad1c90d39 ci: add Drone CI
All checks were successful
continuous-integration/drone/push Build is passing
This is my first experiment to make sure I can actually use this in my
CI.
2021-06-12 19:19:35 +02:00
dfbc17b518 matrix-notifier: use 'auto' default message type
This is the one that makes most sense in CI.
2021-06-12 19:19:26 +02:00
0f701ddbe2 matrix-notifier: refactor handling of message type 2021-06-12 19:19:26 +02:00
7b71469624 matrix-notifier: add 'auto' message type
This is useful to only ping me when the build is failing.
2021-06-12 19:19:26 +02:00
abf66aa479 matrix-notifier: use 'notice' default message type 2021-06-12 19:19:26 +02:00
e017deeaa7 matrix-notifier: allow specifying message type 2021-06-12 19:19:26 +02:00
f45e1378eb matrix-notifier: add usage
And split into functions to make it more manageable.
2021-06-12 19:19:26 +02:00
ca3b5a053c matrix-notifier: add default Drone message 2021-06-12 18:22:20 +02:00
8ae3594c68 doc: add README 2021-06-12 01:25:04 +02:00
4 changed files with 248 additions and 43 deletions

31
.woodpecker/check.yml Normal file
View file

@ -0,0 +1,31 @@
labels:
type: exec
steps:
- name: flake check
image: bash
commands:
- nix flake check
- name: package check
image: bash
commands:
- nix build
- name: notifiy
image: bash
secrets:
- source: matrix_password
target: pass
- source: matrix_homeserver
target: address
- source: matrix_roomid
target: room
- source: matrix_username
target: user
commands:
- nix run .
when:
status:
- failure
- success

34
README.md Normal file
View file

@ -0,0 +1,34 @@
# matrix-notifier
This is a simple to send a message to a Matrix room. It automatically logs in
and sends the message when invoked. This was written to be used a notification
script in my CI/CD pipelines.
## How to use
You need to define the following environment variables for the script to be
executed correctly:
* `USER`: the user to login as.
* `PASS`: the password to login with.
* `ADDRESS`: the address of the homeserver to connect to.
* `ROOM`: the room id, as can be found in the room parameters.
* `MESSAGE`: the message you wish to send to the room.
### Example
```sh
export ADDRESS='https://matrix.org'
export USER='username'
export PASS='password'
export ROOM='!aaaaaaaaaaaaaaaaaa:matrix.org'
export MESSAGE='This is my test message'
./matrix-notifier
```
## How to run/install
This script is packaged with `Nix`, you can just use `nix run .` to run it.
The only dependencies are `bash`, `curl`, and `jq`, install those and you should
be ready to go! Format is needed when using formatting (enabled by default).

View file

@ -1,5 +1,5 @@
{
description = "Ambroisie's blog";
description = "A simple Matrix notifier for CI purposes";
inputs = {
futils = {
@ -36,6 +36,8 @@
in
rec {
apps = {
default = apps.matrix-notifier;
matrix-notifier =
futils.lib.mkApp { drv = packages.matrix-notifier; };
};
@ -56,26 +58,24 @@
};
};
defaultApp = apps.matrix-notifier;
devShells = {
default = pkgs.mkShell {
name = "matrix-notifier";
defaultPackage = packages.matrix-notifier;
inputsFrom = with self.packages.${system}; [
matrix-notifier
];
devShell = pkgs.mkShell {
name = "matrix-notifier";
buildInputs = with pkgs; [
curl
jq
shellcheck
];
inherit (self.checks.${system}.pre-commit) shellHook;
inherit (self.checks.${system}.pre-commit) shellHook;
};
};
packages = {
default = packages.matrix-notifier;
matrix-notifier = pkgs.stdenvNoCC.mkDerivation rec {
pname = "matrix-notifier";
version = "0.1.0";
version = "0.4.0";
src = ./matrix-notifier;
@ -99,12 +99,24 @@
wrapperPath = with pkgs; lib.makeBinPath [
curl
jq
pandoc
];
fixupPhase = ''
patchShebangs $out/bin/${pname}
wrapProgram $out/bin/${pname} --prefix PATH : "${wrapperPath}"
'';
meta = with pkgs.lib; {
description = ''
A very simple bash script that can be used to send a message to
a Matrix room
'';
homepage = "https://gitea.belanyi.fr/ambroisie/${pname}";
license = licenses.mit;
platforms = platforms.unix;
maintainers = with maintainers; [ ambroisie ];
};
};
};
}

View file

@ -4,6 +4,21 @@ print_err() {
printf "%s\n" "$1" >&2
}
usage() {
print_err "Usage: $0 [option]..."
print_err ""
print_err " -h, --help"
print_err " print this usage screen and exit"
print_err " -f, --format"
print_err " should the message be formatted using 'pandoc'."
print_err " Must be either 'true' or 'false'."
print_err " -t, --type"
print_err " which message type should be sent must be one of"
print_err " 'text' or 'notice', or 'auto'."
print_err " The special value 'auto' defaults to 'notice', unless"
print_err " 'CI_PIPELINE_STATUS'/'DRONE_BUILD_STATUS' indicates a failure."
}
# Blessed Stack Overflow
rawurlencode() {
(set +x
@ -23,37 +38,150 @@ rawurlencode() {
echo "$encoded")
}
if [ -z "$USER" ] || [ -z "$PASS" ]; then
print_err "You must provide USER and PASS"
exit 1
elif [ -z "$ADDRESS" ] || [ -z "$ROOM" ]; then
print_err "You must provide ADDRESS and ROOM"
exit 1
elif [ -z "$MESSAGE" ]; then
print_err "You must provide MESSAGE"
exit 1
fi
default_woodpecker_message() {
local msg="Build ${CI_PIPELINE_STATUS}"
local woodpecker_url="${CI_PIPELINE_URL}"
if [ "$FORMAT" == "true" ]; then
msg="$msg [${CI_REPO}#${CI_COMMIT_SHA:0:8}]($woodpecker_url)"
else
msg="$msg $woodpecker_url"
fi
msg="$msg (${CI_COMMIT_TAG:-$CI_COMMIT_BRANCH})"
printf '%s' "$msg"
}
if [ "$(curl -XGET "$ADDRESS/_matrix/client/r0/login" 2>/dev/null |
jq 'any(.flows[].type; .== "m.login.password")')" != "true" ]; then
print_err "Login method not supported"
exit 1
fi
default_drone_message() {
local msg="Build ${DRONE_BUILD_STATUS}"
local drone_url="${DRONE_SYSTEM_PROTO}://${DRONE_SYSTEM_HOST}/${DRONE_REPO}/${DRONE_BUILD_NUMBER}"
if [ "$FORMAT" == "true" ]; then
msg="$msg [${DRONE_REPO_OWNER}/${DRONE_REPO_NAME}#${DRONE_COMMIT:0:8}]($drone_url)"
else
msg="$msg $drone_url"
fi
msg="$msg (${DRONE_TAG:-$DRONE_BRANCH})"
printf '%s' "$msg"
}
ensure_variables() {
if [ "$CI" == "woodpecker" ] && [ -z "$MESSAGE" ]; then
MESSAGE="$(default_woodpecker_message)"
elif [ "$DRONE" == "true" ] && [ -z "$MESSAGE" ]; then
MESSAGE="$(default_drone_message)"
fi
if [ -z "$USER" ] || [ -z "$PASS" ]; then
print_err "You must provide USER and PASS"
exit 1
elif [ -z "$ADDRESS" ] || [ -z "$ROOM" ]; then
print_err "You must provide ADDRESS and ROOM"
exit 1
elif [ -z "$MESSAGE" ]; then
print_err "You must provide MESSAGE"
exit 1
fi
}
get_message_type() {
if [ "$MSG_TYPE" == "auto" ]; then
if [ "$CI_PIPELINE_STATUS" == "failure" ]; then
MSG_TYPE="text"
elif [ "$DRONE_BUILD_STATUS" == "failure" ]; then
MSG_TYPE="text"
else
MSG_TYPE="notice"
fi
fi
printf '%s' "m.$MSG_TYPE"
}
make_message_json() {
{
printf '%s' "$1" |
jq --raw-input --slurp "{msgtype: \"$(get_message_type)\", body: .}"
[ "$FORMAT" == "true" ] && printf '%s' "$1" |
pandoc |
jq --raw-input --slurp "{format: \"org.matrix.custom.html\", formatted_body: .}"
} | jq -s 'add'
}
send_message() {
local login_json
local token
local message_json
if [ "$(curl -XGET "$ADDRESS/_matrix/client/r0/login" 2>/dev/null |
jq 'any(.flows[].type; .== "m.login.password")')" != "true" ]; then
print_err "Login method not supported"
exit 1
fi
LOGIN_JSON="$(printf '%s\n%s' "$USER" "$PASS" |
jq -Rn '[inputs] | {type: "m.login.password", user: .[0], password: .[1]}')" &>/dev/null
TOKEN="$(curl -XPOST \
-d "$LOGIN_JSON" \
"$ADDRESS/_matrix/client/r0/login" 2>/dev/null| jq .access_token --raw-output)"
login_json="$(printf '%s\n%s' "$USER" "$PASS" |
jq -Rn '[inputs] | {type: "m.login.password", user: .[0], password: .[1]}')" &>/dev/null
token="$(curl -XPOST \
-d "$login_json" \
"$ADDRESS/_matrix/client/r0/login" 2>/dev/null| jq .access_token --raw-output)"
if [ -z "$TOKEN" ] || [ "$TOKEN" == "null" ]; then
print_err "Error during login"
exit 1
fi
if [ -z "$token" ] || [ "$token" == "null" ]; then
print_err "Error during login"
exit 1
fi
MESSAGE_JSON="$(printf '%s' "$MESSAGE" |
jq --raw-input --slurp '{msgtype: "m.text", body: .}')"
curl -XPOST \
-d "$MESSAGE_JSON" \
"$ADDRESS/_matrix/client/r0/rooms/$(rawurlencode "$ROOM")/send/m.room.message?access_token=$(rawurlencode "$TOKEN")" 2>/dev/null
message_json="$(make_message_json "$MESSAGE")"
curl -XPOST \
-d "$message_json" \
"$ADDRESS/_matrix/client/r0/rooms/$(rawurlencode "$ROOM")/send/m.room.message?access_token=$(rawurlencode "$token")" 2>/dev/null
}
MSG_TYPE='auto'
FORMAT='true'
while [ $# -gt 0 ]; do
opt="$1"
shift
case "$opt" in
-f|--format)
arg="$1"
shift
if [ "$arg" == "true" ] || [ "$arg" == "false" ]; then
FORMAT="$arg"
continue
fi
print_err "Must give value 'true' or 'false' with '-t|--type'"
exit 1
;;
-t|--type)
arg="$1"
shift
if [ -z "$arg" ]; then
print_err "Must give a message type when using '-t|--type'"
exit 1
fi
for type in text notice auto; do
if [ "$arg" == "$type" ]; then
continue 2 # Go to next argument
fi
done
print_err "Invalid message type '$arg'"
exit 1
;;
-h|--help)
usage
exit
;;
*)
print_err "Unknown argument '$opt'"
usage
exit 1
;;
esac
done
ensure_variables
send_message