diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..3ef84f1 --- /dev/null +++ b/.gitignore @@ -0,0 +1,2 @@ +artifacts/ +test_repo/ diff --git a/README.md b/README.md new file mode 100644 index 0000000..4569f90 --- /dev/null +++ b/README.md @@ -0,0 +1,28 @@ +Plugin tools +============ + +Dependencies +------------ + +- [hub](https://hub.github.com/) +- [jprm](https://pypi.org/project/jprm/) (building) +- dotnet (building) +- git +- bash +- python3 + +Tools +----- + +- `build_all.sh` + Builds (and publishes) all plugins. +- `build_plugin.sh` + Builds (and publishes) a single plugin. +- `show_drafts.sh` + Lists draft releases prepared by release-drafter. +- `show_issues.sh` + Lists all open issues on the plugin repositories. +- `show_pullrequests.sh` + Lists all open pull-requests on the plugin repositories. +- `update_submodules.py` + Updates sub-modules, adds new plugins from the org, and removes archived/moved ones. diff --git a/build_all.sh b/build_all.sh new file mode 100755 index 0000000..3637a2c --- /dev/null +++ b/build_all.sh @@ -0,0 +1,40 @@ +#!/bin/bash +#set -x +MY=$(dirname $(realpath -s "${0}")) + +export ARTIFACT_DIR="${MY}/artifacts" +mkdir -p "${ARTIFACT_DIR}" + +DEFAULT_REPO_DIR="${MY}/test_repo" +DEFAULT_REPO_URL="http://localhost:8080" + +export JELLYFIN_REPO=${JELLYFIN_REPO:-$DEFAULT_REPO_DIR} +export JELLYFIN_REPO_URL=${JELLYFIN_REPO_URL:-$DEFAULT_REPO_URL} + +export VERSION_SUFFIX=$(date -u +%y%m.%d%H.%M%S) + +FAILED=() + +for plugin in $(find . -maxdepth 1 -mindepth 1 -type d -name 'jellyfin-plugin-*' | sort); do + name=$(basename $plugin) + if [ "$name" = "jellyfin-plugin-meta" ]; then + continue + fi + pushd $plugin > /dev/null + echo -e "\n##### ${name} #####" + + bash $MY/build_plugin.sh || { + FAILED+=("$name") + } + + popd > /dev/null +done + +if [ ! ${#FAILED[@]} -eq 0 ]; then + echo -e "\n\nThe following plugins failed to compile:" > /dev/stderr + for plugin in "${FAILED[@]}"; do + echo " - $plugin" > /dev/stderr + done + + exit 1 +fi diff --git a/build_plugin.sh b/build_plugin.sh new file mode 100755 index 0000000..5ac23b7 --- /dev/null +++ b/build_plugin.sh @@ -0,0 +1,64 @@ +#!/bin/bash +# +# Copyright (c) 2020 - Odd Strabo +# +# +# The Unlicense +# ============= +# +# This is free and unencumbered software released into the public domain. +# +# Anyone is free to copy, modify, publish, use, compile, sell, or +# distribute this software, either in source code form or as a compiled +# binary, for any purpose, commercial or non-commercial, and by any +# means. +# +# In jurisdictions that recognize copyright laws, the author or authors +# of this software dedicate any and all copyright interest in the +# software to the public domain. We make this dedication for the benefit +# of the public at large and to the detriment of our heirs and +# successors. We intend this dedication to be an overt act of +# relinquishment in perpetuity of all present and future rights to this +# software under copyright law. +# +# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, +# EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +# MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. +# IN NO EVENT SHALL THE AUTHORS BE LIABLE FOR ANY CLAIM, DAMAGES OR +# OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, +# ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR +# OTHER DEALINGS IN THE SOFTWARE. +# +# For more information, please refer to +# + +MY=$(dirname $(realpath -s "${0}")) +JPRM="jprm" + +DEFAULT_REPO_DIR="${MY}/test_repo" +DEFAULT_REPO_URL="http://localhost:8080" + +PLUGIN=${1:-${PLUGIN:-.}} + +ARTIFACT_DIR=${ARTIFACT_DIR:-"${MY}/artifacts"} +mkdir -p "${ARTIFACT_DIR}" + +JELLYFIN_REPO=${JELLYFIN_REPO:-${DEFAULT_REPO_DIR}} +JELLYFIN_REPO_URL=${JELLYFIN_REPO_URL:-${DEFAULT_REPO_URL}} + +# Each segment of the version is a 16bit number. +# Max number is 65535. +VERSION_SUFFIX=${VERSION_SUFFIX:-$(date -u +%y%m.%d%H.%M%S)} + +meta_version=$(grep -Po '^ *version: * "*\K[^"$]+' "${PLUGIN}/build.yaml") +VERSION=${VERSION:-$(echo $meta_version | sed 's/\.[0-9]*\.[0-9]*\.[0-9]*$/.'"$VERSION_SUFFIX"'/')} + +# !!! VERSION IS OVERWRITTEN HERE +#VERSION="${meta_version}" + +find "${PLUGIN}" -name project.assets.json -exec rm -v '{}' ';' + +zipfile=$($JPRM --verbosity=debug plugin build "${PLUGIN}" --output="${ARTIFACT_DIR}" --version="${VERSION}") && { + $JPRM --verbosity=debug repo add --url=${JELLYFIN_REPO_URL} "${JELLYFIN_REPO}" "${zipfile}" +} +exit $? diff --git a/show_drafts.sh b/show_drafts.sh new file mode 100755 index 0000000..948c357 --- /dev/null +++ b/show_drafts.sh @@ -0,0 +1,52 @@ +#!/bin/bash + +rstrip_ver() { + if [ -z "$1" ]; then + grep -Po "^.*?(?=(\.0\.0\.0|\.0\.0|\.0)?$)" + else + echo $1 | grep -Po "^.*?(?=(\.0\.0\.0|\.0\.0|\.0)?$)" + fi +} + +esc=$(printf '\033') +colorize_changelog() { + #1 pr number + #2 list char + #3 pr submitter + sed -r -e "s/\\((#[0-9]+)\)/(${esc}[32m\1${esc}[0m)/g" \ + -e "s/^\s*[*+-]\s*/ ${esc}[1;30m-${esc}[0m /g" \ + -e "s/@([^ ]+)$/${esc}[1;30m@${esc}[0;36m\1${esc}[0m/gi" +} + +echo "Fetching git release info..." +DRAFTS=$( + git submodule foreach \ + 'hub release --include-drafts -f "$(basename $PWD)|%T|%t|%S%n"' \ + | grep draft +) + +IFS=$'\n' +for draft in $DRAFTS; do + IFS='|' parts=(${draft}) + name=${parts[0]} + tag=${parts[1]} + title=${parts[2]} + + echo + echo -e "\e[1m$name\e[0m: $title" + + pushd $name > /dev/null + description=$(hub release show $tag) + changes=$(echo $description | grep -Po '^\s*\K\*.*$' ) + + meta_version=$(grep -Po "version: ?[\"']?\K.*(?=[\"']$)" build.yaml | rstrip_ver) + draft_version=$(echo $tag | grep -Po 'v\K.*' | rstrip_ver) + + if [ "$meta_version" != "$draft_version" ]; then + echo -e " \e[1;31mVersion bump needed!" + echo -e " \e[0;31mDraft is for v\e[0m\e[1m$draft_version\e[0;31m, but build.yaml specifies v\e[0m\e[1m$meta_version\e[0m" + fi + + echo $changes | colorize_changelog + popd > /dev/null +done diff --git a/show_issues.sh b/show_issues.sh new file mode 100755 index 0000000..6c164e8 --- /dev/null +++ b/show_issues.sh @@ -0,0 +1,4 @@ +#!/bin/bash + +git submodule foreach \ + hub issue --format='%sC%>(8)%i%Creset %t% l%n%Cblue% U%Creset%n' --color=always \ No newline at end of file diff --git a/show_pullrequests.sh b/show_pullrequests.sh new file mode 100755 index 0000000..226dd90 --- /dev/null +++ b/show_pullrequests.sh @@ -0,0 +1,4 @@ +#!/bin/bash + +git submodule foreach \ + hub pr list --format='%pC%>(8)%i%Creset %t% l%n%Cblue% U%Creset%n' --color=always diff --git a/update_submodules.py b/update_submodules.py new file mode 100755 index 0000000..5bc3aa7 --- /dev/null +++ b/update_submodules.py @@ -0,0 +1,107 @@ +#!/usr/bin/env python3 +import os +import subprocess +import requests +import time + + +try: + subprocess.run(["git", "diff", "--staged", "--quiet", "--exit-code"], check=True) +except subprocess.SubprocessError: + print("Error: You have staged changes!") + exit(1) + +available = [] +fetched = [] +failed = [] +removed = [] +added = [] + + +def update(_name, url=None): + if not os.path.exists(_name): + print("Adding {} @ {}".format(_name, url)) + subprocess.run(["git", "submodule", "add", "--force", "-b", "master", url, _name], check=True) + added.append(_name) + subprocess.run(["git", "submodule", "update", "--init", "--remote", "--checkout", "--force", _name], check=True) + + subprocess.run(["git", "fetch", "--all", "--tags"], cwd=_name, check=True) + subprocess.run(["git", "checkout", "-f", "-B", "master", "origin/master"], cwd=_name, check=True) + fetched.append(_name) + + +def remove(_name): + if os.path.exists(_name): + print("Removing {}".format(_name)) + subprocess.run(["git", "rm", _name], check=True) + removed.append(_name) + + +page_num = 1 +per_page = 100 +PAGINATION_URL = "https://api.github.com/orgs/jellyfin/repos?sort=created&per_page={per}&page={page}" + +next = PAGINATION_URL.format(per=per_page, page=page_num) + +while next: + resp = requests.get(next) + repos = resp.json() + + page_num += 1 + next = PAGINATION_URL.format(per=per_page, page=page_num) + if len(repos) < per_page: + next = None + + for repo in repos: + _name = repo.get("name") + url = repo.get("clone_url") + if _name.startswith("jellyfin-plugin-"): + available.append(_name) + try: + update(_name, url) + pass + except Exception as e: + failed.append((_name, e)) + + +for repo in os.listdir("."): + if repo in fetched: + continue + + if not os.path.isdir(repo): + continue + + if not repo.startswith("jellyfin-plugin-"): + continue + + try: + if not repo in available: + remove(repo) + except Exception as e: + failed.append((repo, e)) + + +if failed: + print("The following repositories failed to update:") + for repo, e in failed: + print(repo, e) + +commit_message = ["Updated plugin submodules"] + +if added: + commit_message.append("") + commit_message.append("Added") + commit_message.append("-----") + commit_message.append("") + for plugin in added: + commit_message.append("- {}".format(plugin)) + +if removed: + commit_message.append("") + commit_message.append("Removed") + commit_message.append("-------") + commit_message.append("") + for plugin in removed: + commit_message.append("- {}".format(plugin)) + +subprocess.run(["git", "commit", "-m", "\n".join(commit_message)])