1 /++ 2 + Copyright: Copyright © 2018, Christian Köstlin 3 + License: MIT 4 + Authors: Christian Koestlin 5 +/ 6 7 module ponies.dlang.travis; 8 9 import dyaml; 10 import ponies.dlang; 11 import ponies; 12 import std.algorithm; 13 import std.conv; 14 import std.experimental.logger; 15 import std..string; 16 17 abstract class TravisDlangPony : DlangPony 18 { 19 private Node root; 20 private bool upToDate = false; 21 22 /++ 23 + Do the change on the root node and return if something was changed. 24 + Return: true if something was changed 25 +/ 26 protected abstract bool change(ref Node root); 27 28 override CheckStatus check() 29 { 30 root = Loader(travisYml).load; 31 upToDate = !change(root); 32 return upToDate.to!CheckStatus; 33 } 34 35 override void run() 36 { 37 if (!upToDate) 38 { 39 "Writing new %s".format(travisYml).warning; 40 Dumper(travisYml).dump(root); 41 } 42 } 43 } 44 45 class LanguageTravisDlangPony : TravisDlangPony 46 { 47 override string name() 48 { 49 return "Setup travis to work with language d"; 50 } 51 52 override bool change(ref Node root) 53 { 54 auto language = "language" in root; 55 if (language) 56 { 57 if (language.isScalar) 58 { 59 if (language.as!string == "d") 60 { 61 return false; 62 } 63 } 64 } 65 root["language"] = "d"; 66 return true; 67 } 68 } 69 70 class CompilerTravisDlangPony : TravisDlangPony 71 { 72 override string name() 73 { 74 return "Setup dmd and ldc as compilers"; 75 } 76 77 override bool change(ref Node root) 78 { 79 auto dNode = "d" in root; 80 if (dNode) 81 { 82 bool modified = false; 83 if (dNode.isScalar) 84 { 85 root["d"] = Node([*dNode]); 86 "Converting d node to array".warning; 87 modified = true; 88 } 89 90 dNode = "d" in root; 91 if (!dNode.sequence!string.canFind("dmd")) 92 { 93 dNode.add(Node("dmd")); 94 root["d"] = *dNode; 95 "Adding dmd".warning; 96 modified = true; 97 } 98 if (!dNode.sequence!string.canFind("ldc")) 99 { 100 dNode.add(Node("ldc")); 101 root["d"] = *dNode; 102 "Adding ldc".warning; 103 modified = true; 104 } 105 return modified; 106 } 107 else 108 { 109 root["d"] = Node([Node("dmd"), Node("ldc")]); 110 "Adding new node with dmd and ldc".warning; 111 return true; 112 } 113 } 114 } 115 116 class NoSudoTravisDlangPony : TravisDlangPony 117 { 118 override string name() 119 { 120 return "Setup travis to not run as sudo"; 121 } 122 123 override bool change(ref Node root) 124 { 125 auto sudo = "sudo" in root; 126 if (sudo) 127 { 128 if (sudo.as!string != "false") 129 { 130 root["sudo"] = false; 131 return true; 132 } 133 return false; 134 } 135 else 136 { 137 root["sudo"] = false; 138 return true; 139 } 140 } 141 } 142 143 class GhPagesTravisDlangPony : TravisDlangPony 144 { 145 override string name() 146 { 147 return "Setup travis to autodeploy ddox to ghpages"; 148 } 149 150 override bool change(ref Node root) 151 { 152 return addNeededPackages(root) || addDdoxBuildScript(root) || addDeployNode(root); 153 } 154 155 private bool addDeployNode(ref Node root) 156 { 157 auto deploy = "deploy" in root; 158 if (!deploy) 159 { 160 "Adding deploy node".warning; 161 // dfmt off 162 root["deploy"] = 163 Node(["provider" : Node("pages"), 164 "skip-cleanup" : Node(true), 165 "local-dir" : Node("docs"), 166 "github-token" : Node("$GH_REPO_TOKEN"), 167 "verbose" : Node(true), 168 "keep-history" : Node(true), 169 "on" : Node(["branch" : "master"])]); 170 // dfmt on 171 return true; 172 } 173 return false; 174 } 175 176 private bool addDdoxBuildScript(ref Node root) 177 { 178 const buildDdox = "dub build --compiler=${DC} --build=ddox"; 179 auto script = "script" in root; 180 if (!script) 181 { 182 "Adding ddox build script".warning; 183 root["script"] = Node([buildDdox]); 184 return true; 185 } 186 187 if (script.isScalar) 188 { 189 "Changing script node".warning; 190 191 if (script.as!string != buildDdox) 192 { 193 root["script"] = Node([script.as!string, buildDdox]); 194 } 195 else 196 { 197 root["script"] = Node([buildDdox]); 198 } 199 return true; 200 } 201 202 if (!script.sequence!string.canFind("dub build --compiler=${DC} --build=ddox")) 203 { 204 "Adding ddox script".warning; 205 script.add("dub build --compiler=${DC} --build=ddox"); 206 root["script"] = *script; 207 return true; 208 } 209 return false; 210 } 211 212 private bool addNeededPackages(ref Node root) 213 { 214 auto addons = "addons" in root; 215 if (!addons) 216 { 217 "Adding addons node".warning; 218 root["addons"] = Node(["apt" : Node(["packages" : Node(["libevent-dev"])])]); 219 return true; 220 } 221 222 if (addons.isScalar) 223 { 224 "Changing addons node".warning; 225 root["addons"] = Node(["apt" : Node(["packages" : Node(["libevent-dev"])])]); 226 return true; 227 } 228 229 auto apt = "apt" in root["addons"]; 230 if (!apt) 231 { 232 root["addons"]["apt"] = Node(["packages" : Node(["libevent-dev"])]); 233 return true; 234 } 235 236 if (apt.isScalar) 237 { 238 "Changing addons.apt node".warning; 239 root["addons"]["apt"] = Node(["packages" : Node(["libevent-dev"])]); 240 return true; 241 } 242 243 auto packages = "packages" in root["addons"]["apt"]; 244 if (!packages) 245 { 246 "Adding packages to addons.apt".warning; 247 root["addons"]["apt"]["packages"] = Node(["libevent-dev"]); 248 return true; 249 } 250 251 if (packages.isScalar) 252 { 253 "Changing addons.apt.packages".warning; 254 root["addons"]["apt"]["packages"] = Node(["libevent-dev"]); 255 return true; 256 } 257 258 if (!packages.sequence!string.canFind("libevent-dev")) 259 { 260 "Adding libevent-dev to addons.apt.packages".warning; 261 packages.add("libevent-dev"); 262 root["addons"]["apt"]["packages"] = *packages; 263 return true; 264 } 265 266 return false; 267 } 268 } 269 270 /+ 271 class TravisPony : DlangPony 272 { 273 override string name() 274 { 275 return "Setup travis build in %s".format(travisYml); 276 } 277 278 override CheckStatus check() 279 { 280 return exists(travisYml).to!CheckStatus; 281 } 282 283 override void run() 284 { 285 "Creating %s file".format(travisYml).info; 286 "userinteraction:Please get gh repo token from https://github.com/settings/tokens".warning; 287 "userinteraction:Please enable travis build".warning; 288 "userinteraction:Please enable coverage on codecov".warning; 289 auto content = "language: d 290 d: 291 - dmd 292 - ldc 293 addons: 294 apt: 295 packages: 296 - libevent-dev 297 before_install: pip install --user codecov 298 script: 299 - dub test --compiler=${DC} --coverage 300 - dub build --build=release 301 - dub build --build=ddox 302 after_success: codecov 303 deploy: 304 provider: pages 305 skip-cleanup: true 306 local-dir: \"docs\" 307 github-token: \"$GH_REPO_TOKEN\" 308 verbose: true 309 keep-history: true 310 on: 311 branch: master 312 env: 313 global: 314 secure: create this token with 'travis encrypt GH_REPO_TOKEN=key from https://github.com/settings/tokens' 315 "; 316 std.file.write(travisYml, content); 317 } 318 } 319 +/