aboutsummaryrefslogtreecommitdiffhomepage
path: root/scripts/deploy.sh
blob: 3f34e5b65d39eeb5f970bc6aa6348f1de4e751d4 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
#!/usr/bin/env bash

# little helper for docker deployment to:
# - start development environment for IronOS ("shell" sub-command)
# - generate full set of builds ("build" sub-command)
# - probably doing some other routines (check source briefly before running undocumented commands!)

#set -x
#set -e

### helper functions

# brief help (some supported commands may be missing!)
usage()
{
	echo -e "\nUsage: ${0} [CMD]\n"
	echo "CMD (docker related):"
	echo -e "\tshell - start docker container with shell inside to work on IronOS with all tools needed"
	echo -e "\tbuild - compile builds of IronOS inside docker container for supported hardware"
	echo -e "\tclean - delete created docker image for IronOS & its build cache objects\n"
	echo "CMD (helper routines):"
	echo -e "\tdocs - high level target to run docs_readme and docs_history (see below)\n"
	echo -e "\tdocs_readme - generate & OVERWRITE(!) README.md inside Documentation/ based on nav section from mkdocs.yml if it changed\n"
	echo -e "\tdocs_history - check if History.md has the changelog for the latest stable release\n"
	echo -e "\tcheck_style_file SRC - run code style checks based on clang-format & custom parsers for source code file SRC\n"
	echo -e "\tcheck_style_log - run clang-format using source/Makefile and generate gcc-compatible error log in source/check-style.log\n"
	echo -e "STORAGE NOTICE: for \"shell\" and \"build\" commands extra files will be downloaded so make sure that you have ~5GB of free space.\n"
}

# Documentation/README.md automagical generation routine
docs_readme()
{
	# WARNING: ON RUN Documentaion/README.md MAY BE OVERWRITTEN WITHOUT ANY WARNINGS / CONFIRMATIONS !!!
	# Returns:
	## 0 to the environment & silence - if there are no any changes in README.md nor updates in mkdocs.yml
	## 1 to the environment (as error) & note message - if the update of README.md in repo is required
	yml="scripts/IronOS-mkdocs.yml"
	md_old="Documentation/README.md"
	md_new="Documentation/README"
	# ^^^^ hardcoded paths relative to IronOS/ to make this func very trivial
# file overwritten section looks out of style but hoping to make shellcheck happy
cat << EOF > "${md_new}"

<!-- THIS FILE IS AUTOGENERATED by "scripts/deploy.sh docs_readme" based on nav section in ${yml} config -->
<!-- THIS FILE IS NOT SUPPOSED TO BE EDITED MANUALLY -->

#### This is autogenerated README for brief navigation through github over official documentation for IronOS project
#### This documentation is also available [here online](https://ralim.github.io/IronOS)

EOF
	# it probably will become unexplainable in a few months but so far it works:
	sed '1,/^nav/d; /^ *$/,$d; s,- ,- [,; s,: ,](../Documentation/,; s,.md,.md),; s,:$,],; s,/Pinecil ,/Pinecil%20,; /^  - \[.*\]$/ s,\[,,; s,]$,,' "${yml}" >> "${md_new}"
	ret=0
	if [ -z "$(diff -q "${md_old}" "${md_new}")" ]; then
		rm "${md_new}"
		ret=0
	else
		mv "${md_new}" "${md_old}"
		echo ""
		echo "${yml} seems to be updated..."
		echo "... while ${md_old} is out-of-date!"
		echo ""
		echo "Please, update ${md_old} in your local working copy by command:"
		echo ""
		echo " $ ./scripts/deploy.sh docs_readme"
		echo ""
		echo "And then commit & push changes to update ${md_old} in the repo:"
		echo ""
		echo " $ git commit ${md_old} -m \"${md_old}: update autogenerated file\" && git push"
		echo ""
		ret=1
	fi;
	return "${ret}"
}

# Documentation/History.md automagical changelog routine
docs_history()
{
	md="Documentation/History.md"
	ver_md="$(sed -ne 's/^## //1p' "${md}" | head -1)"
	echo "Latest changelog: ${ver_md}"
	ver_git="$(git tag -l | sort | grep -e "^v" | grep -v "rc" | tail -1)"
	echo "Latest release tag: ${ver_git}"
	ret=0
	if [ "${ver_md}" != "${ver_git}" ]; then
		ret=1
		echo "It seems there is no changelog information for ${ver_git} in ${md} yet."
		echo "Please, update changelog information in ${md}."
	fi;
	return "${ret}"
}

# Check for links to release builds in README.md
docs_links()
{
	ver_git="$(git tag -l | sort | grep -e "^v" | grep -v "rc" | tail -1)"
	md="README.md"
	ver_md="$(grep -c "${ver_git}" "${md}")"
	ret=0
	if [ "${ver_md}" -ne 0 ]; then
		ret=1
		echo "Please, update mention & links in ${md} inside Builds section for release builds with version ${ver_git}."
	fi;
	return "${ret}"
}

# source/Makefile:ALL_LANGUAGES & Translations/*.json automagical routine
build_langs()
{
	mk="../source/Makefile"
	cd Translations/ || exit 1
	langs="$(echo "$(find ./*.json | sed -ne 's,^\./translation_,,; s,\.json$,,; /[A-Z]/p' ; sed -ne 's/^ALL_LANGUAGES=//p;' "${mk}")" | sed 's, ,\n,g; s,\r,,g' | sort | uniq -u)"
	ret=0
	if [ -n "${langs}" ]; then
		ret=1
		echo "It seems there is mismatch between supported languages and enabled builds."
		echo "Please, check files in Translations/ and ALL_LANGUAGES variable in source/Makefile for:"
		echo "${langs}"
	fi;
	return "${ret}"
}

# Helper function to check code style using clang-format & grep/sed custom parsers:
# - basic logic moved from source/Makefile : `check-style` target for better maintainance since a lot of sh script involved;
# - output goes in gcc-like error compatible format for IDEs/editors.
check_style_file()
{
	ret=0
	src="${1}"
	test ! -f "${src}" && echo "ERROR!!! Provided file ${src} is not available to check/read!!!" && exit 1
	# count lines using diff between beauty-fied file & original file to detect format issue
	var="$(clang-format "$src" | diff "$src" - | wc -l)"
	if [ "${var}" -ne 0 ]; then
		# show full log error or, if LIST=anything provided, then show only filename of interest (implemented for debug purposes mainly)
		if [ -z "${LIST}" ]; then
			# sed is here only for pretty logging
			clang-format "${src}" | diff "${src}" - | sed 's/^---/-------------------------------------------------------------------------------/; s/^< /--- /; s/^> /+++ /; /^[0-9].*/ s/[acd,].*$/ERROR1/; /^[0-9].*/ s,^,\n\n\n\n'"${src}"':,; /ERROR1$/ s,ERROR1$,:1: error: clang-format code style mismatch:,; '
		else
			echo "${src}"
		fi;
		ret=1
	fi;
	return "${ret}"
}

# check_style routine for those who too lazy to do it everytime manually
check_style_log()
{
	log="source/check-style.log"
	make  -C source  check-style  2>&1  |  tee  "${log}"
	chmod  0666  "${log}"
	sed -i -e 's,\r,,g' "${log}"
	return 0
}

### main

docker_conf="Env.yml"

# get absolute location of project root dir to make docker happy with config(s)
# (successfully tested on relatively POSIX-compliant Dash shell)

# this script
script_file="/deploy.sh"
# IronOS/scripts/deploy.sh
script_path="${PWD}"/"${0}"
# IronOS/scripts/
script_dir=${script_path%"${script_file}"}
# IronOS/
root_dir="${script_dir}/.."
# IronOS/Env.yml
docker_file="-f ${root_dir}/${docker_conf}"

# allow providing custom path to docker tool using DOCKER_BIN external env. var.
# (compose sub-command must be included, i.e. DOCKER_BIN="/usr/local/bin/docker compose" ./deploy.sh)

if [ -z "${DOCKER_BIN}" ]; then
	docker_app=""
else
	docker_app="${DOCKER_BIN}"
fi;

# detect availability of docker

docker_compose="$(command -v docker-compose)"
if [ -n "${docker_compose}" ] && [ -z "${docker_app}" ]; then
	docker_app="${docker_compose}"
fi;

docker_tool="$(command -v docker)"
if [ -n "${docker_tool}" ] && [ -z "${docker_app}" ]; then
	docker_app="${docker_tool}  compose"
fi;

# give function argument a name

cmd="${1}"

# meta target to verify markdown documents

if [ "docs" = "${cmd}" ]; then
	docs_readme
	readme="${?}"
	docs_history
	hist="${?}"
	build_langs
	langs="${?}"
	docs_links
	links="${?}"
	if [ "${readme}" -eq 0 ] && [ "${hist}" -eq 0 ] && [ "${langs}" -eq 0 ] && [ "${links}" -eq 0 ]; then
		ret=0
	else
		ret=1
	fi;
	exit ${ret}
fi;

# if only README.md for Documentation update is required then run it & exit

if [ "docs_readme" = "${cmd}" ]; then
	docs_readme
	exit "${?}"
fi;

# if only History.md for Documentation update is required then run it & exit

if [ "docs_history" = "${cmd}" ]; then
	docs_history
	exit "${?}"
fi;

if [ "build_langs" = "${cmd}" ]; then
	build_langs
	exit "${?}"
fi;

if [ "docs_links" = "${cmd}" ]; then
	docs_links
	exit "${?}"
fi;

if [ "check_style_file" = "${cmd}" ]; then
	check_style_file "${2}"
	exit "${?}"
fi;

if [ "check_style_log" = "${cmd}" ]; then
	check_style_log
	exit "${?}"
fi;

# if docker is not presented in any way show warning & exit

if [ -z "${docker_app}" ]; then
	echo "ERROR: Can't find docker-compose nor docker tool. Please, install docker and try again."
	exit 1
fi;

# construct command to run

if [ -z "${cmd}" ] || [ "${cmd}" = "shell" ]; then
	docker_cmd="run  --rm  builder"
elif [ "${cmd}" = "build" ]; then
	docker_cmd="run  --rm  builder  make  build-all  OUT=${OUT}"
elif [ "${cmd}" = "clean" ]; then
	docker  rmi  ironos-builder:latest
	docker  system  prune  --filter label=ironos-builder:latest  --force
	exit "${?}"
else
	usage
	exit 1
fi;

# change dir to project root dir & run constructed command

cd "${root_dir}" || exit 1
echo -e "\n====>>>> Firing up & starting container..."
if [ "${cmd}" = "shell" ]; then
echo -e "\t* type \"exit\" to end the session when done;"
fi;
echo -e "\t* type \"${0} clean\" to delete created container (but not cached data)"
echo -e "\n====>>>> ${docker_app}  ${docker_file}  ${docker_cmd}\n"
eval "${docker_app}  ${docker_file}  ${docker_cmd}"
exit "${?}"