Tools for building 32-bit archlinux packages from archlinux.org's official, 64-bit tested PKGBUILDs et al.

interpret-mail 8.6KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341
  1. #!/bin/sh
  2. # shellcheck disable=SC2119,SC2120
  3. # shellcheck source=../lib/load-configuration
  4. . "${0%/*}/../lib/load-configuration"
  5. # shellcheck disable=SC2016
  6. if [ $# -ne 0 ]; then
  7. >&2 echo ''
  8. >&2 echo 'usage: interpret-mail'
  9. >&2 echo ' Read email from stdin and interpret / execute body.'
  10. >&2 echo ''
  11. >&2 echo ' The email needs a valid hashcash-stamp (>=20 bits)'
  12. >&2 echo ' and valid encryption to buildmaster@archlinux32.org,'
  13. >&2 echo ' as well as a valid gpg-signature from anyone in the'
  14. >&2 echo ' list in `gpg_keys`. `allowed_email_actions`'
  15. >&2 echo ' determines what instructions are allowed.'
  16. >&2 echo ''
  17. >&2 echo ' Possible instructions are:'
  18. >&2 echo ''
  19. >&2 echo ' - "block: <state-file> <reason>":'
  20. >&2 echo ' Block the given build assignment for the given reason.'
  21. >&2 echo ''
  22. >&2 echo ' - "copy-to-build-support: <arch> <pkgname>":'
  23. >&2 echo ' Copy the given binary package into [build-support].'
  24. >&2 echo ''
  25. >&2 echo ' - "delete:":'
  26. >&2 echo ' Delete all scheduled, safely deletable packages.'
  27. >&2 echo ''
  28. >&2 echo ' - "delete-from-build-support: <arch> <package-file>":'
  29. >&2 echo ' Delete the given package from <arch>/build-support.'
  30. >&2 echo ''
  31. >&2 echo ' - "prioritize: <pkgbase-regex>":'
  32. >&2 echo ' Increase the priority of matching build assignments.'
  33. >&2 echo ''
  34. >&2 echo ' - "schedule: <pkgbase>":'
  35. >&2 echo ' Put the given package on the build list (again).'
  36. >&2 echo ''
  37. >&2 echo ' - "stabilize: <package-file>":'
  38. >&2 echo ' Mark the given package as tested.'
  39. >&2 echo ''
  40. >&2 echo ' - "unblock: <state-file>":'
  41. >&2 echo ' Unblock the given build assignment.'
  42. >&2 echo ''
  43. exit 1
  44. fi
  45. # log $success $action $count [$comment_file]
  46. # shellcheck disable=SC2039
  47. log() {
  48. local success
  49. local action
  50. local count
  51. local comment
  52. success="$1"
  53. action="$2"
  54. count="$3"
  55. if [ -z "$4" ]; then
  56. comment=''
  57. else
  58. comment=$(
  59. base64 -w0 "$4"
  60. )
  61. fi
  62. # shellcheck disable=SC2016
  63. {
  64. printf 'INSERT IGNORE INTO `email_log` (`success`,`action`,`count`,`gpg_key`,`comment`)'
  65. printf ' SELECT '
  66. if [ "${success}" = '1' ]; then
  67. printf '1,'
  68. else
  69. printf '0,'
  70. fi
  71. printf '`email_actions`.`id`,from_base64("%s"),`gpg_keys`.`id`,from_base64("%s")' \
  72. "$(
  73. printf '%s' "${count}" | \
  74. base64 -w0
  75. )" \
  76. "${comment}"
  77. printf ' FROM `email_actions`'
  78. printf ' JOIN `gpg_keys`'
  79. printf '%s' "${gpg_keys_filter}"
  80. printf ' AND `email_actions`.`name`=from_base64("%s");\n' "$(
  81. printf '%s' "${action}" | \
  82. base64 -w0
  83. )"
  84. } | \
  85. mysql_run_query
  86. }
  87. # run_and_log_on_error $action
  88. # shellcheck disable=SC2039
  89. run_and_log_on_error() {
  90. # shellcheck disable=SC2039
  91. local err
  92. local action
  93. action="$1"
  94. shift
  95. err=0
  96. "$@" 2> "${tmp_dir}/stderr" > "${tmp_dir}/stdout" || \
  97. err=$?
  98. if [ "${err}" -eq 0 ]; then
  99. return 0
  100. fi
  101. cat "${tmp_dir}/stdout" >> "${tmp_dir}/stderr"
  102. if [ "${err}" -eq 1 ]; then
  103. printf '^ temporary error - I keep the message.\n' >> \
  104. "${tmp_dir}/stderr"
  105. fi
  106. log '0' "${action}" '0' "${tmp_dir}/stderr"
  107. if [ "${err}" -eq 1 ]; then
  108. exit 1
  109. else
  110. return 1
  111. fi
  112. }
  113. tmp_dir=$(mktemp -d 'tmp.interpret-mail.XXXXXXXXXX' --tmpdir)
  114. trap 'rm -rf --one-file-system "${tmp_dir}"' EXIT
  115. cat > \
  116. "${tmp_dir}/mail"
  117. if ! hashcash -qXc -b 20 \
  118. -d -f "${tmp_dir}/hashcash.db" \
  119. -r 'archlinux32-buildmaster@eckner.net' \
  120. -r 'buildmaster@archlinux32.org' < \
  121. "${tmp_dir}/mail"; then
  122. # shellcheck disable=SC2016
  123. {
  124. printf 'INSERT IGNORE INTO `email_log` (`success`,`comment`)'
  125. printf ' VALUES (0,"Invalid stamp - ignoring this message.");\n'
  126. } | \
  127. mysql_run_query
  128. exit
  129. fi
  130. if ! sed -n '
  131. /^-----BEGIN PGP MESSAGE-----\s*$/{
  132. :a
  133. /\n-----END PGP MESSAGE-----\s*$/!{
  134. N
  135. ba
  136. }
  137. p
  138. }
  139. ' "${tmp_dir}/mail" | \
  140. gpg --batch --status-file "${tmp_dir}/gpg-status" -q -d -o "${tmp_dir}/plain-content" > /dev/null 2>&1; then
  141. # shellcheck disable=SC2016
  142. {
  143. printf 'INSERT IGNORE INTO `email_log` (`success`,`comment`)'
  144. printf ' VALUES (0,from_base64("%s"));\n' \
  145. "$(
  146. {
  147. printf 'Invalid encryption/signature - ignoring this message.\n'
  148. cat "${tmp_dir}/gpg-status"
  149. } | \
  150. base64 -w0
  151. )"
  152. } | \
  153. mysql_run_query
  154. exit
  155. fi
  156. gpg_keys_filter=$(
  157. # shellcheck disable=SC2016
  158. {
  159. printf 'SELECT DISTINCT `gpg_keys`.`id`'
  160. printf ' FROM `gpg_keys`'
  161. printf ' WHERE `gpg_keys`.`fingerprint` IN ('
  162. grep '^\[GNUPG:] VALIDSIG ' "${tmp_dir}/gpg-status" | \
  163. cut -d' ' -f3 | \
  164. sort -u | \
  165. base64_encode_each | \
  166. sed '
  167. s/^/from_base64("/
  168. s/$/"),/
  169. '
  170. printf '"");\n'
  171. } | \
  172. mysql_run_query | \
  173. sed '
  174. $! s/$/,/
  175. 1 s/^/ WHERE `gpg_keys`.`id` IN (/
  176. $ s/$/)/
  177. '
  178. )
  179. if [ -z "${gpg_keys_filter}" ]; then
  180. # shellcheck disable=SC2016
  181. {
  182. printf 'INSERT IGNORE INTO `email_log` (`success`,`comment`)'
  183. printf ' VALUES (0,from_base64("%s"));\n' \
  184. "$(
  185. {
  186. printf 'No known signature found - I found:\n'
  187. grep '^\[GNUPG:] VALIDSIG ' "${tmp_dir}/gpg-status" | \
  188. cut -d' ' -f3 | \
  189. sort -u | \
  190. sed 's|^|> |'
  191. printf 'Ignoring this message.\n'
  192. } | \
  193. base64 -w0
  194. )"
  195. } | \
  196. mysql_run_query
  197. exit
  198. fi
  199. # shellcheck disable=SC2016
  200. {
  201. printf 'SELECT DISTINCT `email_actions`.`name`'
  202. printf ' FROM `email_actions`'
  203. mysql_join_email_actions_allowed_email_actions
  204. mysql_join_allowed_email_actions_gpg_keys
  205. printf '%s\n' "${gpg_keys_filter}"
  206. } | \
  207. mysql_run_query > \
  208. "${tmp_dir}/allowed-actions"
  209. printf '\n\n' >> "${tmp_dir}/plain-content"
  210. sed -n '
  211. /^$/!b
  212. N
  213. s/^\n//
  214. /^--/b
  215. :a
  216. N
  217. /\n$/!ba
  218. s/\n$//
  219. p
  220. ' "${tmp_dir}/plain-content" | \
  221. sed '
  222. :start_loop
  223. $!{
  224. N
  225. bstart_loop
  226. }
  227. s/[=\]\s*\n//g
  228. s/:\s*\n/: /g
  229. s/\n\(\S\+[^: ]\(\s\|\n\|$\)\)/ \1/g
  230. ' > \
  231. "${tmp_dir}/raw-content"
  232. sed -n "$(
  233. while read -r action; do
  234. if [ -z "${action}" ]; then
  235. continue
  236. fi
  237. printf \
  238. '/^%s:/{ s/^%s:\s*//; w %s/%s\n b; }\n' \
  239. "${action}" \
  240. "${action}" \
  241. "${tmp_dir}" \
  242. "${action}"
  243. done < \
  244. "${tmp_dir}/allowed-actions"
  245. )" "${tmp_dir}/raw-content"
  246. if [ -s "${tmp_dir}/block" ]; then
  247. if run_and_log_on_error 'block' "${base_dir}/bin/modify-package-state" --wait --block "${tmp_dir}/block"; then
  248. log 1 'block' "$(wc -l < "${tmp_dir}/block")"
  249. else
  250. log 0 'block' 0
  251. fi
  252. fi
  253. if [ -s "${tmp_dir}/copy-to-build-support" ]; then
  254. sed -i '
  255. /\.pkg\.tar\.xz$/!s/$/.pkg.tar.xz/
  256. ' "${tmp_dir}/copy-to-build-support"
  257. if run_and_log_on_error 'copy-to-build-support' "${base_dir}/bin/copy-to-build-support" --wait "${tmp_dir}/copy-to-build-support"; then
  258. log 1 'copy-to-build-support' "$(wc -l < "${tmp_dir}/copy-to-build-support")"
  259. else
  260. log 0 'copy-to-build-support' 0
  261. fi
  262. fi
  263. if [ -s "${tmp_dir}/delete" ]; then
  264. if run_and_log_on_error 'delete' "${base_dir}/bin/delete-packages" --wait; then
  265. log 1 'delete' 1
  266. else
  267. log 0 'delete' 0
  268. fi
  269. fi
  270. if [ -s "${tmp_dir}/delete-from-build-support" ]; then
  271. if run_and_log_on_error 'delete-from-build-support' "${base_dir}/bin/delete-packages" --wait --build-support "${tmp_dir}/delete-from-build-support"; then
  272. log 1 'delete-from-build-support' "$(wc -l < "${tmp_dir}/delete-from-build-support")"
  273. else
  274. log 0 'delete-from-build-support' 0
  275. fi
  276. fi
  277. if [ -s "${tmp_dir}/prioritize" ]; then
  278. if run_and_log_on_error 'prioritize' "${base_dir}/bin/prioritize-build-list" --wait "${tmp_dir}/prioritize"; then
  279. log 1 'prioritize' "$(cat "${tmp_dir}/prioritize")"
  280. else
  281. log 0 'prioritize' 0
  282. fi
  283. fi
  284. if [ -s "${tmp_dir}/schedule" ]; then
  285. # shellcheck disable=SC2046
  286. "${base_dir}/bin/seed-build-list" --wait $(
  287. tr '[:space:]' '\n' < \
  288. "${tmp_dir}/schedule" | \
  289. grep -vxF '' | \
  290. while read -r package; do
  291. printf -- '-p ^%s$\n' "$(str_to_regex "${package}")"
  292. done
  293. ) | \
  294. sponge "${tmp_dir}/schedule"
  295. log 1 'schedule' "$(wc -l < "${tmp_dir}/schedule")"
  296. fi
  297. if [ -s "${tmp_dir}/stabilize" ]; then
  298. sed -i '
  299. /\.pkg\.tar\.xz$/!s/$/.pkg.tar.xz/
  300. ' "${tmp_dir}/stabilize"
  301. if run_and_log_on_error 'stabilize' "${base_dir}/bin/modify-package-state" --wait --tested "${tmp_dir}/stabilize"; then
  302. log 1 'stabilize' "$(wc -l < "${tmp_dir}/stabilize")"
  303. else
  304. log 0 'stabilize' 0
  305. fi
  306. fi
  307. if [ -s "${tmp_dir}/unblock" ]; then
  308. if run_and_log_on_error 'unblock' "${base_dir}/bin/modify-package-state" --wait --unblock "${tmp_dir}/unblock"; then
  309. log 1 'unblock' "$(wc -l < "${tmp_dir}/unblock")"
  310. else
  311. log 0 'unblock' 0
  312. fi
  313. fi