commit 3cc2460a9e108c74114842d41d920fc848a928df Author: Markus Koch Date: Tue Jan 18 21:04:35 2022 +0100 Initial commit diff --git a/README.MD b/README.MD new file mode 100644 index 0000000..b580f82 --- /dev/null +++ b/README.MD @@ -0,0 +1,4 @@ +# Micobu +Mini Continous Build + +A tiny continuous build system written in bash and php. diff --git a/gitea.php b/gitea.php new file mode 100644 index 0000000..305e611 --- /dev/null +++ b/gitea.php @@ -0,0 +1,82 @@ +repository->name; +$url = $decoded->repository->html_url; +$hash = $decoded->after; + +preg_match("/^[_\-A-Za-z0-9]{1,30}$/", $name, $matches); +if (!$matches) { + error_log('GITEA HOOK: FAILED - name verification'); + exit(); +} + +preg_match("/^[_\-A-Za-z0-9:\/\.]{1,150}$/", $url, $matches); +if (!$matches) { + error_log('GITEA HOOK: FAILED - url verification'); + exit(); +} + +preg_match("/^[A-Za-z0-9]{1,50}$/", $hash, $matches); +if (!$matches) { + error_log('GITEA HOOK: FAILED - hash verification'); + exit(); +} + +file_put_contents($micobu_pipe, "$micobu_key $name $url $hash\n"); + +?> diff --git a/index.php b/index.php new file mode 100644 index 0000000..61c41ed --- /dev/null +++ b/index.php @@ -0,0 +1,192 @@ +hash = $hash; + $build->result = -1; + $build->project = $project; + + $file = MICOBU_BASE . "/". $project->name . "/" . $hash . "/meta.json"; + if (file_exists($file)) { + $json = json_decode(file_get_contents($file)); + $build->hash = $json->hash; + $build->result = $json->result; + $build->time_start = $json->time_start; + $build->time_stop = $json->time_stop; + $build->description = $json->description; + } + + return $build; + } + + function scan_project($name) { + $project = new micobu_project(); + $project->name = $name; + $project->builds = array(); + + $dirs = glob_sorted_mtime(MICOBU_BASE . "/" . $name); + foreach ($dirs as $dir) { + $hash = basename($dir); + $project->builds += array($hash => scan_build($project, $hash)); + } + + return $project; + } + + function micobu_scan() { + $projects = array(); + foreach (glob(MICOBU_BASE . "/*", GLOB_ONLYDIR) as $project_path) { + $project_name = basename($project_path); + $projects += array($project_name => scan_project($project_name)); + } + return $projects; + } + + function micobu_get_trend($project) { + foreach ($project->builds as $build) { + if ($build->result > 0) + return ""; + else + return ""; + } + return "⌛"; + return "🔼"; + return "❗"; + } + + function micobu_get_build_icon($build) { + if ($build->result > 0) + return ""; + else + return ""; + } + + function micobu_get_build_time($build) { + return gmdate("i\m s\s", $build->time_stop - $build->time_start); + } + + function micobu_get_weblink($build, $filename) { + return MICOBU_BASE_LINK . "/" . $build->project->name . "/" . $build->hash . "/" . $filename; + } + + $projects = micobu_scan(); + + if (isset($_GET['p'])) { + $selected_project = $_GET['p']; + preg_match("/^[_\-A-Za-z0-9]{1,20}$/", $selected_project, $matches); + if (!$matches) + die("Invalid request."); + if (!isset($projects[$selected_project])) + die("Invalid project."); + + if (isset($_GET['h'])) { + $selected_hash = $_GET['h']; + preg_match("/^[_\-A-Za-z0-9]{1,40}$/", $selected_hash, $matches); + if (!$matches) + die("Invalid request."); + if (!isset($projects[$selected_project]->builds[$selected_hash])) + die("Invalid hash."); + } + } +?> + + + + + + + + +$selected_project" : ""); + $dpath .= (isset($selected_hash) ? " / $selected_hash" : ""); + echo "

Micobu CI Dashboard$dpath

"; +?> +
+builds[$selected_hash]); + $build = $projects[$selected_project]->builds[$selected_hash]; + echo ""; + echo ""; + echo ""; + echo "
Build status" . micobu_get_build_icon($build). "
Build time" . micobu_get_build_time($build) . "
"; + } else if (isset($selected_project)) { + echo ""; + foreach ($projects[$selected_project]->builds as $hash => $build) { + echo ""; + } + echo "
" . date(DATE_RFC2822, $build->time_start) . "" . micobu_get_build_icon($build) . "" . $build->description . "📰 🛈 📂
"; + } else { + echo ""; + foreach ($projects as $project) { + echo ""; + } + echo "
" . $project->name . "" . micobu_get_trend($project) . "
"; + } +?> +
+ diff --git a/micobu.sh b/micobu.sh new file mode 100755 index 0000000..957c05a --- /dev/null +++ b/micobu.sh @@ -0,0 +1,117 @@ +#!/bin/bash + +# Chroot instructions +# ArchLinux root via pacstrap, configured with build tools +# User: builduser 1000 + +BUILD_BASE='/opt/micobu/rootfs/home/builduser/base' +ARTEFACT_BASE='/opt/micobu/rootfs/home/builduser/artefacts' +BUILD_TIMEOUT='600' +API_KEY='mykey' +SERVER_PIPE='/var/tmp/micobu_pipe' + +function build() { + NAME="$1" + REPO="$2" + HASH="$3" + + BUILD_DIR="$BUILD_BASE/$NAME" + ARTEFACT_DIR="$ARTEFACT_BASE/$NAME/$HASH" + MICOBU_TEMP_NAME="micobu_$NAME_$HASH" # Relative to $BUILD_BASE + + if [ -d "$ARTEFACT_DIR" ]; then + echo "$NAME revision $HASH has already been built." + echo "Removing old version" + rm -rf $ARTEFACT_DIR + #return + fi + + echo "[env] Building in $BUILD_DIR." + + if [ ! -d "$BUILD_DIR" ]; then + echo "[git] Performing initial clone" + mkdir -p $BUILD_DIR + git clone --recurse-submodules "$REPO" "$BUILD_DIR" + cd $BUILD_DIR + else + echo "[git] Updating existing repo." + cd $BUILD_DIR + git fetch + fi + git clean -xdf + git reset --hard + git checkout $HASH + + DESCRIPTION="`git describe --all`" + + mkdir -p $BUILD_BASE/$MICOBU_TEMP_NAME + cat < $BUILD_BASE/micobu_run.sh +#!/bin/bash +cd ~/$NAME +./run.py --no-color +RET=\$? + +cd vunit_out/test_output +tar cvJf ~/$MICOBU_TEMP_NAME/artefacts.tar.xz * + +exit \$RET +EOF + chmod +x $BUILD_BASE/micobu_run.sh + + echo "[sec] Creating jail" + META_DATE_START="`date '+%s'`" + set +e + set -o pipefail + firejail --noprofile --chroot=/opt/micobu-rootfs --net=none --read-write="$BUILD_DIR" env -i HOME=/home/builduser PATH=/bin:/usr/bin "bash" "-c" "timeout $BUILD_TIMEOUT ~/micobu_run.sh" | tee $BUILD_BASE/$MICOBU_TEMP_NAME/log.txt + RET=$? + set +o pipefail + set -e + META_DATE_STOP="`date '+%s'`" + rm $BUILD_BASE/micobu_run.sh + + cat < $BUILD_BASE/$MICOBU_TEMP_NAME/meta.json +{ + "name" : "$NAME", + "url" : "$REPO", + "hash" : "$HASH", + "description" : "$DESCRIPTION", + "time_start" : "$META_DATE_START", + "time_stop" : "$META_DATE_STOP", + "result" : "$RET" +} +EOF + + mkdir -p $ARTEFACT_DIR + mv -T $BUILD_BASE/$MICOBU_TEMP_NAME $ARTEFACT_DIR + echo "Stored artefacts in $ARTEFACT_DIR" + + find $ARTEFACT_BASE + cat $ARTEFACT_DIR/meta.json + + echo "" + if [ $RET -eq 0 ]; then + echo 'BUILD SUCCEEDED!' + else + echo "BUILD FAILED (exit code $RET)!" + fi + return 0 +} + +function build_s() +{ + if [ "$1" != "$API_KEY" ]; then + echo "error: invalid key" + return + fi + shift + echo Starting build of $@ + build $@ +} + +set -e + +[ ! -p "$SERVER_PIPE" ] && mkfifo "$SERVER_PIPE" +while true; do + args=`cat $SERVER_PIPE | sed -n 's/\([a-zA-Z0-9]\+\) \([a-zA-Z0-9]\+\) \([a-zA-Z0-9:\-_\/\.]\+\) \([a-z0-9]\+\)/\1 \2 \3 \4/p'` + build_s $args +done