16 Commits

Author SHA1 Message Date
90f5a5087d Fix local changes detection
Do not use diff as this only detects modified files, but not added ones.
Run status --porcelain instead and check if there is any output.
2026-01-23 11:28:58 +09:00
c0bdd81cf5 Log update for changed blocks 2026-01-23 11:15:31 +09:00
c612c6c762 README update 2026-01-22 14:37:30 +09:00
3265d75b7d Add reset of current changes before running merge in git_sync.sh
Will create a backup branch of all the changes and then reset the working copy
2026-01-22 14:33:40 +09:00
50f53d3a35 Fix REMOTE HOST in new clone for host in ssh config check 2026-01-09 14:07:30 +09:00
4fc2c7f009 Update new clone.sh usage and argument parsing
Use proper arguments for new clone
2026-01-09 11:30:44 +09:00
08e9ff9e67 Add help and fix problem with Host name set for new clone
The host name ise set as ssh config entry with ssh key, so we use the short name set for the remote host name
2025-11-17 11:12:54 +09:00
329f3abb6b in create SSH command with escaped empty string for passphrase
Make sure there is "" visible in the ouput
2025-11-11 13:03:21 +09:00
495879207c Fix SSH PEM key setup script
Remove ":" from host name
Prepare proper host name without user
Set user from hostname part
Add command for vim to edit ssh config
2025-11-11 12:58:57 +09:00
6048c11791 Readme update 2025-09-11 18:00:48 +09:00
4d0a684ac6 Base setup update with ssh config create script 2025-09-11 17:57:51 +09:00
d81e13a174 Merge branch 'development' 2025-09-11 17:54:51 +09:00
5251fbf140 Create basic SSH config and key generataion, other minor updates
Basis ssh host config and ssh keygen script, does not hard create, but prints out commads
Fix sudo set check in init.sh file
Repository name to ssh config host name fix in the new clone script. Change was done to match ssh config create file
2025-09-11 17:52:53 +09:00
56d6fd8e63 Rename ReadMe.md to README.md 2025-09-11 15:58:27 +09:00
a2a27e1f4c Rename ReadMe.md to README.md 2025-09-11 15:57:13 +09:00
a780df5422 SSH Config creation script, readme update 2025-09-11 15:56:06 +09:00
7 changed files with 263 additions and 20 deletions

View File

@@ -8,6 +8,8 @@ the clone base for one campaign and a simple crontab script to pull data from th
- base_setup.sh: setup for the folder structure, users, etc - base_setup.sh: setup for the folder structure, users, etc
- new_clone.sh: Basic clone script - new_clone.sh: Basic clone script
- git_sync.sh: The script to run in crontab, to sync the changes - git_sync.sh: The script to run in crontab, to sync the changes
- switch_branch.sh: Switch from one branch to the other
- create_ssh_config.sh: setup ssh key and ssh config entry
## Run commands ## Run commands
@@ -30,17 +32,30 @@ as is, if the folder exists it will only copy the scripts, will not alter or cha
Planned to get auto fixes for wrong ACL, etc or missing config settings Planned to get auto fixes for wrong ACL, etc or missing config settings
### SSH Key generation
A SSH Key has to be generated for each git respository that will be synced and the configuration has to be added to the ssh config file
```sh
create_ssh_config.sh [repo url full] ([jump proxy])
```
> [!notice]
> This will currently output the command to create the SSH key and the host config to add to the ssh config file
### new_clone.sh ### new_clone.sh
Create a new clone Create a new clone
```sh ```sh
new_clone.sh [repository] [branch] ([host]) ([remote name]) new_clone.sh -r <Repository URL> -b <Branch Name> [-H <Host name>] [-f <Folder name>] [-n <Remote name>]
``` ```
The [host] is the SSH Host name entry, this sill repalce any "[host]:" in the [repository]. If the [host] is not set the host set in the [repository] will be used. If nothing found the script will abort The [host (-H)] is the SSH Host name entry, this will replace any "[host]:" in the [repository]. If the [host (-H)] is not set the host set in the [repository] will be used. If nothing found the script will abort. Note that if [host (-H)] is not set the host name will be the Repository name which has to match the SSH config setting.
A [branch] name must be set all the time. A [branch (-B)] name must be set all the time.
An override folder naem can be set with `-f`
An optional [remote name] can be set, if not set "origin" will be used. An optional [remote name] can be set, if not set "origin" will be used.
@@ -69,6 +84,23 @@ Sample
[2025-07-04 16:06:31] [<uniq id>] [END] [2025-07-04 16:06:31] [<uniq id>] [END]
``` ```
#### What happens to local changes
Any local changes are stored in a backup branch and then reset and cleaned up. No local changes should be commited or synced up, this would break the pull only flow.
If there are changes and they have been reset it will show up in the log like this
```log
...
[2026-01-22 14:31:02] [F4222EC4] [!] Local or cached changes detected, creating backup branch and resetting changes
[2026-01-22 14:31:02] [F4222EC4] Reset log: HEAD is now at 633f6de Uppdate 14
...
```
If a clean up was run too it will show up as "Clean log" after the Reset log.
The reset will only reset local or cached changs (added) but not changed that have been commited. If changes have been commited a manual reset has to be done.
## TODO ## TODO
Future versions will hold an incoming webhook handler and a polling scripts (systemd based) Future versions will hold an incoming webhook handler and a polling scripts (systemd based)

View File

@@ -90,6 +90,7 @@ if [ -d "${GIT_WEBHOOK_BASE_FOLDER}" ]; then
"${BASE_FOLDER}init.sh" \ "${BASE_FOLDER}init.sh" \
"${BASE_FOLDER}git_sync.sh" \ "${BASE_FOLDER}git_sync.sh" \
"${BASE_FOLDER}switch_branch.sh" \ "${BASE_FOLDER}switch_branch.sh" \
"${BASE_FOLDER}create_ssh_config.sh" \
"${GIT_WEBHOOK_BASE_FOLDER}${CLONE_SCRIPTS_FOLDER}"; "${GIT_WEBHOOK_BASE_FOLDER}${CLONE_SCRIPTS_FOLDER}";
cp "${CONFIG_BASE}/webhook.default.cfg" \ cp "${CONFIG_BASE}/webhook.default.cfg" \
"${GIT_WEBHOOK_BASE_FOLDER}${CONFIG_FOLDER}"; "${GIT_WEBHOOK_BASE_FOLDER}${CONFIG_FOLDER}";
@@ -99,6 +100,7 @@ if [ -d "${GIT_WEBHOOK_BASE_FOLDER}" ]; then
"${BASE_FOLDER}init.sh" \ "${BASE_FOLDER}init.sh" \
"${BASE_FOLDER}git_sync.sh" \ "${BASE_FOLDER}git_sync.sh" \
"${BASE_FOLDER}switch_branch.sh" \ "${BASE_FOLDER}switch_branch.sh" \
"${BASE_FOLDER}create_ssh_config.sh" \
"${CONFIG_BASE}/webhook.default.cfg"; "${CONFIG_BASE}/webhook.default.cfg";
# check config entries missing # check config entries missing
exit; exit;
@@ -180,6 +182,7 @@ EOF
"${BASE_FOLDER}init.sh" \ "${BASE_FOLDER}init.sh" \
"${BASE_FOLDER}git_sync.sh" \ "${BASE_FOLDER}git_sync.sh" \
"${BASE_FOLDER}switch_branch.sh" \ "${BASE_FOLDER}switch_branch.sh" \
"${BASE_FOLDER}create_ssh_config.sh" \
"${GIT_WEBHOOK_BASE_FOLDER}${CLONE_SCRIPTS_FOLDER}"; "${GIT_WEBHOOK_BASE_FOLDER}${CLONE_SCRIPTS_FOLDER}";
cp \ cp \
"${CONFIG_BASE}/webhook.cfg" \ "${CONFIG_BASE}/webhook.cfg" \
@@ -191,6 +194,7 @@ EOF
"${BASE_FOLDER}init.sh" \ "${BASE_FOLDER}init.sh" \
"${BASE_FOLDER}git_sync.sh" \ "${BASE_FOLDER}git_sync.sh" \
"${BASE_FOLDER}switch_branch.sh" \ "${BASE_FOLDER}switch_branch.sh" \
"${BASE_FOLDER}create_ssh_config.sh" \
"${CONFIG_BASE}/webhook.cfg" \ "${CONFIG_BASE}/webhook.cfg" \
"${CONFIG_BASE}/webhook.default.cfg"; "${CONFIG_BASE}/webhook.default.cfg";
fi; fi;

91
src/bin/create_ssh_config.sh Executable file
View File

@@ -0,0 +1,91 @@
#!/usr/bin/env bash
# <s> [SSH Key name] [repo url] ([Jump Proxy])
# ssh-keygen -t ed25519 -N "" -C "${repo_url}" -f "${ssh_key_name}"
# CONFIG
# Host <Repo name flattened>
# Hostname <host name>
# User git
# IdentityFile ~/.ssh/<pem key name>
# [ProxyJump <jump proxy>]
REPOSITORY="$1";
JUMP_PROXY="$2";
if [ "${REPOSITORY}" == "--help" ]; then
echo "$0 <Repo.git> [<Jump Proxy>]";
exit;
fi;
# below are only to skip error
BRANCH="-"
BASE_FOLDER=$(dirname "$(readlink -f "$0")")"/";
# shellcheck source=init.sh
. "${BASE_FOLDER}init.sh";
# base folder for ssh config
SSH_CONFIG_BASE="${GIT_WEBHOOK_BASE_FOLDER}.ssh/";
if [ ! -f "${SSH_CONFIG_BASE}config" ]; then
echo "[!] SSH config file does not exist: ${SSH_CONFIG_BASE}";
error=1;
fi;
if [[ "${REPOSITORY}" == *":"* ]]; then
REMOTE_USER_HOST=$(echo "${REPOSITORY}" | cut -d ":" -f 1);
REMOTE_HOST=$(echo "${REMOTE_USER_HOST}" | cut -d "@" -f 2);
REMOTE_USER=$(echo "${REMOTE_USER_HOST}" | cut -d "@" -f 1);
else
echo "[!] Must set a full repository path with remote host for the repository";
error=1;
fi;
# if we have an ":" in the repository, split by it and replace it with the remote host
if [[ "${REPOSITORY}" == *":"* ]]; then
REPOSITORY=$(echo "${REPOSITORY}" | cut -d ":" -f 2);
fi;
GIT_REPOSITORY_NAME=$(basename "${REPOSITORY}" .git);
if [ -f "${SSH_CONFIG_BASE}${GIT_REPOSITORY_NAME}.pem" ]; then
echo "SSH Key: ${SSH_KEY_NAME} already exists";
error=1
fi;
if
[ -f "${SSH_CONFIG_BASE}config" ] &&
[ -n "${GIT_REPOSITORY_NAME}" ] &&
grep "Host ${GIT_REPOSITORY_NAME}" "${SSH_CONFIG_BASE}config";
then
echo "[!] ssh config entry for Host '${GIT_REPOSITORY_NAME}' already exists";
error=1
fi;
if [ $error -eq 1 ]; then
exit;
fi;
# SUDO_COMMAND= as base
# ssh-keygen -t ed25519 -N "" -C "${GIT_REPOSITORY_NAME}" -f "${SSH_CONFIG_BASE}${SSH_KEY_NAME}"
# must add ".pem" if key name does not end in .pem
SSH_COMMAND=("${SUDO_COMMAND[@]}" "ssh-keygen" "-t" "ed25519" "-N" "\"\"" "-C" "${GIT_REPOSITORY_NAME}" "-f" "${SSH_CONFIG_BASE}${GIT_REPOSITORY_NAME}.pem")
SSH_CONFIG_COMMAND=("${SUDO_COMMAND[@]}" "vim" "${SSH_CONFIG_BASE}config")
# debug output for now
echo "";
echo "* SSH-KEYGEN:"
echo "";
echo "${SSH_COMMAND[*]}";
echo "";
echo "* ADD TO: ${SSH_CONFIG_BASE}config";
echo "";
echo "${SSH_CONFIG_COMMAND[*]}";
echo "";
echo "Host ${GIT_REPOSITORY_NAME}"
echo " Hostname ${REMOTE_HOST}";
echo " User ${REMOTE_USER}";
echo " PreferredAuthentications publickey";
echo " IdentityFile ~/.ssh/${GIT_REPOSITORY_NAME}.pem";
if [ -n "${JUMP_PROXY}" ]; then
echo " ProxyJump ${JUMP_PROXY}";
fi;
echo "";
# __END__

View File

@@ -7,6 +7,10 @@
REPOSITORY="$1"; REPOSITORY="$1";
BRANCH="$2"; BRANCH="$2";
REMOTE_NAME="$3"; REMOTE_NAME="$3";
if [ "${REPOSITORY}" == "--help" ]; then
echo "$0 <Repo.git> <branch> [<remote name, defaults to origin>]";
exit;
fi;
if [ -z "${REMOTE_NAME}" ]; then if [ -z "${REMOTE_NAME}" ]; then
REMOTE_NAME="origin" REMOTE_NAME="origin"
fi; fi;
@@ -29,9 +33,27 @@ GIT_COMMAND=("${GIT_COMMAND_BASE[@]}" "-C" "${GIT_REPOSITORY_FOLDER}" "fetch" "-
"${GIT_COMMAND[@]}" "${GIT_COMMAND[@]}"
# check diff for if we need to update # check diff for if we need to update
GIT_COMMAND=("${GIT_COMMAND_BASE[@]}" "-C" "${GIT_REPOSITORY_FOLDER}" "diff" "--stat" "HEAD" "${REMOTE_NAME}/${BRANCH}") GIT_COMMAND=("${GIT_COMMAND_BASE[@]}" "-C" "${GIT_REPOSITORY_FOLDER}" "diff" "--stat" "HEAD" "${REMOTE_NAME}/${BRANCH}")
# In general all data that should not be checked in should be in the .gitignore file
changes=$("${GIT_COMMAND[@]}" 2>&1) changes=$("${GIT_COMMAND[@]}" 2>&1)
if [ -n "${changes}" ]; then if [ -n "${changes}" ]; then
echo "[$(date +"%Y-%m-%d %H:%M:%S")] [${unique_id}] [START] git merge ${GIT_REPOSITORY_FOLDER} ${REMOTE_NAME}/${BRANCH}" &>> "$LOG_FILE"; echo "[$(date +"%Y-%m-%d %H:%M:%S")] [${unique_id}] [START] git merge ${GIT_REPOSITORY_FOLDER} ${REMOTE_NAME}/${BRANCH}" &>> "$LOG_FILE";
# check if there are local changes, make a backup branch and reset them
changes=$("${GIT_COMMAND_BASE[@]}" "-C" "${GIT_REPOSITORY_FOLDER}" "status" "--porcelain");
if [ -n "$changes" ]; then
echo "[$(date +"%Y-%m-%d %H:%M:%S")] [${unique_id}] [!] Changes detected, creating backup branch and resetting changes" &>> "$LOG_FILE";
GIT_COMMAND=("${GIT_COMMAND_BASE[@]}" "-C" "${GIT_REPOSITORY_FOLDER}" "branch" "backup-$(date +%Y%m%d-%H%M%S)")
"${GIT_COMMAND[@]}";
# Reset everything
GIT_COMMAND=("${GIT_COMMAND_BASE[@]}" "-C" "${GIT_REPOSITORY_FOLDER}" "reset" "--hard" "HEAD")
log_data=$("${GIT_COMMAND[@]}" 2>&1);
echo "[$(date +"%Y-%m-%d %H:%M:%S")] [${unique_id}] Reset log: ${log_data}" &>> "$LOG_FILE";
GIT_COMMAND=("${GIT_COMMAND_BASE[@]}" "-C" "${GIT_REPOSITORY_FOLDER}" "clean" "-fd")
log_data=$("${GIT_COMMAND[@]}" 2>&1);
if [ -n "${log_data}" ]; then
echo "[$(date +"%Y-%m-%d %H:%M:%S")] [${unique_id}] Clean log: ${log_data}" &>> "$LOG_FILE";
fi;
fi;
# MERGE
GIT_COMMAND=("${GIT_COMMAND_BASE[@]}" "-C" "${GIT_REPOSITORY_FOLDER}" merge "${REMOTE_NAME}/${BRANCH}") GIT_COMMAND=("${GIT_COMMAND_BASE[@]}" "-C" "${GIT_REPOSITORY_FOLDER}" merge "${REMOTE_NAME}/${BRANCH}")
log_data=$("${GIT_COMMAND[@]}" 2>&1); log_data=$("${GIT_COMMAND[@]}" 2>&1);
echo "[$(date +"%Y-%m-%d %H:%M:%S")] [${unique_id}] ${log_data}" &>> "$LOG_FILE"; echo "[$(date +"%Y-%m-%d %H:%M:%S")] [${unique_id}] ${log_data}" &>> "$LOG_FILE";

View File

@@ -23,7 +23,7 @@ if [ -z "$(command -v git)" ]; then
fi; fi;
GIT_COMMAND_BASE=("git"); GIT_COMMAND_BASE=("git");
SUDO_COMMAND=() SUDO_COMMAND=()
if [ -n "${USE_SUDO}" ]; then if [ "${USE_SUDO}" == 1 ]; then
# if we are root -> ok, else we must be SUDO USER # if we are root -> ok, else we must be SUDO USER
if [ "$(whoami)" = "root" ]; then if [ "$(whoami)" = "root" ]; then
SUDO_COMMAND=("sudo" "-u" "${SUDO_USER}"); SUDO_COMMAND=("sudo" "-u" "${SUDO_USER}");

View File

@@ -4,10 +4,101 @@
# DATE: 2025/6/27 # DATE: 2025/6/27
# DESC: create a new basic clone # DESC: create a new basic clone
REPOSITORY="$1"; # COMMAND: new_clone.sh <Repo.git> <branch> [<host>] [<Repo Target Name>] [<remote name>]
BRANCH="$2";
REMOTE_HOST="$3";
REMOTE_NAME="$4"; function error() {
if [ -t 1 ]; then echo "[MAK] ERROR: $*" >&2; fi; exit 0;
}
usage() {
cat <<EOF
Usage: $(basename "${BASH_SOURCE[0]}") [-h | --help] -r | --repository <Repository URL> -b | --branch <Branch Name> [-H | --host <Host name>] [-f | --folder <Folder name>] [-n | --remote <Remote name>]
New clone a git repository via ssh into the clone folder.
Available options:
-h, --help Print this help and exit
-r, --repository <Repository URL> Repository path (e.g. user/repo.git)
-b, --branch <Branch Name> Branch to clone (e.g. main)
-H, --host <Host name> Override SSH host from ssh config (e.g. my-ssh-host)
-f, --folder <Folder name> Target folder name for the repository (e.g. repo-name)
-n, --remote <Remote name> Remote name (defaults to origin)
EOF
exit
}
# REPOSITORY="$1";
# BRANCH="$2";
# REMOTE_HOST="$3";
# REPOSITORY_FOLDER="$4"
# REMOTE_NAME="$5";
# if [ "${REPOSITORY}" == "--help" ]; then
# echo "$0 <Repo.git> <branch> [<override host>] [<target folder>] [<remote name, defaults to origin>]";
# exit;
# fi;
REPOSITORY="";
BRANCH="";
REMOTE_HOST="";
REPOSITORY_FOLDER="";
REMOTE_NAME="origin";
while [ -n "${1-}" ]; do
case "${1}" in
-r | --repository)
REPOSITORY="${2-}";
shift
;;
-b | --branch)
BRANCH="${2-}";
shift
;;
-H | --host)
REMOTE_HOST="${2-}";
shift
;;
-f | --folder)
REPOSITORY_FOLDER="${2-}";
shift
;;
-n | --remote)
REMOTE_NAME="${2-}";
shift
;;
-h | --help)
usage
;;
# invalid option
-?*)
error "[!] Unknown option: '$1'."
;;
esac
shift;
done;
# if no repository or banch name given, show error
error=0
if [ -z "${REPOSITORY}" ]; then
echo "[!] Must set a repository full url, ssh only";
error=1;
fi;
if [ -z "${BRANCH}" ]; then
echo "[!] Must set a branch name";
error=1;
fi;
# further checks that repository folder if set can only by alphanumeric, -, _ or .
if [ -n "${REPOSITORY_FOLDER}" ]; then
if ! [[ "${REPOSITORY_FOLDER}" =~ ^[a-zA-Z0-9._-]+$ ]]; then
echo "[!] Repository folder name can only contain alphanumeric characters, dots, dashes or underscores";
error=1;
fi;
fi;
if [ $error -eq 1 ]; then
exit;
fi;
if [ -z "${REMOTE_NAME}" ]; then if [ -z "${REMOTE_NAME}" ]; then
REMOTE_NAME="origin" REMOTE_NAME="origin"
fi; fi;
@@ -19,19 +110,20 @@ if [ -z "${REPOSITORY}" ]; then
echo "[!] Must set a repository path"; echo "[!] Must set a repository path";
error=1; error=1;
fi; fi;
# if remote host is empty try to set from repository
if [ -z "${REMOTE_HOST}" ]; then
if [[ "${REPOSITORY}" == *":"* ]]; then
REMOTE_HOST=$(echo "${REPOSITORY}" | cut -d ":" -f 1);
else
echo "[!] Must set a remote host for the repository";
error=1;
fi;
fi;
# if we have an ":" in the repository, split by it and replace it with the remote host # if we have an ":" in the repository, split by it and replace it with the remote host
if [[ "${REPOSITORY}" == *":"* ]]; then if [[ "${REPOSITORY}" == *":"* ]]; then
REPOSITORY=$(echo "${REPOSITORY}" | cut -d ":" -f 2); REPOSITORY=$(echo "${REPOSITORY}" | cut -d ":" -f 2);
fi; fi;
# strip .git from the repository path, this is folder and ssh key Host name
if [ -z "${REPOSITORY_FOLDER}" ]; then
GIT_REPOSITORY_NAME=$(basename "${REPOSITORY}" .git);
else
GIT_REPOSITORY_NAME="${REPOSITORY_FOLDER}";
fi;
# set remote host if not set to the ssh config name
if [ -z "${REMOTE_HOST}" ]; then
REMOTE_HOST="$(basename "${REPOSITORY}" .git)";
fi;
if [ $error -eq 1 ]; then if [ $error -eq 1 ]; then
exit; exit;
fi; fi;
@@ -39,7 +131,7 @@ fi;
error=0 error=0
echo "* Validate SSH PEM Key exist and SSH config"; echo "* Validate SSH PEM Key exist and SSH config";
if ! grep "Host ${REMOTE_HOST}" "${GIT_WEBHOOK_BASE_FOLDER}"/.ssh/config; then if ! grep "Host ${REMOTE_HOST}" "${GIT_WEBHOOK_BASE_FOLDER}"/.ssh/config; then
echo "ssh config entry for Host ${REMOTE_HOST} is missing"; echo "[!] ssh config entry for Host ${REMOTE_HOST} is missing in ${GIT_WEBHOOK_BASE_FOLDER}/.ssh/config";
error=1; error=1;
else else
# make sure the identiy file is there # make sure the identiy file is there
@@ -60,8 +152,6 @@ fi;
unique_id=$(uuidgen | tr -d '-' | head -c 8); unique_id=$(uuidgen | tr -d '-' | head -c 8);
# strip .git from the repository path
GIT_REPOSITORY_NAME=$(basename "${REPOSITORY}" .git);
# log folder target # log folder target
LOG_FILE="${GIT_WEBHOOK_BASE_FOLDER}${LOG_FOLDER}${GIT_REPOSITORY_NAME}.log"; LOG_FILE="${GIT_WEBHOOK_BASE_FOLDER}${LOG_FOLDER}${GIT_REPOSITORY_NAME}.log";
# from the repository get the last path without the .git so we have the target folder # from the repository get the last path without the .git so we have the target folder

View File

@@ -8,6 +8,10 @@
REPOSITORY="$1"; REPOSITORY="$1";
BRANCH="$2"; BRANCH="$2";
REMOTE_NAME="$3"; REMOTE_NAME="$3";
if [ "${REPOSITORY}" == "--help" ]; then
echo "$0 <Repo.git> <branch> [<remote name, defaults to origin>]";
exit;
fi;
if [ -z "${REMOTE_NAME}" ]; then if [ -z "${REMOTE_NAME}" ]; then
REMOTE_NAME="origin" REMOTE_NAME="origin"
fi; fi;