pthbs-build (10232B)
1 #!/bin/sh 2 if test -n "$pthbs_xtrace"; then set -x; fi 3 bsh=$(sha256sum $1) || exit $? 4 bsh=${bsh%% *} 5 if test -z "$pthbs_workdir"; then 6 printf '%s\n' >&2 "$0: fatal: pthbs_workdir env var undefined or empty" 7 exit 100 8 fi 9 if test -z "$pthbs_versions"; then 10 printf '%s\n' >&2 "$0: fatal: pthbs_versions env var undefined or empty" 11 exit 100 12 fi 13 if test -z "$pthbs_pkgdir"; then 14 printf '%s\n' >&2 "$0: fatal: pthbs_pkgdir env var undefined or empty" 15 exit 100 16 fi 17 if test -z "$pthbs_cache"; then 18 printf '%s\n' >&2 "$0: fatal: pthbs_cache env var undefined or empty" 19 exit 100 20 fi 21 if test -z "$pthbs_source"; then 22 printf '%s\n' >&2 "$0: fatal: pthbs_source env var undefined or empty" 23 exit 100 24 fi 25 26 mkdir -p "$pthbs_workdir/builddir.$$" || exit $? 27 workdir=$(realpath "$pthbs_workdir/builddir.$$") 28 if ! test -d "$workdir"; then 29 printf '%s\n' "Error: could not determine workdir" 30 exit 1 31 fi 32 33 script=$(realpath "$1") 34 if ! test -f "$script"; then 35 printf '%s\n' "Error: could not determine script path" 36 exit 1 37 fi 38 39 pthbs_package=${1##*/} 40 pthbs_package=${pthbs_package%%:*}.$bsh 41 42 printf "BUILDING %s => %s => %s\n" "$1" "$workdir" "$pthbs_package" 43 44 eval "$( 45 awk ' 46 BEGIN { 47 settings["sandbox"] = 1 48 settings["set_path"] = 1 49 FS=":" 50 } 51 /^#@pragma:/ { 52 if($2 == "nosandbox") { 53 settings["sandbox"] = 0 54 } else if($2 == "nopath") { 55 settings["set_path"] = 0 56 } else { 57 fatal("unrecognized @pragma:") 58 } 59 } 60 END { 61 print "setting_sandbox=" (settings["sandbox"]?"true":"false") 62 print "setting_set_path=" (settings["set_path"]?"true":"false") 63 } 64 ' "$1" )" 65 66 if test -f "$pthbs_cache/make/package.sha256.${bsh}.env"; then 67 envfile="$pthbs_cache/make/package.sha256.${bsh}.env" 68 envhash=$(pthbs-getenvhash "$envfile") || exit $? 69 export pthbs_build_environment=/versions/env.$envhash 70 if $setting_set_path; then 71 if ! test -x "$pthbs_build_environment/command/pthbs-enter"; then 72 printf >&2 "Error: %s does not exist!" "$pthbs_build_environment/command/pthbs-enter" 73 exit 1 74 fi 75 fi 76 fi 77 78 mkdir -p "$workdir" 79 case $(id -u) in 80 (0) 81 sandbox_mode=root 82 export pthbs_uid=$(id -u pthbs) || exit $? 83 export pthbs_gid=$(id -g pthbs) || exit $? 84 export pthbs_install_uid=0 || exit $? 85 export pthbs_install_gid=$pthbs_gid || exit $? 86 ;; 87 (*) 88 sandbox_mode=userns 89 ;; 90 esac 91 92 env \ 93 workdir="$workdir" \ 94 script="$script" \ 95 envdir="$pthbs_build_environment" \ 96 awk -v single_quote="'" -v sandbox_mode="$sandbox_mode" >"$workdir/pthbs-setup" ' 97 BEGIN { 98 settings["sandbox"] = 1 99 settings["set_path"] = 1 100 FS=":" 101 print "#!/bin/sh -e" 102 print "if test -n \"$pthbs_xtrace\"; then pthbs_xtrace=-x; set -x; fi" 103 print "cd "q(ENVIRON["workdir"]) 104 if(ENVIRON["pthbs_uid"]) { 105 print "export pthbs_uid=" ENVIRON["pthbs_uid"] 106 } 107 if(ENVIRON["pthbs_gid"]) { 108 print "export pthbs_gid=" ENVIRON["pthbs_gid"] 109 } 110 } 111 112 function q(s) { # quote string for sh 113 gsub(single_quote, single_quote "\\" single_quote single_quote, s) 114 return single_quote s single_quote 115 } 116 117 function dirname(s) { # strip the last path component 118 sub("/[^/]*$", "", s) 119 return s 120 } 121 122 function basename(s) { # strip the last path component 123 sub("^.*/$", "", s) 124 return s 125 } 126 127 function fatal(msg) { 128 printf "FATAL: pthbs-build: %s %s:%d: \"%s\"\n", msg, FILENAME, FNR, $0 >"/dev/stderr" 129 exit 1 130 } 131 132 function qlink(rel) { 133 return q(ENVIRON["pthbs_cache"] "/link/" rel) 134 } 135 136 function at_git(commit_id, dstdir){ 137 print "mkdir -p "q(dstdir) 138 print "(cd "qlink("git-commit-sha1/"commit_id)" && git archive --format=tar "q(commit_id)" ) | tar --no-same-owner --no-same-permissions -xC "q(dstdir) 139 } 140 141 function at_untar(extra_opts, hash_type, file_hash, dstdir){ 142 print "mkdir -p "q(dstdir) 143 print "tar -x "extra_opts" -C "q(dstdir)" -f "qlink("file-"hash_type"/"file_hash) 144 } 145 146 function at_filehash(hash_type, file_hash, dst, dstdir){ 147 if(dst ~ /\//) { 148 dstdir = dst 149 sub("/[^/]*$", "", dstdir) 150 print "mkdir -p "q(dstdir) 151 } 152 print "cp -Lp "qlink("file-"hash_type"/"file_hash)" "q(dst) 153 } 154 155 /^#!/ { next } 156 /^#\+/ { 157 if($0 == "#+*") { 158 settings["sandbox"] = 0 159 } else if(!length(ENVIRON["envdir"])) { 160 fatal("dependency specified but no envfile:") 161 } 162 next 163 } 164 /^#@/ { 165 if($1 == "#@git") { 166 if(match($0, "^#@git:[0-9a-f]+:") == 0) { 167 fatal("invalid syntax for @git:") 168 } 169 at_git($2, substr($0, RLENGTH+1)) 170 } else if($1 == "#@sha256") { 171 if(match($0, "^#@sha256:[0-9a-f]+:") == 0) { 172 fatal("invalid syntax for @sha256:") 173 } 174 at_filehash("sha256", $2, substr($0, RLENGTH+1)) 175 } else if($1 == "#@untar") { 176 if(match($0, "^#@untar:[^:]*:sha256:[0-9a-f]+:") == 0) { 177 fatal("invalid syntax for @untar:") 178 } 179 at_untar($2, $3, $4, substr($0, RLENGTH+1)) 180 } else if($1 == "#@pragma") { 181 if($2 == "nosandbox") { 182 settings["sandbox"] = 0 183 } else if($2 == "nopath") { 184 settings["set_path"] = 0 185 } else { 186 fatal("unrecognized @pragma:") 187 } 188 } else { 189 fatal("unrecognized @command:") 190 } 191 next 192 } 193 /^$/ { 194 if(settings["sandbox"]) { 195 if(length(ENVIRON["PTHBS_SYD"])) { 196 sandbox_cmd=" SYD_NO_SYSLOG=1 SYD_LOG_FD=3 3>syd.log" 197 sandbox_cmd=sandbox_cmd " " ENVIRON["PTHBS_SYD"] " -m sandbox/stat:off -m sandbox/exec:off" 198 sandbox_cmd=sandbox_cmd " -m " q("allow/read+"ENVIRON["workdir"]"/***") 199 sandbox_cmd=sandbox_cmd " -m " q("allow/write+"ENVIRON["workdir"]"/***") 200 sandbox_cmd=sandbox_cmd " -m " q("allow/read+/proc/loadavg") 201 sandbox_cmd=sandbox_cmd " -m " q("allow/read+/etc/passwd") 202 sandbox_cmd=sandbox_cmd " -m " q("allow/read+/etc/group") 203 sandbox_cmd=sandbox_cmd " -m " q("allow/read+/tmp/***") 204 sandbox_cmd=sandbox_cmd " -m " q("allow/write+/tmp/***") 205 sandbox_cmd=sandbox_cmd " -m " q("allow/read+/dev/***") 206 sandbox_cmd=sandbox_cmd " -m " q("allow/write+/dev/***") 207 sandbox_cmd=sandbox_cmd " -m " q("allow/read+"ENVIRON["script"]) 208 sandbox_cmd=sandbox_cmd " -m " q("allow/read+"dirname(ENVIRON["envdir"])"/***") 209 sandbox_cmd=sandbox_cmd " -munshare/user:1" 210 sandbox_cmd=sandbox_cmd " -munshare/mount:1" 211 sandbox_cmd=sandbox_cmd " -mbind+" q(ENVIRON["pthbs_workdir"]"/bin:/bin:ro,nosuid,nodev") 212 sandbox_cmd=sandbox_cmd " -m " q("allow/read+/bin/***") 213 sandbox_cmd=sandbox_cmd " -munshare/net:1 -munshare/ipc:1" 214 } else if(sandbox_mode == "userns") { 215 sandbox_cmd=" "q(ENVIRON["pthbs_source"]"/sandbox/ns_sandbox.py")" --mode=userns" 216 sandbox_cmd=sandbox_cmd" --versions="q(ENVIRON["pthbs_versions"]) 217 sandbox_cmd=sandbox_cmd" --extra-mount=tmpfs:"q(ENVIRON["pthbs_workdir"]) 218 sandbox_cmd=sandbox_cmd" --extra-mount=ro_bind:"q(ENVIRON["pthbs_pkgdir"]":"ENVIRON["pthbs_pkgdir"]) 219 sandbox_cmd=sandbox_cmd" --extra-mount=rw_bind:"q(ENVIRON["workdir"]":"ENVIRON["workdir"]) 220 sandbox_cmd=sandbox_cmd" --extra-mount=rw_bind:"q(ENVIRON["workdir"]"/.tmp:/tmp") 221 sandbox_cmd=sandbox_cmd" -- "q(ENVIRON["pthbs_workdir"]"/root") 222 printf "%s\n", "mkdir -p "q(ENVIRON["workdir"]"/.tmp")" "q(ENVIRON["pthbs_workdir"]"/root") 223 } else if(sandbox_mode == "root") { 224 sandbox_cmd=" "q(ENVIRON["pthbs_cache"]"/venv/bin/python")" "q(ENVIRON["pthbs_source"]"/sandbox/ns_sandbox.py")" --mode=root" 225 sandbox_cmd=sandbox_cmd" --versions="q(ENVIRON["pthbs_versions"]) 226 sandbox_cmd=sandbox_cmd" --untar="q(ENVIRON["pthbs_source"]"/sandbox/root.tar") 227 sandbox_cmd=sandbox_cmd" --chdir="q(ENVIRON["workdir"]) 228 sandbox_cmd=sandbox_cmd" --extra-mount=tmpfs:"q(ENVIRON["pthbs_workdir"]) 229 sandbox_cmd=sandbox_cmd" --extra-mount=ro_bind:"q(ENVIRON["pthbs_pkgdir"]":"ENVIRON["pthbs_pkgdir"]) 230 sandbox_cmd=sandbox_cmd" --extra-mount=rw_bind:"q(ENVIRON["workdir"]":"ENVIRON["workdir"]) 231 sandbox_cmd=sandbox_cmd" --extra-mount=rw_bind:"q(ENVIRON["workdir"]"/.tmp:/tmp") 232 sandbox_cmd=sandbox_cmd" -- "q(ENVIRON["pthbs_workdir"]"/root") 233 printf "%s\n", "mkdir -p "q(ENVIRON["workdir"]"/.tmp")" "q(ENVIRON["pthbs_workdir"]"/root") 234 } else { 235 fatal("unrecognized sanbox_mode " sandbox_mode) 236 } 237 } else if(ENVIRON["pthbs_uid"]){ 238 sandbox_cmd="busybox chpst -u \"$pthbs_uid:$pthbs_gid\" --" 239 } else { 240 sandbox_cmd="" 241 } 242 if(ENVIRON["pthbs_uid"]) { 243 printf "%s\n", "chown -R \"$pthbs_uid:$pthbs_gid\" "q(ENVIRON["workdir"]) 244 } 245 if(length(ENVIRON["envdir"])){ 246 cmd="env pthbs_build_environment="q(ENVIRON["envdir"]) 247 cmd=cmd" "sandbox_cmd 248 if(settings["set_path"]) { 249 cmd=cmd" "q(ENVIRON["envdir"]"/command/pthbs-enter") 250 } 251 cmd=cmd" sh -xe "q(ENVIRON["script"]) 252 } else { 253 cmd=sandbox_cmd" sh -xe "q(ENVIRON["script"]) 254 } 255 print "exec >build.log 2>&1 " cmd 256 exit 0 257 } 258 { 259 fatal("unexpected line") 260 } 261 ' "$1" || exit $? 262 263 if test -z "$JOBS"; then 264 JOBS=$(nproc) 265 if test -z "$JOBS"; then 266 JOBS=$(grep -ce '^processor' /proc/cpuinfo) 267 if test -z "$JOBS"; then 268 JOBS=1 269 fi 270 fi 271 fi 272 273 logdir=$pthbs_workdir/logs/$(date '+%Y-%m-%d-%H%M%S')-$pthbs_package 274 ret=0 275 if test -n "$pthbs_xtrace"; then pthbs_xtrace=-x; set -x; fi 276 trap 'trap - INT' INT 277 if env -i \ 278 PATH="$PATH" \ 279 JOBS="$JOBS" \ 280 pthbs_script="$script" \ 281 pthbs_destdir="$workdir/destdir" \ 282 pthbs_package="$pthbs_package" \ 283 sh $pthbs_xtrace -e "$workdir/pthbs-setup" </dev/null; then 284 trap - INT 285 printf "BUILD SUCCESFUL :: %s\n" "$pthbs_package" 286 if ! pthbs-install "$workdir/destdir" "$pthbs_package"; then 287 ret=1 288 echo "INSTALL FAILED" 289 fi 290 else 291 ret=$? 292 trap - INT 293 if test -n "$pthbs_fail_log_cmd"; then 294 $pthbs_fail_log_cmd "$workdir/build.log" 295 else 296 printf "Errors found in log:\n" 297 grep -C 1 -Eie '(error|fatal)[: ]' "$workdir/build.log" 298 fi 299 printf "BUILD FAILED: exitcode %s :: %s :: %s :: %s\n" "$ret" "$1" "$workdir" "$logdir" 300 mkdir -p "$logdir" 301 rm -v "$(dirname "$logdir")/last_failed_build" 302 ln -v -s -f "$(basename "$logdir")" "$(dirname "$logdir")/last_failed_build" 303 find "$workdir" -name config.log -exec cp -v --backup=numbered '{}' "$logdir/config.log" \; 304 pthbs-digest-tree >"$logdir/workdir-digest" "$workdir" 305 fi 306 307 mkdir -p "$logdir" 308 309 if test -e "$workdir/build.log"; then 310 mv "$workdir/build.log" "$logdir/log" 311 bzip2 "$logdir/log" 312 fi 313 314 if test -e "$workdir/syd.log"; then 315 mv "$workdir/syd.log" "$logdir/syd.log" 316 bzip2 "$logdir/syd.log" 317 fi 318 319 if test -e "$workdir/pthbs-setup"; then 320 mv "$workdir/pthbs-setup" "$logdir/" 321 fi 322 323 if test -n "$pthbs_build_environment"; then 324 ln -s "$pthbs_build_environment" "$logdir/env" 325 fi 326 327 if test -z "$pthbs_skip_cleanup"; then 328 rm -rf "$workdir" || ret=$? 329 fi 330 exit $ret