diff --git a/Containerfile b/Containerfile new file mode 100644 index 00000000..c4ae04f0 --- /dev/null +++ b/Containerfile @@ -0,0 +1,3 @@ +FROM ghcr.io/gardenlinux/builder:d6d24ba1aec66889a2acab83aedcb00e869abfcd + +RUN sed 's/version="$2"/version=\$(echo \$2 | cut -d. -f 1-2)/' -i /builder/bootstrap diff --git a/VERSION b/VERSION deleted file mode 120000 index e96da460..00000000 --- a/VERSION +++ /dev/null @@ -1 +0,0 @@ -gardenlinux/VERSION \ No newline at end of file diff --git a/VERSION b/VERSION new file mode 100644 index 00000000..e6e7decd --- /dev/null +++ b/VERSION @@ -0,0 +1 @@ +1877.9.1 diff --git a/bin/garden-version b/bin/garden-version deleted file mode 120000 index d88969eb..00000000 --- a/bin/garden-version +++ /dev/null @@ -1 +0,0 @@ -../gardenlinux/bin/garden-version \ No newline at end of file diff --git a/bin/garden-version b/bin/garden-version new file mode 100755 index 00000000..48c2b777 --- /dev/null +++ b/bin/garden-version @@ -0,0 +1,155 @@ +#!/usr/bin/env bash + +# Contains sources from https://github.com/debuerreotype/debuerreotype + +set -Eeuo pipefail +# shellcheck disable=2128 +thisDir="$(dirname "$(readlink -f "${BASH_SOURCE}")")" +versionfile="$(readlink -f "${thisDir}/../VERSION")" +startdate="Mar 31 00:00:00 UTC 2020" +build_os="$(uname -s)" + +function check_command() { + if ! command -v "$1" >/dev/null 2>&1; then + echo "Error: The binary '$1' could not be found. Please make sure to install it." >&2 + exit 1 + fi +} + +# Use "gdate" & sed (GNU) which must be installed by "Homebrew" +# on macOS systems to have a normalized date interface +if [ "Darwin" == "$build_os" ]; then + date_gnu="gdate" + sed_gnu="gsed" +else + date_gnu="date" + sed_gnu="sed" +fi +check_command "$date_gnu" +check_command "$sed_gnu" + +# shellcheck disable=1091 +source "${thisDir}/.constants.sh" \ + --flags 'major,minor,patch,date,datefull,epoch,git' \ + --usage '[ --major | --minor | --patch | --date | --datefull | --epoch | --git ] [|]' \ + --sample '20200427' \ + --sample '--date 27.1' \ + --help "Generates version dependent values according to the file $versionfile or to the parameter handed over. Versions can be converted adequately + +--major prints only the major version +--minor prints only the minor version +--patch prints only the patch/patch version +--date prints the date according to the version e.g. 20200427 if garden-version=27 +--datefull prints a full date deteministically usable by debootstrap +--epoch prints the seconds sinc 19700101 till garden-version +--git prints the version plus the last git-hash + +If no parameter is specified the full version . e.g. 27.5 is printed. The version is taken from $versionfile. On HEAD this should always evaluate to 'today', on branch versions this always should resolve to the next version that will be build e.g. 27.1. This implies there is no branch with a .0 in the $versionfile file. +The version calculated expresses the days since $startdate. Calculation is always UTC based." + +# shellcheck disable=2154 +eval "${dgetopt}" +typeout="default" +while true; do + flag="$1"; shift + dgetopt-case "${flag}" + case "${flag}" in + --major|--minor|--patch|--date|--datefull|--epoch|--git) + typeout="${flag}" ;; + --) break ;; + *) eusage "unknown flag '${flag}'" ;; + esac +done + +# Checks repo.gardenlinux.io for the highest available suite minor for the given major +function get_minor_from_repo { + minor=0 # running index + limit=100 # hard limit the search in case of unexpected curl results + major=$1 # major to check the latest minor for + repo_url="https://packages.gardenlinux.io/gardenlinux/dists/$major.__MINOR__/InRelease" + while [ $minor -le $limit ] + do + check_url=${repo_url//__MINOR__/$minor} + if curl -s "$check_url" | grep -q "Error"; then + ((minor--)) + echo $minor + return + fi + ((minor++)) + done +} + +function get_patch_from_repo { + # TODO: implement if we really expect that we'll ever have a nonzero micro/patch version + local major=$1 + local minor=$2 + if [ "$minor" -eq -1 ]; then + echo -1 + return + fi + echo 0 + return +} + +function trim_when_old_version { + if [ "$1" == "today" ] || [ "$1" == "experimental" ]; then + echo "$1" + return + fi + # HACK just for 1877 for SCI + # shellcheck disable=2046 + if [ $(echo "$1" | cut -d. -f1) -lt 1876 ]; then + echo "$1" | cut -d. -f1-2 + else + echo "$1" + fi +} + +input="${1:-$($sed_gnu -e "s/#.*\$//" -e "/^$/d" "${versionfile}")}"; shift || true +input=$($sed_gnu "s/^[[:space:]]*//;s/[[:space:]]*\$//" <<< "${input}") + +# no version / timestamp on versionfile +[ -z "${input}" ] && input="today" + +minor=0 +patch=0 +# shellcheck disable=2046 +if [[ "${input}" =~ ^[0-9\.]*$ && $(cut -d. -f1 <<< "${input}") -lt 10000000 ]]; +then [ $(cut -d. -sf4 <<< "${input}") ] && eusage "invalid version format ${input}. should be [..]" + + major="$(cut -d. -f1 <<< "${input}")" + # shellcheck disable=2046 + if [ $(cut -d. -sf2 <<< "${input}") ]; then + minor="$(cut -d. -f2 <<< "${input}")" + else + minor=$(get_minor_from_repo "$major") + fi + # shellcheck disable=2046 + if [ $(cut -d. -sf3 <<< "${input}") ]; then + patch="$(cut -d. -f3 <<< "${input}")" + else + patch=$(get_patch_from_repo "$major" "$minor") + fi + version="${major}.${minor}.${patch}" +else + if [[ ${input} = today ]] || [[ ${input} = experimental ]]; + then indate=$($date_gnu --date "today" +%s 2>/dev/null) + major="$(( ("${indate}" - $($date_gnu --date "${startdate}" +%s)) / (60*60*24) ))" + version=${input} + else indate=$($date_gnu --date "${input}" +%s 2>/dev/null) || eusage "invalid date ${input}" + major="$(( ("${indate}" - $($date_gnu --date "${startdate}" +%s)) / (60*60*24) ))" + version="${major}.${minor}.${patch}" + fi +fi + +# shellcheck disable=2154 +case "${typeout}" in + --major) echo "${major}" ;; + --minor) echo "${minor}" ;; + --patch) echo "${patch}" ;; + --date) $date_gnu --date "${startdate} + ${major} days" +%Y%m%d ;; + --datefull) $date_gnu --date "${startdate} + ${major} days" +%Y%m%dT%H%M%SZ ;; + --epoch) $date_gnu --date "${startdate} + ${major} days" +%s ;; + --git) echo "$(trim_when_old_version "${version}")-$(git -C "${scriptsDir}" rev-parse --short 'HEAD^{commit}')" ;; + *) trim_when_old_version "${version}" ;; +esac diff --git a/build b/build deleted file mode 120000 index 9a5480ab..00000000 --- a/build +++ /dev/null @@ -1 +0,0 @@ -gardenlinux/build \ No newline at end of file diff --git a/build b/build new file mode 100755 index 00000000..cc890cd0 --- /dev/null +++ b/build @@ -0,0 +1,128 @@ +#!/usr/bin/env bash + +set -euo pipefail +shopt -s nullglob + +exec 3>&1 +exec 1>&2 + +#container_image=ghcr.io/gardenlinux/builder:d6d24ba1aec66889a2acab83aedcb00e869abfcd +container_image=localhost/builder +container_engine=podman +target_dir=.build + +container_run_opts=( + --memory 4G + --security-opt seccomp=unconfined + --security-opt apparmor=unconfined + --security-opt label=disable + --read-only +) + +container_cmd=() + +use_kms=0 +resolve_cname=0 + +while [ $# -gt 0 ]; do + case "$1" in + --container-image) + container_image="$2" + shift 2 + ;; + --container-engine) + container_engine="$2" + shift 2 + ;; + --container-run-opts) + declare -a "container_run_opts=($2)" + shift 2 + ;; + --privileged) + container_run_opts+=(--privileged) + container_cmd=(--second-stage) + shift + ;; + --kms) + use_kms=1 + shift + ;; + --print-container-image) + printf '%s\n' "$container_image" >&3 + exit 0 + ;; + --resolve-cname) + resolve_cname=1 + shift + ;; + --target) + target_dir="$2" + shift 2 + ;; + *) + break + ;; + esac +done + +[ -d "$target_dir" ] || mkdir "$target_dir" + +container_mount_opts=( + -v "$PWD/keyring.gpg:/builder/keyring.gpg:ro" + -v "$(realpath "$target_dir"):/builder/.build" +) + +for feature in features/*; do + if [ -d "$feature" ]; then + container_mount_opts+=(-v "$(realpath -- "$feature"):/builder/$feature:ro") + fi +done + +if [ "$container_image" = localhost/builder ]; then + dir="$(dirname -- "$(realpath -- "${BASH_SOURCE[0]}")")" + "$container_engine" build -t "$container_image" "$dir" +fi + +repo="$(./get_repo)" +commit="$(./get_commit)" +timestamp="$(./get_timestamp)" +default_version="$(./get_version)" + + +if [ "$resolve_cname" = 1 ]; then + arch="$("$container_engine" run --rm "${container_run_opts[@]}" "${container_mount_opts[@]}" "$container_image" dpkg --print-architecture)" + cname="$("$container_engine" run --rm "${container_run_opts[@]}" "${container_mount_opts[@]}" "$container_image" /builder/parse_features --feature-dir /builder/features --default-arch "$arch" --default-version "$default_version" --cname "$1")" + short_commit="$(head -c 8 <<< "$commit")" + echo "$cname-$short_commit" >&3 + exit 0 +fi + +make_opts=( + REPO="$repo" + COMMIT="$commit" + TIMESTAMP="$timestamp" + DEFAULT_VERSION="$default_version" +) + +if [ "$use_kms" = 1 ]; then + for e in AWS_DEFAULT_REGION AWS_REGION AWS_ACCESS_KEY_ID AWS_SECRET_ACCESS_KEY AWS_SESSION_TOKEN; do + if [ -n "${!e-}" ]; then + make_opts+=("$e=${!e}") + fi + done +fi + +# Default values which can be overriden via 'build.config' file +tempfs_size=2G + +if [[ -f "$PWD"/build.config ]]; then + . "$PWD"/build.config +fi + +make_opts+=("TEMPFS_SIZE=$tempfs_size") + +if [ -d cert ]; then + container_mount_opts+=(-v "$PWD/cert:/builder/cert:ro") +fi + +"$container_engine" run --rm "${container_run_opts[@]}" "${container_mount_opts[@]}" "$container_image" ${container_cmd[@]+"${container_cmd[@]}"} fake_xattr make --no-print-directory -C /builder "${make_opts[@]}" "$@" >&3