Skip to content
This repository was archived by the owner on Aug 1, 2023. It is now read-only.

Commit 4899e1d

Browse files
authored
Merge pull request #10 from input-output-hk/rvl/buildkite
Buildkite pipeline with stack rebuild
2 parents dfbefc1 + 382459f commit 4899e1d

File tree

8 files changed

+235
-1
lines changed

8 files changed

+235
-1
lines changed

.buildkite/pipeline.yml

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,14 @@
11
steps:
22
- label: 'nix build'
33
command: 'nix-build release.nix'
4+
- label: 'stack rebuild'
5+
env:
6+
AWS_REGION: us-west-1
7+
S3_BUCKET: appveyor-ci-cache
8+
CACHE_S3_MAX_SIZE: 2500MB
9+
STACK_ROOT: "/build/cardano-shell.stack"
10+
command:
11+
- "nix-build scripts/buildkite -o stack-rebuild"
12+
- "./stack-rebuild --build-dir /build/cardano-shell --base-branch develop"
413
agents:
514
system: x86_64-linux

README.md

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,7 @@
11
# cardano-shell
22

3+
[![Build status](https://badge.buildkite.com/5e4cd5ff2fd87975136914d037c409618deb4d8ed6579f8635.svg)](https://buildkite.com/input-output-hk/cardano-shell)
4+
35
This is the `cardano-shell` project.
46
This project uses Github issues for tracking the project progress.
57

nix/fetch-nixpkgs.nix

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,6 @@
1+
let
2+
spec = builtins.fromJSON (builtins.readFile ./nixpkgs-src.json);
3+
in builtins.fetchTarball {
4+
url = "${spec.url}/archive/${spec.rev}.tar.gz";
5+
inherit (spec) sha256;
6+
}

nix/nixpkgs-src.json

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,6 @@
1+
{
2+
"url": "https://github.com/NixOS/nixpkgs",
3+
"rev": "3f5f9eda9d00f076140906f316554735c18c93d4",
4+
"sha256": "1rmc879rvkb9dm5bd2a1jwrk3sv8bbispbjkb9dnhma7fqwbm6gg",
5+
"fetchSubmodules": false
6+
}

scripts/buildkite/cache-s3.nix

Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,25 @@
1+
{ stdenv, fetchurl, zlib, gmp }:
2+
3+
stdenv.mkDerivation rec {
4+
name = "cache-s3-${version}";
5+
version = "v0.1.6";
6+
src = fetchurl {
7+
url = "https://github.com/fpco/cache-s3/releases/download/${version}/cache-s3-${version}-linux-x86_64.tar.gz";
8+
sha256 = "01qm6mg11g6kq3sfnnj1civmda35mbfmp1fym5yvqwbdsmqd0b19";
9+
};
10+
libPath = stdenv.lib.makeLibraryPath [
11+
stdenv.cc.cc.lib
12+
zlib
13+
gmp
14+
];
15+
sourceRoot = ".";
16+
buildPhase = "true";
17+
installPhase = ''
18+
mkdir -p $out/bin
19+
install -m 0755 cache-s3 $out/bin
20+
'';
21+
postFixup = ''
22+
patchelf --set-interpreter "$(cat $NIX_CC/nix-support/dynamic-linker)" $out/bin/cache-s3
23+
patchelf --set-rpath ${libPath} $out/bin/cache-s3
24+
'';
25+
}

scripts/buildkite/default.nix

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,20 @@
1+
{ pkgs ? import (import ../../nix/fetch-nixpkgs.nix) { }
2+
, buildTools ? with pkgs; [ git nix gnumake ]
3+
}:
4+
5+
with pkgs.lib;
6+
with pkgs;
7+
8+
let
9+
cache-s3 = callPackage ./cache-s3.nix {};
10+
11+
stackRebuild = runCommand "stack-rebuild" {} ''
12+
${haskellPackages.ghcWithPackages (ps: [ps.turtle ps.safe ps.transformers])}/bin/ghc -o $out ${./rebuild.hs}
13+
'';
14+
15+
in
16+
writeScript "stack-rebuild-wrapped" ''
17+
#!${stdenv.shell}
18+
export PATH=${lib.makeBinPath ([ cache-s3 stack gnused coreutils ] ++ buildTools)}
19+
exec ${stackRebuild} "$@"
20+
''

scripts/buildkite/rebuild.hs

Lines changed: 166 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,166 @@
1+
{-# LANGUAGE OverloadedStrings, RecordWildCards, LambdaCase, ScopedTypeVariables #-}
2+
3+
import Turtle hiding (option)
4+
import Prelude hiding (FilePath)
5+
import qualified Filesystem.Path.CurrentOS as FP
6+
import Control.Monad.Trans.Maybe
7+
import Control.Exception
8+
import qualified Data.Text as T
9+
import Safe
10+
import System.Exit (exitWith)
11+
import Options.Applicative
12+
13+
data BuildkiteEnv = BuildkiteEnv
14+
{ bkBuildNum :: Int
15+
, bkPipeline :: Text
16+
, bkBranch :: Text
17+
} deriving (Show)
18+
19+
data CICacheConfig = CICacheConfig
20+
{ ccMaxSize :: Maybe Text
21+
, ccBucket :: Text
22+
, ccRegion :: Maybe Text
23+
, ccPrefix :: Text
24+
, ccBranch :: Text
25+
, ccBaseBranch :: Text
26+
} deriving (Show)
27+
28+
data RebuildOpts = RebuildOpts
29+
{ optBuildDirectory :: Maybe FilePath
30+
, optBaseBranch :: Text
31+
} deriving (Show)
32+
33+
rebuildOpts :: Parser RebuildOpts
34+
rebuildOpts = RebuildOpts <$> optional buildDir <*> baseBranch
35+
where
36+
buildDir = option (FP.decodeString <$> str) (long "build-dir" <> metavar "DIR" <> help "Copy sources to directory before building")
37+
baseBranch = option str ( long "base-branch" <> value "master" <> showDefault <> help "Fallback base branch for cache-s3" )
38+
39+
parseOpts :: IO RebuildOpts
40+
parseOpts = execParser opts
41+
where opts = info (rebuildOpts <**> helper)
42+
( fullDesc <> progDesc "Build cardano-sl project with stack in Buildkite" )
43+
44+
main :: IO ()
45+
main = do
46+
RebuildOpts{..} <- parseOpts
47+
awsCreds
48+
bk <- getBuildkiteEnv
49+
maybe (pure ()) setupBuildDirectory optBuildDirectory
50+
cacheConfig <- getCacheConfig bk optBaseBranch
51+
cacheDownloadStep cacheConfig
52+
buildResult <- buildStep
53+
cacheUploadStep cacheConfig
54+
exitWith buildResult
55+
56+
buildStep :: IO ExitCode
57+
buildStep = do
58+
echo "+++ Build and test"
59+
build .&&. test
60+
where
61+
cfg = ["--dump-logs", "--color", "always"]
62+
stackBuild args = run "stack" $ cfg ++ ["build", "--fast"] ++ args
63+
buildArgs = ["--bench", "--no-run-benchmarks", "--no-haddock-deps"]
64+
buildAndTest = stackBuild $ ["--tests"] ++ buildArgs
65+
build = stackBuild $ ["--no-run-tests"] ++ buildArgs
66+
test = stackBuild ["--test", "--jobs", "1"]
67+
68+
-- buildkite agents have S3 creds installed, but under different names
69+
awsCreds :: IO ()
70+
awsCreds = mapM_ (uncurry copy) things
71+
where
72+
copy src dst = need src >>= maybe (pure ()) (export dst)
73+
things = [ ( "BUILDKITE_S3_ACCESS_KEY_ID"
74+
, "AWS_ACCESS_KEY_ID")
75+
, ( "BUILDKITE_S3_SECRET_ACCESS_KEY"
76+
, "AWS_SECRET_ACCESS_KEY")
77+
, ( "BUILDKITE_S3_DEFAULT_REGION"
78+
, "AWS_DEFAULT_REGION")
79+
]
80+
81+
getBuildkiteEnv :: IO (Maybe BuildkiteEnv)
82+
getBuildkiteEnv = runMaybeT $ do
83+
bkBuildNum <- MaybeT $ needRead "BUILDKITE_BUILD_NUMBER"
84+
bkPipeline <- MaybeT $ need "BUILDKITE_PIPELINE_SLUG"
85+
bkBranch <- MaybeT $ need "BUILDKITE_BRANCH"
86+
pure BuildkiteEnv{..}
87+
88+
needRead :: Read a => Text -> IO (Maybe a)
89+
needRead v = (>>= readMay) . fmap T.unpack <$> need v
90+
91+
getCacheConfig :: Maybe BuildkiteEnv -> Text -> IO (Either Text CICacheConfig)
92+
getCacheConfig Nothing _ = pure (Left "BUILDKITE_* environment variables are not set")
93+
getCacheConfig (Just BuildkiteEnv{..}) ccBaseBranch = do
94+
ccMaxSize <- need "CACHE_S3_MAX_SIZE"
95+
ccRegion <- need "AWS_REGION"
96+
need "S3_BUCKET" >>= \case
97+
Just ccBucket -> pure (Right CICacheConfig{ccBranch=bkBranch, ccPrefix=bkPipeline, ..})
98+
Nothing -> pure (Left "S3_BUCKET environment variable is not set")
99+
100+
cacheDownloadStep :: Either Text CICacheConfig -> IO ()
101+
cacheDownloadStep cacheConfig = do
102+
echo "--- CI Cache Download"
103+
case cacheConfig of
104+
Right cfg -> restoreCICache cfg `catch`
105+
\ (ex :: IOException) -> do
106+
eprintf ("Failed to download CI cache: "%w%"\nContinuing anyway...\n") ex
107+
Left ex -> eprintf ("Not using CI cache because "%s%"\n") ex
108+
109+
cacheUploadStep :: Either Text CICacheConfig -> IO ()
110+
cacheUploadStep cacheConfig = do
111+
echo "--- CI Cache Upload"
112+
case cacheConfig of
113+
Right cfg -> saveCICache cfg `catch`
114+
\ (ex :: IOException) -> do
115+
eprintf ("Failed to upload CI cache: "%w%"\n") ex
116+
Left _ -> printf "CI cache not configured.\n"
117+
118+
restoreCICache :: CICacheConfig -> IO ()
119+
restoreCICache cfg = do
120+
-- cacheS3 cfg (Just $ ccBaseBranch cfg) "restore stack"
121+
cacheS3 cfg (Just $ ccBaseBranch cfg) "restore stack work"
122+
123+
saveCICache :: CICacheConfig -> IO ()
124+
saveCICache cfg = do
125+
-- cacheS3 cfg Nothing "save stack"
126+
cacheS3 cfg Nothing "save stack work"
127+
128+
cacheS3 :: CICacheConfig -> Maybe Text -> Text -> IO ()
129+
cacheS3 CICacheConfig{..} baseBranch cmd = void $ run "cache-s3" args
130+
where
131+
args = ml maxSize ++ ml regionArg ++
132+
[ format ("--bucket="%s) ccBucket
133+
, format ("--prefix="%s) ccPrefix
134+
, format ("--git-branch="%s) ccBranch
135+
, "--suffix=linux"
136+
, "-v"
137+
, "info"
138+
] ++ cmds ++ ml baseBranchArg
139+
baseBranchArg = format ("--base-branch="%s) <$> baseBranch
140+
maxSize = format ("--max-size="%s) <$> ccMaxSize
141+
regionArg = format ("--region="%s) <$> ccRegion
142+
cmds = ("-c":T.words cmd)
143+
ml = maybe [] pure
144+
145+
-- cache-s3 needs a build directory that is the same across all
146+
-- buildkite agents. The build directory option can be used to ensure
147+
-- this is the case.
148+
setupBuildDirectory :: FilePath -> IO ()
149+
setupBuildDirectory buildDir = do
150+
exists <- testpath buildDir
151+
when exists $ do
152+
printf ("Removing old build directory "%fp%"\n") buildDir
153+
rmtree buildDir
154+
src <- pwd
155+
printf ("Copying source tree "%fp%" -> "%fp%"\n") src buildDir
156+
cptree src buildDir
157+
cd buildDir
158+
159+
run :: Text -> [Text] -> IO ExitCode
160+
run cmd args = do
161+
printf (s%" "%s%"\n") cmd (T.unwords args)
162+
res <- proc cmd args empty
163+
case res of
164+
ExitSuccess -> pure ()
165+
ExitFailure code -> eprintf ("error: Command exited with code "%d%"!\nContinuing...\n") code
166+
pure res

stack.yaml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -19,7 +19,7 @@
1919
# resolver: ./custom-snapshot.yaml
2020
# resolver: https://example.com/snapshots/2018-01-01.yaml
2121

22-
resolver: https://raw.githubusercontent.com/input-output-hk/cardano-prelude/0a32ec92c461e144f981864c97546db11b52e46a/snapshot.yaml
22+
resolver: https://raw.githubusercontent.com/input-output-hk/cardano-prelude/4b4457e75303ce352223b9723f7771fac6fe0600/snapshot.yaml
2323

2424
# User packages to be built.
2525
# Various formats can be used as shown in the example below.

0 commit comments

Comments
 (0)