Skip to content

Commit

Permalink
Add library files (#1)
Browse files Browse the repository at this point in the history
  • Loading branch information
shahidhk authored Jun 13, 2019
2 parents 512f07d + 09eee77 commit ad6df73
Show file tree
Hide file tree
Showing 9 changed files with 465 additions and 1 deletion.
1 change: 1 addition & 0 deletions .gitignore
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
ci-info.cabal
dist
dist-*
cabal-dev
Expand Down
19 changes: 18 additions & 1 deletion README.md
Original file line number Diff line number Diff line change
@@ -1,2 +1,19 @@
# ci-info-hs
Get details about the current Continuous Integration environment - Haskell port of https://github.com/watson/ci-info

Checks if the current environment is a Continuous Integration server.

This is a Haskell port of [watson/ci-info](https://github.com/watson/ci-info).

## Usage

Check if the current environment is a CI server:

```haskell
isCI :: IO Bool
```

Get the name of the CI vendor. Returns `Nothing` if no CI could be detected. Returns `Just CI_UNKNOWN_VENDOR` if a CI was detected, but the vendor name could not be determined:

```haskell
getCI :: IO (Maybe CI)
```
3 changes: 3 additions & 0 deletions Setup.hs
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
import Distribution.Simple

main = defaultMain
36 changes: 36 additions & 0 deletions package.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,36 @@
name: ci-info
version: 0.1.0.0
github: "hasura/ci-info-hs"
license: MIT
author: "Ajeet D'Souza"
maintainer: "[email protected]"
copyright: "2019 Hasura Inc."

extra-source-files:
- README.md

description: Please see the README on GitHub at <https://github.com/hasura/ci-info-hs#readme>

dependencies:
- base >= 4.7 && < 5
- aeson
- aeson-casing
- hashable
- template-haskell
- th-lift-instances
- text
- unordered-containers

ghc-options:
- -Wall
- -Wincomplete-uni-patterns
- -Wincomplete-record-updates
- -Wcompat
- -Widentities
- -Wredundant-constraints
- -Wmissing-export-lists
- -Wpartial-fields

library:
exposed-modules: CI
source-dirs: src
159 changes: 159 additions & 0 deletions res/vendors.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,159 @@
[
{
"name": "AppVeyor",
"constant": "APPVEYOR",
"env": "APPVEYOR",
"pr": "APPVEYOR_PULL_REQUEST_NUMBER"
},
{
"name": "Azure Pipelines",
"constant": "AZURE_PIPELINES",
"env": "SYSTEM_TEAMFOUNDATIONCOLLECTIONURI",
"pr": "SYSTEM_PULLREQUEST_PULLREQUESTID"
},
{
"name": "Bamboo",
"constant": "BAMBOO",
"env": "bamboo_planKey"
},
{
"name": "Bitbucket Pipelines",
"constant": "BITBUCKET",
"env": "BITBUCKET_COMMIT",
"pr": "BITBUCKET_PR_ID"
},
{
"name": "Bitrise",
"constant": "BITRISE",
"env": "BITRISE_IO",
"pr": "BITRISE_PULL_REQUEST"
},
{
"name": "Buddy",
"constant": "BUDDY",
"env": "BUDDY_WORKSPACE_ID",
"pr": "BUDDY_EXECUTION_PULL_REQUEST_ID"
},
{
"name": "Buildkite",
"constant": "BUILDKITE",
"env": "BUILDKITE",
"pr": { "env": "BUILDKITE_PULL_REQUEST", "ne": "false" }
},
{
"name": "CircleCI",
"constant": "CIRCLE",
"env": "CIRCLECI",
"pr": "CIRCLE_PULL_REQUEST"
},
{
"name": "Cirrus CI",
"constant": "CIRRUS",
"env": "CIRRUS_CI",
"pr": "CIRRUS_PR"
},
{
"name": "AWS CodeBuild",
"constant": "CODEBUILD",
"env": "CODEBUILD_BUILD_ARN"
},
{
"name": "Codeship",
"constant": "CODESHIP",
"env": { "CI_NAME": "codeship" }
},
{
"name": "Drone",
"constant": "DRONE",
"env": "DRONE",
"pr": { "DRONE_BUILD_EVENT": "pull_request" }
},
{
"name": "dsari",
"constant": "DSARI",
"env": "DSARI"
},
{
"name": "GitLab CI",
"constant": "GITLAB",
"env": "GITLAB_CI"
},
{
"name": "GoCD",
"constant": "GOCD",
"env": "GO_PIPELINE_LABEL"
},
{
"name": "Hudson",
"constant": "HUDSON",
"env": "HUDSON_URL"
},
{
"name": "Jenkins",
"constant": "JENKINS",
"env": ["JENKINS_URL", "BUILD_ID"],
"pr": { "any": ["ghprbPullId", "CHANGE_ID"] }
},
{
"name": "Magnum CI",
"constant": "MAGNUM",
"env": "MAGNUM"
},
{
"name": "Netlify CI",
"constant": "NETLIFY",
"env": "NETLIFY_BUILD_BASE",
"pr": { "env": "PULL_REQUEST", "ne": "false" }
},
{
"name": "Nevercode",
"constant": "NEVERCODE",
"env": "NEVERCODE",
"pr": { "env": "NEVERCODE_PULL_REQUEST", "ne": "false" }
},
{
"name": "Sail CI",
"constant": "SAIL",
"env": "SAILCI",
"pr": "SAIL_PULL_REQUEST_NUMBER"
},
{
"name": "Semaphore",
"constant": "SEMAPHORE",
"env": "SEMAPHORE",
"pr": "PULL_REQUEST_NUMBER"
},
{
"name": "Shippable",
"constant": "SHIPPABLE",
"env": "SHIPPABLE",
"pr": { "IS_PULL_REQUEST": "true" }
},
{
"name": "Solano CI",
"constant": "SOLANO",
"env": "TDDIUM",
"pr": "TDDIUM_PR_ID"
},
{
"name": "Strider CD",
"constant": "STRIDER",
"env": "STRIDER"
},
{
"name": "TaskCluster",
"constant": "TASKCLUSTER",
"env": ["TASK_ID", "RUN_ID"]
},
{
"name": "TeamCity",
"constant": "TEAMCITY",
"env": "TEAMCITY_VERSION"
},
{
"name": "Travis CI",
"constant": "TRAVIS",
"env": "TRAVIS",
"pr": { "env": "TRAVIS_PULL_REQUEST", "ne": "false" }
}
]
59 changes: 59 additions & 0 deletions src/CI.hs
Original file line number Diff line number Diff line change
@@ -0,0 +1,59 @@
{-# LANGUAGE OverloadedStrings #-}
{-# LANGUAGE TemplateHaskell #-}

module CI
( Types.CI(..)
, isCI
, getCI
) where

import Control.Arrow ((***))
import Data.Bool (bool)
import Data.Foldable (find)
import Data.Maybe (isJust)
import System.Environment (getEnvironment)

import CI.TH (getVendors)

import qualified Data.HashMap.Strict as HashMap
import qualified Data.Text as T

import qualified CI.Types as Types


vendors :: [Types.Vendor]
vendors = $(getVendors)

getCI :: IO (Maybe Types.CI)
getCI = do
env <- mkEnvMap <$> getEnvironment
let maybeVendor = find (checkVendor env) vendors
return
$ case maybeVendor of
Nothing -> bool Nothing (Just Types.CI_UNKNOWN_VENDOR)
$ checkUnknownVendor env
Just vendor -> Just $ Types.vendorConstant vendor
where
checkVendor env vendor = case Types.vendorEnv vendor of
(Types.VendorEnvString text) -> HashMap.member text env
(Types.VendorEnvList list) -> all (`HashMap.member` env) list
(Types.VendorEnvObject hashMap) -> all
(\(k, v) -> HashMap.lookup k env == Just v)
$ HashMap.toList hashMap

-- check vendor neutral environment variables
checkUnknownVendor env = any (`HashMap.member` env) unknownVendorEnvVars

unknownVendorEnvVars = map
Types.EnvVarName
[ "CI" -- Travis CI, CircleCI, Cirrus CI, Gitlab CI, Appveyor, CodeShip, dsari
, "CONTINUOUS_INTEGRATION" -- Travis CI, Cirrus CI
, "BUILD_NUMBER" -- Jenkins, TeamCity
, "RUN_ID" -- TaskCluster, dsari
]

mkEnvMap = HashMap.fromList
. map (Types.EnvVarName . T.pack *** Types.EnvVarValue . T.pack)

isCI :: IO Bool
isCI = isJust <$> getCI
22 changes: 22 additions & 0 deletions src/CI/TH.hs
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
module CI.TH
( getVendors
) where

import qualified Data.Aeson as Aeson
import qualified Language.Haskell.TH as TH
import qualified Language.Haskell.TH.Syntax as TH

import qualified CI.Types as Types


getVendors :: TH.Q TH.Exp
getVendors = TH.runIO readVendors >>= TH.lift
where
vendorsPath = "res/vendors.json"

readVendors :: IO [Types.Vendor]
readVendors = do
vendors <- Aeson.eitherDecodeFileStrict' vendorsPath
case vendors of
Left e -> fail $ "parsing vendors.json failed: " <> e
Right v -> return v
Loading

0 comments on commit ad6df73

Please sign in to comment.