build 8.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231
  1. #!/bin/bash
  2. set -x
  3. umask 022
  4. ### functions
  5. fatal () {
  6. echo "$*" >&2
  7. exit 1
  8. }
  9. syslinux_utils_upstream_version () {
  10. dpkg-query -W -f='${Version}\n' syslinux-utils | \
  11. # drop epoch
  12. sed -e 's,.*:,,' | \
  13. # drop +dfsg and everything that follows
  14. sed -e 's,\+dfsg.*,,'
  15. }
  16. print_iso_size () {
  17. local isofile="$1"
  18. [ -f "$isofile" ] || return 23
  19. size=$(stat --printf='%s' "$isofile")
  20. echo "The ISO is ${size} bytes large."
  21. }
  22. ### Main
  23. # we require building from git
  24. git rev-parse --is-inside-work-tree &> /dev/null \
  25. || fatal "${PWD} is not a Git tree."
  26. . config/amnesia
  27. if [ -e config/amnesia.local ] ; then
  28. . config/amnesia.local
  29. fi
  30. # a clean starting point
  31. rm -rf cache/stages_rootfs
  32. # get LB_BINARY_IMAGES
  33. . config/binary
  34. # get LB_ARCHITECTURE and LB_DISTRIBUTION
  35. . config/bootstrap
  36. # save variables that are needed by chroot_local-hooks
  37. echo "KERNEL_VERSION=${KERNEL_VERSION}" \
  38. >> config/chroot_local-includes/usr/share/amnesia/build/variables
  39. echo "KERNEL_SOURCE_VERSION=${KERNEL_SOURCE_VERSION}" \
  40. >> config/chroot_local-includes/usr/share/amnesia/build/variables
  41. echo "LB_DISTRIBUTION=${LB_DISTRIBUTION}" >> config/chroot_local-includes/usr/share/amnesia/build/variables
  42. echo "POTFILES_DOT_IN='$(
  43. /bin/grep -E --no-filename '[^ #]*\.in$' po/POTFILES.in \
  44. | sed -e 's,^config/chroot_local-includes,,' | tr "\n" ' '
  45. )'" \
  46. >> config/chroot_local-includes/usr/share/amnesia/build/variables
  47. # fix permissions on some source files that will be copied as is to the chroot.
  48. # they may be wrong, e.g. if the Git repository was cloned with a strict umask.
  49. chmod -R go+rX config/binary_local-includes/
  50. chmod -R go+rX config/chroot_local-includes/etc
  51. chmod 0440 config/chroot_local-includes/etc/sudoers.d/*
  52. chmod go+rX config/chroot_local-includes/home
  53. chmod go+rX config/chroot_local-includes/lib
  54. chmod go+rX config/chroot_local-includes/lib/live
  55. chmod -R go+rx config/chroot_local-includes/lib/live/config
  56. chmod go+rX config/chroot_local-includes/lib/live/mount
  57. chmod -R go+rX config/chroot_local-includes/lib/systemd
  58. chmod go+rX config/chroot_local-includes/live
  59. chmod -R go+rX config/chroot_local-includes/usr
  60. chmod -R go+rx config/chroot_local-includes/usr/local/bin
  61. chmod -R go+rx config/chroot_local-includes/usr/local/sbin
  62. chmod -R go+rX config/chroot_local-includes/usr/share/doc/tails
  63. chmod -R go+rX config/chroot_local-includes/var
  64. chmod -R go+rX config/chroot_apt
  65. chmod -R go+rX config/chroot_sources
  66. # build the image
  67. # we need /debootstrap/deburis to build a manifest of used packages:
  68. DEBOOTSTRAP_OPTIONS="$DEBOOTSTRAP_OPTIONS --keep-debootstrap-dir"
  69. # we're not ready for merged-/usr yet: Debian#843461, Tails#11903
  70. DEBOOTSTRAP_OPTIONS="$DEBOOTSTRAP_OPTIONS --no-merged-usr"
  71. # use our own APT repository's key:
  72. DEBOOTSTRAP_GNUPG_HOMEDIR=$(mktemp -d)
  73. gpg --homedir "$DEBOOTSTRAP_GNUPG_HOMEDIR" \
  74. --import config/chroot_sources/tails.chroot.gpg
  75. DEBOOTSTRAP_OPTIONS="$DEBOOTSTRAP_OPTIONS --keyring=$DEBOOTSTRAP_GNUPG_HOMEDIR/pubring.gpg"
  76. export DEBOOTSTRAP_OPTIONS
  77. : ${MKSQUASHFS_OPTIONS:='-comp xz -Xbcj x86 -b 1024K -Xdict-size 1024K'}
  78. MKSQUASHFS_OPTIONS="${MKSQUASHFS_OPTIONS} -wildcards -ef chroot/usr/share/amnesia/build/mksquashfs-excludes"
  79. export MKSQUASHFS_OPTIONS
  80. # get git branch or tag so we can set the basename appropriately, i.e.:
  81. # * if we build from a tag: tails-$ARCH-$TAG.iso
  82. # * otherwise: tails-$ARCH-$BRANCH-$VERSION-$TIME-$COMMIT.iso
  83. if GIT_REF="$(git symbolic-ref HEAD)"; then
  84. GIT_BRANCH="${GIT_REF#refs/heads/}"
  85. CLEAN_GIT_BRANCH=$(echo "$GIT_BRANCH" | sed 's,/,_,g')
  86. GIT_SHORT_ID="$(git rev-parse --short HEAD)"
  87. BUILD_BASENAME="tails-${LB_ARCHITECTURE}-${CLEAN_GIT_BRANCH}-${AMNESIA_VERSION}-${AMNESIA_NOW}-${GIT_SHORT_ID}"
  88. else
  89. GIT_CURRENT_COMMIT="$(git rev-parse HEAD)"
  90. if GIT_TAG="$(git describe --tags --exact-match ${GIT_CURRENT_COMMIT})"; then
  91. CLEAN_GIT_TAG=$(echo "$GIT_TAG" | tr '/-' '_~')
  92. BUILD_BASENAME="tails-${LB_ARCHITECTURE}-${CLEAN_GIT_TAG}"
  93. else
  94. # this shouldn't reasonably happen (e.g. only if you checkout a
  95. # tag, remove the tag and then build)
  96. fatal "Neither a Git branch nor a tag, exiting."
  97. fi
  98. fi
  99. GIT_BASE_BRANCH=$(head -n1 config/base_branch) \
  100. || fatal "GIT_BASE_BRANCH could not be guessed."
  101. # Merge base branch into the branch being built, iff. we're building
  102. # in Jenkins, and not building from a tag, and not building the base
  103. # branch itself
  104. if [ -n "$JENKINS_URL" ] && [ -z "$GIT_TAG" ] \
  105. && [ "$GIT_BRANCH" != "$GIT_BASE_BRANCH" ] ; then
  106. GIT_BASE_BRANCH_COMMIT=$(git rev-parse "origin/${GIT_BASE_BRANCH}") \
  107. || fatal "Base branch's top commit could not be guessed."
  108. echo "Merging base branch origin/${GIT_BASE_BRANCH}"
  109. echo "(at commit ${GIT_BASE_BRANCH_COMMIT})..."
  110. git merge --no-edit "origin/${GIT_BASE_BRANCH}" \
  111. || fatal "Failed to merge base branch."
  112. # Adjust BUILD_BASENAME to embed the base branch name and its top commit
  113. CLEAN_GIT_BASE_BRANCH=$(echo "$GIT_BASE_BRANCH" | sed 's,/,_,g')
  114. GIT_BASE_BRANCH_SHORT_ID=$(git rev-parse --short "origin/${GIT_BASE_BRANCH}") \
  115. || fatal "Base branch's top commit short ID could not be guessed."
  116. BUILD_BASENAME="${BUILD_BASENAME}+${CLEAN_GIT_BASE_BRANCH}"
  117. BUILD_BASENAME="${BUILD_BASENAME}@${GIT_BASE_BRANCH_SHORT_ID}"
  118. fi
  119. # build the doc wiki
  120. ./build-website
  121. # refresh translations of our programs
  122. ./refresh-translations || fatal "refresh-translations failed ($?)."
  123. case "$LB_BINARY_IMAGES" in
  124. iso)
  125. BUILD_FILENAME_EXT=iso
  126. BUILD_FILENAME=binary
  127. which isohybrid >/dev/null || fatal 'Cannot find isohybrid in $PATH'
  128. installed_syslinux_utils_upstream_version="$(syslinux_utils_upstream_version)"
  129. if dpkg --compare-versions \
  130. "$installed_syslinux_utils_upstream_version" \
  131. 'lt' \
  132. "$REQUIRED_SYSLINUX_UTILS_UPSTREAM_VERSION" ; then
  133. fatal \
  134. "syslinux-utils '${installed_syslinux_utils_upstream_version}' is installed, " \
  135. "while we need at least '${REQUIRED_SYSLINUX_UTILS_UPSTREAM_VERSION}'."
  136. fi
  137. ;;
  138. iso-hybrid)
  139. BUILD_FILENAME_EXT=iso
  140. BUILD_FILENAME=binary-hybrid
  141. ;;
  142. tar)
  143. BUILD_FILENAME_EXT=tar.gz
  144. BUILD_FILENAME=binary-tar
  145. ;;
  146. usb-hdd)
  147. BUILD_FILENAME_EXT=img
  148. BUILD_FILENAME=binary
  149. ;;
  150. *)
  151. fatal "Image type ${LB_BINARY_IMAGES} is not supported."
  152. ;;
  153. esac
  154. BUILD_DEST_FILENAME="${BUILD_BASENAME}.${BUILD_FILENAME_EXT}"
  155. BUILD_MANIFEST="${BUILD_DEST_FILENAME}.build-manifest"
  156. BUILD_APT_SOURCES="${BUILD_DEST_FILENAME}.apt-sources"
  157. BUILD_PACKAGES="${BUILD_DEST_FILENAME}.packages"
  158. BUILD_LOG="${BUILD_DEST_FILENAME}.buildlog"
  159. BUILD_START_FILENAME="${BUILD_DEST_FILENAME}.start.timestamp"
  160. BUILD_END_FILENAME="${BUILD_DEST_FILENAME}.end.timestamp"
  161. # Clone all output, from this point on, to the log file
  162. exec > >(tee -a "$BUILD_LOG")
  163. trap "kill -9 $! 2>/dev/null" EXIT HUP INT QUIT TERM
  164. exec 2> >(tee -a "$BUILD_LOG" >&2)
  165. trap "kill -9 $! 2>/dev/null" EXIT HUP INT QUIT TERM
  166. (
  167. echo "Mirrors:"
  168. apt-mirror debian
  169. apt-mirror debian-security
  170. apt-mirror torproject
  171. echo "Additional sources:"
  172. cat config/chroot_sources/*.chroot
  173. ) > "$BUILD_APT_SOURCES"
  174. echo "Building $LB_BINARY_IMAGES image ${BUILD_BASENAME}..."
  175. set -o pipefail
  176. [ -z "$JENKINS_URL" ] || date --utc '+%s' > "$BUILD_START_FILENAME"
  177. time eatmydata lb build noauto ${@}
  178. RET=$?
  179. if [ -e "${BUILD_FILENAME}.${BUILD_FILENAME_EXT}" ]; then
  180. echo "Image was successfully created"
  181. [ "$RET" -eq 0 ] || \
  182. echo "Warning: lb build exited with code $RET"
  183. [ -z "$JENKINS_URL" ] || date --utc '+%s' > "$BUILD_END_FILENAME"
  184. if [ "$LB_BINARY_IMAGES" = iso ]; then
  185. ISO_FILE="${BUILD_FILENAME}.${BUILD_FILENAME_EXT}"
  186. print_iso_size "$ISO_FILE"
  187. echo "Hybriding it..."
  188. isohybrid $AMNESIA_ISOHYBRID_OPTS "$ISO_FILE"
  189. print_iso_size "$ISO_FILE"
  190. truncate -s %2048 "$ISO_FILE"
  191. print_iso_size "$ISO_FILE"
  192. fi
  193. echo "Renaming generated files..."
  194. mv -i "${BUILD_FILENAME}.${BUILD_FILENAME_EXT}" "${BUILD_DEST_FILENAME}"
  195. mv -i binary.packages "${BUILD_PACKAGES}"
  196. generate-build-manifest chroot/debootstrap "${BUILD_MANIFEST}"
  197. else
  198. fatal "lb build failed ($?)."
  199. fi