From 53668e986b6b5f9740234ca63aeaef396e196b57 Mon Sep 17 00:00:00 2001 From: Pi-Farm Date: Mon, 22 Sep 2025 12:29:44 +0200 Subject: [PATCH] move to git.pi-farm.de --- README.md | 2 + ToDo.md | 2 + build.sh | 111 +++++++++++++++ delete-tag.sh | 45 ++++++ edit.sh | 269 +++++++++++++++++++++++++++++++++++ manifest-build.sh | 90 ++++++++++++ manifest-build.sh-old | 71 +++++++++ manifest-build.sh.new | 124 ++++++++++++++++ manifest-build.sh_newer | 77 ++++++++++ projects/.gitkeep | 0 setup.sh | 82 +++++++++++ setup/install-builder.sh | 11 ++ setup/install-docker.sh | 35 +++++ setup/setup-builder.sh | 5 + setup/show-active-builder.sh | 2 + start.sh | 238 +++++++++++++++++++++++++++++++ 16 files changed, 1164 insertions(+) create mode 100644 README.md create mode 100644 ToDo.md create mode 100644 build.sh create mode 100755 delete-tag.sh create mode 100644 edit.sh create mode 100755 manifest-build.sh create mode 100755 manifest-build.sh-old create mode 100755 manifest-build.sh.new create mode 100755 manifest-build.sh_newer create mode 100644 projects/.gitkeep create mode 100644 setup.sh create mode 100644 setup/install-builder.sh create mode 100644 setup/install-docker.sh create mode 100644 setup/setup-builder.sh create mode 100644 setup/show-active-builder.sh create mode 100644 start.sh diff --git a/README.md b/README.md new file mode 100644 index 0000000..82adbf7 --- /dev/null +++ b/README.md @@ -0,0 +1,2 @@ +# image-builder +Docker Image-Builder with BuildX diff --git a/ToDo.md b/ToDo.md new file mode 100644 index 0000000..c46aca6 --- /dev/null +++ b/ToDo.md @@ -0,0 +1,2 @@ +add a project from git +add git-setup .git/config \ No newline at end of file diff --git a/build.sh b/build.sh new file mode 100644 index 0000000..4e67c89 --- /dev/null +++ b/build.sh @@ -0,0 +1,111 @@ +#!/bin/bash +CONF=".config" +PROJECTPATH=$(sed -n '1p' $CONF) +PROJECT_CONF="$PROJECTPATH/.config" +PROJECTNAME=$(sed -n '1p' "$PROJECT_CONF") +VERSION=$(sed -n '3p' "$PROJECT_CONF").$(sed -n '4p' "$PROJECT_CONF") +REPO=$(sed -n '2p' "$PROJECT_CONF") +ARCH=$(sed -n '5p' "$PROJECT_CONF") +PUSH=$(sed -n '6p' "$PROJECT_CONF") +INCREASE=$(sed -n '7p' "$PROJECT_CONF") +LATEST=$(sed -n '8p' "$PROJECT_CONF") +BUILDCACHE=$(sed -n '9p' "$PROJECT_CONF") + +green_checkmark="\033[32m\xE2\x9C\x93\033[0m" +red_x="\033[31m\xE2\x9C\x97\033[0m" + +if [[ $PUSH = "yes" ]]; + then RPUSH="--push" && PUSHSTAT=$green_checkmark; fi +if [[ $PUSH = "no" ]]; + then RPUSH="--load" && PUSHSTAT=$red_x; fi + +if [[ $INCREASE = "yes" ]]; + then INCREASESTAT=$green_checkmark; fi +if [[ $INCREASE = "no" ]]; + then INCREASESTAT=$red_x; fi + +if [[ $LATEST = "yes" ]]; + then LATESTSTAT=$green_checkmark; fi +if [[ $LATEST = "no" ]]; + then LATESTSTAT=$red_x; fi + +if [[ $BUILDCACHE = "yes" ]]; + then BUILDCACHESTAT=$green_checkmark; fi +if [[ $BUILDCACHE = "no" ]]; + then BUILDCACHESTAT=$red_x; fi + +echo "" +echo "------------- CURRENT SETTINGS -------------" +echo -e "\033[4mProject-Path:\033[0m \033[3m$PROJECTPATH\033[0m" +echo -e "\033[4mProject:\033[0m \033[3m$PROJECTNAME\033[0m" +echo -e "\033[4mImage-Name:\033[0m \033[3m$REPO/$PROJECTNAME:$VERSION\033[0m" +echo -e "\033[4mArch:\033[0m \033[3m$ARCH\033[0m" +echo -e "\033[4mUpload:\033[0m \033[3m$PUSHSTAT\033[0m" +echo -e "\033[4mIncrease Subversion:\033[0m \033[3m$INCREASESTAT\033[0m" +echo -e "\033[4mTag as 'latest':\033[0m \033[3m$LATESTSTAT\033[0m" +echo -e "\033[4mUse Build-Cache:\033[0m \033[3m$BUILDCACHESTAT\033[0m" +echo "--------------------------------------------" +echo "" + +cd $PROJECTPATH + +if [[ $PUSH = "yes" ]]; then + if [[ $LATEST = "yes" ]]; then + if [[ $BUILDCACHE = "yes" ]]; then + echo docker buildx build --platform="$ARCH" "$RPUSH" -t "$REPO"/"$PROJECTNAME":"$VERSION" -t "$REPO"/"$PROJECTNAME":latest -f Dockerfile . + DOCKER_COMMAND="docker buildx build --platform="$ARCH" "$RPUSH" -t "$REPO"/"$PROJECTNAME":"$VERSION" -t "$REPO"/"$PROJECTNAME":latest -f Dockerfile ."; + fi + if [[ $BUILDCACHE = "no" ]]; then + echo docker buildx build --no-cache --platform="$ARCH" "$RPUSH" -t "$REPO"/"$PROJECTNAME":"$VERSION" -t "$REPO"/"$PROJECTNAME":latest -f Dockerfile . + echo "test" + DOCKER_COMMAND="docker buildx build --no-cache --platform linux/amd64 --file Dockerfile --output type=local,dest=./output/amd64 -t "$REPO"/"$PROJECTNAME":"$VERSION" -t "$REPO"/"$PROJECTNAME":latest --no-cache --platform linux/arm64 --file Dockerfile.aarch64 --output type=local,dest=./output/arm64 -t "$REPO"/"$PROJECTNAME":"$VERSION" -t "$REPO"/"$PROJECTNAME":latest --push ."; + + #DOCKER_COMMAND="docker buildx build --no-cache --platform="$ARCH" "$RPUSH" -t "$REPO"/"$PROJECTNAME":"$VERSION" -t "$REPO"/"$PROJECTNAME":latest -f Dockerfile ."; + fi + fi + if [[ $LATEST = "no" ]]; then + if [[ $BUILDCACHE = "yes" ]]; then + echo docker buildx build --platform="$ARCH" "$RPUSH" -t "$REPO"/"$PROJECTNAME":"$VERSION" -f Dockerfile . + DOCKER_COMMAND="docker buildx build --platform="$ARCH" "$RPUSH" -t "$REPO"/"$PROJECTNAME":"$VERSION" -f Dockerfile ."; + fi + if [[ $BUILDCACHE = "no" ]]; then + echo docker buildx build --no-cache --platform="$ARCH" "$RPUSH" -t "$REPO"/"$PROJECTNAME":"$VERSION" -f Dockerfile . + DOCKER_COMMAND="docker buildx build --no-cache --platform="$ARCH" "$RPUSH" -t "$REPO"/"$PROJECTNAME":"$VERSION" -f Dockerfile ."; + fi + fi +fi +if [[ $PUSH = "no" ]]; then + if [[ $LATEST = "yes" ]]; then + if [[ $BUILDCACHE = "yes" ]]; then + echo docker buildx build --platform="$ARCH" "$RPUSH" -t "$REPO"/"$PROJECTNAME":"$VERSION" -t "$REPO"/"$PROJECTNAME":latest -f Dockerfile . + DOCKER_COMMAND="docker buildx build --platform="$ARCH" "$RPUSH" -t "$REPO"/"$PROJECTNAME":"$VERSION" -t "$REPO"/"$PROJECTNAME":latest -f Dockerfile ."; + fi + if [[ $BUILDCACHE = "no" ]]; then + echo docker buildx build --no-cache --platform="$ARCH" "$RPUSH" -t "$REPO"/"$PROJECTNAME":"$VERSION" -t "$REPO"/"$PROJECTNAME":latest -f Dockerfile . + DOCKER_COMMAND="docker buildx build --no-cache --platform="$ARCH" "$RPUSH" -t "$REPO"/"$PROJECTNAME":"$VERSION" -t "$REPO"/"$PROJECTNAME":latest -f Dockerfile ."; + fi + fi + if [[ $LATEST = "no" ]]; then + if [[ $BUILDCACHE = "yes" ]]; then + echo docker buildx build --platform="$ARCH" "$RPUSH" -t "$REPO"/"$PROJECTNAME":"$VERSION" -f Dockerfile . + DOCKER_COMMAND="docker buildx build --platform="$ARCH" "$RPUSH" -t "$REPO"/"$PROJECTNAME":"$VERSION" -f Dockerfile ."; + fi + if [[ $BUILDCACHE = "no" ]]; then + echo docker buildx build --no-cache --platform="$ARCH" "$RPUSH" -t "$REPO"/"$PROJECTNAME":"$VERSION" -f Dockerfile . + DOCKER_COMMAND="docker buildx build --no-cache --platform="$ARCH" "$RPUSH" -t "$REPO"/"$PROJECTNAME":"$VERSION" -f Dockerfile ."; + fi + fi +fi +$DOCKER_COMMAND +EXIT_CODE=$? +cd ../../ +if [ $EXIT_CODE -eq 0 ]; then + echo "Image build successfull" + if [[ $INCREASE = "yes" ]]; then + sv=$(sed -n '4p' "$PROJECT_CONF") + svn=$((sv + 1)) + sed -i "4s/.*/$svn/" "$PROJECT_CONF" + fi +else + echo "ERROR in build-process: $EXIT_CODE" +fi diff --git a/delete-tag.sh b/delete-tag.sh new file mode 100755 index 0000000..0e5b4a4 --- /dev/null +++ b/delete-tag.sh @@ -0,0 +1,45 @@ +#!/bin/bash + +# Variables passed from the calling script +# REPO: The registry URL +# PROJECTNAME: Project name (used as part of the repo) + +if [ -z "$REPO" ] || [ -z "$PROJECTNAME" ]; then + echo "Error: Required variables (REPO, PROJECTNAME) are not set." + exit 1 +fi + +# List of tags to delete +TAGS_TO_DELETE=("latest" "latest-386" "latest-amd64" "latest-arm64") + +# Loop through each tag and delete it +for TAG in "${TAGS_TO_DELETE[@]}"; do + echo "Deleting tag '$TAG' from '$REPO/$PROJECTNAME'..." + + # Special handling for 'latest' (Multi-Arch-Manifest) + if [[ "$TAG" == "latest" ]]; then + DIGEST=$(docker manifest inspect "$REPO/$PROJECTNAME:$TAG" 2>/dev/null | jq -r '.digest // empty') + else + DIGEST=$(docker manifest inspect "$REPO/$PROJECTNAME:$TAG" 2>/dev/null | jq -r '.Descriptor.digest // empty') + fi + + if [ -z "$DIGEST" ]; then + echo "Warning: Tag '$TAG' does not exist or cannot retrieve digest. Skipping." + continue + fi + + echo "Digest for $TAG: $DIGEST" + + # Construct DELETE URL + DELETE_URL="https://$REPO/v2/$PROJECTNAME/manifests/$DIGEST" + + # Perform the deletion + echo "Deleting manifest digest '$DIGEST' for tag '$TAG'..." + if curl -s -X DELETE "$DELETE_URL"; then + echo "Successfully deleted tag '$TAG' from '$REPO/$PROJECTNAME'." + else + echo "Error: Failed to delete the tag '$TAG'. Please check the registry or credentials." + fi +done + +echo "Tag deletion process completed." diff --git a/edit.sh b/edit.sh new file mode 100644 index 0000000..4fd3603 --- /dev/null +++ b/edit.sh @@ -0,0 +1,269 @@ +#!/bin/bash + + +############################################################## +ende() +{ + exit +} +############################################################## + +menue() +{ + CONF=".config" + PROJECTPATH=$(sed -n '1p' $CONF) + if [ ! -f "$PROJECTPATH/.config" ]; then + touch "$PROJECTPATH/.config" + echo -e "PROJECTNAME\nREPOSITORY\nVERSION\nSUBVERSION\nARCH\nPUSH\n" > "$PROJECTPATH/.config" + fi + + PROJECT_CONF="$PROJECTPATH/.config" + PROJECTNAME=$(sed -n '1p' "$PROJECT_CONF") + VERSION=$(sed -n '3p' "$PROJECT_CONF").$(sed -n '4p' "$PROJECT_CONF") + REPO=$(sed -n '2p' "$PROJECT_CONF") + ARCH=$(sed -n '5p' "$PROJECT_CONF") + PUSH=$(sed -n '6p' "$PROJECT_CONF") + INCREASE=$(sed -n '7p' "$PROJECT_CONF") + LATEST=$(sed -n '8p' "$PROJECT_CONF") + BUILDCACHE=$(sed -n '9p' "$PROJECT_CONF") + DF386=$(sed -n '10p' "$PROJECT_CONF") + DFAMD64=$(sed -n '11p' "$PROJECT_CONF") + DFARM64=$(sed -n '12p' "$PROJECT_CONF") + + green_checkmark="\033[32m\xE2\x9C\x93\033[0m" + red_x="\033[31m\xE2\x9C\x97\033[0m" + + if [[ $PUSH = "yes" ]]; + then PUSHSTAT=$green_checkmark; fi + if [[ $PUSH = "no" ]]; + then PUSHSTAT=$red_x; fi + + if [[ $INCREASE = "yes" ]]; + then INCREASESTAT=$green_checkmark; fi + if [[ $INCREASE = "no" ]]; + then INCREASESTAT=$red_x; fi + + if [[ $LATEST = "yes" ]]; + then LATESTSTAT=$green_checkmark; fi + if [[ $LATEST = "no" ]]; + then LATESTSTAT=$red_x; fi + + if [[ $BUILDCACHE = "yes" ]]; + then BUILDCACHESTAT=$green_checkmark; fi + if [[ $BUILDCACHE = "no" ]]; + then BUILDCACHESTAT=$red_x; fi + + + clear + echo "" + echo "------------- CURRENT SETTINGS -------------" + echo -e "\033[4mProject-Path:\033[0m \033[3m$PROJECTPATH\033[0m" + echo -e "\033[4mProject:\033[0m \033[3m$PROJECTNAME\033[0m" + echo -e "\033[4mImage-Name:\033[0m \033[3m$REPO/$PROJECTNAME:$VERSION\033[0m" + echo -e "\033[4mArch:\033[0m \033[3m$ARCH\033[0m" + echo -e "\033[4mDockerfile 386:\033[0m \033[3m$DF386\033[0m" + echo -e "\033[4mDockerfile amd64:\033[0m \033[3m$DFAMD64\033[0m" + echo -e "\033[4mDockerfile arm64:\033[0m \033[3m$DFARM64\033[0m" + echo -e "\033[4mUpload:\033[0m \033[3m$PUSHSTAT\033[0m" + echo -e "\033[4mIncrease Subversion:\033[0m \033[3m$INCREASESTAT\033[0m" + echo -e "\033[4mTag as 'latest':\033[0m \033[3m$LATESTSTAT\033[0m" + echo -e "\033[4mUse Build-Cache:\033[0m \033[3m$BUILDCACHESTAT\033[0m" + echo "--------------------------------------------" + echo "" + echo "b) Back to Build-Menue" + echo "" + echo "f) Project-Path" + echo "p) Project" + echo "r) Docker-Registy" + echo "m) Main-Version" + echo "s) Start of Sub-Version" + echo "a) Arch" + echo "d1) Set Dockerfile-name for i386" + echo "d2) Set Dockerfile-name for amd64" + echo "d3) Set Dockerfile-name for arm64" + echo "u) Upload to Registry (yes/no)" + echo "i) Automatic Increase Subversion (yes/no)" + echo "l) Tag as 'latest' (yes/no)" + echo "c) Use Build-Cache (yes/no)" + echo "x) Exit Image-Builder" + echo "" + read -p "Edit: " -n 2 menue_wahl + + case "$menue_wahl" in + d1) + clear + echo "Current Dockerfile-name: $DF386" + echo "Change to: " + + read NEW_DF + sed -i "10s/.*/$NEW_DF/" "$PROJECT_CONF" + menue + ;; + d2) + clear + echo "Current Dockerfile-name: $DFAMD64" + echo "Change to: " + + read NEW_DF + sed -i "11s/.*/$NEW_DF/" "$PROJECT_CONF" + menue + ;; + d3) + clear + echo "Current Dockerfile-name: $DFARM64" + echo "Change to: " + + read NEW_DF + sed -i "12s/.*/$NEW_DF/" "$PROJECT_CONF" + menue + ;; + f) + clear + echo "Current Project-Path: $PROJECTPATH" + echo "Change to: " + + folder=(projects/*) + #ordner=( "${ordner[@]%/}" ) + + PS3="Please chose the Project-Directory (or 'q' to quit): " + select foldername in "${folder[@]}" "quit"; do + if [ "$foldername" = "quit" ]; then + break + fi + if [ -n "$foldername" ]; then + echo "Change Project-Directory to '$foldername'" + sed -i "1s%.*%$foldername%" "$CONF" + break + else + echo "Not valid. Try again..." + fi + done + menue + ;; + p) + clear + echo "Current Project: $PROJECTNAME" + echo "Change to: " + read NEW_PROJECTNAME + sed -i "1s/.*/$NEW_PROJECTNAME/" "$PROJECT_CONF" + menue + ;; + ############################################# + r) + clear + echo "Current Repository: $REPO" + echo "Change to: (for hub.docker.com, simply set your username)" + read NEW_REPO + sed -i "2s/.*/$NEW_REPO/" "$PROJECT_CONF" + menue + ;; + ############################################# + m) + clear + echo "Current Main-Version: $VERSION" + echo "Change to: " + read NEW_VERSION + sed -i "3s/.*/$NEW_VERSION/" "$PROJECT_CONF" + menue + ;; + ############################################# + s) + clear + echo "Current Sub-Version: $SUBVERSION" + echo "Change to: " + read NEW_SUBVERSION + sed -i "4s/.*/$NEW_SUBVERSION/" "$PROJECT_CONF" + menue + ;; + ############################################# + a) + clear + + options=( + 1 "386" off + 2 "amd64" off + 3 "arm64" off + ) + + selection=$(dialog --checklist "Arch to build:" 10 40 3 "${options[@]}" 2>&1 >/dev/tty) + if [ $? -ne 0 ]; then + echo "Canceled." + exit 1 + fi + + echo "Build Archs:" + selected_options="" + for choice in $selection; do + case $choice in + 1) selected_options+="linux/386,";; + 2) selected_options+="linux/amd64,";; + 3) selected_options+="linux/arm64,";; + esac + done + + selected_options=${selected_options%,} + sed -i "5s%.*%$selected_options%" "$PROJECT_CONF" + menue + ;; + ############################################# + u) + clear + echo "Current status of Push: ($PUSH)" + echo "Change to: " + read NEW_PUSH + sed -i "6s/.*/$NEW_PUSH/" "$PROJECT_CONF" + menue + ;; + ############################################# + i) + clear + echo "Current status of Automatic Increase Subversion: ($INCREASE)" + echo "Change to: " + read NEW_INCREASE + sed -i "7s/.*/$NEW_INCREASE/" "$PROJECT_CONF" + menue + ;; + ############################################# + l) + clear + echo "Current status of Tag as 'latest': ($LATEST)" + echo "Change to: " + read NEW_LATEST + sed -i "8s/.*/$NEW_LATEST/" "$PROJECT_CONF" + menue + ;; + ############################################# + c) + clear + echo "Current status of User Build-Cache: ($BUILDCACHE)" + echo "Change to: " + read NEW_BUILDCACHE + sed -i "9s/.*/$NEW_BUILDCACHE/" "$PROJECT_CONF" + menue + ;; + ############################################# + b) + clear + bash start.sh + ;; + ############################################# + x|X) + clear + ende + ;; + ############################################# + *) + echo "Key not valid" + read -p "Try again... " WEITER + clear + menue + ;; + ############################################# + esac + +} + +##################################################################### + +clear +menue diff --git a/manifest-build.sh b/manifest-build.sh new file mode 100755 index 0000000..a081b1a --- /dev/null +++ b/manifest-build.sh @@ -0,0 +1,90 @@ +#!/bin/bash + +# Navigate to project path +#cd "$PROJECTPATH" || { echo "Error: Cannot change to project directory"; exit 1; } + +# Split the ARCH variable into an array +IFS=',' read -ra ARCH_ARRAY <<< "$ARCH" + +# Map architectures to Dockerfiles +declare -A ARCH_DOCKERFILES=( + ["linux/386"]="$DF386" + ["linux/amd64"]="$DFAMD64" + ["linux/arm64"]="$DFARM64" +) + +# Ensure delete-tag.sh exists on the same level as this script +#DELETE_TAG_SCRIPT="$(dirname "$0")/delete-tag.sh" +#if [[ ! -f "$DELETE_TAG_SCRIPT" ]]; then +# echo "Error: delete-tag.sh script not found!" +# exit 1 +#fi + +# Navigate to project path +cd "$PROJECTPATH" || { echo "Error: Cannot change to project directory"; exit 1; } + +# Delete existing 'latest' tags +echo "Removing existing 'latest' tags..." +source ../../delete-tag.sh + +# Build and tag images for each architecture +for ARCH in "${ARCH_ARRAY[@]}"; do + DOCKERFILE="${ARCH_DOCKERFILES[$ARCH]}" + TAG_ARCH="latest-${ARCH##*/}" + VERSION_TAG="$REPO/$PROJECTNAME:$VERSION-${ARCH##*/}" + + if [[ -z "$DOCKERFILE" ]]; then + echo "Error: No Dockerfile specified for architecture $ARCH. Skipping..." + continue + fi + + echo "Building image for $ARCH with Dockerfile: $DOCKERFILE..." + docker buildx build --platform "$ARCH" -f "$DOCKERFILE" $BUILDER_CACHE_OPTION --load \ + -t "$VERSION_TAG" \ + -t "$REPO/$PROJECTNAME:$TAG_ARCH" . + + if [[ $? -ne 0 ]]; then + echo "Error: Failed to build image for $ARCH. Aborting." + cd ../.. + exit 1 + fi + + echo "Image built for $ARCH: $VERSION_TAG" +done + +# Push the images +for ARCH in "${ARCH_ARRAY[@]}"; do + TAG_ARCH="latest-${ARCH##*/}" + VERSION_TAG="$REPO/$PROJECTNAME:$VERSION-${ARCH##*/}" + + echo "Pushing image for $ARCH..." + docker push "$VERSION_TAG" + docker push "$REPO/$PROJECTNAME:$TAG_ARCH" +done + +# Create and push the multi-architecture manifest for the version tag +echo "Creating multi-architecture manifest for version $VERSION..." +docker manifest create "$REPO/$PROJECTNAME:$VERSION" \ + $(for ARCH in "${ARCH_ARRAY[@]}"; do echo "$REPO/$PROJECTNAME:$VERSION-${ARCH##*/}"; done) + +docker manifest push "$REPO/$PROJECTNAME:$VERSION" + +# Create and push the multi-architecture manifest for the 'latest' tag +echo "Creating multi-architecture manifest for 'latest'..." +docker manifest create "$REPO/$PROJECTNAME:latest" \ + $(for ARCH in "${ARCH_ARRAY[@]}"; do echo "$REPO/$PROJECTNAME:latest-${ARCH##*/}"; done) + +docker manifest push "$REPO/$PROJECTNAME:latest" + +# Navigate two levels up +cd ../.. + +# Increment the version number if enabled +if [[ $INCREASE == "yes" ]]; then + sv=$(sed -n '4p' "$PROJECT_CONF") + svn=$((sv + 1)) + sed -i "4s/.*/$svn/" "$PROJECT_CONF" + echo "Version number increased to $svn in $PROJECT_CONF." +fi + +echo "Build and push process completed successfully." diff --git a/manifest-build.sh-old b/manifest-build.sh-old new file mode 100755 index 0000000..61e3081 --- /dev/null +++ b/manifest-build.sh-old @@ -0,0 +1,71 @@ +#!/bin/bash +set -e +cd $PROJECTPATH + +# AMD64 Build +if [[ $ARCH == *"amd64"* ]]; then + docker buildx build \ + $( [[ $BUILDCACHE == "no" ]] && echo "--no-cache" ) \ + --platform linux/amd64 \ + --file "$DFAMD64" \ + -t "$REPO/$PROJECTNAME:$VERSION-amd64" \ + $( [[ $LATEST == "yes" ]] && echo "-t $REPO/$PROJECTNAME:latest-amd64" ) \ + --push . +fi + +# ARM64 Build +if [[ $ARCH == *"arm64"* ]]; then + docker buildx build \ + $( [[ $BUILDCACHE == "no" ]] && echo "--no-cache" ) \ + --platform linux/arm64 \ + --file "$DFARM64" \ + -t "$REPO/$PROJECTNAME:$VERSION-arm64" \ + $( [[ $LATEST == "yes" ]] && echo "-t $REPO/$PROJECTNAME:latest-arm64" ) \ + --push . +fi + +# 386 Build +if [[ $ARCH == *"386"* ]]; then + docker buildx build \ + $( [[ $BUILDCACHE == "no" ]] && echo "--no-cache" ) \ + --platform linux/386 \ + --file "$DF386" \ + -t "$REPO/$PROJECTNAME:$VERSION-386" \ + $( [[ $LATEST == "yes" ]] && echo "-t $REPO/$PROJECTNAME:latest-386" ) \ + --push . +fi + +# Manifest erstellen und pushen +if [[ $PUSH == "yes" ]]; then + # Manifest für Version + docker manifest create "$REPO/$PROJECTNAME:$VERSION" \ + $( [[ $ARCH == *"amd64"* ]] && echo "--amend $REPO/$PROJECTNAME:$VERSION-amd64" ) \ + $( [[ $ARCH == *"arm64"* ]] && echo "--amend $REPO/$PROJECTNAME:$VERSION-arm64" ) \ + $( [[ $ARCH == *"386"* ]] && echo "--amend $REPO/$PROJECTNAME:$VERSION-386" ) + + docker manifest push "$REPO/$PROJECTNAME:$VERSION" + + # Manifest für "latest" + if [[ $LATEST == "yes" ]]; then + docker manifest create "$REPO/$PROJECTNAME:latest" \ + $( [[ $ARCH == *"amd64"* ]] && echo "--amend $REPO/$PROJECTNAME:latest-amd64" ) \ + $( [[ $ARCH == *"arm64"* ]] && echo "--amend $REPO/$PROJECTNAME:latest-arm64" ) \ + $( [[ $ARCH == *"386"* ]] && echo "--amend $REPO/$PROJECTNAME:latest-386" ) + + docker manifest push "$REPO/$PROJECTNAME:latest" + fi +fi + +echo "Build und Deployment abgeschlossen." + +cd ../.. + +###if [ $EXIT_CODE -eq 0 ]; then + echo "Image build successfull" + if [[ $INCREASE = "yes" ]]; then + sv=$(sed -n '4p' "$PROJECT_CONF") + svn=$((sv + 1)) + sed -i "4s/.*/$svn/" "$PROJECT_CONF" + fi +##else +## echo "ERROR in build-process: $EXIT_CODE" diff --git a/manifest-build.sh.new b/manifest-build.sh.new new file mode 100755 index 0000000..17e878a --- /dev/null +++ b/manifest-build.sh.new @@ -0,0 +1,124 @@ +#!/bin/bash + +# Variablen, die über das aufrufende Script übergeben werden +# ARCH: Architekturen, die gebaut werden sollen (z.B. "linux/amd64,linux/arm64") +# DF386: Dockerfile für die Architektur linux/386 +# DFAMD64: Dockerfile für die Architektur linux/amd64 +# DFARM64: Dockerfile für die Architektur linux/arm64 +# BUILDCACHE: Ob der Build-Cache verwendet werden soll (yes/no) +# PUSH: Ob die Images auf die Registry gepusht werden sollen (yes/no) +# VERSION: Versionsnummer für die Images +# REPO: Die URL der Registry +# PROJECT_CONF: Pfad zur Konfigurationsdatei mit der Versionsnummer +# INCREASE: Ob die Versionsnummer automatisch erhöht werden soll (yes/no) + +# Funktion zur automatischen Erhöhung der Versionsnummer +increment_version() { + if [[ $INCREASE == "yes" ]]; then + echo "Erhöhe die Versionsnummer in $PROJECT_CONF" + current_version=$(sed -n '4p' "$PROJECT_CONF") + new_version=$((current_version + 1)) + sed -i "4s/.*/$new_version/" "$PROJECT_CONF" + echo "Neue Versionsnummer: $new_version" + fi +} + +cd "$PROJECTPATH" + +# 1. Lokales Build der Images mit --load +echo "Bauen der Images für Architekturen: $ARCH" +EXIT_CODE=0 + +for arch in $(echo $ARCH | tr "," "\n"); do + case $arch in + "linux/386") + echo "Bauen für $arch mit Dockerfile: $DF386" + if [ "$BUILDCACHE" == "yes" ]; then + docker buildx build --platform $arch -f $DF386 --cache-from=type=registry,ref=$REPO/$PROJECTNAME:$VERSION-386 --load --tag $REPO/$PROJECTNAME:$VERSION-386 . + else + docker buildx build --platform $arch -f $DF386 --load --tag $REPO/$PROJECTNAME:$VERSION-386 . + fi + docker tag $REPO/$PROJECTNAME:$VERSION-386 $REPO/$PROJECTNAME:latest-386 + ;; + "linux/amd64") + echo "Bauen für $arch mit Dockerfile: $DFAMD64" + if [ "$BUILDCACHE" == "yes" ]; then + docker buildx build --platform $arch -f $DFAMD64 --cache-from=type=registry,ref=$REPO/$PROJECTNAME:$VERSION-amd64 --load --tag $REPO/$PROJECTNAME:$VERSION-amd64 . + else + docker buildx build --platform $arch -f $DFAMD64 --load --tag $REPO/$PROJECTNAME:$VERSION-amd64 . + fi + docker tag $REPO/$PROJECTNAME:$VERSION-amd64 $REPO/$PROJECTNAME:latest-amd64 + ;; + "linux/arm64") + echo "Bauen für $arch mit Dockerfile: $DFARM64" + if [ "$BUILDCACHE" == "yes" ]; then + docker buildx build --platform $arch -f $DFARM64 --cache-from=type=registry,ref=$REPO/$PROJECTNAME:$VERSION-arm64 --load --tag $REPO/$PROJECTNAME:$VERSION-arm64 . + else + docker buildx build --platform $arch -f $DFARM64 --load --tag $REPO/$PROJECTNAME:$VERSION-arm64 . + fi + docker tag $REPO/$PROJECTNAME:$VERSION-arm64 $REPO/$PROJECTNAME:latest-arm64 + ;; + *) + echo "Unbekannte Architektur: $arch" + EXIT_CODE=1 + ;; + esac +done + +# 2. Pushen der Images (sowohl Versionstag als auch latest-$ARCH) auf die Registry +if [ "$EXIT_CODE" -eq 0 ] && [ "$PUSH" == "yes" ]; then + echo "Pushe die Images auf die Registry" + for arch in $(echo $ARCH | tr "," "\n"); do + case $arch in + "linux/386") + docker push $REPO/$PROJECTNAME:$VERSION-386 + docker push $REPO/$PROJECTNAME:latest-386 + ;; + "linux/amd64") + docker push $REPO/$PROJECTNAME:$VERSION-amd64 + docker push $REPO/$PROJECTNAME:latest-amd64 + ;; + "linux/arm64") + docker push $REPO/$PROJECTNAME:$VERSION-arm64 + docker push $REPO/$PROJECTNAME:latest-arm64 + ;; + esac + done +fi + +# 3. Erstellen und Pushen des Multi-Arch-Manifests für die Version +if [ "$EXIT_CODE" -eq 0 ]; then + echo "Erstelle Multi-Arch-Manifest für Version $VERSION" + docker manifest create $REPO/$PROJECTNAME:$VERSION \ + --amend $REPO/$PROJECTNAME:$VERSION-386 \ + --amend $REPO/$PROJECTNAME:$VERSION-amd64 \ + --amend $REPO/$PROJECTNAME:$VERSION-arm64 + + if [ "$PUSH" == "yes" ]; then + docker manifest push $REPO/$PROJECTNAME:$VERSION + fi + + # 4. Erstellen und Pushen des Multi-Arch-Manifests für den 'latest'-Tag + echo "Erstelle Multi-Arch-Manifest für 'latest'" + docker manifest create $REPO/$PROJECTNAME:latest \ + --amend $REPO/$PROJECTNAME:latest-386 \ + --amend $REPO/$PROJECTNAME:latest-amd64 \ + --amend $REPO/$PROJECTNAME:latest-arm64 + + if [ "$PUSH" == "yes" ]; then + docker manifest push $REPO/$PROJECTNAME:latest + fi +fi + +cd ../../ + +# 5. Erhöhen der Versionsnummer (falls gewünscht) +if [ "$EXIT_CODE" -eq 0 ]; then + echo "Image-Build erfolgreich!" + increment_version +else + echo "Fehler beim Build-Prozess: $EXIT_CODE" + exit $EXIT_CODE +fi + +echo "Fertig!" diff --git a/manifest-build.sh_newer b/manifest-build.sh_newer new file mode 100755 index 0000000..e946f6e --- /dev/null +++ b/manifest-build.sh_newer @@ -0,0 +1,77 @@ +#!/bin/bash +set -e +cd "$PROJECTPATH" + +# Build für jede Architektur +if [[ $ARCH == *"amd64"* ]]; then + docker buildx build \ + $( [[ $BUILDCACHE == "no" ]] && echo "--no-cache" ) \ + --platform linux/amd64 \ + --file "$DFAMD64" \ + -t "$REPO/$PROJECTNAME:$VERSION-amd64" \ + --push . +fi + +if [[ $ARCH == *"arm64"* ]]; then + docker buildx build \ + $( [[ $BUILDCACHE == "no" ]] && echo "--no-cache" ) \ + --platform linux/arm64 \ + --file "$DFARM64" \ + -t "$REPO/$PROJECTNAME:$VERSION-arm64" \ + --push . +fi + +if [[ $ARCH == *"386"* ]]; then + docker buildx build \ + $( [[ $BUILDCACHE == "no" ]] && echo "--no-cache" ) \ + --platform linux/386 \ + --file "$DF386" \ + -t "$REPO/$PROJECTNAME:$VERSION-386" \ + --push . +fi + +# Manifest erstellen +if [[ $PUSH == "yes" ]]; then + docker manifest create "$REPO/$PROJECTNAME:$VERSION" \ + $( [[ $ARCH == *"amd64"* ]] && echo "--amend $REPO/$PROJECTNAME:$VERSION-amd64" ) \ + $( [[ $ARCH == *"arm64"* ]] && echo "--amend $REPO/$PROJECTNAME:$VERSION-arm64" ) \ + $( [[ $ARCH == *"386"* ]] && echo "--amend $REPO/$PROJECTNAME:$VERSION-386" ) + + docker manifest push "$REPO/$PROJECTNAME:$VERSION" + + if [[ $LATEST == "yes" ]]; then + docker manifest create "$REPO/$PROJECTNAME:latest" \ + $( [[ $ARCH == *"amd64"* ]] && echo "--amend $REPO/$PROJECTNAME:$VERSION-amd64" ) \ + $( [[ $ARCH == *"arm64"* ]] && echo "--amend $REPO/$PROJECTNAME:$VERSION-arm64" ) \ + $( [[ $ARCH == *"386"* ]] && echo "--amend $REPO/$PROJECTNAME:$VERSION-386" ) + + docker manifest push "$REPO/$PROJECTNAME:latest" + fi +fi + + +#: << 'END' + # Architektur-Tags löschen, um die Registry aufzuräumen + if [[ $CLEANUP == "yes" ]]; then + if [[ $ARCH == *"amd64"* ]]; then + docker rmi "$REPO/$PROJECTNAME:$VERSION-amd64" + if [[ $LATEST == "yes" ]]; then + docker rmi "$REPO/$PROJECTNAME:latest-amd64" + fi + fi + if [[ $ARCH == *"arm64"* ]]; then + docker rmi "$REPO/$PROJECTNAME:$VERSION-arm64" + if [[ $LATEST == "yes" ]]; then + docker rmi "$REPO/$PROJECTNAME:latest-arm64" + fi + fi + if [[ $ARCH == *"386"* ]]; then + docker rmi "$REPO/$PROJECTNAME:$VERSION-386" + if [[ $LATEST == "yes" ]]; then + docker rmi "$REPO/$PROJECTNAME:latest-386" + fi + fi + fi +#END +cd ../.. + diff --git a/projects/.gitkeep b/projects/.gitkeep new file mode 100644 index 0000000..e69de29 diff --git a/setup.sh b/setup.sh new file mode 100644 index 0000000..63ff0f0 --- /dev/null +++ b/setup.sh @@ -0,0 +1,82 @@ +#!/bin/bash + +ende() +{ + exit +} + + +DOCKERVERSION=$(docker --version) +BUILDXVERSION=$(docker buildx version) +BUILDERINFO=$(docker buildx inspect --bootstrap | grep -E 'Name:|BuildKit version:|Status:') + + +menue() +{ +echo "------------- DOCKER SETTINGS -------------" +echo -e "\033[4mDocker Version:\033[0m \033[3m$DOCKERVERSION\033[0m" +echo -e "\033[4mBuildX Version:\033[0m \033[3m$BUILDXVERSION\033[0m" +echo -e "\033[4mBuilder-Info:\033[0m \033[3m$BUILDERINFO\033[0m" +echo "--------------------------------------------" +echo "" +echo "b) Back to Build-Menue" +echo "" +echo "d) Install Docker Engine" +echo "p) Install BuildX-PlugIn" +echo "s) Setup BuildX-Builder" +echo "a) Active BuildX-Builder" +echo "x) Exit Image-Builder" +echo "" +read -p 'Your choice: ' -n 1 menue_wahl + + case "$menue_wahl" in + b) + bash start.sh + menue + ;; + ############################################# + d) + sudo bash setup/install-docker.sh + clear + menue + ;; + ############################################# + p) + sudo bash setup/install-builder.sh + clear + menue + ;; + ############################################# + s) + bash setup/setup-builder.sh + clear + menue + ;; + ############################################# + a) + bash setup/show-active-builder.sh + echo "" + # clear + menue + ;; + ############################################# + x|X) + clear + ende + ;; + ############################################# + *) + echo "Key not valid" + read -p "Try again..." WEITER + clear + menue + ;; + ############################################# + esac + +} + +##################################################################### + +clear +menue \ No newline at end of file diff --git a/setup/install-builder.sh b/setup/install-builder.sh new file mode 100644 index 0000000..33bbdba --- /dev/null +++ b/setup/install-builder.sh @@ -0,0 +1,11 @@ +#!/bin/bash +apt-get update +apt-get install -y docker-buildx-plugin +#apt-get install binfmt-support qemu-user-static -y + +#apt-get install jq -y +#rm -r ~/.docker/cli-plugins +#mkdir -p ~/.docker/cli-plugins +#BUILDX_URL=$(curl https://api.github.com/repos/docker/buildx/releases/latest | jq -r .assets[].browser_download_url | grep arm64) +#wget $BUILDX_URL -O ~/.docker/cli-plugins/docker-buildx +#chmod +x ~/.docker/cli-plugins/docker-buildx \ No newline at end of file diff --git a/setup/install-docker.sh b/setup/install-docker.sh new file mode 100644 index 0000000..609413a --- /dev/null +++ b/setup/install-docker.sh @@ -0,0 +1,35 @@ +#!/bin/bash + +# Remove old docker versions +for pkg in docker.io docker-doc docker-compose podman-docker containerd runc; do apt-get remove $pkg; done + +# Add Docker's official GPG key: +apt-get update +apt-get -y install ca-certificates curl +install -m 0755 -d /etc/apt/keyrings +curl -fsSL https://download.docker.com/linux/debian/gpg -o /etc/apt/keyrings/docker.asc +chmod a+r /etc/apt/keyrings/docker.asc + +# Add the repository to Apt sources: +echo \ + "deb [arch=$(dpkg --print-architecture) signed-by=/etc/apt/keyrings/docker.asc] https://download.docker.com/linux/debian \ + $(. /etc/os-release && echo "$VERSION_CODENAME") stable" | \ + tee /etc/apt/sources.list.d/docker.list > /dev/null +apt-get update + +# Add Docker's official GPG key: +#apt-get update +#apt-get install ca-certificates curl +#install -m 0755 -d /etc/apt/keyrings +#curl -fsSL https://download.docker.com/linux/ubuntu/gpg -o /etc/apt/keyrings/docker.asc +#chmod a+r /etc/apt/keyrings/docker.asc + +# Add the repository to Apt sources: +#echo \ +# "deb [arch=$(dpkg --print-architecture) signed-by=/etc/apt/keyrings/docker.asc] https://download.docker.com/linux/ubuntu \ +# $(. /etc/os-release && echo "$VERSION_CODENAME") stable" | \ +# tee /etc/apt/sources.list.d/docker.list > /dev/null +#apt-get update + +apt-get install -y docker-ce docker-ce-cli containerd.io docker-buildx-plugin docker-compose-plugin +usermod -aG docker $USER diff --git a/setup/setup-builder.sh b/setup/setup-builder.sh new file mode 100644 index 0000000..f45039f --- /dev/null +++ b/setup/setup-builder.sh @@ -0,0 +1,5 @@ +#!/bin/bash +docker buildx install +docker buildx create --name buildx-builder +docker buildx use buildx-builder +docker buildx inspect --bootstrap \ No newline at end of file diff --git a/setup/show-active-builder.sh b/setup/show-active-builder.sh new file mode 100644 index 0000000..06cb4eb --- /dev/null +++ b/setup/show-active-builder.sh @@ -0,0 +1,2 @@ +#!/bin/bash +docker buildx ls \ No newline at end of file diff --git a/start.sh b/start.sh new file mode 100644 index 0000000..3ff7551 --- /dev/null +++ b/start.sh @@ -0,0 +1,238 @@ +#!/bin/bash + + +if [ ! -f ".config" ]; then + touch ".config" + echo -e "PROJECTPATH" > ".config" +fi + +PACKAGE="dialog" +if command -v "$PACKAGE" &> /dev/null; then + true +else + echo "$PACKAGE is not installed, please install it first." +fi + +ende() +{ + exit +} + + +menue() +{ + +CONF=".config" +PROJECTPATH=$(sed -n '1p' "$CONF") + +if [ ! -f "$PROJECTPATH/.config" ]; then + touch "$PROJECTPATH/.config" + echo -e "PROJECTNAME\nREPOSITORY\nVERSION\nSUBVERSION\nARCH\nPUSH\nINCREASE" > "$PROJECTPATH/.config" +fi + +PROJECT_CONF="$PROJECTPATH/.config" + +PROJECTNAME=$(sed -n '1p' "$PROJECT_CONF") +VERSION=$(sed -n '3p' "$PROJECT_CONF").$(sed -n '4p' "$PROJECT_CONF") +REPO=$(sed -n '2p' "$PROJECT_CONF") +ARCH=$(sed -n '5p' "$PROJECT_CONF") +PUSH=$(sed -n '6p' "$PROJECT_CONF") +INCREASE=$(sed -n '7p' "$PROJECT_CONF") +LATEST=$(sed -n '8p' "$PROJECT_CONF") +BUILDCACHE=$(sed -n '9p' "$PROJECT_CONF") +DF386=$(sed -n '10p' "$PROJECT_CONF") +DFAMD64=$(sed -n '11p' "$PROJECT_CONF") +DFARM64=$(sed -n '12p' "$PROJECT_CONF") + +green_checkmark="\033[32m\xE2\x9C\x93\033[0m" +red_x="\033[31m\xE2\x9C\x97\033[0m" + +if [[ $PUSH = "yes" ]]; + then PUSHSTAT=$green_checkmark; fi +if [[ $PUSH = "no" ]]; + then PUSHSTAT=$red_x; fi + +if [[ $INCREASE = "yes" ]]; + then INCREASESTAT=$green_checkmark; fi +if [[ $INCREASE = "no" ]]; + then INCREASESTAT=$red_x; fi + +if [[ $LATEST = "yes" ]]; + then LATESTSTAT=$green_checkmark; fi +if [[ $LATEST = "no" ]]; + then LATESTSTAT=$red_x; fi + +if [[ $BUILDCACHE = "yes" ]]; + then BUILDCACHESTAT=$green_checkmark; fi +if [[ $BUILDCACHE = "no" ]]; + then BUILDCACHESTAT=$red_x; fi + +#clear +echo "" +echo "-------------------- CURRENT SETTINGS --------------------" +echo "" +echo -e "\033[4mProject-Path:\033[0m \033[3m$PROJECTPATH\033[0m" +echo -e "\033[4mProject:\033[0m \033[3m$PROJECTNAME\033[0m" +echo -e "\033[4mImage-Name:\033[0m \033[3m$REPO/$PROJECTNAME:$VERSION\033[0m" +echo -e "\033[4mArch:\033[0m \033[3m$ARCH\033[0m" +echo -e "\033[4mUpload:\033[0m \033[3m$PUSHSTAT\033[0m" +echo -e "\033[4mIncrease Subversion:\033[0m \033[3m$INCREASESTAT\033[0m" +echo -e "\033[4mTag as 'latest':\033[0m \033[3m$LATESTSTAT\033[0m" +echo -e "\033[4mUse Build-Cache:\033[0m \033[3m$BUILDCACHESTAT\033[0m" +echo "----------------------------------------------------------" +echo "" +echo "b) Build the Image with current settings" +echo "m) Build with Docker manifest with different Dockerfiles for dif. architectures" +echo +echo "n) Create new Project" +echo "g) Create new Project from Git-URL" +echo "c) Change to another Project" +echo "r) Rename a Project" +echo "d) Remove Project" +echo "e) Edit Project-settings" +echo "" +echo "s) Setup Docker and BuildX-PlugIn" +echo "x) Exit Image-Builder" +echo "" +read -p 'Your choice: ' -n 1 menue_wahl + + case "$menue_wahl" in + c) + clear + echo "Current Project-Path: $PROJECTPATH" + echo "Change to: " + + folder=(projects/*) + PS3="Please chose the Project-Directory (or 'q' to quit): " + select foldername in "${folder[@]}" "quit"; do + if [ "$foldername" = "quit" ]; then + break + fi + if [ -n "$foldername" ]; then + clear + echo "Change Project-Directory to '$foldername'" + sed -i "1s%.*%$foldername%" "$CONF" + break + else + echo "Not valid. Try again..." + fi + done + menue + ;; + ############################################# + n) + clear + read -p 'Project-Name: ' NEWPROJECT + mkdir projects/$NEWPROJECT + touch projects/$NEWPROJECT/.config + echo -e "$NEWPROJECT\nREPOSITORY\nVERSION\nSUBVERSION\nARCH\nPUSH\nINCREASE\nLATEST\nBUILDCACHE" > "projects/$NEWPROJECT/.config" + sed -i "1s%.*%projects/$NEWPROJECT%" "$CONF" + menue + ;; + ############################################# + g) + clear + read -p 'Project-Name: ' NEWPROJECT + read -p 'Git-URL: ' GITURL + mkdir projects/$NEWPROJECT + git clone $GITURL projects/$NEWPROJECT + touch projects/$NEWPROJECT/.config + echo -e "$NEWPROJECT\nREPOSITORY\nVERSION\nSUBVERSION\nARCH\nPUSH\nINCREASE\nLATEST\nBUILDCACHE" > "projects/$NEWPROJECT/.config" + sed -i "1s%.*%projects/$NEWPROJECT%" "$CONF" + menue + ;; + ############################################# + r) + clear + echo "Select the Project to rename: " + + folder=(projects/*) + PS3="Please chose the Project-Directory: " + select foldername in "${folder[@]}" "quit"; do + if [ "$foldername" = "quit" ]; then + break + fi + if [ "$foldername" = "$(sed -n '1p' $CONF)" ]; then + echo "Renaming not possible, Project is active. Please change to another Project first." + break + fi + if [ -n "$foldername" ]; then + read -p 'New Project-Name: ' NEWPROJECT + echo "Renaming to : '$NEWPROJECT'" + mv $foldername projects/$NEWPROJECT + sed -i "1s%.*%$NEWPROJECT%" "projects/$NEWPROJECT/$CONF" + clear + echo "Renaming succuessfull..." + break + else + echo "Not valid. Try again..." + fi + done + menue + ;; + ############################################# + d) + clear + echo "Select the Project to delete: " + + folder=(projects/*) + PS3="Please chose the Project-Directory: " + select foldername in "${folder[@]}" "quit"; do + if [ "$foldername" = "quit" ]; then + break + fi + if [ "$foldername" = "$(sed -n '1p' $CONF)" ]; then + echo "Delete not possible, Project is active. Please change to another Project first." + break + fi + if [ -n "$foldername" ]; then + echo "Deleting Project-Directory: '$foldername'" + rm -r $foldername + break + else + echo "Not valid. Try again..." + fi + done + menue + ;; + ############################################# + b) + bash build.sh + menue + ;; + ############################################# + m) + source ./manifest-build.sh + menue + ;; + ############################################# + e) + clear + bash edit.sh + ;; + ############################################# + s) + clear + bash setup.sh + ;; + ############################################# + x|X) + clear + ende + ;; + ############################################# + *) + echo "Key not valid" + read -p "Try again..." WEITER + clear + menue + ;; + ############################################# + esac + +} + +##################################################################### + +clear +menue