Compare commits
45 Commits
Author | SHA1 | Date |
---|---|---|
|
c74762858b | |
|
14ed4ab071 | |
|
f9a5808607 | |
|
e797b705ab | |
|
08237fc626 | |
|
8958bea96b | |
|
e0c2fa89de | |
|
734bbb8ecf | |
|
d204aec2a6 | |
|
5ec38ad657 | |
|
89131ec9ee | |
|
d5ca04a90d | |
|
40324e5be9 | |
|
c6373af98c | |
|
4af7c48a52 | |
|
048a325166 | |
|
cde881f1b8 | |
|
a51c1f3d46 | |
|
711ad6dc9e | |
|
8df10d8ad4 | |
|
6a2617a688 | |
|
d98f5f993b | |
|
e31ef119eb | |
|
5f73a1d0ed | |
|
c02759b511 | |
|
5a5847b9ef | |
|
1a168a295b | |
|
5245f85581 | |
|
30dc6bc29b | |
|
5543d1f38c | |
|
606760d54e | |
|
6684563006 | |
|
f80cf827af | |
|
9d816b668f | |
|
f518e8037a | |
|
3d087e401c | |
|
0f28de2bee | |
|
13085feb9c | |
|
8b5600d38f | |
|
aa90bedd37 | |
|
48ab309698 | |
|
c28172b63f | |
|
3b42898889 | |
|
28ab1f36bd | |
|
77e75ef71e |
11
Makefile
11
Makefile
|
@ -1,6 +1,5 @@
|
||||||
NAME = netoik-cicd
|
NAME = netoik-cicd
|
||||||
VERSION = $(shell [ -d ".git" ] && git describe | sed "s/-/./g")
|
VERSION = $(shell [ -d ".git" ] && git describe | sed "s/-/./g")
|
||||||
BRANCH = $(shell [ -d ".git" ] && git branch --show-current)
|
|
||||||
|
|
||||||
TEMP_DIR = "${PWD}/.temp"
|
TEMP_DIR = "${PWD}/.temp"
|
||||||
RPM_SOURCEDIR = $(shell rpm --eval "%{_sourcedir}")
|
RPM_SOURCEDIR = $(shell rpm --eval "%{_sourcedir}")
|
||||||
|
@ -41,7 +40,7 @@ $(RPM_SOURCEDIR)/$(NAME)-%.tar.gz: *
|
||||||
--prefix="$(NAME)-$(VERSION)/" \
|
--prefix="$(NAME)-$(VERSION)/" \
|
||||||
--worktree-attributes \
|
--worktree-attributes \
|
||||||
--verbose \
|
--verbose \
|
||||||
"$(BRANCH)"
|
HEAD
|
||||||
|
|
||||||
.PHONY: tarball
|
.PHONY: tarball
|
||||||
tarball: $(RPM_SOURCEDIR)/$(NAME)-$(VERSION).tar.gz
|
tarball: $(RPM_SOURCEDIR)/$(NAME)-$(VERSION).tar.gz
|
||||||
|
@ -82,16 +81,18 @@ install: conf/*.sample systemd/*.service bin/*
|
||||||
install --directory "$(DESTDIR)$(RUNDIR)/$(NAME)/deployer"
|
install --directory "$(DESTDIR)$(RUNDIR)/$(NAME)/deployer"
|
||||||
install --directory "$(DESTDIR)$(RUNDIR)/$(NAME)/runner"
|
install --directory "$(DESTDIR)$(RUNDIR)/$(NAME)/runner"
|
||||||
install --directory "$(DESTDIR)$(RUNDIR)/$(NAME)/pipeline"
|
install --directory "$(DESTDIR)$(RUNDIR)/$(NAME)/pipeline"
|
||||||
|
install --directory "$(DESTDIR)$(RUNDIR)/$(NAME)/pids"
|
||||||
install --directory "$(DESTDIR)$(TMPDIR)/$(NAME)/repositories"
|
install --directory "$(DESTDIR)$(TMPDIR)/$(NAME)/repositories"
|
||||||
|
|
||||||
.PHONY: check_format
|
.PHONY: check_format
|
||||||
check_format:
|
check_format:
|
||||||
shfmt --diff ./src
|
shfmt --diff ./src ./tests
|
||||||
|
|
||||||
.PHONY: check_linting
|
.PHONY: check_linting
|
||||||
check_linting:
|
check_linting:
|
||||||
shfmt --find ./src | xargs bash -o noexec
|
shfmt --find ./src ./tests | while read f; do bash -o noexec $$f; done
|
||||||
shfmt --find ./src | xargs shellcheck --external-sources
|
shfmt --find ./src ./tests | while read f; do \
|
||||||
|
shellcheck --external-sources $$f; done
|
||||||
|
|
||||||
.PHONY: unit_test
|
.PHONY: unit_test
|
||||||
unit_test:
|
unit_test:
|
||||||
|
|
|
@ -1,61 +1,81 @@
|
||||||
# Config parsing errors.
|
# Deployer config parsing errors.
|
||||||
err_deployer_sock_empty=11
|
err_deployer_sock_empty=11
|
||||||
err_deployer_sock_dir_not_directory=12
|
err_deployer_sock_dir_not_directory=12
|
||||||
err_deployer_sock_dir_not_writable=13
|
err_deployer_sock_dir_not_writable=13
|
||||||
err_deployer_sock_already_in_use=14
|
err_deployer_sock_dir_not_accessible=14
|
||||||
err_deployer_sock_not_exist=15
|
err_deployer_sock_already_in_use=15
|
||||||
err_repos_dir_empty=16
|
err_deployer_sock_not_exist=16
|
||||||
err_repos_dir_not_directory=17
|
err_deployer_pid_empty=17
|
||||||
err_repos_dir_not_accessible=18
|
err_deployer_pid_dir_not_directory=18
|
||||||
err_rpms_dir_empty=19
|
err_deployer_pid_dir_not_writable=19
|
||||||
err_rpms_dir_not_directory=20
|
err_deployer_timeout_empty=20
|
||||||
err_rpms_dir_not_accessible=21
|
err_deployer_timeout_not_valid=21
|
||||||
err_runner_username_empty=22
|
err_deployer_username_empty=22
|
||||||
err_runner_user_not_exist=23
|
err_deployer_user_not_exist=23
|
||||||
err_deployer_timeout_empty=24
|
|
||||||
err_deployer_timeout_not_valid=25
|
|
||||||
err_runner_sock_empty=26
|
|
||||||
err_runner_sock_dir_not_directory=27
|
|
||||||
err_runner_sock_dir_not_writable=28
|
|
||||||
err_runner_sock_already_in_use=29
|
|
||||||
err_runner_sock_not_exist=30
|
|
||||||
err_deployer_username_empty=31
|
|
||||||
err_deployer_user_not_exist=32
|
|
||||||
err_runner_cloning_dir_empty=33
|
|
||||||
err_runner_cloning_dir_not_directory=34
|
|
||||||
err_runner_cloning_dir_not_writable=35
|
|
||||||
err_runner_timeout_empty=36
|
|
||||||
err_runner_timeout_not_valid=37
|
|
||||||
err_git_runner_groupname_empty=38
|
|
||||||
err_git_runner_group_not_exist=39
|
|
||||||
err_runner_deployer_groupname_empty=40
|
|
||||||
err_runner_deployer_group_not_exist=41
|
|
||||||
err_pipeline_sock_dir_empty=42
|
|
||||||
err_pipeline_sock_dir_not_directory=43
|
|
||||||
err_pipeline_sock_dir_not_writable=44
|
|
||||||
|
|
||||||
# JSON parsing errors
|
# Runner config parsing errors.
|
||||||
err_json_bad_format=51
|
err_runner_username_empty=41
|
||||||
err_pkg_name_missing=52
|
err_runner_user_not_exist=42
|
||||||
err_pkg_name_empty=53
|
err_runner_sock_empty=43
|
||||||
err_repo_dir_not_exist=54
|
err_runner_sock_dir_not_directory=44
|
||||||
err_pkg_version_missing=55
|
err_runner_sock_dir_not_writable=45
|
||||||
err_pkg_version_empty=56
|
err_runner_sock_already_in_use=46
|
||||||
err_rpm_path_not_exist=57
|
err_runner_sock_not_exist=47
|
||||||
err_repo_name_missing=58
|
err_runner_pid_empty=48
|
||||||
err_repo_name_empty=59
|
err_runner_pid_dir_not_directory=49
|
||||||
err_repo_hash_missing=60
|
err_runner_pid_dir_not_writable=50
|
||||||
err_repo_hash_empty=61
|
err_runner_pid_not_exist=51
|
||||||
err_repo_tag_empty=62
|
err_runner_pid_not_readable=52
|
||||||
err_clone_repo=63
|
err_runner_process_not_running=53
|
||||||
err_checkout_hash=64
|
err_runner_process_not_killed=54
|
||||||
err_check_format=65
|
err_runner_cloning_dir_empty=55
|
||||||
err_check_linting=66
|
err_runner_cloning_dir_not_directory=56
|
||||||
err_unit_test=67
|
err_runner_cloning_dir_not_writable=57
|
||||||
err_add_tag=68
|
err_runner_timeout_empty=58
|
||||||
err_make_tarball=69
|
err_runner_timeout_not_valid=59
|
||||||
err_rpm_build=70
|
err_runner_deployer_groupname_empty=60
|
||||||
|
err_runner_deployer_group_not_exist=61
|
||||||
|
err_repos_dir_empty=62
|
||||||
|
err_repos_dir_not_directory=63
|
||||||
|
err_repos_dir_not_accessible=64
|
||||||
|
err_rpms_dir_empty=65
|
||||||
|
err_rpms_dir_not_directory=66
|
||||||
|
err_rpms_dir_not_accessible=67
|
||||||
|
|
||||||
|
# Pipeline config parsing errors.
|
||||||
|
err_git_runner_groupname_empty=81
|
||||||
|
err_git_runner_group_not_exist=82
|
||||||
|
err_pipeline_sock_dir_empty=83
|
||||||
|
err_pipeline_sock_dir_not_directory=84
|
||||||
|
err_pipeline_sock_dir_not_writable=85
|
||||||
|
|
||||||
|
# JSON parsing errors.
|
||||||
|
err_json_bad_format=101
|
||||||
|
err_pkg_name_missing=102
|
||||||
|
err_pkg_name_empty=103
|
||||||
|
err_repo_dir_not_exist=104
|
||||||
|
err_pkg_version_missing=105
|
||||||
|
err_pkg_version_empty=106
|
||||||
|
err_rpm_path_not_exist=107
|
||||||
|
err_repo_name_missing=108
|
||||||
|
err_repo_name_empty=109
|
||||||
|
err_repo_hash_missing=110
|
||||||
|
err_repo_hash_empty=111
|
||||||
|
err_repo_tag_empty=112
|
||||||
|
|
||||||
# Operationnal errors.
|
# Operationnal errors.
|
||||||
err_rpm_upgrade=101
|
err_clone_repo=131
|
||||||
err_rpm_install=102
|
err_checkout_hash=132
|
||||||
|
err_check_format=133
|
||||||
|
err_check_linting=134
|
||||||
|
err_unit_test=135
|
||||||
|
err_add_tag=136
|
||||||
|
err_make_tarball=137
|
||||||
|
err_rpm_build=138
|
||||||
|
err_rpm_upgrade=139
|
||||||
|
err_rpm_install=140
|
||||||
|
err_deployer_pid_not_exist=141
|
||||||
|
err_deployer_pid_not_readable=142
|
||||||
|
err_deployer_process_not_running=143
|
||||||
|
err_deployer_process_not_running=144
|
||||||
|
err_deployer_process_not_killed=145
|
||||||
|
|
|
@ -10,6 +10,9 @@ deployer_username="netoik-cicd-deployer"
|
||||||
# Location of unixsock file used to send requests to the deployer server.
|
# Location of unixsock file used to send requests to the deployer server.
|
||||||
deployer_sock="/run/netoik-cicd/deployer/deployer.sock"
|
deployer_sock="/run/netoik-cicd/deployer/deployer.sock"
|
||||||
|
|
||||||
|
# Location of deployer pid.
|
||||||
|
deployer_pid="/run/netoik-cicd/pids/deployer.pid"
|
||||||
|
|
||||||
# Maximum number of seconds to wait for deployer response.
|
# Maximum number of seconds to wait for deployer response.
|
||||||
# Set to 0 to disable timeout.
|
# Set to 0 to disable timeout.
|
||||||
deployer_timeout=30
|
deployer_timeout=30
|
||||||
|
@ -20,6 +23,9 @@ runner_username="netoik-cicd-runner"
|
||||||
# Location of unixsock file used to send requests to the runner server.
|
# Location of unixsock file used to send requests to the runner server.
|
||||||
runner_sock="/run/netoik-cicd/runner/runner.sock"
|
runner_sock="/run/netoik-cicd/runner/runner.sock"
|
||||||
|
|
||||||
|
# Location of runner pid.
|
||||||
|
runner_pid="/run/netoik-cicd/pids/runner.pid"
|
||||||
|
|
||||||
# Directory in which to clone git repositories.
|
# Directory in which to clone git repositories.
|
||||||
runner_cloning_dir="/var/tmp/netoik-cicd/repositories"
|
runner_cloning_dir="/var/tmp/netoik-cicd/repositories"
|
||||||
|
|
||||||
|
@ -34,4 +40,4 @@ pipeline_sock_dir="/run/netoik-cicd/pipeline"
|
||||||
repos_dir="/var/gogs/repositories/samuel"
|
repos_dir="/var/gogs/repositories/samuel"
|
||||||
|
|
||||||
# Directory containing rpm packages.
|
# Directory containing rpm packages.
|
||||||
rpms_dir="/var/netoik-cicd/runner/rpmbuild/RPMS"
|
rpms_dir="/home/netoik-cicd-runner/rpmbuild/RPMS"
|
||||||
|
|
|
@ -10,7 +10,7 @@ Source0: %{name}-%{version}.tar.gz
|
||||||
|
|
||||||
BuildArch: x86_64
|
BuildArch: x86_64
|
||||||
BuildRequires: make
|
BuildRequires: make
|
||||||
Requires: bash,inotify-tools,jq,nmap-ncat,rpm-build,rpmdevtools,ShellCheck
|
Requires: bash,go-toolset,inotify-tools,jq,nmap-ncat,rpm-build,rpmdevtools,ShellCheck,shfmt
|
||||||
|
|
||||||
%description
|
%description
|
||||||
Netoik Continuous Deployment tool
|
Netoik Continuous Deployment tool
|
||||||
|
@ -35,12 +35,17 @@ if ! getent group %{name}-runner-deployer; then
|
||||||
fi
|
fi
|
||||||
if ! id %{name}-runner; then
|
if ! id %{name}-runner; then
|
||||||
useradd --create-home \
|
useradd --create-home \
|
||||||
--home-dir %{_var}/%{name}-runner \
|
--home-dir /home/%{name}-runner \
|
||||||
--shell=%{_bindir}/rpmdev-setuptree \
|
--shell=%{_bindir}/rpmdev-setuptree \
|
||||||
--groups %{name}-git-runner,%{name}-runner-deployer \
|
--groups %{name}-git-runner,%{name}-runner-deployer \
|
||||||
--user-group \
|
--gid %{name}-runner-deployer \
|
||||||
%{name}-runner
|
%{name}-runner
|
||||||
|
chmod 710 /home/%{name}-runner
|
||||||
runuser --login %{name}-runner
|
runuser --login %{name}-runner
|
||||||
|
runuser --user %{name}-runner -- git config \
|
||||||
|
--global user.email %{name}-runner@netoik.io
|
||||||
|
runuser --user %{name}-runner -- git config \
|
||||||
|
--global user.name %{name}-runner
|
||||||
fi
|
fi
|
||||||
if ! id %{name}-deployer; then
|
if ! id %{name}-deployer; then
|
||||||
useradd --no-create-home \
|
useradd --no-create-home \
|
||||||
|
@ -55,23 +60,17 @@ fi
|
||||||
# Reload systemctl daemon.
|
# Reload systemctl daemon.
|
||||||
systemctl daemon-reload
|
systemctl daemon-reload
|
||||||
# Restart deployer service.
|
# Restart deployer service.
|
||||||
systemctl stop %{name}-deployer.service
|
systemctl restart %{name}-deployer.service
|
||||||
rm --force %{_rundir}/%{name}/deployer/deployer.sock
|
|
||||||
systemctl start %{name}-deployer.service
|
|
||||||
systemctl enable %{name}-deployer.service
|
systemctl enable %{name}-deployer.service
|
||||||
# Restart runner service.
|
# Restart runner service.
|
||||||
systemctl stop %{name}-runner.service
|
systemctl restart %{name}-runner.service
|
||||||
rm --force %{_rundir}/%{name}/runner/runner.sock
|
|
||||||
systemctl start %{name}-runner.service
|
|
||||||
systemctl enable %{name}-runner.service
|
systemctl enable %{name}-runner.service
|
||||||
|
|
||||||
%preun
|
%preun
|
||||||
# Stop service only if uninstalling.
|
# Stop service only if uninstalling.
|
||||||
if [ $1 -eq 0 ]; then
|
if [ $1 -eq 0 ]; then
|
||||||
systemctl disable --now %{name}-deployer.service
|
systemctl disable --now %{name}-deployer.service
|
||||||
rm --force %{_rundir}/%{name}/deployer/deployer.sock
|
|
||||||
systemctl disable --now %{name}-runner.service
|
systemctl disable --now %{name}-runner.service
|
||||||
rm --force %{_rundir}/%{name}/runner/runner.sock
|
|
||||||
fi
|
fi
|
||||||
|
|
||||||
%postun
|
%postun
|
||||||
|
@ -99,5 +98,6 @@ fi
|
||||||
%attr(755, %{name}-deployer, %{name}-deployer) %dir %{_rundir}/%{name}/deployer
|
%attr(755, %{name}-deployer, %{name}-deployer) %dir %{_rundir}/%{name}/deployer
|
||||||
%attr(755, git, git) %dir %{_rundir}/%{name}/pipeline
|
%attr(755, git, git) %dir %{_rundir}/%{name}/pipeline
|
||||||
%attr(755, %{name}-runner, %{name}-runner) %dir %{_rundir}/%{name}/runner
|
%attr(755, %{name}-runner, %{name}-runner) %dir %{_rundir}/%{name}/runner
|
||||||
|
%attr(775, %{name}-deployer, %{name}-runner-deployer) %dir %{_rundir}/%{name}/pids
|
||||||
%attr(755, root, root) %dir %{_tmppath}/%{name}
|
%attr(755, root, root) %dir %{_tmppath}/%{name}
|
||||||
%attr(755, %{name}-runner, %{name}-runner) %dir %{_tmppath}/%{name}/repositories
|
%attr(755, %{name}-runner, root) %dir %{_tmppath}/%{name}/repositories
|
||||||
|
|
122
src/deployer.sh
122
src/deployer.sh
|
@ -77,7 +77,7 @@ fail() (
|
||||||
)
|
)
|
||||||
|
|
||||||
usage() (
|
usage() (
|
||||||
echo "Usage: ${PROGRAM_NAME} [OPTION]...
|
echo "Usage: ${PROGRAM_NAME} [OPTION]... ACTION
|
||||||
Start deployer server, wait for unixsock requests to deploy rpm packages.
|
Start deployer server, wait for unixsock requests to deploy rpm packages.
|
||||||
|
|
||||||
Mandatory argumentes for long options are mandatory for short options too.
|
Mandatory argumentes for long options are mandatory for short options too.
|
||||||
|
@ -89,10 +89,14 @@ Mandatory argumentes for long options are mandatory for short options too.
|
||||||
${DEFAULT_ERRORS_FILE}
|
${DEFAULT_ERRORS_FILE}
|
||||||
-o, --once stop listening after first request process
|
-o, --once stop listening after first request process
|
||||||
-q, --quiet set level verbosity to WARN, default to INFO
|
-q, --quiet set level verbosity to WARN, default to INFO
|
||||||
-t, --test just test config file and do not run start loop
|
|
||||||
-v, --verbose set level verbosity to DEBUG, default to INFO
|
-v, --verbose set level verbosity to DEBUG, default to INFO
|
||||||
|
|
||||||
-h, --help display this help message and exit
|
-h, --help display this help message and exit
|
||||||
|
|
||||||
|
Positional argument ACTION
|
||||||
|
start start deployer server
|
||||||
|
stop stop deployer server
|
||||||
|
test test configuration and exit
|
||||||
"
|
"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
@ -194,9 +198,9 @@ process_request() (
|
||||||
fi
|
fi
|
||||||
log_debug "RPM path found at '${rpm_path}'."
|
log_debug "RPM path found at '${rpm_path}'."
|
||||||
|
|
||||||
# Upgrade package if already installed.
|
|
||||||
log_debug "Check if pkg '${pkg_name}' is already installed."
|
log_debug "Check if pkg '${pkg_name}' is already installed."
|
||||||
if rpm --query "${pkg_name}" 1>/dev/null 2>/dev/null; then
|
if rpm --query "${pkg_name}" 1>/dev/null 2>/dev/null; then
|
||||||
|
# Upgrade package if already installed.
|
||||||
log_debug "Package '${pkg_name}' already installed, so upgrade to v
|
log_debug "Package '${pkg_name}' already installed, so upgrade to v
|
||||||
${pkg_version}"
|
${pkg_version}"
|
||||||
if ! output="$(sudo rpm --upgrade \
|
if ! output="$(sudo rpm --upgrade \
|
||||||
|
@ -206,8 +210,7 @@ process_request() (
|
||||||
return
|
return
|
||||||
fi
|
fi
|
||||||
log_debug "RPM package '${pkg_name}' upgraded to v${pkg_version}."
|
log_debug "RPM package '${pkg_name}' upgraded to v${pkg_version}."
|
||||||
fi
|
else
|
||||||
|
|
||||||
# Install package if not already installed.
|
# Install package if not already installed.
|
||||||
log_debug "Package '${pkg_name}' is not already installed, so install
|
log_debug "Package '${pkg_name}' is not already installed, so install
|
||||||
v${pkg_version}."
|
v${pkg_version}."
|
||||||
|
@ -216,6 +219,7 @@ process_request() (
|
||||||
"Cannot install package '${pkg_name}' v${pkg_version}: ${output}."
|
"Cannot install package '${pkg_name}' v${pkg_version}: ${output}."
|
||||||
return
|
return
|
||||||
fi
|
fi
|
||||||
|
fi
|
||||||
|
|
||||||
# Package deployed.
|
# Package deployed.
|
||||||
reply 0 "RPM package '${pkg_name}' v${pkg_version} has been deployed."
|
reply 0 "RPM package '${pkg_name}' v${pkg_version} has been deployed."
|
||||||
|
@ -227,41 +231,30 @@ process_loop() (
|
||||||
log_info "Start listening unixsock with keep-open at '${deployer_sock}'."
|
log_info "Start listening unixsock with keep-open at '${deployer_sock}'."
|
||||||
while read -r request; do
|
while read -r request; do
|
||||||
log_info "Process new request '${request}'."
|
log_info "Process new request '${request}'."
|
||||||
process_request
|
process_request &
|
||||||
done < <(ncat --listen --keep-open --unixsock "${deployer_sock}")
|
done < <(ncat --listen --keep-open --unixsock "${deployer_sock}")
|
||||||
|
log_critical "Unexpected end of listening at '${deployer_sock}'."
|
||||||
else
|
else
|
||||||
log_info "Start listening unixsock without keep-open at '${deployer_sock}'."
|
log_info "Start listening unixsock without keep-open at '${deployer_sock}'."
|
||||||
while read -r request; do
|
while read -r request; do
|
||||||
log_info "Process new request '${request}'."
|
log_info "Process new request '${request}'."
|
||||||
process_request
|
process_request
|
||||||
done < <(ncat --listen --unixsock "${deployer_sock}")
|
done < <(ncat --listen --unixsock "${deployer_sock}")
|
||||||
|
log_info "End of listening at '${deployer_sock}'."
|
||||||
fi
|
fi
|
||||||
|
|
||||||
# Kill all remaining subprocesses only if daemon.
|
|
||||||
log_info "End of loop."
|
|
||||||
if "${daemon}"; then
|
|
||||||
log_debug "Kill child jobs."
|
|
||||||
jobs -p | xargs kill 2>/dev/null || true
|
|
||||||
fi
|
|
||||||
|
|
||||||
# Remove sock file
|
|
||||||
log_debug "Remove deployer unixsock file."
|
|
||||||
rm --force "${deployer_sock}"
|
|
||||||
log_info "End of process."
|
|
||||||
)
|
)
|
||||||
|
|
||||||
main() (
|
main() (
|
||||||
# Parse arguments.
|
# Parse arguments.
|
||||||
daemon="false"
|
daemonize="false"
|
||||||
testing="false"
|
|
||||||
keep_open="true"
|
keep_open="true"
|
||||||
config_file="${DEFAULT_CONFIG_FILE}"
|
config_file="${DEFAULT_CONFIG_FILE}"
|
||||||
errors_file="${DEFAULT_ERRORS_FILE}"
|
errors_file="${DEFAULT_ERRORS_FILE}"
|
||||||
verbosity_option=""
|
verbosity_option=""
|
||||||
verbosity_level="${DEFAULT_VERBOSITY_LEVEL}"
|
verbosity_level="${DEFAULT_VERBOSITY_LEVEL}"
|
||||||
if ! args="$(getopt --name "${PROGRAM_NAME}" \
|
if ! args="$(getopt --name "${PROGRAM_NAME}" \
|
||||||
--options c:de:hoqtv \
|
--options c:de:hoqv \
|
||||||
--longoptions conf:,daemon,errs:,help,once,quiet,test,verbose \
|
--longoptions conf:,daemon,errs:,help,once,quiet,verbose \
|
||||||
-- "$@")"; then
|
-- "$@")"; then
|
||||||
usage
|
usage
|
||||||
fail "Bad arguments."
|
fail "Bad arguments."
|
||||||
|
@ -275,7 +268,7 @@ main() (
|
||||||
shift 2
|
shift 2
|
||||||
;;
|
;;
|
||||||
-d | --daemon)
|
-d | --daemon)
|
||||||
daemon="true"
|
daemonize="true"
|
||||||
shift
|
shift
|
||||||
;;
|
;;
|
||||||
-e | --errs)
|
-e | --errs)
|
||||||
|
@ -299,10 +292,6 @@ main() (
|
||||||
((verbosity_level -= 10))
|
((verbosity_level -= 10))
|
||||||
shift
|
shift
|
||||||
;;
|
;;
|
||||||
-t | --test)
|
|
||||||
testing="true"
|
|
||||||
shift
|
|
||||||
;;
|
|
||||||
-v | --verbose)
|
-v | --verbose)
|
||||||
if [ "${verbosity_option}" ]; then
|
if [ "${verbosity_option}" ]; then
|
||||||
usage
|
usage
|
||||||
|
@ -322,10 +311,19 @@ main() (
|
||||||
;;
|
;;
|
||||||
esac
|
esac
|
||||||
done
|
done
|
||||||
if [ "$@" ]; then
|
if [ $# -ne 1 ]; then
|
||||||
usage
|
usage
|
||||||
fail "Unexpected extra arguments '$*'."
|
fail "Missing positional argument ACTION"
|
||||||
fi
|
fi
|
||||||
|
case "$1" in
|
||||||
|
start | stop | test)
|
||||||
|
action="$1"
|
||||||
|
;;
|
||||||
|
*)
|
||||||
|
usage
|
||||||
|
fail "Bad positional argument ACTION '$1'."
|
||||||
|
;;
|
||||||
|
esac
|
||||||
|
|
||||||
# Load config file.
|
# Load config file.
|
||||||
if [ ! -r "${config_file}" ]; then
|
if [ ! -r "${config_file}" ]; then
|
||||||
|
@ -355,10 +353,6 @@ main() (
|
||||||
fail "Directory of deployer_sock='${deployer_sock}' is not writable." \
|
fail "Directory of deployer_sock='${deployer_sock}' is not writable." \
|
||||||
"${err_deployer_sock_dir_not_writable}"
|
"${err_deployer_sock_dir_not_writable}"
|
||||||
fi
|
fi
|
||||||
if [ -e "${deployer_sock}" ]; then
|
|
||||||
fail "Sock deployer_sock='${deployer_sock}' is already in use." \
|
|
||||||
"${err_deployer_sock_already_in_use}"
|
|
||||||
fi
|
|
||||||
|
|
||||||
if [ -z "${repos_dir}" ]; then
|
if [ -z "${repos_dir}" ]; then
|
||||||
fail "Variable repos_dir is empty." "${err_repos_dir_empty}"
|
fail "Variable repos_dir is empty." "${err_repos_dir_empty}"
|
||||||
|
@ -381,34 +375,84 @@ main() (
|
||||||
fi
|
fi
|
||||||
|
|
||||||
if [ -z "${runner_deployer_groupname}" ]; then
|
if [ -z "${runner_deployer_groupname}" ]; then
|
||||||
fail "Variable runner_deployer_username is empty." "${err_runner_deployer_groupname_empty}"
|
fail "Variable runner_deployer_username is empty." \
|
||||||
|
"${err_runner_deployer_groupname_empty}"
|
||||||
fi
|
fi
|
||||||
if ! getent group "${runner_deployer_groupname}"; then
|
if ! getent group "${runner_deployer_groupname}" >/dev/null; then
|
||||||
fail "Runner-deployer group '${runner_deployer_groupname}' does not exist." \
|
fail "Runner-deployer group '${runner_deployer_groupname}' does not exist." \
|
||||||
"${err_runner_deployer_group_not_exist}"
|
"${err_runner_deployer_group_not_exist}"
|
||||||
fi
|
fi
|
||||||
|
|
||||||
|
if [ -z "${deployer_pid}" ]; then
|
||||||
|
fail "Variable deployer_pid is empty." "${err_deployer_pid_empty}"
|
||||||
|
fi
|
||||||
|
if [ ! -d "$(dirname "${deployer_pid}")" ]; then
|
||||||
|
fail "Dirname of deployer_pid='${deployer_pid}' is not a directory." \
|
||||||
|
"${err_deployer_pid_dir_not_directory}"
|
||||||
|
fi
|
||||||
|
if [ ! -w "$(dirname "${deployer_pid}")" ]; then
|
||||||
|
fail "Dirname of deployer_pid='${deployer_pid}' is not writable." \
|
||||||
|
"${err_deployer_pid_dir_not_writable}"
|
||||||
|
fi
|
||||||
|
|
||||||
|
case "${action}" in
|
||||||
|
test)
|
||||||
# Stop now if we are only testing config.
|
# Stop now if we are only testing config.
|
||||||
if "${testing}"; then
|
|
||||||
exit 0
|
exit 0
|
||||||
|
;;
|
||||||
|
start)
|
||||||
|
if [ -e "${deployer_sock}" ]; then
|
||||||
|
fail "Sock deployer_sock='${deployer_sock}' is already in use." \
|
||||||
|
"${err_deployer_sock_already_in_use}"
|
||||||
fi
|
fi
|
||||||
|
|
||||||
# Set right access in background after nc listen.
|
# Set right access in background after nc listen.
|
||||||
(
|
(
|
||||||
inotifywait --event create "$(dirname "${deployer_sock}")" --quiet --quiet
|
inotifywait --timeout 1 --quiet --quiet \
|
||||||
|
--event create "$(dirname "${deployer_sock}")" || true
|
||||||
chmod 775 "${deployer_sock}"
|
chmod 775 "${deployer_sock}"
|
||||||
chgrp "${runner_deployer_groupname}" "${deployer_sock}"
|
chgrp "${runner_deployer_groupname}" "${deployer_sock}"
|
||||||
) &
|
) &
|
||||||
|
|
||||||
# Run process loop in background or foreground.
|
# Run process loop in background or foreground.
|
||||||
if "${daemon}"; then
|
if "${daemonize}"; then
|
||||||
log_info "Run process loop in background."
|
log_info "Run process loop in background."
|
||||||
process_loop &
|
process_loop &
|
||||||
|
echo "$!" >"${deployer_pid}"
|
||||||
else
|
else
|
||||||
log_info "Run process loop in foreground."
|
log_info "Run process loop in foreground."
|
||||||
|
echo "$$" >"${deployer_pid}"
|
||||||
process_loop
|
process_loop
|
||||||
jobs -p | xargs kill 2>/dev/null || true
|
|
||||||
fi
|
fi
|
||||||
|
;;
|
||||||
|
stop)
|
||||||
|
if [ ! -f "${deployer_pid}" ]; then
|
||||||
|
fail "File deployer_pid='${deployer_pid}' does not exist." \
|
||||||
|
"${err_deployer_pid_not_exist}"
|
||||||
|
fi
|
||||||
|
if [ ! -r "${deployer_pid}" ]; then
|
||||||
|
fail "File deployer_pid='${deployer_pid}' is not readable." \
|
||||||
|
"${err_deployer_pid_not_readable}"
|
||||||
|
fi
|
||||||
|
pid="$(cat "${deployer_pid}")"
|
||||||
|
rm --force "${deployer_pid}"
|
||||||
|
|
||||||
|
# Kill deployer process.
|
||||||
|
log_info "Kill deployer process with pid '${pid}'."
|
||||||
|
if ! ps -p "${pid}" >/dev/null; then
|
||||||
|
fail "Deployer process with pid='${pid}' is not running." \
|
||||||
|
"${err_deployer_process_not_running}"
|
||||||
|
fi
|
||||||
|
if ! output="$(kill "${pid}" 2>&1 || kill -KILL "${pid}" 2>&1)"; then
|
||||||
|
fail "Cannot kill deployer process: ${output}." \
|
||||||
|
"${err_deployer_process_not_killed}"
|
||||||
|
fi
|
||||||
|
|
||||||
|
# Remove deployer sock file.
|
||||||
|
log_info "Remove deployer sock at '${deployer_sock}'."
|
||||||
|
rm --force "${deployer_sock}"
|
||||||
|
;;
|
||||||
|
esac
|
||||||
)
|
)
|
||||||
|
|
||||||
main "$@"
|
main "$@"
|
||||||
|
|
|
@ -130,7 +130,39 @@ main() (
|
||||||
usage
|
usage
|
||||||
fail "Missing positionnal argument PIPELINE."
|
fail "Missing positionnal argument PIPELINE."
|
||||||
fi
|
fi
|
||||||
|
|
||||||
|
# Check pipeline validity.
|
||||||
pipeline="$1"
|
pipeline="$1"
|
||||||
|
case "${pipeline}" in
|
||||||
|
newcommit)
|
||||||
|
if [ -z "${repo_name}" ]; then
|
||||||
|
usage
|
||||||
|
fail "missing option -n|--name for pipeline '${pipeline}'."
|
||||||
|
fi
|
||||||
|
if [ -z "${repo_hash}" ]; then
|
||||||
|
usage
|
||||||
|
fail "missing option -h|--hash for pipeline '${pipeline}'."
|
||||||
|
fi
|
||||||
|
;;
|
||||||
|
newtag)
|
||||||
|
if [ -z "${repo_name}" ]; then
|
||||||
|
usage
|
||||||
|
fail "Missing option -n|--name for pipeline '${pipeline}'."
|
||||||
|
fi
|
||||||
|
if [ -z "${repo_hash}" ]; then
|
||||||
|
usage
|
||||||
|
fail "Missing option -H|--hash for pipeline '${pipeline}'."
|
||||||
|
fi
|
||||||
|
if [ -z "${repo_tag}" ]; then
|
||||||
|
usage
|
||||||
|
fail "Missing option -T|--tag for pipeline '${pipeline}'."
|
||||||
|
fi
|
||||||
|
;;
|
||||||
|
*)
|
||||||
|
usage
|
||||||
|
fail "Unexpected value for PIPELINE: '${pipeline}'."
|
||||||
|
;;
|
||||||
|
esac
|
||||||
|
|
||||||
# Load config file.
|
# Load config file.
|
||||||
if [ ! -r "${config_file}" ]; then
|
if [ ! -r "${config_file}" ]; then
|
||||||
|
@ -166,7 +198,7 @@ main() (
|
||||||
if [ -z "${git_runner_groupname}" ]; then
|
if [ -z "${git_runner_groupname}" ]; then
|
||||||
fail "Variable git_runner_groupname is empty." "${err_git_runner_groupname_empty}"
|
fail "Variable git_runner_groupname is empty." "${err_git_runner_groupname_empty}"
|
||||||
fi
|
fi
|
||||||
if ! getent group "${git_runner_groupname}"; then
|
if ! getent group "${git_runner_groupname}" >/dev/null; then
|
||||||
fail "Git-runner group '${git_runner_groupname}' does not exist." \
|
fail "Git-runner group '${git_runner_groupname}' does not exist." \
|
||||||
"${err_git_runner_group_not_exist}"
|
"${err_git_runner_group_not_exist}"
|
||||||
fi
|
fi
|
||||||
|
@ -183,44 +215,24 @@ main() (
|
||||||
"${err_pipeline_sock_dir_not_writable}"
|
"${err_pipeline_sock_dir_not_writable}"
|
||||||
fi
|
fi
|
||||||
|
|
||||||
# Generate pipeline tmp sock.
|
# Generate random string.
|
||||||
tsp="$(date +%s)"
|
random="$(echo "${RANDOM}" | md5sum | head --bytes 7)"
|
||||||
random="$(echo "${RANDOM}" | md5sum | head --bytes 32)"
|
|
||||||
rd_pipeline_sock_dir="${pipeline_sock_dir}/${pipeline}-${tsp}-${random}"
|
|
||||||
rd_pipeline_sock="${rd_pipeline_sock_dir}/pipeline.sock"
|
|
||||||
|
|
||||||
# Check pipeline with options.
|
# Build runner request.
|
||||||
case "${pipeline}" in
|
case "${pipeline}" in
|
||||||
newcommit)
|
newcommit)
|
||||||
if [ -z "${repo_name}" ]; then
|
repo_id="$(echo "${repo_hash}" | head -c 7)"
|
||||||
usage
|
rd_pipeline_sock_dir="${pipeline_sock_dir}/${pipeline}-${repo_id}-${random}"
|
||||||
fail "Missing option -n|--name for pipeline '${pipeline}'."
|
|
||||||
fi
|
|
||||||
if [ -z "${repo_hash}" ]; then
|
|
||||||
usage
|
|
||||||
fail "Missing option -H|--hash for pipeline '${pipeline}'."
|
|
||||||
fi
|
|
||||||
runner_request="$(jq --null-input --compact-output \
|
runner_request="$(jq --null-input --compact-output \
|
||||||
--arg s "${rd_pipeline_sock}" \
|
--arg s "${rd_pipeline_sock_dir}/pipeline.sock" \
|
||||||
--arg n "${repo_name}" \
|
--arg n "${repo_name}" \
|
||||||
--arg h "${repo_hash}" \
|
--arg h "${repo_hash}" \
|
||||||
'{"response_sock":$s,"repo_name":$n,"repo_hash":$h}')"
|
'{"response_sock":$s,"repo_name":$n,"repo_hash":$h}')"
|
||||||
;;
|
;;
|
||||||
newtag)
|
newtag)
|
||||||
if [ -z "${repo_name}" ]; then
|
rd_pipeline_sock_dir="${pipeline_sock_dir}/${pipeline}-${repo_tag}-${random}"
|
||||||
usage
|
|
||||||
fail "Missing option -n|--name for pipeline '${pipeline}'."
|
|
||||||
fi
|
|
||||||
if [ -z "${repo_hash}" ]; then
|
|
||||||
usage
|
|
||||||
fail "Missing option -H|--hash for pipeline '${pipeline}'."
|
|
||||||
fi
|
|
||||||
if [ -z "${repo_tag}" ]; then
|
|
||||||
usage
|
|
||||||
fail "Missing option -T|--tag for pipeline '${pipeline}'."
|
|
||||||
fi
|
|
||||||
runner_request="$(jq --null-input --compact-output \
|
runner_request="$(jq --null-input --compact-output \
|
||||||
--arg s "${rd_pipeline_sock}" \
|
--arg s "${rd_pipeline_sock_dir}/pipeline.sock" \
|
||||||
--arg n "${repo_name}" \
|
--arg n "${repo_name}" \
|
||||||
--arg h "${repo_hash}" \
|
--arg h "${repo_hash}" \
|
||||||
--arg t "${repo_tag}" \
|
--arg t "${repo_tag}" \
|
||||||
|
@ -240,26 +252,32 @@ main() (
|
||||||
# Send request to runner.
|
# Send request to runner.
|
||||||
mkdir "${rd_pipeline_sock_dir}"
|
mkdir "${rd_pipeline_sock_dir}"
|
||||||
(
|
(
|
||||||
inotifywait --quiet --quiet --event create "${rd_pipeline_sock_dir}"
|
inotifywait --timeout 1 --quiet --quiet \
|
||||||
chmod 775 "${rd_pipeline_sock}"
|
--event create "${rd_pipeline_sock_dir}" || true
|
||||||
chgrp "${git_runner_groupname}" "${rd_pipeline_sock}"
|
chmod 775 "${rd_pipeline_sock_dir}/pipeline.sock"
|
||||||
|
chgrp "${git_runner_groupname}" "${rd_pipeline_sock_dir}/pipeline.sock"
|
||||||
echo "${runner_request}" | ncat --unixsock "${runner_sock}"
|
echo "${runner_request}" | ncat --unixsock "${runner_sock}"
|
||||||
) &
|
) &
|
||||||
|
|
||||||
# Wait for runner response.
|
# Start CI runner.
|
||||||
|
echo -e "Starting CI runner..."
|
||||||
|
cd "${rd_pipeline_sock_dir}"
|
||||||
|
ncat_cmd="ncat --listen --unixsock --keep-open pipeline.sock"
|
||||||
if [ "${runner_timeout}" -gt 0 ]; then
|
if [ "${runner_timeout}" -gt 0 ]; then
|
||||||
response="$(timeout "${runner_timeout}" ncat --listen \
|
ncat_cmd="timeout ${runner_timeout} ${ncat_cmd}"
|
||||||
--unixsock "${rd_pipeline_sock}")"
|
|
||||||
else
|
|
||||||
response="$(ncat --listen --unixsock "${rd_pipeline_sock}")"
|
|
||||||
fi
|
fi
|
||||||
|
while read -r response; do
|
||||||
|
echo -e "$(echo "${response}" | jq --raw-output .msg)"
|
||||||
|
code="$(echo "${response}" | jq .code)"
|
||||||
|
[ "${code}" = "null" ] || break
|
||||||
|
done < <($ncat_cmd)
|
||||||
|
pkill --full --exact --parent "$$" "${ncat_cmd}" || true
|
||||||
|
|
||||||
# Remove random directory.
|
# Remove random directory.
|
||||||
rm --recursive "${rd_pipeline_sock_dir}"
|
rm --recursive "${rd_pipeline_sock_dir}"
|
||||||
|
|
||||||
# Display response.
|
# Display response.
|
||||||
echo -e "$(echo "${response}" | jq .msg)"
|
exit "${code}"
|
||||||
exit "$(echo "${response}" | jq .code)"
|
|
||||||
)
|
)
|
||||||
|
|
||||||
main "$@"
|
main "$@"
|
||||||
|
|
245
src/runner.sh
245
src/runner.sh
|
@ -70,7 +70,7 @@ fail() (
|
||||||
)
|
)
|
||||||
|
|
||||||
usage() (
|
usage() (
|
||||||
echo "Usage: ${PROGRAM_NAME} [OPTION]...
|
echo "Usage: ${PROGRAM_NAME} [OPTION]... ACTION
|
||||||
Start runner server, wait for unixsock requests to clone git repo, run tests
|
Start runner server, wait for unixsock requests to clone git repo, run tests
|
||||||
and build rpm package.
|
and build rpm package.
|
||||||
|
|
||||||
|
@ -83,29 +83,41 @@ Mandatory argumentes for long options are mandatory for short options too.
|
||||||
${DEFAULT_ERRORS_FILE}
|
${DEFAULT_ERRORS_FILE}
|
||||||
-o, --once stop listening after first request process
|
-o, --once stop listening after first request process
|
||||||
-q, --quiet set level verbosity to WARN, default to INFO
|
-q, --quiet set level verbosity to WARN, default to INFO
|
||||||
-t, --test just test config file and do not run start loop
|
|
||||||
-v, --verbose set level verbosity to DEBUG, default to INFO
|
-v, --verbose set level verbosity to DEBUG, default to INFO
|
||||||
|
|
||||||
-h, --help display this help message and exit
|
-h, --help display this help message and exit
|
||||||
|
|
||||||
|
Positional argument ACTION
|
||||||
|
start start runner server
|
||||||
|
stop stop runner server
|
||||||
|
test tests configuration and exit
|
||||||
"
|
"
|
||||||
)
|
)
|
||||||
|
|
||||||
reply() (
|
reply() (
|
||||||
code="$1"
|
msg="$1"
|
||||||
msg="$2"
|
code="$2"
|
||||||
|
|
||||||
if [ "${code}" -gt 0 ]; then
|
if [ -z "${code}" ]; then
|
||||||
log_error "${msg}"
|
|
||||||
else
|
|
||||||
log_info "${msg}"
|
log_info "${msg}"
|
||||||
|
json="$(jq --null-input \
|
||||||
|
--compact-output \
|
||||||
|
--arg m "${msg}" \
|
||||||
|
'{"msg":$m}')"
|
||||||
|
else
|
||||||
|
if [ "${code}" -eq 0 ]; then
|
||||||
|
log_info "${msg}"
|
||||||
|
else
|
||||||
|
log_error "${msg}"
|
||||||
|
fi
|
||||||
|
json="$(jq --null-input \
|
||||||
|
--compact-output \
|
||||||
|
--arg m "${msg}" \
|
||||||
|
--arg c "${code}" \
|
||||||
|
'{"msg":$m,"code":$c|tonumber}')"
|
||||||
fi
|
fi
|
||||||
|
|
||||||
if ! output="$(jq --null-input \
|
if ! output="$(echo "${json}" | ncat --unixsock "${response_sock}" 2>&1)"; then
|
||||||
--compact-output \
|
|
||||||
--arg c "${code}" \
|
|
||||||
--arg m "${msg}" \
|
|
||||||
'{"code":$c|tonumber,"msg":$m}' |
|
|
||||||
ncat --unixsock "${response_sock}" 2>&1)"; then
|
|
||||||
log_error "Cannot write to sock '${response_sock}': ${output}."
|
log_error "Cannot write to sock '${response_sock}': ${output}."
|
||||||
fi
|
fi
|
||||||
)
|
)
|
||||||
|
@ -113,7 +125,7 @@ reply() (
|
||||||
fwd_reply() (
|
fwd_reply() (
|
||||||
read -r json
|
read -r json
|
||||||
|
|
||||||
if ! output="$(echo "${json}" | ncat --unixsock 2>&1)"; then
|
if ! output="$(echo "${json}" | ncat --unixsock "${response_sock}" 2>&1)"; then
|
||||||
log_error "Cannot write to sock '${response_sock}': ${output}."
|
log_error "Cannot write to sock '${response_sock}': ${output}."
|
||||||
fi
|
fi
|
||||||
)
|
)
|
||||||
|
@ -145,17 +157,18 @@ process_request() (
|
||||||
log_debug "Get repo_name from json."
|
log_debug "Get repo_name from json."
|
||||||
if ! repo_name="$(echo "${request}" |
|
if ! repo_name="$(echo "${request}" |
|
||||||
jq --raw-output ".repo_name" 2>&1)"; then
|
jq --raw-output ".repo_name" 2>&1)"; then
|
||||||
reply "${err_json_bad_format}" \
|
reply "Cannot parse json '${request}': ${repo_name}." \
|
||||||
"Cannot parse json '${request}': ${repo_name}."
|
"${err_json_bad_format}"
|
||||||
return
|
return
|
||||||
fi
|
fi
|
||||||
if [ "${repo_name}" = "null" ]; then
|
if [ "${repo_name}" = "null" ]; then
|
||||||
reply "${err_repo_name_missing}" "Missing key repo_name in '${request}'."
|
reply "Missing key repo_name in '${request}'." \
|
||||||
|
"${err_repo_name_missing}"
|
||||||
return
|
return
|
||||||
fi
|
fi
|
||||||
if [ -z "${repo_name}" ]; then
|
if [ -z "${repo_name}" ]; then
|
||||||
reply "${err_repo_name_empty}" \
|
reply "Empty value for key repo_name in '${request}'." \
|
||||||
"Empty value for key repo_name in '${request}'."
|
"${err_repo_name_empty}"
|
||||||
return
|
return
|
||||||
fi
|
fi
|
||||||
log_debug "Got pkg name: '${repo_name}'."
|
log_debug "Got pkg name: '${repo_name}'."
|
||||||
|
@ -163,7 +176,8 @@ process_request() (
|
||||||
# Get repository folder.
|
# Get repository folder.
|
||||||
repo_dir="${repos_dir}/${repo_name}.git"
|
repo_dir="${repos_dir}/${repo_name}.git"
|
||||||
if [ ! -d "${repo_dir}" ]; then
|
if [ ! -d "${repo_dir}" ]; then
|
||||||
reply "${err_repo_dir_not_exist}" "Repository '${repo_dir}' does not exist."
|
reply "Repository '${repo_dir}' does not exist." \
|
||||||
|
"${err_repo_dir_not_exist}"
|
||||||
return
|
return
|
||||||
fi
|
fi
|
||||||
log_debug "Repository is present at '${repo_dir}'."
|
log_debug "Repository is present at '${repo_dir}'."
|
||||||
|
@ -171,99 +185,109 @@ process_request() (
|
||||||
# Get repo_hash from json.
|
# Get repo_hash from json.
|
||||||
log_debug "Get repo_hash from json."
|
log_debug "Get repo_hash from json."
|
||||||
if ! repo_hash=$(echo "${request}" | jq --raw-output ".repo_hash" 2>&1); then
|
if ! repo_hash=$(echo "${request}" | jq --raw-output ".repo_hash" 2>&1); then
|
||||||
reply "${err_json_bad_format}" \
|
reply "Cannot parse json '${request}': ${repo_hash}." \
|
||||||
"Cannot parse json '${request}': ${repo_hash}."
|
"${err_json_bad_format}"
|
||||||
return
|
return
|
||||||
fi
|
fi
|
||||||
if [ "${repo_hash}" = "null" ]; then
|
if [ "${repo_hash}" = "null" ]; then
|
||||||
reply "${err_repo_hash_missing}" "Missing key repo_hash in '${request}'."
|
reply "Missing key repo_hash in '${request}'." \
|
||||||
|
"${err_repo_hash_missing}"
|
||||||
return
|
return
|
||||||
fi
|
fi
|
||||||
if [ -z "${repo_hash}" ]; then
|
if [ -z "${repo_hash}" ]; then
|
||||||
reply "${err_repo_hash_empty}" \
|
reply "Empty value for key repo_hash in '${request}'." \
|
||||||
"Empty value for key repo_hash in '${request}'." 1>&2
|
"${err_repo_hash_empty}"
|
||||||
return
|
return
|
||||||
fi
|
fi
|
||||||
|
|
||||||
# Get repo_tag from json.
|
# Get repo_tag from json.
|
||||||
log_debug "Get repo_tag from json."
|
log_debug "Get repo_tag from json."
|
||||||
if ! repo_tag=$(echo "${request}" | jq --raw-output ".repo_tag"); then
|
if ! repo_tag=$(echo "${request}" | jq --raw-output ".repo_tag"); then
|
||||||
reply "${err_json_bad_format}" \
|
reply "Cannot parse json '${request}': ${repo_tag}." \
|
||||||
"Cannot parse json '${request}': ${repo_tag}."
|
"${err_json_bad_format}"
|
||||||
return
|
return
|
||||||
fi
|
fi
|
||||||
if [ -z "${repo_tag}" ]; then
|
if [ -z "${repo_tag}" ]; then
|
||||||
reply "${err_repo_tag_empty}" \
|
reply "Empty value for key repo_tag in '${request}'." \
|
||||||
"Empty value for key repo_tag in '${request}'."
|
"${err_repo_tag_empty}"
|
||||||
return
|
return
|
||||||
fi
|
fi
|
||||||
|
|
||||||
# Clone repo and move into it.
|
# Clone repo and move into it.
|
||||||
rand="$(echo "${RANDOM}" | md5sum | head --bytes 32)"
|
repo_id="$(echo "${repo_hash}" | head --bytes 7)"
|
||||||
repo_clone="${runner_cloning_dir}/${repo_name}-${repo_hash}-${rand}"
|
[ "${repo_tag}" != "null" ] && repo_id="${repo_tag}"
|
||||||
log_info "Clone '$repo_name'."
|
rand="$(echo "${RANDOM}" | md5sum | head --bytes 7)"
|
||||||
if ! output="$(git clone "$repo_dir" "$repo_clone" 2>&1)"; then
|
repo_clone="${runner_cloning_dir}/${repo_name}-${repo_id}-${rand}"
|
||||||
reply "${err_clone_repo}" "Cannot clone repo '${repo_name}': ${output}."
|
reply "Cloning repo '${repo_name}'..."
|
||||||
|
if ! output="$(git clone "${repo_dir}" "${repo_clone}" 2>&1)"; then
|
||||||
|
reply "Cannot clone repo '${repo_name}': ${output}." \
|
||||||
|
"${err_clone_repo}"
|
||||||
return
|
return
|
||||||
fi
|
fi
|
||||||
cd "$repo_clone"
|
cd "$repo_clone"
|
||||||
|
|
||||||
# Checkout git hash.
|
# Checkout git hash.
|
||||||
log_info "Checkout hash $repo_hash."
|
reply "Checkouting hash '${repo_hash}..."
|
||||||
if ! output="$(git checkout "$repo_hash" 2>&1)"; then
|
if ! output="$(git checkout "$repo_hash" 2>&1)"; then
|
||||||
reply "${err_checkout_hash}" \
|
reply "Cannot checkout hash '${repo_hash}': ${output}." \
|
||||||
"Cannot checkout hash '${repo_hash}': ${output}."
|
"${err_checkout_hash}"
|
||||||
return
|
return
|
||||||
fi
|
fi
|
||||||
|
|
||||||
# Check code validity.
|
# Check code validity.
|
||||||
log_info "Check code validity."
|
reply "Checking code format..."
|
||||||
if ! output="$(make check_format 2>&1)"; then
|
if ! output="$(make check_format 2>&1)"; then
|
||||||
reply "${err_check_format}" "Check format error: ${output}."
|
reply "Check format error: ${output}." "${err_check_format}"
|
||||||
return
|
return
|
||||||
fi
|
fi
|
||||||
|
reply "Checking code linting..."
|
||||||
if ! output="$(make check_linting 2>&1)"; then
|
if ! output="$(make check_linting 2>&1)"; then
|
||||||
reply "${err_check_linting}" "Check linting error: ${output}."
|
reply "Check linting error: ${output}." "${err_check_linting}"
|
||||||
return
|
return
|
||||||
fi
|
fi
|
||||||
|
reply "Running unit tests..."
|
||||||
if ! output="$(make unit_test 2>&1)"; then
|
if ! output="$(make unit_test 2>&1)"; then
|
||||||
reply "${err_unit_test}" "Unit test error: ${output}."
|
reply "Unit test error: ${output}." "${err_unit_test}"
|
||||||
return
|
return
|
||||||
fi
|
fi
|
||||||
|
|
||||||
# Stop now if no tag specified.
|
# Stop now if no tag specified.
|
||||||
if [ "$repo_tag" = "null" ]; then
|
if [ "$repo_tag" = "null" ]; then
|
||||||
reply 0 "Hash '${repo_hash}' OK for repo '${repo_name}'."
|
reply "Hash '${repo_hash}' OK for repo '${repo_name}'." 0
|
||||||
return
|
return
|
||||||
fi
|
fi
|
||||||
|
|
||||||
# Build rpm package.
|
# Build rpm package.
|
||||||
echo "Build RPM package."
|
reply "Adding tag '${repo_tag}'..."
|
||||||
if ! output="$(git tag --message="$repo_tag" "$repo_tag" 2>&1)"; then
|
if ! output="$(git tag --message="$repo_tag" "$repo_tag" 2>&1)"; then
|
||||||
reply "${err_add_tag}" "Cannot add git tag '${repo_tag}': ${output}."
|
reply "Cannot add git tag '${repo_tag}': ${output}." "${err_add_tag}"
|
||||||
return
|
return
|
||||||
fi
|
fi
|
||||||
|
reply "Making source tarball..."
|
||||||
if ! output="$(make tarball 2>&1)"; then
|
if ! output="$(make tarball 2>&1)"; then
|
||||||
reply "${err_make_tarball}" \
|
reply "Cannot make tarball for tag '${repo_tag}': ${output}." \
|
||||||
"Cannot make tarball for tag '${repo_tag}': ${output}."
|
"${err_make_tarball}"
|
||||||
return
|
return
|
||||||
fi
|
fi
|
||||||
|
repo_version="$(make version)"
|
||||||
|
reply "Building RPM package '${repo_name}' v${repo_version}..."
|
||||||
if ! output="$(rpmbuild -bb "$repo_name.spec" 2>&1)"; then
|
if ! output="$(rpmbuild -bb "$repo_name.spec" 2>&1)"; then
|
||||||
reply "${err_rpm_build}" \
|
reply "Cannot build rpm for tag '${repo_tag}': ${output}." \
|
||||||
"Cannot build rpm for tag '${repo_tag}': ${output}."
|
"${err_rpm_build}"
|
||||||
return
|
return
|
||||||
fi
|
fi
|
||||||
|
|
||||||
# Deploy rpm package.
|
# Deploy rpm package.
|
||||||
log_info "Deploy RPM package."
|
reply "Deploying RPM package '${repo_name}' v${repo_version}..."
|
||||||
deployer_request="$(jq --null-input \
|
deployer_request="$(jq --null-input \
|
||||||
--compact-output \
|
--compact-output \
|
||||||
--arg s "${repo_clone}/runner.sock" \
|
--arg s "${repo_clone}/runner.sock" \
|
||||||
--arg n "${repo_name}" \
|
--arg n "${repo_name}" \
|
||||||
--arg v "$(make version)" \
|
--arg v "${repo_version}" \
|
||||||
'{"response_sock":$s,"pkg_name":$n,"pkg_version":$v}')"
|
'{"response_sock":$s,"pkg_name":$n,"pkg_version":$v}')"
|
||||||
(
|
(
|
||||||
inotifywait --event create "${repo_clone}" 1>/dev/null 2>/dev/null
|
inotifywait --timeout 1 --quiet --quiet \
|
||||||
|
--event create "${repo_clone}" || true
|
||||||
chmod 775 "${repo_clone}/runner.sock"
|
chmod 775 "${repo_clone}/runner.sock"
|
||||||
chgrp "${runner_deployer_groupname}" "${repo_clone}/runner.sock"
|
chgrp "${runner_deployer_groupname}" "${repo_clone}/runner.sock"
|
||||||
echo "${deployer_request}" | ncat --unixsock "${deployer_sock}"
|
echo "${deployer_request}" | ncat --unixsock "${deployer_sock}"
|
||||||
|
@ -284,41 +308,30 @@ process_loop() (
|
||||||
log_info "Start listening unixsock with keep-open at '${runner_sock}'."
|
log_info "Start listening unixsock with keep-open at '${runner_sock}'."
|
||||||
while read -r request; do
|
while read -r request; do
|
||||||
log_info "Process new request '${request}'."
|
log_info "Process new request '${request}'."
|
||||||
process_request
|
process_request &
|
||||||
done < <(ncat --listen --keep-open --unixsock "${runner_sock}")
|
done < <(ncat --listen --keep-open --unixsock "${runner_sock}")
|
||||||
|
log_critical "Unexpected end of listening at '${deployer_sock}'."
|
||||||
else
|
else
|
||||||
log_info "Start listening unixsock without keep-open at '${runner_sock}'."
|
log_info "Start listening unixsock without keep-open at '${runner_sock}'."
|
||||||
while read -r request; do
|
while read -r request; do
|
||||||
log_info "Process new request '${request}'."
|
log_info "Process new request '${request}'."
|
||||||
process_request
|
process_request
|
||||||
done < <(ncat --listen --unixsock "${runner_sock}")
|
done < <(ncat --listen --unixsock "${runner_sock}")
|
||||||
|
log_info "End of listening at '${deployer_sock}'."
|
||||||
fi
|
fi
|
||||||
|
|
||||||
# Kill all remaining subprocesses only if daemon.
|
|
||||||
log_info "End of loop."
|
|
||||||
if "${daemonize}"; then
|
|
||||||
log_debug "Kill child jobs."
|
|
||||||
jobs -p | xargs kill 2>/dev/null || true
|
|
||||||
fi
|
|
||||||
|
|
||||||
# Remove sock file.
|
|
||||||
log_debug "Remove deployer unixsock file."
|
|
||||||
rm --force "${runner_sock}"
|
|
||||||
log_info "End of process."
|
|
||||||
)
|
)
|
||||||
|
|
||||||
main() (
|
main() (
|
||||||
# Parse arguments.
|
# Parse arguments.
|
||||||
daemonize="false"
|
daemonize="false"
|
||||||
testing="false"
|
|
||||||
keep_open="true"
|
keep_open="true"
|
||||||
config_file="${DEFAULT_CONFIG_FILE}"
|
config_file="${DEFAULT_CONFIG_FILE}"
|
||||||
errors_file="${DEFAULT_ERRORS_FILE}"
|
errors_file="${DEFAULT_ERRORS_FILE}"
|
||||||
verbosity_option=""
|
verbosity_option=""
|
||||||
verbosity_level="${DEFAULT_VERBOSITY_LEVEL}"
|
verbosity_level="${DEFAULT_VERBOSITY_LEVEL}"
|
||||||
if ! args="$(getopt --name "${PROGRAM_NAME}" \
|
if ! args="$(getopt --name "${PROGRAM_NAME}" \
|
||||||
--options c:de:hoqtv \
|
--options c:de:hoqv \
|
||||||
--longoptions conf:,daemon,errs:,help,once,quiet,test,verbose \
|
--longoptions conf:,daemon,errs:,help,once,quiet,verbose \
|
||||||
-- "$@")"; then
|
-- "$@")"; then
|
||||||
usage
|
usage
|
||||||
fail "Bad arguments."
|
fail "Bad arguments."
|
||||||
|
@ -356,10 +369,6 @@ main() (
|
||||||
((verbosity_level -= 10))
|
((verbosity_level -= 10))
|
||||||
shift
|
shift
|
||||||
;;
|
;;
|
||||||
-t | --test)
|
|
||||||
testing="true"
|
|
||||||
shift
|
|
||||||
;;
|
|
||||||
-v | --verbose)
|
-v | --verbose)
|
||||||
if [ "${verbosity_option}" ]; then
|
if [ "${verbosity_option}" ]; then
|
||||||
usage
|
usage
|
||||||
|
@ -379,10 +388,19 @@ main() (
|
||||||
;;
|
;;
|
||||||
esac
|
esac
|
||||||
done
|
done
|
||||||
if [ "$@" ]; then
|
if [ $# -ne 1 ]; then
|
||||||
usage
|
usage
|
||||||
fail "Unexpected extra arguments '$*'."
|
fail "Missing positional argument ACTION."
|
||||||
fi
|
fi
|
||||||
|
case "$1" in
|
||||||
|
start | stop | test)
|
||||||
|
action="$1"
|
||||||
|
;;
|
||||||
|
*)
|
||||||
|
usage
|
||||||
|
fail "Bad postional argument ACTION '$1'."
|
||||||
|
;;
|
||||||
|
esac
|
||||||
|
|
||||||
# Load config file.
|
# Load config file.
|
||||||
if [ ! -r "${config_file}" ]; then
|
if [ ! -r "${config_file}" ]; then
|
||||||
|
@ -404,9 +422,13 @@ main() (
|
||||||
if [ -z "${deployer_sock}" ]; then
|
if [ -z "${deployer_sock}" ]; then
|
||||||
fail "Variable deployer_sock is empty." "${err_deployer_sock_empty}"
|
fail "Variable deployer_sock is empty." "${err_deployer_sock_empty}"
|
||||||
fi
|
fi
|
||||||
if [ ! -S "${deployer_sock}" ]; then
|
if [ ! -d "$(dirname "${deployer_sock}")" ]; then
|
||||||
fail "Sock deployer_sock='${deployer_sock}' does not exist." \
|
fail "Dirname of deployer_sock='${deployer_sock}' is not a directory." \
|
||||||
"${err_deployer_sock_not_exist}"
|
"${err_deployer_sock_dir_not_directory}"
|
||||||
|
fi
|
||||||
|
if [ ! -x "$(dirname "${deployer_sock}")" ]; then
|
||||||
|
fail "Dirname of deployer_sock='${deployer_sock}' is not accessible." \
|
||||||
|
"${err_deployer_sock_dir_not_accessible}"
|
||||||
fi
|
fi
|
||||||
|
|
||||||
if [ -z "${deployer_timeout}" ]; then
|
if [ -z "${deployer_timeout}" ]; then
|
||||||
|
@ -428,10 +450,6 @@ main() (
|
||||||
fail "Directory of runner_sock='${runner_sock}' is not writable." \
|
fail "Directory of runner_sock='${runner_sock}' is not writable." \
|
||||||
"${err_runner_sock_dir_not_writable}"
|
"${err_runner_sock_dir_not_writable}"
|
||||||
fi
|
fi
|
||||||
if [ -e "${runner_sock}" ]; then
|
|
||||||
fail "Sock deployer_sock='${runner_sock}' is already in use." \
|
|
||||||
"${err_runner_sock_already_in_use}"
|
|
||||||
fi
|
|
||||||
|
|
||||||
if [ -z "${runner_cloning_dir}" ]; then
|
if [ -z "${runner_cloning_dir}" ]; then
|
||||||
fail "Variable runner_cloning_dir is empty." \
|
fail "Variable runner_cloning_dir is empty." \
|
||||||
|
@ -469,7 +487,7 @@ main() (
|
||||||
if [ -z "${runner_deployer_groupname}" ]; then
|
if [ -z "${runner_deployer_groupname}" ]; then
|
||||||
fail "Variable runner_deployer_groupname is empty." "${err_runner_deployer_groupname_empty}"
|
fail "Variable runner_deployer_groupname is empty." "${err_runner_deployer_groupname_empty}"
|
||||||
fi
|
fi
|
||||||
if ! getent group "${runner_deployer_groupname}"; then
|
if ! getent group "${runner_deployer_groupname}" >/dev/null; then
|
||||||
fail "Runner-deployer group '${runner_deployer_groupname}' does not exist." \
|
fail "Runner-deployer group '${runner_deployer_groupname}' does not exist." \
|
||||||
"${err_runner_deployer_group_not_exist}"
|
"${err_runner_deployer_group_not_exist}"
|
||||||
fi
|
fi
|
||||||
|
@ -477,19 +495,44 @@ main() (
|
||||||
if [ -z "${git_runner_groupname}" ]; then
|
if [ -z "${git_runner_groupname}" ]; then
|
||||||
fail "Variable git_runner_groupname is empty." "${err_git_runner_groupname_empty}"
|
fail "Variable git_runner_groupname is empty." "${err_git_runner_groupname_empty}"
|
||||||
fi
|
fi
|
||||||
if ! getent group "${git_runner_groupname}"; then
|
if ! getent group "${git_runner_groupname}" >/dev/null; then
|
||||||
fail "Git-runner group '${git_runner_groupname}' does not exist." \
|
fail "Git-runner group '${git_runner_groupname}' does not exist." \
|
||||||
"${err_git_runner_group_not_exist}"
|
"${err_git_runner_group_not_exist}"
|
||||||
fi
|
fi
|
||||||
|
|
||||||
# Stop now if we are only testing config.
|
if [ -z "${runner_pid}" ]; then
|
||||||
if "${testing}"; then
|
fail "Variable runner_pid is empty." "${err_runner_pid_empty}"
|
||||||
|
fi
|
||||||
|
if [ ! -d "$(dirname "${runner_pid}")" ]; then
|
||||||
|
fail "Dirname of runner_pid='${runner_pid}' is not a directory." \
|
||||||
|
"${err_runner_pid_dir_not_directory}"
|
||||||
|
fi
|
||||||
|
if [ ! -w "$(dirname "${runner_pid}")" ]; then
|
||||||
|
fail "Dirname of runner_pid='${runner_pid}' is not writable." \
|
||||||
|
"${err_runner_pid_dir_not_writable}"
|
||||||
|
fi
|
||||||
|
|
||||||
|
# Run chosen action.
|
||||||
|
case "${action}" in
|
||||||
|
test)
|
||||||
|
# Stop now if we are only testing.
|
||||||
|
log_info "Configuration OK."
|
||||||
exit 0
|
exit 0
|
||||||
|
;;
|
||||||
|
start)
|
||||||
|
if [ ! -S "${deployer_sock}" ]; then
|
||||||
|
fail "Sock deployer_sock='${deployer_sock}' does not exist." \
|
||||||
|
"${err_deployer_sock_not_exist}"
|
||||||
|
fi
|
||||||
|
if [ -e "${runner_sock}" ]; then
|
||||||
|
fail "Sock deployer_sock='${runner_sock}' is already in use." \
|
||||||
|
"${err_runner_sock_already_in_use}"
|
||||||
fi
|
fi
|
||||||
|
|
||||||
# Set right access in background after nc listen.
|
# Set right access in background after nc listen.
|
||||||
(
|
(
|
||||||
inotifywait --event create "$(dirname "${runner_sock}")" --quiet --quiet
|
inotifywait --timeout 1 --quiet --quiet \
|
||||||
|
--event create "$(dirname "${runner_sock}")" || true
|
||||||
chmod 775 "${runner_sock}"
|
chmod 775 "${runner_sock}"
|
||||||
chgrp "${git_runner_groupname}" "${runner_sock}"
|
chgrp "${git_runner_groupname}" "${runner_sock}"
|
||||||
) &
|
) &
|
||||||
|
@ -498,11 +541,41 @@ main() (
|
||||||
if "${daemonize}"; then
|
if "${daemonize}"; then
|
||||||
log_info "Run process loop in background."
|
log_info "Run process loop in background."
|
||||||
process_loop &
|
process_loop &
|
||||||
|
echo "$!" >"${runner_pid}"
|
||||||
else
|
else
|
||||||
log_info "Run process loop in foreground."
|
log_info "Run process loop in foreground."
|
||||||
|
echo "$$" >"${runner_pid}"
|
||||||
process_loop
|
process_loop
|
||||||
jobs -p | xargs kill 2>/dev/null || true
|
|
||||||
fi
|
fi
|
||||||
|
;;
|
||||||
|
stop)
|
||||||
|
if [ ! -f "${runner_pid}" ]; then
|
||||||
|
fail "File runner_pid='${runner_pid}' does not exist." \
|
||||||
|
"${err_runner_pid_not_exist}"
|
||||||
|
fi
|
||||||
|
if [ ! -r "${runner_pid}" ]; then
|
||||||
|
fail "File runner_pid='${runner_pid}' is not readable." \
|
||||||
|
"${err_runner_pid_not_readable}"
|
||||||
|
fi
|
||||||
|
pid="$(cat "${runner_pid}")"
|
||||||
|
rm --force "${runner_pid}"
|
||||||
|
|
||||||
|
# Kill runner process.
|
||||||
|
log_info "Kill runner process with pid '${pid}'."
|
||||||
|
if ! ps -p "${pid}" >/dev/null; then
|
||||||
|
fail "Runner process with pid='${pid}' is not running." \
|
||||||
|
"${err_runner_process_not_running}"
|
||||||
|
fi
|
||||||
|
if ! output="$(kill "${pid}" || kill -KILL "${pid}")"; then
|
||||||
|
fail "Cannot kill runner process: ${output}." \
|
||||||
|
"${err_runner_process_not_killed}"
|
||||||
|
fi
|
||||||
|
|
||||||
|
# Remove runner sock file.
|
||||||
|
log_info "Remove runner sock at '${runner_sock}'."
|
||||||
|
rm --force "${runner_sock}"
|
||||||
|
;;
|
||||||
|
esac
|
||||||
)
|
)
|
||||||
|
|
||||||
main "$@"
|
main "$@"
|
||||||
|
|
|
@ -5,7 +5,8 @@ After=network.target
|
||||||
[Service]
|
[Service]
|
||||||
User=netoik-cicd-deployer
|
User=netoik-cicd-deployer
|
||||||
Group=netoik-cicd-deployer
|
Group=netoik-cicd-deployer
|
||||||
ExecStart=/usr/bin/netoik-cicd-deployer
|
ExecStart=/usr/bin/netoik-cicd-deployer start
|
||||||
|
ExecStop=/usr/bin/netoik-cicd-deployer stop
|
||||||
Restart=always
|
Restart=always
|
||||||
|
|
||||||
[Install]
|
[Install]
|
||||||
|
|
|
@ -4,8 +4,9 @@ After=network.target netoik-cicd-deployer.service
|
||||||
|
|
||||||
[Service]
|
[Service]
|
||||||
User=netoik-cicd-runner
|
User=netoik-cicd-runner
|
||||||
Group=netoik-cicd-runner
|
Group=netoik-cicd-runner-deployer
|
||||||
ExecStart=/usr/bin/netoik-cicd-runner
|
ExecStart=/usr/bin/netoik-cicd-runner start
|
||||||
|
ExecStop=/usr/bin/netoik-cicd-runner stop
|
||||||
Restart=always
|
Restart=always
|
||||||
|
|
||||||
[Install]
|
[Install]
|
||||||
|
|
|
@ -5,6 +5,7 @@
|
||||||
bats_require_minimum_version 1.5.0
|
bats_require_minimum_version 1.5.0
|
||||||
|
|
||||||
setup() {
|
setup() {
|
||||||
|
# shellcheck source=./tests/tests.conf
|
||||||
source "${PWD}/tests/tests.conf"
|
source "${PWD}/tests/tests.conf"
|
||||||
make build >/dev/null
|
make build >/dev/null
|
||||||
DESTDIR="${temp}" make install >/dev/null
|
DESTDIR="${temp}" make install >/dev/null
|
||||||
|
@ -13,6 +14,7 @@ setup() {
|
||||||
"${temp}${sysconf_dir}/${name}/${name}.conf"
|
"${temp}${sysconf_dir}/${name}/${name}.conf"
|
||||||
install --directory "${temp}${var_dir}/${name}/repositories/test.git"
|
install --directory "${temp}${var_dir}/${name}/repositories/test.git"
|
||||||
install --directory "${temp}${var_dir}/${name}/RPMS"
|
install --directory "${temp}${var_dir}/${name}/RPMS"
|
||||||
|
# shellcheck source=./conf/errors.conf.sample
|
||||||
source "${errs_file}"
|
source "${errs_file}"
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -21,86 +23,89 @@ teardown() {
|
||||||
make clean >/dev/null
|
make clean >/dev/null
|
||||||
}
|
}
|
||||||
|
|
||||||
@test "run with bad arguments" {
|
run_with_bad_arguments() { #@test
|
||||||
run -1 "${deployer_bin}" -z
|
run -1 "${deployer_bin}" -z test
|
||||||
run -1 "${deployer_bin}" --zzz
|
run -1 "${deployer_bin}" --zzz test
|
||||||
run -1 "${deployer_bin}" zzz
|
run -1 "${deployer_bin}" zzz
|
||||||
|
|
||||||
run -1 "${deployer_bin}" --conf
|
run -1 "${deployer_bin}" --conf
|
||||||
run -1 "${deployer_bin}" --conf=/path/to/nowhere
|
run -1 "${deployer_bin}" --conf=/path/to/nowhere test
|
||||||
|
|
||||||
run -1 "${deployer_bin}" --errs
|
run -1 "${deployer_bin}" --errs
|
||||||
run -1 "${deployer_bin}" --errs=/path/to/nowhere
|
run -1 "${deployer_bin}" --errs=/path/to/nowhere test
|
||||||
|
|
||||||
run -1 "${deployer_bin}" --verbose --quiet
|
run -1 "${deployer_bin}" --verbose --quiet test
|
||||||
}
|
}
|
||||||
|
|
||||||
@test "run without loop" {
|
run_without_loop() { #@test
|
||||||
"${deployer_bin}" --conf="${conf_file}" --errs="${errs_file}" --test --verbose
|
"${deployer_bin}" --conf="${conf_file}" --errs="${errs_file}" --verbose test
|
||||||
}
|
}
|
||||||
|
|
||||||
send_request() (
|
send_request() (
|
||||||
request="$1"
|
request="$1"
|
||||||
|
|
||||||
"${deployer_bin}" --conf="${conf_file}" --errs="${errs_file}" \
|
"${deployer_bin}" --conf="${conf_file}" --errs="${errs_file}" \
|
||||||
--daemon --once --verbose || return $?
|
--once --daemon --verbose start || return $?
|
||||||
(
|
(
|
||||||
inotifywait --event create --quiet --quiet "${response_sock_dir}"
|
inotifywait --timeout 1 --quiet --quiet \
|
||||||
|
--event create "${response_sock_dir}" || true
|
||||||
echo "${request}" | ncat --unixsock "${deployer_sock}"
|
echo "${request}" | ncat --unixsock "${deployer_sock}"
|
||||||
) &
|
) &
|
||||||
return "$(ncat --listen --unixsock "${response_sock}" | jq .code)"
|
code="$(ncat --listen --unixsock "${response_sock}" | jq .code)"
|
||||||
|
"${deployer_bin}" --conf="${conf_file}" --errs="${errs_file}" stop
|
||||||
|
return "${code}"
|
||||||
)
|
)
|
||||||
|
|
||||||
@test "run with err_pkg_name_missing" {
|
run_with_err_pkg_name_missing() { #@test
|
||||||
request="$(jq --null-input --compact-output \
|
request="$(jq --null-input --compact-output \
|
||||||
--arg s "${response_sock}" \
|
--arg s "${response_sock}" \
|
||||||
'{"response_sock":$s}')"
|
'{"response_sock":$s}')"
|
||||||
run send_request "${request}"
|
run send_request "${request}"
|
||||||
echo "status: got ${status}, expected ${err_pkg_name_missing}"
|
echo "status: got ${status:?}, expected ${err_pkg_name_missing}"
|
||||||
[ "${status}" -eq "${err_pkg_name_missing}" ]
|
[ "${status}" -eq "${err_pkg_name_missing}" ]
|
||||||
}
|
}
|
||||||
|
|
||||||
@test "run with err_pkg_name_empty" {
|
run_with_err_pkg_name_empty() { #@test
|
||||||
request="$(jq --null-input --compact-output \
|
request="$(jq --null-input --compact-output \
|
||||||
--arg s "${response_sock}" \
|
--arg s "${response_sock}" \
|
||||||
'{"response_sock":$s,"pkg_name":""}')"
|
'{"response_sock":$s,"pkg_name":""}')"
|
||||||
run send_request "${request}"
|
run send_request "${request}"
|
||||||
echo "status: got ${status}, expected ${err_pkg_name_empty}"
|
echo "status: got ${status:?}, expected ${err_pkg_name_empty}"
|
||||||
[ "${status}" -eq "${err_pkg_name_empty}" ]
|
[ "${status}" -eq "${err_pkg_name_empty}" ]
|
||||||
}
|
}
|
||||||
|
|
||||||
@test "run with err_repo_dir_not_exist" {
|
run_with_err_repo_dir_not_exist() { #@test
|
||||||
request="$(jq --null-input --compact-output \
|
request="$(jq --null-input --compact-output \
|
||||||
--arg s "${response_sock}" \
|
--arg s "${response_sock}" \
|
||||||
'{"response_sock":$s,"pkg_name":"not_exist"}')"
|
'{"response_sock":$s,"pkg_name":"not_exist"}')"
|
||||||
run send_request "${request}"
|
run send_request "${request}"
|
||||||
echo "status: got ${status}, expected ${err_repo_dir_not_existyy}"
|
echo "status: got ${status:?}, expected ${err_repo_dir_not_exist}"
|
||||||
[ "${status}" -eq "${err_repo_dir_not_exist}" ]
|
[ "${status}" -eq "${err_repo_dir_not_exist}" ]
|
||||||
}
|
}
|
||||||
|
|
||||||
@test "run with err_pkg_version_missing" {
|
run_with_err_pkg_version_missing() { #@test
|
||||||
request="$(jq --null-input --compact-output \
|
request="$(jq --null-input --compact-output \
|
||||||
--arg s "${response_sock}" \
|
--arg s "${response_sock}" \
|
||||||
'{"response_sock":$s,"pkg_name":"test"}')"
|
'{"response_sock":$s,"pkg_name":"test"}')"
|
||||||
run send_request "${request}"
|
run send_request "${request}"
|
||||||
echo "status: got ${status}, expected ${err_pkg_version_missing}"
|
echo "status: got ${status:?}, expected ${err_pkg_version_missing}"
|
||||||
[ "${status}" -eq "${err_pkg_version_missing}" ]
|
[ "${status}" -eq "${err_pkg_version_missing}" ]
|
||||||
}
|
}
|
||||||
|
|
||||||
@test "run with err_pkg_version_empty" {
|
run_with_err_pkg_version_empty() { #@test
|
||||||
request="$(jq --null-input --compact-output \
|
request="$(jq --null-input --compact-output \
|
||||||
--arg s "${response_sock}" \
|
--arg s "${response_sock}" \
|
||||||
'{"response_sock":$s,"pkg_name":"test","pkg_version":""}')"
|
'{"response_sock":$s,"pkg_name":"test","pkg_version":""}')"
|
||||||
run send_request "${request}"
|
run send_request "${request}"
|
||||||
echo "status: got ${status}, expected ${err_pkg_version_empty}"
|
echo "status: got ${status:?}, expected ${err_pkg_version_empty}"
|
||||||
[ "${status}" -eq "${err_pkg_version_empty}" ]
|
[ "${status}" -eq "${err_pkg_version_empty}" ]
|
||||||
}
|
}
|
||||||
|
|
||||||
@test "run with err_rpm_path_not_exist" {
|
run_with_err_rpm_path_not_exist() { #@test
|
||||||
request="$(jq --null-input --compact-output \
|
request="$(jq --null-input --compact-output \
|
||||||
--arg s "${response_sock}" \
|
--arg s "${response_sock}" \
|
||||||
'{"response_sock":$s,"pkg_name":"test","pkg_version":"0.1"}')"
|
'{"response_sock":$s,"pkg_name":"test","pkg_version":"0.1"}')"
|
||||||
run send_request "${request}"
|
run send_request "${request}"
|
||||||
echo "status: got ${status}, expected ${err_rpm_path_not_exist}"
|
echo "status: got ${status:?}, expected ${err_rpm_path_not_exist}"
|
||||||
[ "${status}" -eq "${err_rpm_path_not_exist}" ]
|
[ "${status}" -eq "${err_rpm_path_not_exist}" ]
|
||||||
}
|
}
|
||||||
|
|
|
@ -5,12 +5,14 @@
|
||||||
bats_require_minimum_version 1.5.0
|
bats_require_minimum_version 1.5.0
|
||||||
|
|
||||||
setup() {
|
setup() {
|
||||||
|
# shellcheck source=./tests/tests.conf
|
||||||
source "${PWD}/tests/tests.conf"
|
source "${PWD}/tests/tests.conf"
|
||||||
make build >/dev/null
|
make build >/dev/null
|
||||||
DESTDIR="${temp}" make install >/dev/null
|
DESTDIR="${temp}" make install >/dev/null
|
||||||
install --no-target-directory \
|
install --no-target-directory \
|
||||||
"${PWD}/tests/tests.conf" \
|
"${PWD}/tests/tests.conf" \
|
||||||
"${temp}${sysconf_dir}/${name}/${name}.conf"
|
"${temp}${sysconf_dir}/${name}/${name}.conf"
|
||||||
|
# shellcheck source=./conf/errors.conf.sample
|
||||||
source "${errs_file}"
|
source "${errs_file}"
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -19,7 +21,7 @@ teardown() {
|
||||||
make clean >/dev/null
|
make clean >/dev/null
|
||||||
}
|
}
|
||||||
|
|
||||||
@test "run with bad arguments" {
|
run_with_bad_arguments() { #@test
|
||||||
run -1 "${pipeline_bin}"
|
run -1 "${pipeline_bin}"
|
||||||
run -1 "${pipeline_bin}" bad_pipeline
|
run -1 "${pipeline_bin}" bad_pipeline
|
||||||
|
|
||||||
|
@ -39,21 +41,21 @@ teardown() {
|
||||||
run -1 "${pipeline_bin}" -e /path/to/nowhere -H hash -n name newcommit
|
run -1 "${pipeline_bin}" -e /path/to/nowhere -H hash -n name newcommit
|
||||||
}
|
}
|
||||||
|
|
||||||
@test "run without runner sock" {
|
run_without_runner_sock() { #@test
|
||||||
run "${pipeline_bin}" --conf="${conf_file}" --errs="${errs_file}" \
|
run "${pipeline_bin}" --conf="${conf_file}" --errs="${errs_file}" \
|
||||||
--test --hash hash --name name newcommit
|
--test --hash hash --name name newcommit
|
||||||
echo "status: got ${status}, expected ${err_runner_sock_not_exist}"
|
echo "status: got ${status:?}, expected ${err_runner_sock_not_exist}"
|
||||||
[ "${status}" -eq "${err_runner_sock_not_exist}" ]
|
[ "${status}" -eq "${err_runner_sock_not_exist}" ]
|
||||||
}
|
}
|
||||||
|
|
||||||
@test "run newcommit ok" {
|
run_newcommit_ok() { #@test
|
||||||
ncat --listen --unixsock "${runner_sock}" &
|
ncat --listen --unixsock "${runner_sock}" &
|
||||||
"${pipeline_bin}" --conf="${conf_file}" --errs="${errs_file}" \
|
"${pipeline_bin}" --conf="${conf_file}" --errs="${errs_file}" \
|
||||||
--test --hash hash --name name newcommit
|
--test --hash hash --name name newcommit
|
||||||
echo "done" | ncat --unixsock "${runner_sock}"
|
echo "done" | ncat --unixsock "${runner_sock}"
|
||||||
}
|
}
|
||||||
|
|
||||||
@test "run newtag ok" {
|
run_newtag_ok() { #@test
|
||||||
ncat --listen --unixsock "${runner_sock}" &
|
ncat --listen --unixsock "${runner_sock}" &
|
||||||
"${pipeline_bin}" --conf="${conf_file}" --errs="${errs_file}" \
|
"${pipeline_bin}" --conf="${conf_file}" --errs="${errs_file}" \
|
||||||
--test --hash hash --name name --tag tag newtag
|
--test --hash hash --name name --tag tag newtag
|
||||||
|
|
|
@ -5,6 +5,7 @@
|
||||||
bats_require_minimum_version 1.5.0
|
bats_require_minimum_version 1.5.0
|
||||||
|
|
||||||
setup() {
|
setup() {
|
||||||
|
# shellcheck source=./tests/tests.conf
|
||||||
source "${PWD}/tests/tests.conf"
|
source "${PWD}/tests/tests.conf"
|
||||||
make build >/dev/null
|
make build >/dev/null
|
||||||
DESTDIR="${temp}" make install >/dev/null
|
DESTDIR="${temp}" make install >/dev/null
|
||||||
|
@ -13,6 +14,7 @@ setup() {
|
||||||
"${temp}${sysconf_dir}/${name}/${name}.conf"
|
"${temp}${sysconf_dir}/${name}/${name}.conf"
|
||||||
install --directory "${temp}${var_dir}/${name}/repositories/test.git"
|
install --directory "${temp}${var_dir}/${name}/repositories/test.git"
|
||||||
install --directory "${temp}${var_dir}/${name}/RPMS"
|
install --directory "${temp}${var_dir}/${name}/RPMS"
|
||||||
|
# shellcheck source=./conf/errors.conf.sample
|
||||||
source "${errs_file}"
|
source "${errs_file}"
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -21,7 +23,7 @@ teardown() {
|
||||||
make clean >/dev/null
|
make clean >/dev/null
|
||||||
}
|
}
|
||||||
|
|
||||||
@test "run with bad arguments" {
|
run_with_bad_arguments() { #@test
|
||||||
run -1 "${runner_bin}" -z
|
run -1 "${runner_bin}" -z
|
||||||
run -1 "${runner_bin}" --zzz
|
run -1 "${runner_bin}" --zzz
|
||||||
run -1 "${runner_bin}" zzz
|
run -1 "${runner_bin}" zzz
|
||||||
|
@ -35,9 +37,9 @@ teardown() {
|
||||||
run -1 "${runner_bin}" --verbose --quiet
|
run -1 "${runner_bin}" --verbose --quiet
|
||||||
}
|
}
|
||||||
|
|
||||||
@test "run without loop" {
|
run_without_loop() { #@test
|
||||||
ncat --listen --unixsock "${deployer_sock}" &
|
ncat --listen --unixsock "${deployer_sock}" &
|
||||||
"${runner_bin}" --conf="${conf_file}" --errs="${errs_file}" --test --verbose
|
"${runner_bin}" --conf="${conf_file}" --errs="${errs_file}" --verbose test
|
||||||
echo "done" | ncat --unixsock "${deployer_sock}"
|
echo "done" | ncat --unixsock "${deployer_sock}"
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -46,70 +48,74 @@ send_request() (
|
||||||
|
|
||||||
ncat --listen --unixsock "${deployer_sock}" &
|
ncat --listen --unixsock "${deployer_sock}" &
|
||||||
"${runner_bin}" --conf="${conf_file}" --errs="${errs_file}" \
|
"${runner_bin}" --conf="${conf_file}" --errs="${errs_file}" \
|
||||||
--daemon --once --verbose
|
--daemon --once --verbose start
|
||||||
code=$?
|
code=$?
|
||||||
if [ "${code}" -ne 0 ]; then
|
if [ "${code}" -ne 0 ]; then
|
||||||
echo "fail" | ncat --unixsock "${deployer_sock}"
|
echo "fail" | ncat --unixsock "${deployer_sock}"
|
||||||
|
"${runner_bin}" --conf="${conf_file}" --errs="${errs_file}" stop
|
||||||
return "${code}"
|
return "${code}"
|
||||||
fi
|
fi
|
||||||
(
|
(
|
||||||
inotifywait --quiet --quiet --event create "${response_sock_dir}"
|
inotifywait --timeout 1 --quiet --quiet \
|
||||||
|
--event create "${response_sock_dir}" >&3
|
||||||
echo "${request}" | ncat --unixsock "${runner_sock}"
|
echo "${request}" | ncat --unixsock "${runner_sock}"
|
||||||
) &
|
) &
|
||||||
echo "done" | ncat --unixsock "${deployer_sock}"
|
echo "done" | ncat --unixsock "${deployer_sock}"
|
||||||
return "$(ncat --listen --unixsock "${response_sock}" | jq .code)"
|
code="$(ncat --listen --unixsock "${response_sock}" | jq .code)"
|
||||||
|
"${runner_bin}" --conf="${conf_file}" --errs="${errs_file}" stop
|
||||||
|
return "${code}"
|
||||||
)
|
)
|
||||||
|
|
||||||
@test "run with err_repo_name_missing" {
|
run_with_err_repo_name_missing() { #@test
|
||||||
request="$(jq --null-input --compact-output \
|
request="$(jq --null-input --compact-output \
|
||||||
--arg s "${response_sock}" \
|
--arg s "${response_sock}" \
|
||||||
'{"response_sock":$s}')"
|
'{"response_sock":$s}')"
|
||||||
run send_request "${request}"
|
run send_request "${request}"
|
||||||
echo "status: got ${status}, expected ${err_repo_name_missing}"
|
echo "status: got ${status:?}, expected ${err_repo_name_missing}"
|
||||||
[ "${status}" -eq "${err_repo_name_missing}" ]
|
[ "${status}" -eq "${err_repo_name_missing}" ]
|
||||||
}
|
}
|
||||||
|
|
||||||
@test "run with err_repo_name_empty" {
|
run_with_err_repo_name_empty() { #@test
|
||||||
request="$(jq --null-input --compact-output \
|
request="$(jq --null-input --compact-output \
|
||||||
--arg s "${response_sock}" \
|
--arg s "${response_sock}" \
|
||||||
'{"response_sock":$s,"repo_name":""}')"
|
'{"response_sock":$s,"repo_name":""}')"
|
||||||
run send_request "${request}"
|
run send_request "${request}"
|
||||||
echo "status: got ${status}, expected ${err_repo_name_empty}"
|
echo "status: got ${status:?}, expected ${err_repo_name_empty}"
|
||||||
[ "${status}" -eq "${err_repo_name_empty}" ]
|
[ "${status}" -eq "${err_repo_name_empty}" ]
|
||||||
}
|
}
|
||||||
|
|
||||||
@test "run with err_repo_dir_not_exist" {
|
run_with_err_repo_dir_not_exist() { #@test
|
||||||
request="$(jq --null-input --compact-output \
|
request="$(jq --null-input --compact-output \
|
||||||
--arg s "${response_sock}" \
|
--arg s "${response_sock}" \
|
||||||
'{"response_sock":$s,"repo_name":"not_exist"}')"
|
'{"response_sock":$s,"repo_name":"not_exist"}')"
|
||||||
run send_request "${request}"
|
run send_request "${request}"
|
||||||
echo "status: got ${status}, expected ${err_repo_dir_not_exist}"
|
echo "status: got ${status:?}, expected ${err_repo_dir_not_exist}"
|
||||||
[ "${status}" -eq "${err_repo_dir_not_exist}" ]
|
[ "${status}" -eq "${err_repo_dir_not_exist}" ]
|
||||||
}
|
}
|
||||||
|
|
||||||
@test "run with err_repo_hash_missing" {
|
run_with_err_repo_hash_missing() { #@test
|
||||||
request="$(jq --null-input --compact-output \
|
request="$(jq --null-input --compact-output \
|
||||||
--arg s "${response_sock}" \
|
--arg s "${response_sock}" \
|
||||||
'{"response_sock":$s,"repo_name":"test"}')"
|
'{"response_sock":$s,"repo_name":"test"}')"
|
||||||
run send_request "${request}"
|
run send_request "${request}"
|
||||||
echo "status: got ${status}, expected ${err_repo_hash_missing}"
|
echo "status: got ${status:?}, expected ${err_repo_hash_missing}"
|
||||||
[ "${status}" -eq "${err_repo_hash_missing}" ]
|
[ "${status}" -eq "${err_repo_hash_missing}" ]
|
||||||
}
|
}
|
||||||
|
|
||||||
@test "run with err_repo_hash_empty" {
|
run_with_err_repo_hash_empty() { #@test
|
||||||
request="$(jq --null-input --compact-output \
|
request="$(jq --null-input --compact-output \
|
||||||
--arg s "${response_sock}" \
|
--arg s "${response_sock}" \
|
||||||
'{"response_sock":$s,"repo_name":"test","repo_hash":""}')"
|
'{"response_sock":$s,"repo_name":"test","repo_hash":""}')"
|
||||||
run send_request "${request}"
|
run send_request "${request}"
|
||||||
echo "status: got ${status}, expected ${err_repo_hash_empty}"
|
echo "status: got ${status:?}, expected ${err_repo_hash_empty}"
|
||||||
[ "${status}" -eq "${err_repo_hash_empty}" ]
|
[ "${status}" -eq "${err_repo_hash_empty}" ]
|
||||||
}
|
}
|
||||||
|
|
||||||
@test "run with err_repo_tag_empty" {
|
run_with_err_repo_tag_empty() { #@test
|
||||||
request="$(jq --null-input --compact-output \
|
request="$(jq --null-input --compact-output \
|
||||||
--arg s "${response_sock}" \
|
--arg s "${response_sock}" \
|
||||||
'{"response_sock":$s,"repo_name":"test","repo_hash":"hash","repo_tag":""}')"
|
'{"response_sock":$s,"repo_name":"test","repo_hash":"hash","repo_tag":""}')"
|
||||||
run send_request "${request}"
|
run send_request "${request}"
|
||||||
echo "status: got ${status}, expected ${err_repo_tag_empty}"
|
echo "status: got ${status:?}, expected ${err_repo_tag_empty}"
|
||||||
[ "${status}" -eq "${err_repo_tag_empty}" ]
|
[ "${status}" -eq "${err_repo_tag_empty}" ]
|
||||||
}
|
}
|
||||||
|
|
|
@ -14,10 +14,10 @@ conf_file="${temp}${sysconf_dir}/${name}/${name}.conf"
|
||||||
errs_file="${temp}${sysconf_dir}/${name}/errors.conf"
|
errs_file="${temp}${sysconf_dir}/${name}/errors.conf"
|
||||||
|
|
||||||
# Name of group unifying git and runner.
|
# Name of group unifying git and runner.
|
||||||
git_runner_groupname="$(id --user --name)"
|
git_runner_groupname="$(id --group --name)"
|
||||||
|
|
||||||
# Name of group unifying runner and deployer.
|
# Name of group unifying runner and deployer.
|
||||||
runner_deployer_groupname="$(id --user --name)"
|
runner_deployer_groupname="$(id --group --name)"
|
||||||
|
|
||||||
# Name of the user responsible of the deployer server.
|
# Name of the user responsible of the deployer server.
|
||||||
deployer_username="$(id --user --name)"
|
deployer_username="$(id --user --name)"
|
||||||
|
@ -25,6 +25,9 @@ deployer_username="$(id --user --name)"
|
||||||
# Location of unixsock file used to send requests to the deployer server.
|
# Location of unixsock file used to send requests to the deployer server.
|
||||||
deployer_sock="${temp}${run_dir}/${name}/deployer/deployer.sock"
|
deployer_sock="${temp}${run_dir}/${name}/deployer/deployer.sock"
|
||||||
|
|
||||||
|
# Location of deployer pid.
|
||||||
|
deployer_pid="${temp}${run_dir}/${name}/pids/deployer.pid"
|
||||||
|
|
||||||
# Maximum number of seconds to wait for deployer response.
|
# Maximum number of seconds to wait for deployer response.
|
||||||
# Set to 0 to disable timeout.
|
# Set to 0 to disable timeout.
|
||||||
deployer_timeout=30
|
deployer_timeout=30
|
||||||
|
@ -35,6 +38,9 @@ runner_username="$(id --user --name)"
|
||||||
# Location of unixsock file used to send requests to the runner server.
|
# Location of unixsock file used to send requests to the runner server.
|
||||||
runner_sock="${temp}${run_dir}/${name}/runner/runner.sock"
|
runner_sock="${temp}${run_dir}/${name}/runner/runner.sock"
|
||||||
|
|
||||||
|
# Location of deployer pid.
|
||||||
|
runner_pid="${temp}${run_dir}/${name}/pids/runner.pid"
|
||||||
|
|
||||||
# Directory in which to clone git repositories.
|
# Directory in which to clone git repositories.
|
||||||
runner_cloning_dir="${temp}${tmp_dir}/${name}/repositories"
|
runner_cloning_dir="${temp}${tmp_dir}/${name}/repositories"
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue