summoner-2.0.0.0: src/Summoner/Template/GitHub.hs
{-# LANGUAGE QuasiQuotes #-}
{-# LANGUAGE ViewPatterns #-}
{-|
Copyright: (c) 2017-2019 Kowainik
SPDX-License-Identifier: MPL-2.0
Maintainer: Kowainik <xrom.xkov@gmail.com>
This module contains template for GitHub related docs:
* @.gitignore@ — static file with all Haskell related ignored files.
* @.github/workflows/ci.yml@ — GitHub acttions for Cabal projects.
* @appveyor.yml@ — Appveyor CI for Cabal or Stack projects.
* @.travis.yml@ — depending on the build tool and supported GHC versions
builds the Travis matrix with all necessary checks, including HLint check.
__NOTE:__ Old GHC versions are included into @allow_failure@ Travis matrix
section for Stack due to Stack limitations with the Cabal version usage on
each GHC. See this issue to track the problem:
+ https://github.com/commercialhaskell/stack/issues/4488
-}
module Summoner.Template.GitHub
( gitHubFiles
) where
import Data.List (delete, intersect)
import NeatInterpolation (text)
import Summoner.Default (defaultCabal, defaultGHC)
import Summoner.GhcVer (GhcVer (..), oldGhcs, showGhcVer)
import Summoner.Settings (Settings (..))
import Summoner.Template.Mempty (memptyIfFalse)
import Summoner.Text (endLine, intercalateMap, tconcatMap)
import Summoner.Tree (TreeFs (..))
gitHubFiles :: Settings -> [TreeFs]
gitHubFiles Settings{..} = concat
[ [File ".gitignore" (gitignoreDefault <> gitignoreCustom) | settingsGitHub]
, [Dir ".github" [ Dir "workflows" [ File "ci.yml" ghActionsYml ]] | settingsGhActions ]
, [File ".travis.yml" travisYml | settingsTravis]
, [File "appveyor.yml" appVeyorYml | settingsAppVeyor]
]
where
-- default .gitignore template
gitignoreDefault :: Text
gitignoreDefault =
[text|
### Haskell
dist
dist-*
cabal-dev
*.o
*.hi
*.chi
*.chs.h
*.dyn_o
*.dyn_hi
*.prof
*.aux
*.hp
*.eventlog
.virtualenv
.hsenv
.hpc
.cabal-sandbox/
cabal.sandbox.config
cabal.config
cabal.project.local
.ghc.environment.*
.HTF/
# Stack
.stack-work/
stack.yaml.lock
### IDE/support
# Vim
[._]*.s[a-v][a-z]
[._]*.sw[a-p]
[._]s[a-v][a-z]
[._]sw[a-p]
*~
tags
# IntellijIDEA
.idea/
.ideaHaskellLib/
*.iml
# Atom
.haskell-ghc-mod.json
# VS
.vscode/
# Emacs
*#
.dir-locals.el
TAGS
# other
.DS_Store
|]
-- additional .gitignore
gitignoreCustom :: Text
gitignoreCustom = if null settingsGitignore
then ""
else unlines ("\n# User specific" : settingsGitignore)
ghActionsYml :: Text
ghActionsYml = [text|
name: CI
# Trigger the workflow on push or pull request, but only for the master branch
on:
pull_request:
push:
branches: [master]
jobs:
build:
name: ghc ${{ matrix.ghc }}
runs-on: ubuntu-16.04
strategy:
matrix:
cabal: ["${defaultCabal}"]
ghc:
${ghActionsVersions}
steps:
- uses: actions/checkout@v2
if: github.event.action == 'opened' || github.event.action == 'synchronize' || github.event.ref == 'refs/heads/master'
- uses: actions/setup-haskell@v1
name: Setup Haskell
with:
ghc-version: ${{ matrix.ghc }}
cabal-version: ${{ matrix.cabal }}
- uses: actions/cache@v1
name: Cache ~/.cabal/store
with:
path: ~/.cabal/store
key: ${{ runner.os }}-${{ matrix.ghc }}-cabal
- name: Build
run: |
$cabalUpdate
$cabalBuild
- name: Test
run: |
${cabalTest}
|]
ghActionsVersions :: Text
ghActionsVersions = intercalateMap
"\n"
(\ghc -> "- " <> ghActionsMatrixItem ghc)
settingsTestedVersions
ghActionsMatrixItem :: GhcVer -> Text
ghActionsMatrixItem v = "\"" <> showGhcVer v <> "\""
-- create travis.yml template
travisYml :: Text
travisYml =
[text|
sudo: true
language: haskell
git:
depth: 5
cabal: "${defaultCabal}"
cache:
directories:
$travisCabalCache
$travisStackCache
matrix:
include:
$travisCabalMtr
$travisStackMtr
$travisStackAllowFailuresMtr
$installAndScript
notifications:
email: false
|]
travisCabalCache, travisStackCache :: Text
travisCabalCache = memptyIfFalse settingsCabal "- \"$HOME/.cabal/store\""
travisStackCache = memptyIfFalse settingsStack
[text|
- "$$HOME/.stack"
- "$$TRAVIS_BUILD_DIR/.stack-work"
|]
travisCabalMtr :: Text
travisCabalMtr = memptyIfFalse settingsCabal $
tconcatMap travisCabalMatrixItem settingsTestedVersions
travisCabalMatrixItem :: GhcVer -> Text
travisCabalMatrixItem (showGhcVer -> ghcV) = [text|- ghc: $ghcV|]
-- Due to the Stack issues with newer Cabal versions TravisCI for 'oldGhcs'
-- can fail. Possible failure jobs are added to the @allow-failures@ section.
travisStackMtr :: Text
travisStackMtr = memptyIfFalse settingsStack $ tconcatMap
travisStackMatrixItem (delete defaultGHC settingsTestedVersions)
<> travisStackMatrixDefaultItem
travisStackAllowFailuresMtr :: Text
travisStackAllowFailuresMtr = memptyIfFalse (settingsStack && not (null old))
[text|
$endLine
allow_failures:
$matrix
|]
where
old :: [GhcVer]
old = settingsTestedVersions `intersect` oldGhcs
matrix :: Text
matrix = tconcatMap travisStackMatrixItem old
travisStackMatrixItem :: GhcVer -> Text
travisStackMatrixItem (showGhcVer -> ghcV) =
[text|
$endLine
- ghc: ${ghcV}
env: STACK_YAML="$$TRAVIS_BUILD_DIR/stack-$ghcV.yaml"
|]
travisStackMatrixDefaultItem :: Text
travisStackMatrixDefaultItem = let defGhc = showGhcVer defaultGHC in
[text|
$endLine
- ghc: ${defGhc}
env: STACK_YAML="$$TRAVIS_BUILD_DIR/stack.yaml"
|]
installAndScript :: Text
installAndScript =
if settingsCabal
then if settingsStack
then installScriptBoth
else installScriptCabal
else installScriptStack
installScriptBoth :: Text
installScriptBoth =
[text|
install:
$hlintCheck
- |
if [ -z "$$STACK_YAML" ]; then
$cabalUpdate
$cabalBuild
else
curl -sSL https://get.haskellstack.org/ | sh
stack --version
$stackBuild
fi
script:
- |
if [ -z "$$STACK_YAML" ]; then
${cabalTest}
else
$stackTest
fi
|]
installScriptCabal :: Text
installScriptCabal =
[text|
install:
$hlintCheck
- $cabalUpdate
- $cabalBuild
script:
- ${cabalTest}
|]
installScriptStack :: Text
installScriptStack =
[text|
install:
$hlintCheck
- curl -sSL https://get.haskellstack.org/ | sh
- stack --version
- $stackBuild
script:
- $stackTest
|]
cabalUpdate :: Text
cabalUpdate = "cabal v2-update"
cabalBuild :: Text
cabalBuild = "cabal v2-build --enable-tests --enable-benchmarks"
cabalTest :: Text
cabalTest = if settingsTest
then "cabal v2-test --enable-tests"
else "echo 'No tests'"
stackBuild :: Text
stackBuild = "stack build --system-ghc --test --bench --no-run-tests --no-run-benchmarks --ghc-options=-Werror"
stackTest :: Text
stackTest = "stack test --system-ghc"
hlintCheck :: Text
hlintCheck =
[text|
# HLint check
- curl -sSL https://raw.github.com/ndmitchell/neil/master/misc/travis.sh | sh -s -- hlint .
|]
appVeyorYml :: Text
appVeyorYml =
if settingsCabal
then appVeyorYmlCabal
else appVeyorYmlStack
appVeyorYmlCabal :: Text
appVeyorYmlCabal = let defGhc = showGhcVer defaultGHC in
[text|
clone_folder: "c:\\WORK"
clone_depth: 5
# Do not build feature branch with open Pull Requests
skip_branch_with_pr: true
platform:
- x86_64
cache:
- "C:\\SR"
- dist-newstyle
environment:
global:
CABOPTS: --store-dir=C:\\SR
matrix:
- GHCVER: $defGhc
install:
- choco source add -n mistuke -s https://www.myget.org/F/mistuke/api/v2
- choco install -y cabal --version 2.4.1.0
- choco install -y ghc --version $defGhc
- refreshenv
before_build:
- cabal --version
- ghc --version
- cabal %CABOPTS% v2-update
build_script:
- cabal %CABOPTS% v2-build --enable-tests
- cabal %CABOPTS% v2-test --enable-tests
|]
-- create appveyor.yml template
appVeyorYmlStack :: Text
appVeyorYmlStack =
[text|
clone_depth: 5
# Do not build feature branch with open Pull Requests
skip_branch_with_pr: true
environment:
STACK_ROOT: C:\sr
STACK_VERSION: 2.1.1
# Workaround a gnarly bug https://github.com/haskell/cabal/issues/5386
# See: https://www.fpcomplete.com/blog/2018/06/sed-a-debugging-story
# TODO: check if it's fixed once we switch to lst-13 and GHC 8.6
TMP: "c:\\tmp"
matrix:
- STACK_YAML: stack.yaml
cache:
- "%STACK_ROOT% -> %STACK_YAML%, appveyor.yml"
- ".stack-work -> %STACK_YAML%, appveyor.yml"
install:
- choco install -y haskell-stack --version %STACK_VERSION%
- stack setup > nul
build_script:
- stack build --test --bench --no-run-tests --no-run-benchmarks --ghc-options=-Werror
test_script:
- stack test
|]