propellor

propellor config for hosts.
git clone git://git.ricketyspace.net/propellor.git
Log | Files | Refs | LICENSE

GitAnnexBuilder.hs (7398B)


      1 {-# LANGUAGE FlexibleContexts #-}
      2 
      3 module Propellor.Property.SiteSpecific.GitAnnexBuilder where
      4 
      5 import Propellor.Base
      6 import qualified Propellor.Property.Apt as Apt
      7 import qualified Propellor.Property.User as User
      8 import qualified Propellor.Property.Cron as Cron
      9 import qualified Propellor.Property.File as File
     10 import qualified Propellor.Property.Systemd as Systemd
     11 import qualified Propellor.Property.Chroot as Chroot
     12 import Propellor.Property.Cron (Times)
     13 
     14 builduser :: UserName
     15 builduser = "builder"
     16 
     17 homedir :: FilePath
     18 homedir = "/home/builder"
     19 
     20 gitbuilderdir :: FilePath
     21 gitbuilderdir = homedir </> "gitbuilder"
     22 
     23 builddir :: FilePath
     24 builddir = gitbuilderdir </> "build"
     25 
     26 type TimeOut = String -- eg, 5h
     27 
     28 type ArchString = String
     29 
     30 autobuilder :: ArchString -> Times -> TimeOut -> Property (HasInfo + DebianLike)
     31 autobuilder arch crontimes timeout = combineProperties "gitannexbuilder" $ props
     32 	& Apt.serviceInstalledRunning "cron"
     33 	& Cron.niceJob "gitannexbuilder" crontimes (User builduser) gitbuilderdir
     34 		("git pull ; timeout " ++ timeout ++ " ./autobuild")
     35 	& rsyncpassword
     36   where
     37 	context = Context ("gitannexbuilder " ++ arch)
     38 	pwfile = homedir </> "rsyncpassword"
     39 	-- The builduser account does not have a password set,
     40 	-- instead use the password privdata to hold the rsync server
     41 	-- password used to upload the built image.
     42 	rsyncpassword :: Property (HasInfo + DebianLike)
     43 	rsyncpassword = withPrivData (Password builduser) context $ \getpw ->
     44 		property "rsync password" $ getpw $ \pw -> do
     45 			have <- liftIO $ catchDefaultIO "" $
     46 				readFileStrict pwfile
     47 			let want = privDataVal pw
     48 			if want /= have
     49 				then makeChange $ writeFile pwfile want
     50 				else noChange
     51 
     52 tree :: ArchString -> Flavor -> Property DebianLike
     53 tree buildarch flavor = combineProperties "gitannexbuilder tree" $ props
     54 	& Apt.installed ["git"]
     55 	& File.dirExists gitbuilderdir
     56 	& File.ownerGroup gitbuilderdir (User builduser) (Group builduser)
     57 	& gitannexbuildercloned
     58 	& builddircloned
     59   where
     60 	gitannexbuildercloned = check (not <$> (doesDirectoryExist (gitbuilderdir </> ".git"))) $
     61 		userScriptProperty (User builduser)
     62 			[ "git clone git://git.kitenet.net/gitannexbuilder " ++ gitbuilderdir
     63 			, "cd " ++ gitbuilderdir
     64 			, "git checkout " ++ buildarch ++ fromMaybe "" flavor
     65 			]
     66 			`assume` MadeChange
     67 			`describe` "gitbuilder setup"
     68 	builddircloned = check (not <$> doesDirectoryExist builddir) $ userScriptProperty (User builduser)
     69 		[ "git clone git://git-annex.branchable.com/ " ++ builddir
     70 		]
     71 
     72 buildDepsApt :: Property DebianLike
     73 buildDepsApt = combineProperties "gitannexbuilder build deps" $ props
     74 	& Apt.buildDep ["git-annex"]
     75 	& buildDepsNoHaskellLibs
     76 	& Apt.buildDepIn builddir
     77 		`describe` "git-annex source build deps installed"
     78 
     79 buildDepsNoHaskellLibs :: Property DebianLike
     80 buildDepsNoHaskellLibs = Apt.installed
     81 	["git", "rsync", "moreutils", "ca-certificates",
     82 	"debhelper", "ghc", "curl", "openssh-client", "git-remote-gcrypt",
     83 	"liblockfile-simple-perl", "locales", "cabal-install", "vim", "less",
     84 	-- needed by haskell libs
     85 	"libxml2-dev", "libidn11-dev", "libgsasl7-dev", "libgnutls28-dev",
     86 	"libmagic-dev", "alex", "happy", "c2hs"
     87 	]
     88 
     89 haskellPkgsInstalled :: String -> Property DebianLike
     90 haskellPkgsInstalled dir = tightenTargets $
     91 	flagFile go ("/haskellpkgsinstalled")
     92   where
     93 	go = userScriptProperty (User builduser)
     94 		[ "cd " ++ builddir ++ " && ./standalone/" ++ dir ++ "/install-haskell-packages"
     95 		]
     96 		`assume` MadeChange
     97 
     98 -- Installs current versions of git-annex's deps from cabal, but only
     99 -- does so once.
    100 cabalDeps :: Property UnixLike
    101 cabalDeps = flagFile go cabalupdated
    102 	where
    103 		go = userScriptProperty (User builduser)
    104 			["cabal update && cabal install git-annex --only-dependencies || true"]
    105 			`assume` MadeChange
    106 		cabalupdated = homedir </> ".cabal" </> "packages" </> "hackage.haskell.org" </> "00-index.cache"
    107 
    108 autoBuilderContainer :: (DebianSuite -> Architecture -> Flavor -> Property (HasInfo + Debian)) -> DebianSuite -> Architecture -> Flavor -> Times -> TimeOut -> Systemd.Container
    109 autoBuilderContainer mkprop suite arch flavor crontime timeout =
    110 	Systemd.container name $ \d -> Chroot.debootstrapped mempty d $ props
    111 		& mkprop suite arch flavor
    112 		& autobuilder (architectureToDebianArchString arch) crontime timeout
    113   where
    114 	name = architectureToDebianArchString arch ++ fromMaybe "" flavor ++ "-git-annex-builder"
    115 
    116 type Flavor = Maybe String
    117 
    118 standardAutoBuilder :: DebianSuite -> Architecture -> Flavor -> Property (HasInfo + Debian)
    119 standardAutoBuilder suite arch flavor =
    120 	propertyList "standard git-annex autobuilder" $ props
    121 		& osDebian suite arch
    122 		& Apt.stdSourcesList
    123 		& Apt.unattendedUpgrades
    124 		& Apt.cacheCleaned
    125 		& User.accountFor (User builduser)
    126 		& tree (architectureToDebianArchString arch) flavor
    127 		& buildDepsApt
    128 
    129 stackAutoBuilder :: DebianSuite -> Architecture -> Flavor -> Property (HasInfo + Debian)
    130 stackAutoBuilder suite arch flavor =
    131 	propertyList "git-annex autobuilder using stack" $ props
    132 		& osDebian suite arch
    133 		& buildDepsNoHaskellLibs
    134 		& Apt.stdSourcesList
    135 		& Apt.unattendedUpgrades
    136 		& Apt.cacheCleaned
    137 		& User.accountFor (User builduser)
    138 		& tree (architectureToDebianArchString arch) flavor
    139 		& stackInstalled
    140 		-- Workaround https://github.com/commercialhaskell/stack/issues/2093
    141 		& Apt.installed ["libtinfo-dev"]
    142 
    143 stackInstalled :: Property DebianLike
    144 stackInstalled = withOS "stack installed" $ \w o ->
    145 	case o of
    146 		(Just (System (Debian Linux (Stable "jessie")) arch)) ->
    147 			ensureProperty w $ manualinstall arch
    148 		_ -> ensureProperty w $ Apt.installed ["haskell-stack"]
    149   where
    150 	-- Warning: Using a binary downloaded w/o validation.
    151 	manualinstall :: Architecture -> Property Linux
    152 	manualinstall arch = tightenTargets $ check (not <$> doesFileExist binstack) $
    153 		propertyList "stack installed from upstream tarball" $ props
    154 			& cmdProperty "wget" [url, "-O", tmptar]
    155 				`assume` MadeChange
    156 			& File.dirExists tmpdir
    157 			& cmdProperty "tar" ["xf", tmptar, "-C", tmpdir, "--strip-components=1"]
    158 				`assume` MadeChange
    159 			& cmdProperty "mv" [tmpdir </> "stack", binstack]
    160 				`assume` MadeChange
    161 			& cmdProperty "rm" ["-rf", tmpdir, tmptar]
    162 				`assume` MadeChange
    163 			& case arch of
    164 				ARMEL -> setupRevertableProperty $
    165 					"/lib/ld-linux-armhf.so.3"
    166 					`File.isSymlinkedTo`
    167 					File.LinkTarget "/lib/ld-linux.so.3"
    168 				_ -> doNothing
    169 	  where
    170 		url = case arch of
    171 			X86_32 -> "https://www.stackage.org/stack/linux-i386"
    172 			X86_64 -> "https://www.stackage.org/stack/linux-x86_64"
    173 			ARMEL -> "https://github.com/commercialhaskell/stack/releases/download/v1.7.1/stack-1.7.1-linux-arm.tar.gz"
    174 			-- Probably not available.
    175 			a -> "https://www.stackage.org/stack/linux-" ++ architectureToDebianArchString a
    176 	binstack = "/usr/bin/stack"
    177 	tmptar = "/root/stack.tar.gz"
    178 	tmpdir = "/root/stack"
    179 
    180 armAutoBuilder :: (DebianSuite -> Architecture -> Flavor -> Property (HasInfo + Debian)) -> DebianSuite -> Architecture -> Flavor -> Property (HasInfo + Debian)
    181 armAutoBuilder baseautobuilder suite arch flavor =
    182 	propertyList "arm git-annex autobuilder" $ props
    183 		& baseautobuilder suite arch flavor
    184 		-- Works around ghc crash with parallel builds on arm.
    185 		& File.dirExists (homedir </> ".cabal")
    186 		& (homedir </> ".cabal" </> "config")
    187 			`File.containsLine` "jobs: 1"
    188 		-- Work around https://github.com/systemd/systemd/issues/7135
    189 		& Systemd.containerCfg "--system-call-filter=set_tls"