2

I want to automate pulling git repo and building that repo unattended.

Is there any way I can clone repository and run make immediately after running git clone? Something like:

git clone << myrepo >> && make
4
  • Hi Kos, The question is not duplicate as I tried the solution mentioned in question but does not work with git when git looses connection or fails to clone all objects, other commands still run.
    – Humble
    Commented Dec 30, 2015 at 7:13
  • What did you use? ; or &&?
    – kos
    Commented Dec 30, 2015 at 7:19
  • I used && in the command
    – Humble
    Commented Dec 30, 2015 at 7:20
  • git should return 0 on success and 1 on failure. Run git clone on a valid repository, cut the connection mid-downloading and run echo $?, what's the output?
    – kos
    Commented Dec 30, 2015 at 7:22

1 Answer 1

3

An unattended build after a git clone makes not really sense. Most of the time you'll need to install additional libraries beforehand. Partially also configurations are necessary.

If after these adjustments, the project can be built, then you can automate the process, e.g. after a git pull using git hooks.

To use git hooks, place or link a script with the name post-merge in the .git/hooks folder of the project.

A simple post-merge script looks like this:

#!/bin/bash
./configure
make
sudo make install

I have two examples for you that I use myself. The scripts are not perfect. They are illustrative only.:

A post-merge git hook for the Atom editor

#!/bin/bash
#
# A post-merge git hook for
# https://github.com/atom/atom
#
# ln -s  [your_source_folder]/githooks/post-merge/post-merge_4_atom [your_source_folder]/atom/.git/hooks/post-merge
#

# Trap the INT signal (ctrl-c, for example)
trap trapint 2

packageConfig="package.json"

green="\e[0;32m"
red="\e[0;31m"
TOA="\e[0m" # Turn off character attributes

# Prints OK or FAILED! depending on previous command return value
function okfail () {
  if [ $? -gt 0 ]; then
    logError "There was an error. Aborting."
    return 1
  else
    logInfo "OK"
    return 0
  fi
}

function trapint {
  echo
  echo
  echo "$(basename "$0") SIGINT received"
  cleanup
}

function cleanup {
  echo "Cleaning up..."
  removeRelease
  echo "Bye."
  echo
  exit 1
}

function logInfo () {
  echo -e "${green}$1${TOA}"
}

function logError () {
  echo -e "${red}$1${TOA}"
}

function addRelease () {
  version=$(jshon -e 'version' < "package.json"  | tr -d "\"" | tr -d "\\\\")
  release=$(git log | grep -c "^commit")
  logInfo "Version: $version"
  logInfo "Release: $release"

  newVersion="$version-$release"

  if [ -f "$packageConfig" ]; then
    logInfo "Create backup file $packageConfig.bak"
    cp "$packageConfig" "$packageConfig.bak"
    okfail; [ $? -gt 0 ] && cleanup
    if [ -f "$packageConfig.bak" ]; then
      logInfo "Update $packageConfig with $newVersion"
      sed -i "s/\"version\" *: *\"$version\"/\"version\": \"$newVersion\"/g" "$packageConfig"
      okfail; [ $? -gt 0 ] && cleanup
    fi
  fi
}

function removeRelease () {
  if [ -f "$packageConfig.bak" ]; then
    logInfo "Restore file $packageConfig"
    mv "$packageConfig.bak" "$packageConfig"
    okfail
  fi
}

exec < /dev/tty

while true; do
  read -n 1 -p "Compile and install? [y/n]: " yn
  echo;
  case $yn in
    [Yy]* )

    break;;
    [Nn]* ) exit;;
    * ) echo "Please respond with [y]es or [n]o.";;
  esac
done

cd ~/src/atom

addRelease

echo -e "${green}compile${TOA}"
script/build

echo -e "${green}build debian packge${TOA}"
script/grunt mkdeb

removeRelease

echo -e "${green}You can find the deb package here: \"/tmp/atom-build\"${TOA}"
ls -la /tmp/atom-build

echo -e "${green}Please install with \"sudo dpkg -i /tmp/atom-build/[deb-package]\"${TOA}"

A post-merge script to configure, build and install via checkinstall

#!/bin/bash
#
#    This program is free software; you can redistribute it and/or modify
#    it under the terms of the version 2 of the GNU General Public License
#    as published by the Free Software Foundation
#
#    This program is distributed in the hope that it will be useful,
#    but WITHOUT ANY WARRANTY; without even the implied warranty of
#    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
#    GNU General Public License for more details.
#
#    You should have received a copy of the GNU General Public License
#    along with this program; if not, write to the Free Software
#    Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
#
#    Thanks to Felipe Eduardo Sanchez Diaz Duran <[email protected]>,
#    the author of checkinstall for the many ideas
#
#
# Trap the INT signal (ctrl-c, for example)
trap trapint 2

red="\e[0;31m"
green="\e[0;32m"
yellow="\e[0;33m"
TOA="\e[0m" # Turn off character attributes
bold="\e[0;1m"

# Enable alias expansion in command substitution
shopt -s expand_aliases

# Vefify that we have gettext available
gettext "Bye." &> /dev/null
if [ $? -gt 0 ]; then
  alias ck_gettext="echo -e"
else
  alias ck_gettext="gettext -s --"
fi

## echo with newline at the end
function echog() {
  local format="$1"
  shift
  printf -- "$(ck_gettext "$format")\n" "$@" >&2
}

## echo with NO newline at the end
function   echogn() {
  local format="$1"
  shift
  printf -- "$(ck_gettext "$format")" "$@" >&2
}

# Prints OK or FAILED! depending on previous command return value
function okfail () {
  if [ $? -gt 0 ]; then
    logError "There was an error. Aborting."
    return 1
  else
    logInfo "OK"
    return 0
  fi
}

function logInfo () {
  green="\e[0;32m"
  echog "${green}$1${TOA}"
}

function logWarn () {
  yellow="\e[0;33m"
  echog "${yellow}$1${TOA}"
}

function logError () {
  red="\e[0;31m"
  echog "${red}$1${TOA}"
}

function trapint {
  echo
  echo
  echog "$(basename "$0") SIGINT received"
  cleanup
}

function cleanup {
  echogn "Cleaning up..."
  okfail
  echog "Bye."
  echo
  exit 1
}

function writeDescriptionPak {
  if [ "$1" != "" ]
  then
    echo "$1" > description-pak
  fi
}

function logArchitecture {
  echog "\tArchitecture: ${green}$1${TOA}"
}

function logRequires {
  echog "\tRequires: ${green}$1${TOA}"
}

function logMaintainer {
  echog "\tMaintainer: ${green}$1${TOA}"
}

function logGroup {
  echog "\tGroup: ${green}$1${TOA}"
}

function logSummary {
  echog "\tSummary: ${green}$1${TOA}"
}

function logVersion {
  echog "\tVersion: ${green}$1${TOA}"
}

function logName {
  echog "\tName: ${green}$1${TOA}"
}

function logLicense {
  echog "\tLicense: ${green}$1${TOA}"
}

if [ "$(command -v checkinstall)" == "" ]
then
  logError "checkinstall not installed. Aborting."
  cleanup
fi

if [ "$(command -v jshon)" == "" ]
then
  logError "jshon not installed. Aborting."
  cleanup
fi

isGit="1"
if [ ! -d ".git" ]
then
  logWarn "No GIT project."
  isGit="0"
  #cleanup
fi

autogenParam=""
configureParam=""
checkinstallParam=""

projectBasename=$(basename "${PWD}")
configPath="$HOME/.config/postmergerc/$projectBasename"

# Found an old configuration
if [ -f ".git/hooks/postmergerc" ]
then
  exec < /dev/tty

  while true; do
    read -n 1 -p "Old configuration \".git/hooks/postmergerc\" found. Should I copy it to the new location.? [y/n]: " yn
    echo;
    case $yn in
      [Yy]* ) mv ".git/hooks/postmergerc" "$configPath";
        okfail; [ $? -gt 0 ] && exit 1
      break;;
      [Nn]* )
      break;;
      * ) echo "Please respond with [y]es or [n]o.";;
    esac
  done
fi

if [ ! -f "$configPath" ]
then
  logWarn "\"$configPath\" not found, create a default configuration."
  mkdir -p "$HOME/.config/postmergerc"
  echo -e "{\n \"autogen\": \"\",\n \"configure\": \"\",\n \"make\": \"\",\n \"checkinstall\": \"\"\n}" > "$configPath"
  okfail; [ $? -gt 0 ] && exit 1
else
  logInfo "\"$configPath\" found"

  autogenParam=$(jshon -e 'autogen' < "$configPath" | tr -d "\"" | tr -d "\\\\")
  if [ "$autogenParam" != "" ]; then echog "Additional parameters for ${bold}autogen${TOA}"; echog "\t${green}$autogenParam${TOA}"; fi

  configureParam=$(jshon -e 'configure' < "$configPath" | tr -d "\"" | tr -d "\\\\")
  if [ "$configureParam" != "" ]; then echog "Additional parameters for ${bold}configure${TOA}"; echog "\t${green}$configureParam${TOA}"; fi

  makeParam=$(jshon -e 'make' < "$configPath" | tr -d "\"" | tr -d "\\\\")
  if [ "$makeParam" != "" ]; then echog "Additional parameters for ${bold}make${TOA}"; echog "\t${green}$makeParam${TOA}"; fi

  checkinstallParam=$(jshon -e 'checkinstall' < "$configPath" | tr -d "\"" | tr -d "\\\\")
  if [ "$checkinstallParam" != "" ]; then echog "Additional parameters for ${bold}checkinstall${TOA}"; echog "\t${green}$checkinstallParam${TOA}"; fi
  echo
fi

# GIT
if [ "$isGit" == "1" ]
then
  source=$(git config --get remote.origin.url)
  #name=$(echo $source | gawk -F "/" '{print $5}' | sed -e 's/\.git$//')
  #name=$(git remote -v | head -n1 | awk '{print $2}' | sed -e 's,.*:\(.*/\)\?,,' -e 's/\.git$//')
  name=$(basename $(git config --get remote.$(git config --get branch.master.remote).url) .git)
  gitowner=$(echo "$source" | gawk -F "/" '{ print ( $(NF-1) ) }' | gawk -F ":" '{ print ( $(NF) ) }')
  #release=$(($(git rev-list HEAD --count)))
  release=$(git log | grep -c "^commit")

  responseGitHub=$(curl -s "https://api.github.com/search/repositories?q=+repo:$gitowner/$name")
  responseGitHubError=$(echo "$responseGitHub" | jshon -Q -e "errors")

  if [ "$responseGitHubError" == "" ]
  then
    isGitHub="true"
  else
    isGitHub="false"
  fi
fi

if [ "$(command -v easy_install)" != "" ]
then
  logWarn "The program \"easy_install\" from the package \"python-setuptools\" is installed. This can make problems with \"checkinstall\"."
fi

exec < /dev/tty

#while true; do
#  read -n 1 -p "Show diff? [y/n]: " yn
#  echo;
#  case $yn in
#    [Yy]* ) git diff HEAD^ HEAD;
#    break;;
#    [Nn]* )
#    break;;
#    * ) echo "Please respond with [y]es or [n]o.";;
#  esac
#done

while true; do
  read -n 1 -p "Compile and install $name? [y/n]: " yn
  echo;
  case $yn in
    [Yy]* )

    break;;
    [Nn]* ) exit;;
    * ) echo "Please respond with [y]es or [n]o.";;
  esac
done

if [ -f description-pak ]
then
  logWarn "Delete description-pak"
  if [ -w description-pak ]
  then
    rm description-pak
  else
    sudo rm description-pak
  fi
fi



if [ -f autogen.sh ]
then
  logInfo "Starting autogen.sh"
  ./autogen.sh "$autogenParam"
  okfail; [ $? -gt 0 ] && exit 1
fi

if [ -f autogen.sh ] && [ -f configure ]
then
  exec < /dev/tty

  while true; do
    read -n 1 -p "\"autogen.sh\" and \"configure\" found. Should I also run \"configure\"? [y/n]: " yn
    echo;
    case $yn in
      [Yy]* )  logInfo "Starting configure";
        ./configure "$configureParam"
        okfail; [ $? -gt 0 ] && exit 1
      break;;
      [Nn]* )
      break;;
      * ) echo "Please respond with [y]es or [n]o.";;
    esac
  done
elif [ -f configure ]
then
  logInfo "Starting configure"
  ./configure "$configureParam"
  okfail; [ $? -gt 0 ] && exit 1
fi

if [ -f "Makefile.PL" ]
then
    logInfo "Starting perl Makefile.PL"
    perl Makefile.PL
    okfail; [ $? -gt 0 ] && exit 1
fi

if [ -f "Makefile" ]
then
  optionRule=-1
  while [ "$optionRule" -ne "0" ]
  do
    makeRules=$(grep "^[a-zA-Z_\-]*:" Makefile | cut -d: -f1)
    ruleCount=0
    echog "[$ruleCount] continue with \"make\""

    for rule in $makeRules
    do
      ruleCount=$((ruleCount+1))
      if [ "$rule" == "install" ]
      then
        echogn "[$ruleCount] make $rule"
        echog " ${yellow}(this is a bad idea)${TOA}"
      else
        echog "[$ruleCount] make $rule"
      fi
    done
    logInfo "$ruleCount rules found"
    echogn "Make your choice or hit return to continue with \"make\": "
    read optionRule
    if [ -z "$optionRule" ]
    then
      optionRule=0
    else
      selectedRule=$(echo "$makeRules" | awk NR=="$optionRule")
      logInfo "Starting \"make $selectedRule\""
      make "$selectedRule"
    fi
  done

  logInfo "Starting make"
  if [ "$makeParam" == "" ]
  then
    make
  else
    make "$makeParam"
  fi
  okfail; [ $? -gt 0 ] && exit 1
fi

version=""
maintainer=""
license=""
requires=""
summary=""
group=""
architecture=""
sourceHtmlUrl=""

if [ "$isGitHub" == "true" ]
then
  sourceHtmlUrl=$(echo "$responseGitHub" | jshon -e "items" -e 0 -e "html_url")
fi

####################
# DEBIAN/CHANGELOG
####################
if [ -f "debian/changelog" ]
then
  echog "Search for information via ${bold}debian/changelog${TOA}"

  versionDebianChangelog=$(head -1 "debian/changelog" | gawk -F " " '{print $2}' |  tr -d "()")
  logVersion "$versionDebianChangelog"
  if [ "$version" == "" ]; then version=$versionDebianChangelog; fi
fi

####################
# DEBIAN/CONTROL
####################
if [ -f "debian/control" ]
then
  echog "Search for information via ${bold}debian/control${TOA}"

  architectureDebianControl=$(grep '^ *Architecture *' "debian/control" | gawk -F ":" '{print $2}' |  tr -d " ")
  logArchitecture "$architectureDebianControl"
  if [ "$architecture" == "" ]; then architecture=$architectureDebianControl; fi

  requiresDebianControl=$(grep '^ *Depends *' "debian/control" | gawk -F ":" '{print $2}' |  tr -d " ")
  logRequires "$requiresDebianControl"
  if [ "$requires" == "" ]; then requires=$requiresDebianControl; fi

  maintainerDebianControl=$(grep '^ *Maintainer *' "debian/control" | gawk -F ":" '{print $2}' | sed -e 's/^ *//' -e 's/ *$//')
  logMaintainer "$maintainerDebianControl"
  if [ "$maintainer" == "" ]; then maintainer=$maintainerDebianControl; fi

  groupDebianControl=$(grep '^ *Section *' "debian/control" | gawk -F ":" '{print $2}' | sed -e 's/^ *//' -e 's/ *$//')
  logGroup "$groupDebianControl"
  if [ "$group" == "" ]; then group=$groupDebianControl; fi

  summaryDebianControl=$(grep '^ *Description *' "debian/control" | gawk -F ":" '{print $2}' | sed -e 's/^ *//' -e 's/ *$//')
  logSummary "$summaryDebianControl"
  if [ "$summary" == "" ]
  then
    summary=$summaryDebianControl
    writeDescriptionPak "$summaryDebianControl"
  fi
fi

####################
# MAKEFILE
####################
if [ -f "Makefile" ]
then
  echog "Search for information via ${bold}Makefile${TOA}"

  versionMakefile=$(grep '^ *PACKAGE_VERSION *= *' Makefile | gawk -F "=" '{print $2}' |  tr -d " ")
  logVersion "$versionMakefile"
  if [ "$version" == "" ]; then version=$versionMakefile; fi
fi

####################
# *.DOAP
####################
if [ -f "$name.doap" ]
then
  echog "Search for information via ${bold}$name.doap${TOA}"

  lengthMaintainerDoap=$(xpath -q -e "count(//maintainer)" "$name.doap" 2>/dev/null)
  for ((i = 1; i <= $lengthMaintainerDoap; i++)); do
    if [ "$maintainerDoap" == "" ]
    then
      maintainerDoap="$(xpath -q -e "//maintainer[$i]/foaf:Person/foaf:name/text()" "$name.doap")"
    else
      maintainerDoap="$maintainerDoap, $(xpath -q -e "//maintainer[$i]/foaf:Person/foaf:name/text()" "$name.doap")"
    fi
    maintainerDoap="$maintainerDoap ($(xpath -q -e "string(//maintainer[$i]/foaf:Person/foaf:mbox/@rdf:resource)" "$name.doap" 2>/dev/null | sed 's/^.*mailto:\(.*\)$/\1/'))"
  done
  logMaintainer "$maintainerDoap"
  if [ "$maintainer" == "" ]; then maintainer=$maintainerDoap; fi

  summaryDoap=$(xpath -q -e "*/shortdesc/text()" "$name.doap" | tr -d '\n')
  logSummary "$summaryDoap"
  if [ "$summary" == "" ]
  then
    summary=$summaryDoap
    writeDescriptionPak "$summaryDoap"
  fi
fi

####################
# *.SPEC
####################
if [ -f "$name.spec" ]
then
  echog "Search for information via ${bold}$name.spec${TOA}"

  licenseSpec=$(grep '^ *License *' "$name.spec" | gawk -F ":" '{print $2}' |  tr -d " ")
  logLicense "$licenseSpec"
  if [ "$license" == "" ]; then license=$licenseSpec; fi

  groupSpec=$(grep '^ *Group *' "$name.spec" | gawk -F ":" '{print $2}' |  tr -d " ")
  logGroup "$groupSpec"
  if [ "$group" == "" ]; then group=$groupSpec; fi

  summarySpec=$(grep '^ *Summary *' "$name.spec" | gawk -F ":" '{print $2}' | sed -e 's/^ *//' -e 's/ *$//')
  logSummary "$summarySpec"
  if [ "$summary" == "" ]
  then
    summary=$summarySpec
    writeDescriptionPak "$summarySpec"
  fi

  requiresSpec=$(grep '^ *Requires *' "$name.spec" | gawk -F ":" '{print $2}' |  tr -d " " | tr '\n' ',' | sed -e 's/^,*//' -e 's/,*$//')
  logRequires "$requiresSpec"
  if [ "$requires" == "" ]; then requires=$requiresSpec; fi
fi

####################
# SETUP.PY
####################
if [ -f "setup.py" ]
then
  if [ ! -x "setup.py" ]
  then
    echog "${red}setup.py is not executable. Aborting.${TOA}"
    exit 1
  else
    echog "Search for information via ${bold}setup.py${TOA}"

    maintainerSetupPy="$(./setup.py --author) ($(./setup.py --author-email))"
    logMaintainer "$maintainerSetupPy"
    if [ "$maintainer" == "" ]; then maintainer=$maintainerSetupPy; fi

    versionSetupPy=$(./setup.py --version)
    logVersion "$versionSetupPy"
    if [ "$version" == "" ]; then version=$versionSetupPy; fi

    licenseSetupPy=$(./setup.py --license)
    logLicense "$licenseSetupPy"
    if [ "$license" == "" ]; then license=$licenseSetupPy; fi

    requiresSetupPy=$(./setup.py --requires)
    logRequires "$requiresSetupPy"
    if [ "$requires" == "" ]; then requires=$requiresSetupPy; fi

    summarySetupPy=$(./setup.py --description)
    logSummary "$summarySetupPy"
    if [ "$summary" == "" ]
    then
      summary=$summarySetupPy
      writeDescriptionPak "$summarySetupPy"
    fi
  fi
fi

####################
# GITHUB API
####################
if [ "$isGitHub" == "true" ]
then
  echog "Search for information via ${bold}GitHub-API${TOA}"

  summaryGitHubApi=$(echo "$responseGitHub" | jshon -e "items" -e 0 -e "description" | sed -e 's/^"*//' -e 's/"*$//' | tr -d "\\\\")
  logSummary "$summaryGitHubApi"
  if [ "$summary" == "" ]
  then
    summary=$summaryGitHubApi
    writeDescriptionPak "$summaryGitHubApi"
  fi
fi

####################
# PATH
####################
firstParts=$(echo "$projectBasename" |  awk -F "-" '{ for (i=1; i<NF; i++) printf $i"-"}')
lastPart=$(echo "$projectBasename" | awk -F "-" '{ print $NF }')

if [[ ${lastPart:0:1} =~ ^[0-9] ]]
then
  versionPath=$lastPart
  namePath=${firstParts%?}
else
  versionPath=""
  namePath=$projectBasename
fi

echog "Search for information via ${bold}Path${TOA}"

logVersion "$versionPath"
if [ "$version" == "" ]; then version=$versionPath; fi

logName "$namePath"
if [ "$name" == "" ]; then name=$namePath; fi

####################
# Set standard values if nothing
####################

if [ "$version" == "" ] || [[ ${version:0:1} =~ ^[^0-9] ]]
then
  version="$(date +%Y%m%d)"
fi

if [ "$sourceHtmlUrl" == "" ]
then
  sourceHtmlUrl="$source"
fi

if [ "$name" == "" ]
then
  name=$projectBasename
fi
if [ "$name" == "" ]
then
  name=$(basename $(git config --get remote.$(git config --get branch.master.remote).url) .git)
fi

requires=$(echo "$requires" | tr ',' '\n' | sed 's/\([<<>>==].*\)/(\1)/' | sed -e $'s/((/(/g' | sed -e $'s/))/)/g')
requires=$(echo "$requires" | tr '\n' ',' | sed -e 's/^,*//' -e 's/,*$//')

if [ -f "setup.py" ]
then
  echo
  echog "Install with ${green}checkinstall ... python setup.py install${TOA}"
  sudo checkinstall --spec foo --maintainer \""$maintainer"\" --pkglicense \""$license"\" --pkgname \""$name"\" --pkgrelease \""$release"\" --pkgversion \""$version"\" --pkgsource \""$sourceHtmlUrl"\" --pkggroup \""$group"\" --requires \""$requires"\" --pkgarch \""$architecture"\" $(if [ "$checkinstallParam" != "" ]; then echo "$checkinstallParam"; fi) python setup.py install
else
  echo
  echog "Install with ${green}checkinstall ...${TOA}"
  sudo checkinstall --spec foo --maintainer \""$maintainer"\" --pkglicense \""$license"\" --pkgname \""$name"\" --pkgrelease \""$release"\" --pkgversion \""$version"\" --pkgsource \""$sourceHtmlUrl"\" --pkggroup \""$group"\" --requires \""$requires"\" --pkgarch \""$architecture"\" $(if [ "$checkinstallParam" != "" ]; then echo "$checkinstallParam"; fi)
fi

Not the answer you're looking for? Browse other questions tagged .