Skip to content

Instantly share code, notes, and snippets.

@abailly
Created April 9, 2015 09:07
Show Gist options
  • Star 2 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save abailly/994ee16437b9c7409a39 to your computer and use it in GitHub Desktop.
Save abailly/994ee16437b9c7409a39 to your computer and use it in GitHub Desktop.
Build file including docker containers
{-# LANGUAGE DeriveDataTypeable #-}
import Data.List as L
import Data.Maybe (fromMaybe)
import Data.Monoid ((<>))
import Data.Set
import Data.Typeable
import Development.Shake
import Development.Shake.Command
import Development.Shake.FilePath
import Development.Shake.Util
import GHC.IO.Exception
type Tag = String
-- |Track the uuid of an image, so we can rebuild our part of the chain if a FROM container outside of our project changes
trackImage :: FilePath -> String -> Maybe Tag -> Action ()
trackImage uuidFile image Nothing = do
Stdout stdout <- cmd "docker images " [image]
let uuid = words (last $ lines stdout) !! 2
writeFileChanged uuidFile uuid
trackImage uuidFile image (Just tag) = do
Stdout stdout <- cmd "docker images " [image]
let imgs = L.filter (tag `isInfixOf`) (lines stdout)
case imgs of
[] -> writeFileChanged uuidFile "000000000000"
(img:_) -> let uuid = words img !! 2
in writeFileChanged uuidFile uuid
buildImage :: FilePath -> String -> String -> Action ()
buildImage uuidFile repository image = do
() <- cmd "docker" ["build","--no-cache","-t", imageName, image]
trackImage uuidFile imageName Nothing
where imageName = repository </> image
buildAppImage :: FilePath -> String -> Action ()
buildAppImage uuidFile repository = do
gitCommit <- getEnv "CM_GIT_HASH"
let dockerTag = fromMaybe "latest" gitCommit
let imageName = repository </> "app"
let taggedImage = imageName <> ":" <> dockerTag
() <- cmd "docker" ["build","-t", imageName, "."]
() <- case gitCommit of
Just _ -> cmd "docker" ["tag", "-f", imageName, taggedImage ]
Nothing -> cmd "echo" ["no commit hash passed, only tagged this image with :latest"]
trackImage uuidFile imageName (Just dockerTag)
recursiveNeed :: FilePath -> [FilePattern] -> Action ()
recursiveNeed dir filePatterns = do
files <- getDirectoryFiles dir filePatterns
mapM_ (readFile' . (dir </>)) files
main :: IO ()
main = do
putStrLn "Building Capital Match..."
shakeArgs shakeOptions{shakeFiles="_build/"} $ do
want [ "images/app.uuid"
, "images/nginx.uuid"
, endToEndTest
]
phony "clean" $ do
putNormal "Cleaning files in _build"
removeFilesAfter "_build" ["//*"]
"images/ubuntu.uuid" %> \out -> do
alwaysRerun
() <- cmd "docker pull ubuntu:trusty"
trackImage out "ubuntu" (Just "trusty")
"images/ghc-clojure.uuid" *> \uuidFile -> do
need ["images/ubuntu.uuid", "ghc-clojure/Dockerfile"]
buildImage uuidFile organisation "ghc-clojure"
"images/nginx.uuid" *> \uuidFile -> do
need ["images/ubuntu.uuid", "nginx/Dockerfile","nginx/reload_nginx.sh"]
buildImage uuidFile organisation "nginx"
"images/deps.uuid" *> \uuidFile -> do
need ["images/ghc-clojure.uuid","deps/Dockerfile","deps/project.clj","deps/capital-match.cabal","deps/Setup.hs"]
buildImage uuidFile organisation "deps"
"deps/project.clj" *> \out-> do
let tgt = "ui" </> "project.clj"
need [tgt]
copyFileChanged tgt out
"deps/capital-match.cabal" *> \out-> do
need ["capital-match.cabal"]
copyFileChanged "capital-match.cabal" out
"deps/Setup.hs" *> \out-> do
need ["Setup.hs"]
copyFileChanged "Setup.hs" out
"images/app.uuid" *> \uuidFile -> do
recursiveNeed "ui" ["//*.cljs","//*.clj","//*.html"]
recursiveNeed "src" ["//*.hs"]
recursiveNeed "test" ["//*.hs"]
recursiveNeed "end-to-end-test" ["//*.hs"]
recursiveNeed "main" ["//*.hs"]
need ["images/deps.uuid", "Dockerfile", "ui/project.clj", "404.html"]
buildAppImage uuidFile organisation
"images/devcontainer.uuid" *> \uuidFile -> do
need ["images/app.uuid","devcontainer/Dockerfile","devcontainer/rerun-cabal.sh"]
buildImage uuidFile organisation "devcontainer"
endToEndTest *> \uuidFile -> do
let etedir = "end-to-end-test"
need ["images/devcontainer.uuid","end-to-end-test/Dockerfile",etedir </> "ete-ci.sh"]
recursiveNeed etedir ["//*.hs"]
buildImage uuidFile organisation "end-to-end-test"
etetWithEmacsUuid *> \uuidFile -> do
need [endToEndTest]
let workdir = etetWithEmacs
recursiveNeed workdir ["//*"]
buildImage uuidFile organisation etetWithEmacs
where
endToEndTest = "images/end-to-end-test.uuid"
etetWithEmacs = "etet-withemacs"
organisation = "capitalmatch"
etetWithEmacsUuid =" images" </> etetWithEmacs <> ".uuid"
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment