aboutsummaryrefslogtreecommitdiff
path: root/msci
diff options
context:
space:
mode:
authortoufic ar <contact@toufy.me>2026-05-07 02:13:21 +0300
committertoufic ar <contact@toufy.me>2026-05-07 02:13:21 +0300
commitef46ad47b5c1b6b77604f6de28e0dd342654b9e9 (patch)
tree7e6147584e2fb84600a34d39391eac78816e1feb /msci
parent099f2d1979990df66be9fc03a8cd471f31f66d79 (diff)
downloadmakeshiftci-ef46ad47b5c1b6b77604f6de28e0dd342654b9e9.tar.gz
makeshiftci-ef46ad47b5c1b6b77604f6de28e0dd342654b9e9.zip
nix support
Diffstat (limited to 'msci')
-rwxr-xr-x[l---------]msci228
1 files changed, 227 insertions, 1 deletions
diff --git a/msci b/msci
index 701f6e9..b2a533c 120000..100755
--- a/msci
+++ b/msci
@@ -1 +1,227 @@
-makeshiftci \ No newline at end of file
+#!/usr/bin/env bash
+
+set -e
+shopt -s nullglob
+mkdir -p "$MSCI_HOME"/projects \
+ "$MSCI_HOME"/stdout/public \
+ "$MSCI_HOME"/stdout/private \
+ "$MSCI_HOME"/tmp
+[ ! -f "$MSCI_HOME"/cron ] && touch "$MSCI_HOME"/cron
+
+confirm_in() {
+ read -rp "$1 (y/N): " confirm
+ [[ $confirm == [yY]* ]] && return 0 || return 1
+}
+
+find_project() {
+ if list_projects | grep -xFq -- "$1"; then
+ return 0
+ fi
+ return 1
+}
+
+list_projects() {
+ paths=("$MSCI_HOME"/projects/*)
+ names=("${paths[@]##*/}")
+ projects=("${names[@]%.json}")
+ printf '%s\n' "${projects[@]}"
+}
+
+write_cron() {
+ cfile="MSCI_HOME=$MSCI_HOME\n"
+ for project in $(list_projects); do
+ ppath="$MSCI_HOME"/projects/"$project".json
+ schedule=$(jq -r '.cron' "$ppath")
+ [ "$schedule" = 'null' ] && continue
+ cfile="${cfile}$schedule $MSCI_HOME/makeshiftci run $project\n"
+ done
+ echo -e "$cfile" >"$MSCI_HOME"/tmp.cron
+ if crontab "$MSCI_HOME"/tmp.cron; then
+ mv -fv "$MSCI_HOME"/tmp.cron "$MSCI_HOME"/cron
+ else
+ rm -fv "$MSCI_HOME"/tmp.cron
+ fi
+}
+
+run_project() {
+ ppath="$MSCI_HOME"/projects/"$1".json
+ repo_name=$(jq -r '.name' "$ppath")
+ repo_url=$(jq -r '.url' "$ppath")
+ repo_path="$MSCI_HOME"/tmp/"$repo_name"
+ echo "cloning repo: $repo_url" | tee -a "$2"
+ git clone --quiet "$repo_url" "$repo_path"
+ pushd "$repo_path" >/dev/null || return 1
+ for job in "$repo_path"/.makeshiftci/*; do
+ pname=$(jq -r '.name' "$job")
+ echo "running job: $pname" | tee -a "$2"
+ pimage=$(jq -r '.image' "$job")
+ psecrets=$(jq -r '.secrets' "$job")
+ prun=$(jq -r '.run[]' "$job")
+ env_secrets=()
+ secret_mounts=()
+ if [ ! "$psecrets" = 'null' ]; then
+ for secret_key in $(echo "$psecrets" | jq -r '. | keys[]'); do
+ secret_value=$(echo "$psecrets" | jq -r ".$secret_key")
+ secret_name=$(openssl rand -hex 16)
+ secret_mounts+=("--mount=type=bind,source=$secret_value,target=/$secret_name,readonly")
+ env_secrets+=("$secret_key=/$secret_name")
+ done
+ fi
+ docker run --rm \
+ "${env_secrets[@]/#/--env=}" \
+ --mount type=bind,source="$repo_path",target=/"$repo_name" \
+ "${secret_mounts[@]}" \
+ --workdir="/$repo_name" \
+ "$pimage" \
+ sh -c "exec $prun" | tee -a "$2"
+ done
+ popd >/dev/null && rm -rf "$repo_path"
+ echo "finished" | tee -a "$2"
+}
+
+create_project() {
+ name="$1"
+ if find_project "$name"; then
+ echo "project file already exists"
+ return 1
+ fi
+ read -rp "project name: " pname
+ read -rp ".makeshiftci repo URL: " purl
+ phidden=$(confirm_in "hidden?" && echo true || echo false)
+ read -rp "cron (optional): " pcron
+ jq -n \
+ --arg pname "$pname" \
+ --arg purl "$purl" \
+ --argjson phidden "$phidden" \
+ --arg pcron "$pcron" \
+ '{
+ name: $pname,
+ url: $purl,
+ hidden: $phidden,
+ cron: (if $pcron == "" then null else $pcron end)
+ }' \
+ >"$MSCI_HOME"/projects/"$name".json
+ [ -n "$pcron" ] && write_cron
+ ([ "$phidden" = "true" ] &&
+ mkdir -p "$MSCI_HOME"/stdout/private/"$1") ||
+ mkdir -p "$MSCI_HOME"/stdout/public/"$1"
+}
+
+edit_project() {
+ name="$1"
+ if ! find_project "$name"; then
+ echo "project file doesn't exist"
+ return 1
+ fi
+ ppath="$MSCI_HOME"/projects/"$name".json
+ echo "editing $ppath"
+ oldname=$(jq -r '.name' "$ppath")
+ oldurl=$(jq -r '.url' "$ppath")
+ washidden=$(jq '.hidden' "$ppath")
+ keephidden=$([ "$washidden" = 'true' ] && echo "keep" || echo "make")
+ oldcron=$(jq -r '.cron' "$ppath")
+ echo "project name: $oldname"
+ read -rp "new name (optional): " pname
+ [ -z "$pname" ] && pname=$oldname
+ echo ".makeshiftci repo URL: $oldurl"
+ read -rp "new URL (optional): " purl
+ [ -z "$purl" ] && purl=$oldurl
+ echo "hidden: $washidden"
+ phidden=$(confirm_in "$keephidden hidden?" && echo true || echo false)
+ echo "cron: $oldcron"
+ read -rp "new cron (optional): " pcron
+ [ -z "$pcron" ] && pcron=$oldcron
+ jq -n \
+ --arg pname "$pname" \
+ --arg purl "$purl" \
+ --argjson phidden "$phidden" \
+ --arg pcron "$pcron" \
+ '{
+ name: $pname,
+ url: $purl,
+ hidden: $phidden,
+ cron: (if $pcron == "null" then null else $pcron end)
+ }' \
+ >"$ppath"
+ [ ! "$pcron" = "$oldcron" ] && write_cron
+ privout="$MSCI_HOME"/stdout/private/"$1"
+ pubout="$MSCI_HOME"/stdout/public/"$1"
+ (
+ [ "$phidden" = "true" ] &&
+ ([ ! -d "$privout" ] && mv "$pubout" "$privout")
+ ) ||
+ ([ ! -d "$pubout" ] && mv "$privout" "$pubout")
+}
+
+case $1 in
+create)
+ if [ -z "$2" ]; then
+ echo "no project file name is supplied"
+ exit 1
+ fi
+ create_project "$2"
+ ;;
+edit)
+ if [ -z "$2" ]; then
+ echo "no project file name is supplied"
+ exit 1
+ fi
+ edit_project "$2"
+ ;;
+delete)
+ if [ -z "$2" ]; then
+ echo "no project file name is supplied"
+ exit 1
+ fi
+ if ! find_project "$2"; then
+ echo "project file doesn't exist"
+ exit 1
+ fi
+ ppath="$MSCI_HOME"/projects/"$2".json
+ cat "$ppath"
+ confirm_in "delete '$2' (details above)?" &&
+ rm -vf "$MSCI_HOME"/projects/"$2".json ||
+ exit 0
+ rm -rf "$MSCI_HOME"/stdout/**/"$2"
+ write_cron
+ ;;
+run)
+ if [ -z "$2" ]; then
+ echo "no project file name is supplied"
+ exit 1
+ fi
+ if ! find_project "$2"; then
+ echo "project file doesn't exist"
+ exit 1
+ fi
+ ppath="$MSCI_HOME"/projects/"$2".json
+ phidden=$(jq -r '.hidden' "$ppath")
+ stdout_type=$([ "$phidden" = 'false' ] && echo "public" || echo "private")
+ stdout_path="$MSCI_HOME"/stdout/"$stdout_type"/"$2"
+ last_run=$(
+ find "$stdout_path" \
+ -maxdepth 1 \
+ -mindepth 1 \
+ -type f -printf '%f\n' |
+ grep -E '^[0-9]+$' |
+ sort -n |
+ tail -n 1
+ )
+ next_run=$(
+ [ -z "$last_run" ] &&
+ echo "1" ||
+ echo $((last_run + 1))
+ )
+ stdout_path="$stdout_path"/"$next_run"
+ run_project "$2" "$stdout_path"
+ ;;
+list)
+ list_projects
+ ;;
+*)
+ echo "unknown option '$1'"
+ exit 1
+ ;;
+esac
+
+# vim: set filetype=bash: