From 51198bb298fe7d30085906501c16d2aea55cf0db Mon Sep 17 00:00:00 2001 From: William Petit Date: Tue, 4 Aug 2015 17:45:10 +0200 Subject: [PATCH 1/3] Base nouveau process d'empaquetage --- get-updated-manifest-from-git.sh | 3 +- lib/build.sh | 68 +++++++++++++++++++++----------- lib/hooks/git-prebuild.sh | 1 + package-project.sh | 19 +++++---- src-example/tamarin.json | 9 ++--- 5 files changed, 62 insertions(+), 38 deletions(-) create mode 100644 lib/hooks/git-prebuild.sh diff --git a/get-updated-manifest-from-git.sh b/get-updated-manifest-from-git.sh index c45a5cf..f855d58 100755 --- a/get-updated-manifest-from-git.sh +++ b/get-updated-manifest-from-git.sh @@ -37,11 +37,12 @@ function main { current_version=$(echo "$MANIFEST" | jq -r ".version" | sed 's/null//') current_changelog=$(echo "$MANIFEST" | jq -r ".changelog" | sed 's/null//') current_maintainer=$(echo "$MANIFEST" | jq -r ".maintainer" | sed 's/null//') + timestamp=$(date +%Y%m%d%H%M) # Complete manifest # Add commit number to version - MANIFEST=$(echo "$MANIFEST" | jq -r ".version = \"${current_version:-0.0.0}~$current_commit\"") + MANIFEST=$(echo "$MANIFEST" | jq -r ".version = \"${current_version:-0.0.0}+$timestamp~$current_commit\"") # Set name if not defined MANIFEST=$(echo "$MANIFEST" | jq -r ".name = \"${current_name:-$repo_name}\"") # Set maintainer if not defined diff --git a/lib/build.sh b/lib/build.sh index 9899bd6..70a20e0 100755 --- a/lib/build.sh +++ b/lib/build.sh @@ -1,5 +1,7 @@ #!/usr/bin/env bash +#set -x + DIR=$( cd "$( dirname "${BASH_SOURCE[0]}" )" && pwd ) source "${DIR}/util.sh" @@ -9,7 +11,9 @@ SRC_DIR="${BASE_DIR}/src" function get_project_opt { filter=${1} manifest_path=${SRC_DIR}/tamarin.json - jq -r "${filter}" ${manifest_path} | sed 's/null//g' + if [ -e "${manifest_path}" ]; then + jq -r "${filter}" ${manifest_path} | sed 's/null//g' + fi } function get_build_dir { @@ -25,10 +29,15 @@ function exec_hook { hook_name=${1} build_dir=${2} - hook_script="${SRC_DIR}/$(get_project_opt .hooks.${hook_name})" + hook_script="$(get_project_opt .hooks.${hook_name} | sed 's/null//')" # Test hook script existence - if [ ! -f "${hook_script}" ]; then + # if [ ! -f "${hook_script}" ]; then + # info "No ${hook_name} hook." + # return + # fi + + if [ -z "${hook_script}" ]; then info "No ${hook_name} hook." return fi @@ -36,10 +45,10 @@ function exec_hook { info "Executing ${hook_name} hook..." # Ensure the hook script is executable - chmod +x "${hook_script}" + #chmod +x "${hook_script}" # Execute hook in a subshell - ( cd ${SRC_DIR} && DESTDIR="${build_dir}" SRCDIR="${SRC_DIR}" exec "${hook_script}" ) + ( cd ${SRC_DIR} && DESTDIR="${build_dir}" SRCDIR="${SRC_DIR}" ${hook_script} ) # If the script did not execute properly, we stop here if [ $? != 0 ]; then @@ -70,7 +79,18 @@ function create_debian_control_file { package_arch=$(get_project_opt .arch) echo "Architecture: ${package_arch:-all}" >> "${control_file}" - dependencies=$( get_project_opt ".dependencies | .[\"${DISTRIB}\"] | @sh" | sed "s/' '/, /g" | sed "s/'//g" ) + dependencies=$(get_project_opt ".dependencies | .[\"${DISTRIB}\"]") + + if [ ! -z "${dependencies}" ]; then + dependencies="" + for depKey in $(get_project_opt ".dependencies | .[\"${DISTRIB}\"] | keys | @sh"); do + depKey=$(echo ${depKey} | sed "s/^'\(.*\)'$/\1/"); + depValue=$(get_project_opt ".dependencies | .[\"${DISTRIB}\"] | .[\"${depKey}\"]" | sed "s/^'\(.*\)'$/\1/") + dependencies="${depKey} ($depValue), ${dependencies}" + done + fi + + dependencies=$(echo ${dependencies} | sed 's/,$//') debug "Package dependencies: ${dependencies:-None}" @@ -119,7 +139,8 @@ function create_debian_changelog { debian_dir="${1}" changelog="${debian_dir}/changelog" - logs="$(get_project_opt '.changelog | map(.+"\n") | add')" + logs="$(get_project_opt '.changelog' | sed 's/null//')" + logs="$(echo ${logs:-[]} | jq 'map(.+"\n") | add' | sed 's/null/No information/g')" package_name=$(get_project_opt .name) package_version=$(get_project_opt .version) maintainer=$(get_project_opt .maintainer) @@ -133,7 +154,7 @@ function create_debian_changelog { echo >> "${changelog}" - echo "-- ${maintainer} $(date -R)" >> "${changelog}" + echo "-- ${maintainer:-Unknown} $(date -R)" >> "${changelog}" } @@ -153,40 +174,43 @@ function create_debian_metadata { function build_project { - project_name="$(get_project_opt '.name')" + info "Building project '${PROJECT_NAME}'..." - info "Building project '${project_name}'..." - - build_dir="$(get_build_dir "${project_name}")" + build_dir="$(get_build_dir '${PROJECT_NAME}')" debug "Build dir: ${build_dir}" # We don't generate Debian metadata files if a debian directory is present - if [ ! -d "${SRC_DIR}/DEBIAN" ] && [ ! -d "${SRC_DIR}/debian" ]; then + if [ ! -d "${SRC_DIR}/debian" ]; then info "No Debian directory detected in sources." - info "Generating Debian metadata files from manifest..." + info "Generating Debian metadata files from Tamarin manifest..." create_debian_metadata "${build_dir}" else info "A Debian directory is already present in sources." fi - exec_hook "preBuild" "${build_dir}" + exec_hook "prebuild" "${build_dir}" # Ensure $DIST_DIR exists mkdir -p "${DIST_DIR}" - cd "${build_dir}/.." - dpkg-deb --build "${project_name}" ${DIST_DIR} - - info "Package created ! (${build_dir}/${project_name}.deb)" + cd ${SRC_DIR} + dpkg-buildpackage -us -uc if [ $? != 0 ]; then fatal "The build process has not completed successfuly !" fi - cd ${SRC_DIR} + # Create new directory + mkdir -p "${DIST_DIR}/${PROJECT_NAME}/" - exec_hook "postBuild" "${build_dir}" + # Move generated files + mv ../*.deb "${DIST_DIR}/${PROJECT_NAME}/" + mv ../*.changes "${DIST_DIR}/${PROJECT_NAME}/" + mv ../*.dsc "${DIST_DIR}/${PROJECT_NAME}/" + mv ../*.tar.xz "${DIST_DIR}/${PROJECT_NAME}/" + + exec_hook "postbuild" "${build_dir}" } @@ -194,7 +218,7 @@ function main { manifest_path=${SRC_DIR}/tamarin.json - if [ ! -f "${manifest_path}" ] && [ ! -d "${SRC_DIR}/debian" ] && [ ! -d "${SRC_DIR}/DEBIAN" ]; then + if [ ! -f "${manifest_path}" ] && [ ! -d "${SRC_DIR}/debian" ]; then fatal "There is no 'tamarin.json' nor debian packaging files in the project directory !" fi diff --git a/lib/hooks/git-prebuild.sh b/lib/hooks/git-prebuild.sh new file mode 100644 index 0000000..a9bf588 --- /dev/null +++ b/lib/hooks/git-prebuild.sh @@ -0,0 +1 @@ +#!/bin/bash diff --git a/package-project.sh b/package-project.sh index d68f264..fdf7644 100755 --- a/package-project.sh +++ b/package-project.sh @@ -7,13 +7,13 @@ source "$DIR/lib/util.sh" function show_usage { echo - echo "Usage: $0 " + echo "Usage: $0 src dist [image]" echo echo "Paramètres: " echo - echo " - Chemin vers le répertoire des sources du projet à empaqueter" - echo " - Chemin vers le répertoire de destination du paquet à créer" - echo " - Nom de l'image Docker à utiliser comme base pourl'environnement de build. Exemple: debian:jessie" + echo " - src Chemin vers le répertoire des sources du projet à empaqueter" + echo " - dist Chemin vers le répertoire de destination du paquet à créer" + echo " - image Nom de l'image Docker à utiliser comme base pourl'environnement de build. Défaut: debian:jessie" echo } @@ -37,7 +37,7 @@ function create_container { ENV DEBIAN_FRONTEND noninteractive RUN apt-get update &&\ - apt-get install jq + apt-get install --yes jq build-essential dh-make ADD ./lib /root/.tamarin RUN chmod +x /root/.tamarin/build.sh @@ -64,23 +64,22 @@ function main { info "Building container from $BASE_IMAGE..." container_tag="$(create_container)" + project_name="$(basename "${PROJECT_PATH}")" info "Launching container..." - docker run -e "DISTRIB=$BASE_IMAGE" --rm -v="$PROJECT_PATH:/src" -v="$PROJECT_DIST:/dist" "$container_tag" - - info "Cleaning container data..." + docker run -e "DISTRIB=$BASE_IMAGE" -e "PROJECT_NAME=$project_name" --rm -v="$PROJECT_PATH:/src" -v="$PROJECT_DIST:/dist" "$container_tag" info "Done" } # Test for arguments -if [ -z "$1" ] || [ -z "$2" ] || [ -z "$3" ]; then +if [ -z "$1" ] || [ -z "$2" ]; then show_usage exit 1 fi PROJECT_PATH="$(readlink -f $1)" PROJECT_DIST="$(readlink -f $2)" -BASE_IMAGE="$3" +BASE_IMAGE="${3:-debian:jessie}" main diff --git a/src-example/tamarin.json b/src-example/tamarin.json index 565ecf9..be7a6b0 100644 --- a/src-example/tamarin.json +++ b/src-example/tamarin.json @@ -1,14 +1,13 @@ { "name": "hello-world", "dependencies": { - "debian:jessie": [ - "apache2 (>= 2.4)", - "php5 (>= 5.4)" - ] + "debian:jessie": { + "apache2": ">= 2.4", + "php5": ">= 5.4" + } }, "hooks": { "preBuild": "./scripts/pre-build.sh", - "postBuild": "./scripts/post-build.sh", "preInstall": "./scripts/pre-install.sh", "preRemove": "", "postInstall": "", From 5b0882ce7afbb2358dbca83b251bec0b7cd7e3be Mon Sep 17 00:00:00 2001 From: William Petit Date: Tue, 4 Aug 2015 23:58:43 +0200 Subject: [PATCH 2/3] Basic debian package build with hooks --- hooks/debian/install-build-depends-prebuild | 8 + hooks/git/create-changelog-prebuild | 43 ++++ hooks/tamarin/export-dist-postbuild | 10 + lib/build.sh | 224 +++----------------- lib/hooks/git-prebuild.sh | 1 - lib/util.sh | 18 ++ package-project.sh => package.sh | 23 +- 7 files changed, 121 insertions(+), 206 deletions(-) create mode 100755 hooks/debian/install-build-depends-prebuild create mode 100755 hooks/git/create-changelog-prebuild create mode 100755 hooks/tamarin/export-dist-postbuild delete mode 100644 lib/hooks/git-prebuild.sh rename package-project.sh => package.sh (71%) diff --git a/hooks/debian/install-build-depends-prebuild b/hooks/debian/install-build-depends-prebuild new file mode 100755 index 0000000..f98c2a1 --- /dev/null +++ b/hooks/debian/install-build-depends-prebuild @@ -0,0 +1,8 @@ +#!/bin/bash + +source "${TAMARIN_UTIL}" + +if [ -f debian/control ]; then + info "Installing build dependencies..." + mk-build-deps --install debian/control +fi diff --git a/hooks/git/create-changelog-prebuild b/hooks/git/create-changelog-prebuild new file mode 100755 index 0000000..3fd2633 --- /dev/null +++ b/hooks/git/create-changelog-prebuild @@ -0,0 +1,43 @@ +#!/usr/bin/env bash + +source "${TAMARIN_UTIL}" + +if [ -f debian/changelog ] || [ ! -d .git ]; then + info "Not a Git repository or Debian changelog already exists !" + exit +fi + +if [ -z $(which git) ]; then + info "Installing Git..." + apt-get install --yes --no-install-recommends git-core +fi + +# Get commits log as changelog + +logs=$(git log --pretty=format:"%an - %h : %s" | sed 's/"/\\"/g') + +# Set the top commiter as the maintainer of the project if not defined +top_contributor=$(git log --pretty=short | git shortlog -s -n -e | sed 's/^\s*[0-9]*\s*//g' | head -n 1) +maintainer=$(get_opt maintainer "${top_contributor}") + +project_name=$(get_opt project_name) +version=$(get_opt version 0.0.0) +distribution=$(get_opt distribution UNRELEASED) +urgency=$(get_opt urgency low) + +commit_count=$(git rev-list --count --first-parent HEAD) +current_commit=$(git log -n 1 --pretty=format:"%h") +version_suffix=${commit_count}-${current_commit} + +echo "${project_name} (${version}) ${distribution}; urgency=${urgency}" > debian/changelog + +echo >> debian/changelog + +while read -r entry; do + echo " * ${entry}" >> debian/changelog +done <<< "$(echo -e "${logs}" | sed 's/^"//')" + +echo >> debian/changelog + +echo " -- ${maintainer} $(date -R)" >> debian/changelog +echo >> debian/changelog diff --git a/hooks/tamarin/export-dist-postbuild b/hooks/tamarin/export-dist-postbuild new file mode 100755 index 0000000..cd06a60 --- /dev/null +++ b/hooks/tamarin/export-dist-postbuild @@ -0,0 +1,10 @@ +#!/bin/bash + +# Create new directory +mkdir -p /dist + +# Move generated files +mv ../*.deb /dist +mv ../*.changes /dist +mv ../*.dsc /dist +mv ../*.tar.xz /dist diff --git a/lib/build.sh b/lib/build.sh index 70a20e0..caf9491 100755 --- a/lib/build.sh +++ b/lib/build.sh @@ -1,229 +1,61 @@ #!/usr/bin/env bash -#set -x +LIB_DIR=$( cd "$( dirname "${BASH_SOURCE[0]}" )" && pwd ) +export TAMARIN_UTIL="${LIB_DIR}/util.sh" -DIR=$( cd "$( dirname "${BASH_SOURCE[0]}" )" && pwd ) -source "${DIR}/util.sh" +source "${TAMARIN_UTIL}" DIST_DIR="${BASE_DIR}/dist" SRC_DIR="${BASE_DIR}/src" +HOOKS_DIR="${BASE_DIR}/hooks" -function get_project_opt { - filter=${1} - manifest_path=${SRC_DIR}/tamarin.json - if [ -e "${manifest_path}" ]; then - jq -r "${filter}" ${manifest_path} | sed 's/null//g' - fi -} +function exec_hooks { -function get_build_dir { - project_name="${1}" - temp_dir=$(mktemp -d) - build_dir="${temp_dir}/${project_name}" - mkdir -p "${build_dir}" - echo ${build_dir} -} + hook=${1} + workspace=${2} -function exec_hook { + hook_scripts=$( find "${HOOKS_DIR}" -type f -name "*${hook}" -executable) - hook_name=${1} - build_dir=${2} + for hook_script in ${hook_scripts}; do - hook_script="$(get_project_opt .hooks.${hook_name} | sed 's/null//')" + info "[hook-${hook}] Executing ${hook_script}" - # Test hook script existence - # if [ ! -f "${hook_script}" ]; then - # info "No ${hook_name} hook." - # return - # fi + ( cd "${workspace}" && "${hook_script}" ) - if [ -z "${hook_script}" ]; then - info "No ${hook_name} hook." - return - fi + # If the script did not execute properly, we stop here + if [ $? != 0 ]; then + fatal "The '${hook_script}' hook script did not finished properly !" + fi - info "Executing ${hook_name} hook..." + info "[hook-${hook}] ${hook_script} done." - # Ensure the hook script is executable - #chmod +x "${hook_script}" - - # Execute hook in a subshell - ( cd ${SRC_DIR} && DESTDIR="${build_dir}" SRCDIR="${SRC_DIR}" ${hook_script} ) - - # If the script did not execute properly, we stop here - if [ $? != 0 ]; then - fatal "The '${hook_name}' hook script did not finished properly !" - fi - -} - -function create_debian_control_file { - - debian_dir="${1}" - - control_file="${debian_dir}/control" - touch "${control_file}" - - package_name=$(get_project_opt .name) - echo "Package: ${package_name}" > "${control_file}" - - package_version=$(get_project_opt .version) - echo "Version: ${package_version:-0.0.0}" >> "${control_file}" - - package_section=$(get_project_opt .section) - echo "Section: ${package_section:-unknown}" >> "${control_file}" - - package_priority=$(get_project_opt .priority) - echo "Priority: ${package_priority:-optional}" >> "${control_file}" - - package_arch=$(get_project_opt .arch) - echo "Architecture: ${package_arch:-all}" >> "${control_file}" - - dependencies=$(get_project_opt ".dependencies | .[\"${DISTRIB}\"]") - - if [ ! -z "${dependencies}" ]; then - dependencies="" - for depKey in $(get_project_opt ".dependencies | .[\"${DISTRIB}\"] | keys | @sh"); do - depKey=$(echo ${depKey} | sed "s/^'\(.*\)'$/\1/"); - depValue=$(get_project_opt ".dependencies | .[\"${DISTRIB}\"] | .[\"${depKey}\"]" | sed "s/^'\(.*\)'$/\1/") - dependencies="${depKey} ($depValue), ${dependencies}" - done - fi - - dependencies=$(echo ${dependencies} | sed 's/,$//') - - debug "Package dependencies: ${dependencies:-None}" - - echo "Depends: ${dependencies}" >> "${control_file}" - - package_maintainer=$(get_project_opt .maintainer) - echo "Maintainer: ${package_maintainer:-Unknown}" >> "${control_file}" - - package_description=$(get_project_opt .description) - echo "Description: ${package_description:-No description}" >> "${control_file}" - -} - -function create_debian_hooks { - - debian_dir="${1}" - - pre_install="$(get_project_opt .hooks.preInstall)" - if [ ! -z "${pre_install}" ]; then - cp "${SRC_DIR}/${pre_install}" "${debian_dir}/preinst" - chmod +x "${debian_dir}/preinst" - fi - - post_install="$(get_project_opt .hooks.postInstall)" - if [ ! -z "${post_install}" ]; then - cp "${SRC_DIR}/${post_install}" "${debian_dir}/postinst" - chmod +x "${debian_dir}/postinst" - fi - - pre_remove="$(get_project_opt .hooks.preRemove)" - if [ ! -z "${pre_remove}" ]; then - cp "${SRC_DIR}/${pre_remove}" "${debian_dir}/prerm" - chmod +x "${debian_dir}/prerm" - fi - - post_remove="$(get_project_opt .hooks.postRemove)" - if [ ! -z "${post_remove}" ]; then - cp "${SRC_DIR}/${post_remove}" "${debian_dir}/postrm" - chmod +x "${debian_dir}/postrm" - fi - -} - -function create_debian_changelog { - - debian_dir="${1}" - changelog="${debian_dir}/changelog" - - logs="$(get_project_opt '.changelog' | sed 's/null//')" - logs="$(echo ${logs:-[]} | jq 'map(.+"\n") | add' | sed 's/null/No information/g')" - package_name=$(get_project_opt .name) - package_version=$(get_project_opt .version) - maintainer=$(get_project_opt .maintainer) - - echo "${package_name} (${package_version:-0.0.0}), ${DISTRIB}; urgency=low" > "${changelog}" - echo >> "${changelog}" - - while read -r entry; do - echo " * ${entry}" >> "${changelog}" - done <<< "$(echo -e "${logs}" | sed 's/^"//')" - - echo >> "${changelog}" - - echo "-- ${maintainer:-Unknown} $(date -R)" >> "${changelog}" - -} - -function create_debian_metadata { - - build_dir="${1}" - debian_dir="${build_dir}/DEBIAN" - - # Ensure debian dir exists - mkdir -p "${debian_dir}" - - create_debian_control_file "${debian_dir}" - create_debian_hooks "${debian_dir}" - create_debian_changelog "${debian_dir}" + done } function build_project { - info "Building project '${PROJECT_NAME}'..." + info "Building project ${PROJECT_NAME}..." - build_dir="$(get_build_dir '${PROJECT_NAME}')" + set_opt project_name "${PROJECT_NAME}" - debug "Build dir: ${build_dir}" - - # We don't generate Debian metadata files if a debian directory is present - if [ ! -d "${SRC_DIR}/debian" ]; then - info "No Debian directory detected in sources." - info "Generating Debian metadata files from Tamarin manifest..." - create_debian_metadata "${build_dir}" - else - info "A Debian directory is already present in sources." - fi - - exec_hook "prebuild" "${build_dir}" - - # Ensure $DIST_DIR exists - mkdir -p "${DIST_DIR}" + workspace=$(mktemp -d) + # Copy sources to workspace cd ${SRC_DIR} + cp -r ${SRC_DIR}/. "${workspace}" + + exec_hooks "prebuild" "${workspace}" + + cd "${workspace}" dpkg-buildpackage -us -uc if [ $? != 0 ]; then fatal "The build process has not completed successfuly !" fi - # Create new directory - mkdir -p "${DIST_DIR}/${PROJECT_NAME}/" - - # Move generated files - mv ../*.deb "${DIST_DIR}/${PROJECT_NAME}/" - mv ../*.changes "${DIST_DIR}/${PROJECT_NAME}/" - mv ../*.dsc "${DIST_DIR}/${PROJECT_NAME}/" - mv ../*.tar.xz "${DIST_DIR}/${PROJECT_NAME}/" - - exec_hook "postbuild" "${build_dir}" + exec_hooks "postbuild" "${workspace}" } -function main { - - manifest_path=${SRC_DIR}/tamarin.json - - if [ ! -f "${manifest_path}" ] && [ ! -d "${SRC_DIR}/debian" ]; then - fatal "There is no 'tamarin.json' nor debian packaging files in the project directory !" - fi - - build_project - -} - -main +build_project diff --git a/lib/hooks/git-prebuild.sh b/lib/hooks/git-prebuild.sh deleted file mode 100644 index a9bf588..0000000 --- a/lib/hooks/git-prebuild.sh +++ /dev/null @@ -1 +0,0 @@ -#!/bin/bash diff --git a/lib/util.sh b/lib/util.sh index 8310de4..3596a92 100644 --- a/lib/util.sh +++ b/lib/util.sh @@ -1,5 +1,7 @@ #!/usr/bin/env bash +OPT_FILE="/tmp/.tamarin_opts" + function info { echo "[${HOSTNAME}] [INFO] $@" } @@ -16,3 +18,19 @@ function fatal { echo "[${HOSTNAME}] [FATAL] $@" >&2 exit 1 } + +function get_opt { + opt_name=${1} + default_value=${2} + touch "${OPT_FILE}" + source "${OPT_FILE}" + echo ${!opt_name:-${default_value}} +} + +function set_opt { + opt_name=${1} + opt_value=${2} + touch "${OPT_FILE}" + sed -i "s/^${opt_name}*$//" "${OPT_FILE}" + echo "${opt_name}=\"${opt_value}\"" >> "${OPT_FILE}" +} diff --git a/package-project.sh b/package.sh similarity index 71% rename from package-project.sh rename to package.sh index fdf7644..679b9ef 100755 --- a/package-project.sh +++ b/package.sh @@ -2,8 +2,8 @@ set -e -DIR=$( cd "$( dirname "${BASH_SOURCE[0]}" )" && pwd ) -source "$DIR/lib/util.sh" +TAMARIN_DIR=$( cd "$( dirname "${BASH_SOURCE[0]}" )" && pwd ) +source "$TAMARIN_DIR/lib/util.sh" function show_usage { echo @@ -13,7 +13,7 @@ function show_usage { echo echo " - src Chemin vers le répertoire des sources du projet à empaqueter" echo " - dist Chemin vers le répertoire de destination du paquet à créer" - echo " - image Nom de l'image Docker à utiliser comme base pourl'environnement de build. Défaut: debian:jessie" + echo " - image Optionel - Nom de l'image Docker à utiliser comme base pourl'environnement de build. Défaut: debian:jessie" echo } @@ -27,8 +27,9 @@ function create_container { # Create temporary dir for the Dockerfile temp_dir="$(mktemp -d)" - # Link lib folder - ln -s $(readlink -f "$DIR/lib") "$temp_dir/lib" + # Link lib & hooks folders + ln -s $(readlink -f "$TAMARIN_DIR/lib") "$temp_dir/lib" + ln -s $(readlink -f "$TAMARIN_DIR/hooks") "$temp_dir/hooks" # Create Dockerfile cat << EOF > "$temp_dir/Dockerfile" @@ -37,15 +38,19 @@ function create_container { ENV DEBIAN_FRONTEND noninteractive RUN apt-get update &&\ - apt-get install --yes jq build-essential dh-make + apt-get install --yes build-essential devscripts - ADD ./lib /root/.tamarin - RUN chmod +x /root/.tamarin/build.sh + RUN mkdir /root/.tamarin + RUN mkdir /project + + ADD ./lib /root/.tamarin/lib + ADD ./hooks /hooks + RUN chmod +x /root/.tamarin/lib/build.sh VOLUME /src VOLUME /dist - CMD /root/.tamarin/build.sh + CMD /root/.tamarin/lib/build.sh EOF # Build image From 086142156117711237747c36eb6fd2128d490b41 Mon Sep 17 00:00:00 2001 From: William Petit Date: Wed, 5 Aug 2015 15:49:04 +0200 Subject: [PATCH 3/3] =?UTF-8?q?Empaquetage=20=C3=A0=20partir=20des=20hooks?= =?UTF-8?q?=20ok?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- check-install.sh | 21 +++---- get-updated-manifest-from-git.sh | 78 -------------------------- hooks/git/create-changelog-prebuild | 9 +-- hooks/git/install-git-containerbuild | 3 + lib/build.sh | 30 +--------- lib/install.sh | 4 +- lib/util.sh | 84 +++++++++++++++++++++++----- package.sh | 26 +++++---- 8 files changed, 104 insertions(+), 151 deletions(-) delete mode 100755 get-updated-manifest-from-git.sh create mode 100755 hooks/git/install-git-containerbuild diff --git a/check-install.sh b/check-install.sh index 4902db5..6364a11 100755 --- a/check-install.sh +++ b/check-install.sh @@ -5,23 +5,23 @@ source "$DIR/lib/util.sh" function show_usage { echo - echo "Usage: $0 " + echo "Usage: $0 deb_file [image]" echo echo "Paramètres: " echo - echo " - Chemin vers le paquet Debian dont on doit vérifier l'installation" - echo " - Nom de l'image Docker à utiliser comme environnement pour tester l'installation" + echo " - deb_file Chemin vers le paquet Debian dont on doit vérifier l'installation" + echo " - image Optionnel - Nom de l'image Docker à utiliser comme environnement pour tester l'installation. Défaut: debian:jessie" echo } function create_container { # Escape image name - escaped_basename=$(echo "$BASE_IMAGE" | sed 's/[^a-z0-9\-\_\.]/\_/gi') + local escaped_basename=$(echo "$BASE_IMAGE" | sed 's/[^a-z0-9\-\_\.]/\_/gi') # Generate container tag container_tag="tamarin:${escaped_basename}_$(date +%s)" # Create temporary dir for the Dockerfile - temp_dir="$(mktemp -d)" + local temp_dir="$(mktemp -d)" # Link lib folder ln -s $(readlink -f "$DIR/lib") "$temp_dir/lib" @@ -44,20 +44,17 @@ function create_container { EOF # Build image - tar -C "$temp_dir" -czh . | docker build -t "$container_tag" - 1>&2 + tar -C "$temp_dir" -czh . | docker build -t "$container_tag" - 2> >(error) 1> >(info) # Delete temporary folder rm -rf "$temp_dir" - # Return newly created container's tag - echo $container_tag - } function main { # Create container image - container_tag=$(create_container) + create_container # Run container and install package docker run -e "DISTRIB=$BASE_IMAGE" --rm -v="$DEB_DIR:/deb" "$container_tag" "/deb/$DEB_NAME" @@ -72,7 +69,7 @@ function main { } # Test for arguments -if [ -z "$1" ] || [ -z "$2" ]; then +if [ -z "$1" ]; then show_usage exit 1 fi @@ -80,6 +77,6 @@ fi DEB_PATH=$(readlink -f "$1") DEB_NAME=$(basename "$DEB_PATH") DEB_DIR=$(dirname "$DEB_PATH") -BASE_IMAGE="$2" +BASE_IMAGE="${2:-debian:jessie}" main diff --git a/get-updated-manifest-from-git.sh b/get-updated-manifest-from-git.sh deleted file mode 100755 index f855d58..0000000 --- a/get-updated-manifest-from-git.sh +++ /dev/null @@ -1,78 +0,0 @@ -#!/usr/bin/env bash - -function show_usage { - echo - echo "Usage: $0 " - echo - echo "Paramètres: " - echo - echo " - Chemin vers le répertoire des sources du projet. Le projet doit être un dépôt Git valide." - echo -} - -function main { - - cd "$SRC_DIR" - - if [ ! -d '.git' ]; then - fatal "The directory $SRC_DIR seems not to be a valid Git repository." - fi - - MANIFEST=$(cat tamarin.json 2>/dev/null) - - if [ -z "$MANIFEST" ]; then - MANIFEST="{}" - fi - - # Extract project info from Git - repo_name=$(basename `git rev-parse --show-toplevel`) - current_commit=$(git log -n 1 --pretty=format:"%h") - # Get commits log as changelog - logs=$(git log --pretty=format:"%an - %h : %s" | sed 's/"/\\"/g') - # Set the top commiter as the maintainer of the project - git_maintainer=$(git log --pretty=short | git shortlog -s -n -e | sed 's/^\s*[0-9]*\s*//g' | head -n 1) - - # Get current version from manifest - current_name=$(echo "$MANIFEST" | jq -r ".name" | sed 's/null//') - current_version=$(echo "$MANIFEST" | jq -r ".version" | sed 's/null//') - current_changelog=$(echo "$MANIFEST" | jq -r ".changelog" | sed 's/null//') - current_maintainer=$(echo "$MANIFEST" | jq -r ".maintainer" | sed 's/null//') - timestamp=$(date +%Y%m%d%H%M) - - # Complete manifest - - # Add commit number to version - MANIFEST=$(echo "$MANIFEST" | jq -r ".version = \"${current_version:-0.0.0}+$timestamp~$current_commit\"") - # Set name if not defined - MANIFEST=$(echo "$MANIFEST" | jq -r ".name = \"${current_name:-$repo_name}\"") - # Set maintainer if not defined - MANIFEST=$(echo "$MANIFEST" | jq -r ".maintainer = \"${current_maintainer:-$git_maintainer}\"") - - # Set changelog from git log if not defined - if [ -z "$current_changelog" ]; then - - MANIFEST=$(echo "$MANIFEST" | jq -r ".changelog = []") - - while read -r entry; do - MANIFEST=$(echo "$MANIFEST" | jq -r ".changelog += [\"$entry\"]") - done <<< "$logs" - - fi - - echo "$MANIFEST" - -} - -# Load util lib -DIR=$( cd "$( dirname "${BASH_SOURCE[0]}" )" && pwd ) -source "$DIR/lib/util.sh" - -# Test for arguments -if [ -z "$1" ]; then - show_usage - exit 1 -fi - -SRC_DIR=$(readlink -f "$1") - -main diff --git a/hooks/git/create-changelog-prebuild b/hooks/git/create-changelog-prebuild index 3fd2633..dbd0bcc 100755 --- a/hooks/git/create-changelog-prebuild +++ b/hooks/git/create-changelog-prebuild @@ -7,11 +7,6 @@ if [ -f debian/changelog ] || [ ! -d .git ]; then exit fi -if [ -z $(which git) ]; then - info "Installing Git..." - apt-get install --yes --no-install-recommends git-core -fi - # Get commits log as changelog logs=$(git log --pretty=format:"%an - %h : %s" | sed 's/"/\\"/g') @@ -27,9 +22,9 @@ urgency=$(get_opt urgency low) commit_count=$(git rev-list --count --first-parent HEAD) current_commit=$(git log -n 1 --pretty=format:"%h") -version_suffix=${commit_count}-${current_commit} +version_suffix=${commit_count}~${current_commit} -echo "${project_name} (${version}) ${distribution}; urgency=${urgency}" > debian/changelog +echo "${project_name} (${version}.tamarin${version_suffix}) ${distribution}; urgency=${urgency}" > debian/changelog echo >> debian/changelog diff --git a/hooks/git/install-git-containerbuild b/hooks/git/install-git-containerbuild new file mode 100755 index 0000000..585549f --- /dev/null +++ b/hooks/git/install-git-containerbuild @@ -0,0 +1,3 @@ +#!/usr/bin/env bash + +echo "RUN apt-get install --yes --no-install-recommends git-core" >> Dockerfile diff --git a/lib/build.sh b/lib/build.sh index caf9491..4268f31 100755 --- a/lib/build.sh +++ b/lib/build.sh @@ -7,31 +7,6 @@ source "${TAMARIN_UTIL}" DIST_DIR="${BASE_DIR}/dist" SRC_DIR="${BASE_DIR}/src" -HOOKS_DIR="${BASE_DIR}/hooks" - -function exec_hooks { - - hook=${1} - workspace=${2} - - hook_scripts=$( find "${HOOKS_DIR}" -type f -name "*${hook}" -executable) - - for hook_script in ${hook_scripts}; do - - info "[hook-${hook}] Executing ${hook_script}" - - ( cd "${workspace}" && "${hook_script}" ) - - # If the script did not execute properly, we stop here - if [ $? != 0 ]; then - fatal "The '${hook_script}' hook script did not finished properly !" - fi - - info "[hook-${hook}] ${hook_script} done." - - done - -} function build_project { @@ -39,7 +14,8 @@ function build_project { set_opt project_name "${PROJECT_NAME}" - workspace=$(mktemp -d) + local workspace=$(mktemp -d)/${PROJECT_NAME} + mkdir -p "${workspace}" # Copy sources to workspace cd ${SRC_DIR} @@ -48,7 +24,7 @@ function build_project { exec_hooks "prebuild" "${workspace}" cd "${workspace}" - dpkg-buildpackage -us -uc + dpkg-buildpackage -us -uc 2> >(error) 1> >(info) if [ $? != 0 ]; then fatal "The build process has not completed successfuly !" diff --git a/lib/install.sh b/lib/install.sh index 775793c..68ea518 100644 --- a/lib/install.sh +++ b/lib/install.sh @@ -6,7 +6,7 @@ DIR=$( cd "$( dirname "${BASH_SOURCE[0]}" )" && pwd ) source "${DIR}/util.sh" info "Updating packages definition..." -apt-get update +apt-get update 2> >(error) 1> >(info) info "Installing package $1..." -gdebi --n "$1" +gdebi --n "$1" 2> >(error) 1> >(info) diff --git a/lib/util.sh b/lib/util.sh index 3596a92..cb404e2 100644 --- a/lib/util.sh +++ b/lib/util.sh @@ -1,36 +1,90 @@ #!/usr/bin/env bash -OPT_FILE="/tmp/.tamarin_opts" +HOOKS_DIR="${BASE_DIR}/hooks" +OPT_FILE="${BASE_DIR}/tmp/.tamarin_opts" function info { - echo "[${HOSTNAME}] [INFO] $@" + if [ -z "$@" ]; then + while read str; do + log INFO "${str}" + done + else + log INFO "$@" + fi } function debug { - echo "[${HOSTNAME}] [DEBUG] $@" + if [ -z "$@" ]; then + while read str; do + log DEBUG "${str}" + done + else + log DEBUG "$@" + fi } function error { - echo "[${HOSTNAME}] [ERROR] $@" >&2 + if [ -z "$@" ]; then + while read str; do + log ERROR "${str}" >&2 + done + else + log ERROR "$@" >&2 + fi } function fatal { - echo "[${HOSTNAME}] [FATAL] $@" >&2 + if [ -z "$@" ]; then + while read str; do + log FATAL "${str}" >&2 + done + else + log FATAL "$@" >&2 + fi exit 1 } +function log { + local args=( $@ ) + echo "[${HOSTNAME}] [${args[0]}] ${args[@]:1}" +} + function get_opt { - opt_name=${1} - default_value=${2} - touch "${OPT_FILE}" - source "${OPT_FILE}" - echo ${!opt_name:-${default_value}} + local opt_name=${1} + local default_value=${2} + touch "${OPT_FILE}" + source "${OPT_FILE}" + echo ${!opt_name:-${default_value}} } function set_opt { - opt_name=${1} - opt_value=${2} - touch "${OPT_FILE}" - sed -i "s/^${opt_name}*$//" "${OPT_FILE}" - echo "${opt_name}=\"${opt_value}\"" >> "${OPT_FILE}" + local opt_name=${1} + local opt_value=${2} + touch "${OPT_FILE}" + sed -i "s/^${opt_name}*$//" "${OPT_FILE}" + echo "${opt_name}=\"${opt_value}\"" >> "${OPT_FILE}" +} + +function exec_hooks { + + local hook=${1} + local workspace=${2} + + local hook_scripts=$( find "${HOOKS_DIR}" -type f -name "*${hook}" -executable) + + for hook_script in ${hook_scripts}; do + + info "[${hook}] Executing ${hook_script}" + + ( cd "${workspace}" && "${hook_script}" ) 2> >(error) 1> >(info) + + # If the script did not execute properly, we stop here + if [ $? != 0 ]; then + fatal "The '${hook_script}' hook script did not finished properly !" + fi + + info "[${hook}] ${hook_script} Done." + + done + } diff --git a/package.sh b/package.sh index 679b9ef..252722e 100755 --- a/package.sh +++ b/package.sh @@ -3,7 +3,9 @@ set -e TAMARIN_DIR=$( cd "$( dirname "${BASH_SOURCE[0]}" )" && pwd ) -source "$TAMARIN_DIR/lib/util.sh" + + +BASE_DIR="$TAMARIN_DIR" source "$TAMARIN_DIR/lib/util.sh" function show_usage { echo @@ -21,11 +23,11 @@ function show_usage { function create_container { # Escape image name - escaped_basename=$(echo "$BASE_IMAGE" | sed 's/[^a-z0-9\-\_\.]/\_/gi') + local escaped_basename=$(echo "$BASE_IMAGE" | sed 's/[^a-z0-9\-\_\.]/\_/gi') # Generate container tag container_tag="tamarin:${escaped_basename}_$(date +%s)" # Create temporary dir for the Dockerfile - temp_dir="$(mktemp -d)" + local temp_dir="$(mktemp -d)" # Link lib & hooks folders ln -s $(readlink -f "$TAMARIN_DIR/lib") "$temp_dir/lib" @@ -51,30 +53,34 @@ function create_container { VOLUME /dist CMD /root/.tamarin/lib/build.sh + EOF + exec_hooks "containerbuild" "$temp_dir" + # Build image - tar -C "$temp_dir" -czh . | docker build -t "$container_tag" - 1>&2 + tar -C "$temp_dir" -czh . | docker build -t "$container_tag" - 2> >(error) 1> >(info) # Delete temporary folder rm -rf "$temp_dir" - # Return newly created container's tag - echo $container_tag - } # Main function function main { info "Building container from $BASE_IMAGE..." - container_tag="$(create_container)" - project_name="$(basename "${PROJECT_PATH}")" - info "Launching container..." + # Create container & "$container_tag" variable + create_container + + local project_name="$(basename "${PROJECT_PATH}")" + + info "Switching to container..." docker run -e "DISTRIB=$BASE_IMAGE" -e "PROJECT_NAME=$project_name" --rm -v="$PROJECT_PATH:/src" -v="$PROJECT_DIST:/dist" "$container_tag" info "Done" + } # Test for arguments