-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathShakefile.hs
executable file
·155 lines (99 loc) · 4.81 KB
/
Shakefile.hs
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
#!/usr/bin/env stack
{- stack
runghc
--package basic-prelude
--package shake
-}
{-# LANGUAGE NoImplicitPrelude #-}
{-# LANGUAGE OverloadedStrings #-}
import BasicPrelude
import Development.Shake
import Development.Shake.FilePath
main :: IO ()
main = do
-- Call shake with defaults and an updated version on file contents chage.
version <- getHashedShakeVersion [ "Shakefile.hs" ]
shakeArgs shakeOptions { shakeVersion = version } $ do
-- Build the "Dockerfile" file if necessary.
want [ "Dockerfile" ]
-- "dependencies" recipe - Collect "dependencies" files for each project and merge them together.
"dependencies" %> \out -> do
-- List out projects under "projects", tracking the result as a shake dependency.
projects <- getDirectoryDirs "projects"
-- Ensure the projects are sync'd up to origin/master.
let masters = map (\project -> addExtension project "master") projects
need masters
-- Build the "dependencies" file (without versions) for each project if necessary.
let dependencies = map (\project -> addExtension project "dependencies.versionless") projects
need dependencies
-- Merge "dependencies" files for each project.
cmd_ ("sort" :: String) (FileStdout out) ("-u" : dependencies)
-- "*.dependencies" recipe - Collect dependencies for a project.
"*.dependencies" %> \out ->
-- List external dependencies for project without base dependencies.
cmd_ ("stack" :: String) (Cwd ("projects" </> dropExtension out)) (FileStdout out) [ "ls" :: String, "dependencies", "--external", "--no-include-base" ]
-- "*.dependencies.versionless" recipe - Collect dependencies for a project without versions.
"*.dependencies.versionless" %> \out -> do
-- Build the "dependencies" file for each project if necessary.
need [ dropExtension out ]
-- Cut off the version column.
cmd_ ("cut" :: String) (FileStdin (dropExtension out)) (FileStdout out) [ "-d" :: String, " ", "-f1" ]
-- "Dockerfile" recipe - Buld a Dockerfile that builds all dependencies.
"Dockerfile" %> \out -> do
-- Base Docker image to use, read from a file, and trakced as a shake dependency.
from <- readFile' "FROM"
-- Stack resolver to use.
resolver <- readFile' "RESOLVER"
-- Get "dependencies" file contents, remove "rts".
dependencies <- readFileLines "dependencies"
let dependencies' = dependencies \\ [ "rts" ]
-- Write the Dockerfile out.
writeFileLines out $
[ "FROM " <> from
, "RUN stack build --resolver " <> resolver <> " \\"
]
<> map (\dependency -> dependency <> " \\") (init dependencies')
<> [ last dependencies' ]
-- "build" phony recipe - build all of the dependencies locally.
"build" ~> do
-- Stack resolver to use.
resolver <- readFile' "RESOLVER"
-- Get "dependencies" file contents, remove "rts".
dependencies <- readFileLines "dependencies"
let dependencies' = dependencies \\ [ "rts" ]
-- Build all dependencies.
cmd_ ("stack" :: String) ("build" : "--resolver" : resolver : dependencies')
-- "*.master" recipe - If local version does not match remote version, sync up.
"*.master" %> \out -> do
-- Get local version contents to compare with.
local <- readFile' (out -<.> "local")
-- Get remote version contents to compare with.
remote <- readFile' (out -<.> "remote")
-- If local version does not match remote version, sync local version to remote version.
unless (local == remote) $
cmd_ ("git" :: String) (Cwd ("projects" </> dropExtension out)) [ "reset" :: String, "--hard", "origin/master" ]
-- Write out remote version.
writeFileChanged out remote
-- "*.local" recipe - Get local version of project.
"*.local" %> \out ->
-- Find the local origin/master version of the project.
cmd ("git" :: String) (Cwd ("projects" </> dropExtension out)) (FileStdout out) [ "rev-parse" :: String, "origin/master" ]
-- "*.remote" recipe - Get remote version of project.
"*.remote" %> \out -> do
-- Always run this recipe to force remote fetching.
alwaysRerun
-- Fetch from origin, then find remote origin/master version of the project.
cmd_ ("git" :: String) (Cwd ("projects" </> dropExtension out)) [ "fetch" :: String, "origin" ]
cmd ("git" :: String) (Cwd ("projects" </> dropExtension out)) (FileStdout out) [ "rev-parse" :: String, "origin/master" ]
-- "clean" phony recipe - remove generated files.
"clean" ~>
-- Remove Dockerfile and generated files.
removeFilesAfter "."
[ "Dockerfile"
, "dependencies"
, "*.dependencies"
, "*.versionless"
, "*.master"
, "*.local"
, "*.remote"
]