diff --git a/lib/build.sh b/lib/build.sh index 9899bd6..f48e264 100755 --- a/lib/build.sh +++ b/lib/build.sh @@ -1,205 +1,41 @@ #!/usr/bin/env bash -DIR=$( cd "$( dirname "${BASH_SOURCE[0]}" )" && pwd ) -source "${DIR}/util.sh" +LIB_DIR=$( cd "$( dirname "${BASH_SOURCE[0]}" )" && pwd ) +export TAMARIN_UTIL="${LIB_DIR}/util.sh" + +source "${TAMARIN_UTIL}" DIST_DIR="${BASE_DIR}/dist" SRC_DIR="${BASE_DIR}/src" +PROJECT_NAME=${1} +BUILD_DIR=${2} -function get_project_opt { - filter=${1} - manifest_path=${SRC_DIR}/tamarin.json - jq -r "${filter}" ${manifest_path} | sed 's/null//g' -} +function build_project() +{ -function get_build_dir { - project_name="${1}" - temp_dir=$(mktemp -d) - build_dir="${temp_dir}/${project_name}" - mkdir -p "${build_dir}" - echo ${build_dir} -} + info "Building project '${PROJECT_NAME}'..." -function exec_hook { + set_opt project_name "${PROJECT_NAME}" + set_opt build_dir "${BUILD_DIR}" - hook_name=${1} - build_dir=${2} + local workspace=$(mktemp -p ${BUILD_DIR} -d)/${PROJECT_NAME} + info "Build dir is ${workspace}" + mkdir -p "${workspace}" + # Copy sources to workspace + cd ${SRC_DIR} + cp -r ${SRC_DIR}/. "${workspace}" - hook_script="${SRC_DIR}/$(get_project_opt .hooks.${hook_name})" + exec_hooks "prebuild" "${workspace}" - # Test hook script existence - if [ ! -f "${hook_script}" ]; then - info "No ${hook_name} hook." - return - fi - - info "Executing ${hook_name} hook..." - - # Ensure the hook script is executable - chmod +x "${hook_script}" - - # Execute hook in a subshell - ( cd ${SRC_DIR} && DESTDIR="${build_dir}" SRCDIR="${SRC_DIR}" exec "${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}\"] | @sh" | sed "s/' '/, /g" | sed "s/'//g" ) - - 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 | map(.+"\n") | add')" - 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} $(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}" - -} - -function build_project { - - project_name="$(get_project_opt '.name')" - - info "Building project '${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 - info "No Debian directory detected in sources." - info "Generating Debian metadata files from 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}" - - cd "${build_dir}/.." - dpkg-deb --build "${project_name}" ${DIST_DIR} - - info "Package created ! (${build_dir}/${project_name}.deb)" + cd "${workspace}" + dpkg-buildpackage -us -uc 2> >(error) 1> >(info) if [ $? != 0 ]; then fatal "The build process has not completed successfuly !" fi - cd ${SRC_DIR} - - 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" ] && [ ! -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/package.sh b/package.sh new file mode 100755 index 0000000..702e59f --- /dev/null +++ b/package.sh @@ -0,0 +1,157 @@ +#!/usr/bin/env bash +set -e + +TAMARIN_DIR=$( cd "$( dirname "${BASH_SOURCE[0]}" )" && pwd ) + + +BASE_DIR="$TAMARIN_DIR" source "$TAMARIN_DIR/lib/util.sh" + +function show_usage { + echo + echo "Usage: $0 -p project_path [-d destination] [-i image] [-k]" + echo + echo "Parameters: " + echo + echo " -p Path to the project to build" + echo " -d Optional : Destination of the builed packages (default ./packages)" + echo " -i Optional : Name of the Docker image to use for build (default: debian:jessie)" + echo " -k Optional : Keep the Docker container after build " + echo " -b Optional : Build directory (default /tmp)" + echo + exit 2 +} + +# Create a build container based on the $BASE_IMAGE argument +function create_container { + # Escape image name + 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 + local temp_dir="$(mktemp -d)" + + local projectName=${1} + local buildDir=${2} + + # 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" + FROM $BASE_IMAGE + + ENV DEBIAN_FRONTEND noninteractive + + RUN apt-get update &&\ + apt-get install --yes build-essential devscripts equivs + + 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 +EOF + + if [[ -z ${BUILD_DIR} ]] + then + echo " CMD /root/.tamarin/lib/build.sh ${projectName} /tmp" >> "$temp_dir/Dockerfile" + else + echo " VOLUME /build" >> "$temp_dir/Dockerfile" + echo " CMD /root/.tamarin/lib/build.sh ${projectName} /build" >> "$temp_dir/Dockerfile" + fi + + + exec_hooks "containerbuild" "$temp_dir" + + # Build image + tar -C "$temp_dir" -czh . | docker build -t "$container_tag" - 2> >(error) 1> >(info) + + # Delete temporary folder + rm -rf "$temp_dir" + +} + +# Main function +function main { + local res=0 + local project_name="$(basename "${PROJECT_PATH}")" + + info "Building container from $BASE_IMAGE..." + + # Create container & "$container_tag" variable + create_container ${project_name} + + local docker_opt="run -e \"DISTRIB=$BASE_IMAGE\" -e \"PROJECT_NAME=$project_name\"" + + if [[ ${PERSIST_CONTAINER} -eq 0 ]] + then + docker_opt="${docker_opt} --rm " + else + docker_opt="${docker_opt}" + fi + + if [[ -z ${BUILD_DIR} ]] + then + docker_opt="${docker_opt} -v=\"$PROJECT_PATH:/src\" -v=\"$PROJECT_DEST:/dist\" $container_tag" + else + docker_opt="${docker_opt} -v=\"$PROJECT_PATH:/src\" -v=\"$PROJECT_DEST:/dist\" -v=\"${BUILD_DIR}:/build\" $container_tag" + fi + + info "Switching to container..." + echo "docker ${docker_opt}" + docker ${docker_opt} + res=${?} + + info "Done" + return ${res} +} + +# +# Parsing options +# +while getopts "kp:d:i:b:" option +do + case $option in + k) + PERSIST_CONTAINER=1 + ;; + p) + PROJECT_PATH=$(readlink -f ${OPTARG}) + ;; + d) + PROJECT_DEST=$(readlink -f ${OPTARG}) + ;; + i) + BASE_IMAGE="${OPTARG}" + ;; + b) + BUILD_DIR=$(readlink -f ${OPTARG}) + ;; + *) + show_usage + ;; + esac +done + +[[ -z ${PROJECT_PATH} ]] && show_usage +[[ -z ${PROJECT_DEST} ]] && PROJECT_DEST=$(readlink -f "./packages") +[[ -z ${BASE_IMAGE} ]] && BASE_IMAGE="debian:jessie" +[[ -z ${PERSIST_CONTAINER} ]] && PERSIST_CONTAINER=0 + +# +# Warn user about "proxy" +# + +if [[ -n ${http_proxy} ]] +then + info "-" + info "[WARN] You have a proxy defined please make sure docker deamon is configured to use this proxy" + info "-" +fi + +main