Giter Site home page Giter Site logo

bake's Introduction

WARNING: UNMAINTAINED PROJECT

This project is not actively developed - you are likely to be better of using something more complete (if you do want to use it, consider forking it and taking it over). See the blog post giving notes on why it is now unmaintained.

Bake is a continuous integration server, designed for large, productive, semi-trusted teams. In particular it primarily targets:

  • Large teams where there are at least several contributors working full-time on a single code base.
  • Productive teams which are regularly pushing code, many times a day.
  • Semi-trusted teams where code does not go through manual code review, but code does need to pass a test suite and perhaps some static analysis. People are assumed to be fallible.

To give a flavour, the web GUI looks of a running Bake system looks like:

Acknowledgements: The name "Bake" is thanks to Andy Adams-Moran.

The Design

Bake is a Haskell library that can be used to put together a continuous integration server. To run Bake you start a single server for your project, which coordinates tasks, provides an HTTP API for submitting new patches, and a web-based GUI for viewing the progress of your patches. You also run some Bake clients which run the tests on behalf of the server. While Bake is written in Haskell, most of the tests are expected to just call some system command.

There are a few aspects that make Bake different from most alternatives:

  • Patches are submitted to Bake, but are not applied to the main repo until they have passed all their tests. There is no way for someone to "break the build" - at all points the repo will build on all platforms and all tests will pass.
  • Bake scales up so that even if you have 5 hours of testing and 50 commits a day it will not require 250 hours of computation per day. In order for Bake to prove that a set of patches pass a test, it does not have to test each patch individually.
  • Bake allows multiple clients to run tests, even if some tests are only able to be run on some clients, allowing both parallelisation and specialisation (testing both Windows and Linux, for example).
  • Bake can detect that tests are no longer valid, for example because they access a server that is no longer running, and report the issue without blaming the submitted patches.

The Workflow

Bake is highly parametrisable, and can be reconfigured to support several different styles of use, but here I give one plausible workflow. Imagine a number of developers, somewhere between 5 and 50. Each developer has 1 or 2 active branches they are working on. You have a master branch, which developers merge from once a day. When a developer has completed something they push their branch to the Git repo and register the SHA1 with Bake. Bake then tests the patch on all tests (in conjunction with all other patches that got promoted) and if it passes merges it into the master branch. Once a day (say 7pm) you pause the incoming patches, ensure the queue has emptied, then resume.

An Example

The test suite provides both an example configuration and commands to drive it. Here we annotate a slightly simplified version of the example, for lists of imports see the original code.

First we define an enumeration for where we want tests to run. Our server is going to require tests on both Windows and Linux before a patch is accepted.

    data Platform = Linux | Windows deriving (Show,Read)
    platforms = [Linux,Windows]

Next we define the test type. A test is something that must pass before a patch is accepted.

    data Action = Compile | Run Int deriving (Show,Read)

Our type is named Action. We have two distinct types of tests, compiling the code, and running the result with a particular argument. Now we need to supply some information about the tests:

    allTests = [(p,t) | p <- platforms, t <- Compile : map Run [1,10,0]]
    
    execute :: (Platform,Action) -> TestInfo (Platform,Action)
    execute (p,Compile) = matchOS p $ run $ do
        cmd "ghc --make Main.hs"
    execute (p,Run i) = require [(p,Compile)] $ matchOS p $ run $ do
        cmd ("." </> "Main") (show i)

We have to declare allTests, then list of all tests that must pass, and execute, which gives information about a test. Note that the test type is (Platform,Action), so a test is a platform (where to run the test) and an Action (what to run). The run function gives an IO action to run, and require specifies dependencies. We use an auxiliary matchOS to detect whether a test is running on the right platform:

    #if WINDOWS
    myPlatform = Windows
    #else
    myPlatform = Linux
    #endif

    matchOS :: Platform -> TestInfo t -> TestInfo t
    matchOS p = suitable (return . (==) myPlatform)

We use the suitable function to declare whether a test can run on a particular client. Finally, we define the main function:

    main :: IO ()
    main = bake $
        ovenGit "http://example.com/myrepo.git" "master" $
        ovenTest readShowStringy (return allTests) execute
        defaultOven{ovenServer=("127.0.0.1",5000)}

We define main = bake, then fill in some configuration. We first declare we are working with Git, and give a repo name and branch name. Next we declare what the tests are, passing the information about the tests. Finally we give a host/port for the server, which we can visit in a web browser or access via the HTTP API.

Using the Example

Now we have defined the example, we need to start up some servers and clients using the command line for our tool. Assuming we compiled as bake, we can write bake server and bake client (we'll need to launch at least one client per OS). We can view the state by visiting http://127.0.0.1:5000 in a web browser.

To add a patch we can run bake addpatch --name=d088cc3c677a867185f083aca200cb421c27b984, using the SHA1 of the commit, which will try and integrate that patch into the master branch, after all the tests have passed. Alternatively, we can run bake addpatch --name=$(git rev-parse HEAD) to try and integrate our working tree into master.

When viewing the server, there are a few additional URL's that may be of use:

  • ?stats= will show stats about which tests take longest, how long a test run takes, which test fails most often.
  • ?raw= will give internal details of the implementation.
  • /dump will download an SQLite database containing all of the persistent state.
  • ?admin= will give you an admin control panel on any page, letting you retry/delete patches and skip tests. If you want to restrict access to this panel, run bake admin myPassword which says that running bake server --admin=3A18885C will then require ?admin=myPassword.

More Examples

You can find more examples at:

bake's People

Contributors

abailly avatar malcolmwallace avatar ndmitchell avatar nkaretnikov avatar snoyberg avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

bake's Issues

How do I know the commit id for a 'test' action?

I would like to be able to pass the currently built patch to one of the test actions I am running as part of a triggered build. I am having a hard time trying to find the right place to extract that information from. It seems to me it should be readily available somewhere in the environment so that I can just extract it but not sure how to do that. Out of the top of my head I was thinking of pattern matching over the actual command run but this does seem the best way to do it.

Help greatly appreciated.

Merged summary issues are in the wrong order

The web page lists the most recent commit at the top. The email has the most recent at the bottom. Should be consistent. Still ideally want to send emails to the first person first though.

Bake client process is too CPU heavy

In my example it is running at full CPU, which means it isn't having time to actually spawn off jobs and run them, which is pretty sad. Takes my test CPU from 100% to about 30%.

bake-0.5

As seen on the Stackage build server:

[13 of 27] Compiling General.Web      ( src/General/Web.hs, dist/build/General/Web.o )

src/General/Web.hs:76:21: error:
    Variable not in scope: conduitManagerSettings :: ManagerSettings
   |
76 |     m <- newManager conduitManagerSettings
   |                     ^^^^^^^^^^^^^^^^^^^^^^

I was able to reproduce this build failure locally like so:

stack unpack bake-0.5 && cd bake-0.5
edit stack.yaml # add the following stack.yaml
stack build
# stack.yaml
resolver: nightly-2018-03-10
extra-deps:
- http-conduit-2.3.0

How do I `git notes` on git repository after bake has run?

I would like to add notes to git repository when bake has run, to store a summary of the build outcome and docker images ids that I generate from a given commit. I was thinking of overloading ovenUpdateState :: Maybe (state, [patch]) -> IO state in Oven, as I think this is executed at the end of the run. Is this assumption correct? How do I retrieve the outcome of the tests at this stage?

Thanks for your help

Add support for incrementality

There are two key incremental features required:

  • ovenIncremental to always rebuild by trying to find someone in a "similar" state and rebuild starting from them.
  • ovenGit should use a local bake-repo-hash file to store a local copy of the repo so it always clones from there after doing an update. The assumption should be the repo might be a very long way away.

How to run tests in parallel with multiple clients?

I guess everything is in the question but let's elaborate a bit:

  • Build process is a "complex" pipeline made of several stages, some of which can be run in parallel, e.g. integration tests, end-to-end tests, UI tests, some must be sequential
  • AFAIK, bake clients will build everything when a patch is submitted: Having multiple clients is mostly intended to run the same tests in multiple configurations
  • To implement that feature, some clients would need to wait for sequential parts to complete, so I guess the logic should reside in the server which will be responsible for dispatching tests to clients

I had a look at Development/Bake/Server/ code, more particularly at Brain module but I must confess the code is a bit opaque for me. I would be interested in contributing that feature but not sure how/where to start.

Document all functions

I currently disable the complete Haddock doc check because lots of things fail. I should fix the docs and enable it.

Not merging patches, delayed/queued builds

I'm on Bake 0.3 because I use stack and the said version is on
Hackage. I've modified the provided Example.hs slightly (an aside:
I've read in some issue here that you recommend to run Bake outside
the project directory, but my version doesn't support that for now due
to a call to stack build despite the fact that functions take a repo
argument, ignore this sloppiness).

For now, I just want to build the project with stack build on
Compile and call the test executable on Run. The code seems to
work, but some things I don't understand yet.

I ran bake server and bake client from the project root, made a
new branch, committed a patch, and ran bake addpatch on that hash.
Then I looked at the server UI and there were no signs of activity, so
I committed another patch and added it to Bake (I gathered it might
trigger it or something). After a while, Bake started building and
testing the first patch. Why was there a delay? The build succeeded
according to the status message, so I expected it to be merged into
master, which didn't happen. Here's the tail of the build log:

Registering Snowdrift-0.1.4...
Waited 0.00s to acquire the file lock /home/nikita/haskell/snowdrift/bake-step-git-4762652644488644249/.bake-lock
[BAKE-TIME] 13.47s (total of 13.53s): git fetch
Waited 0.00s to acquire the file lock /home/nikita/haskell/snowdrift/bake-step-git-4762652644488644249/.bake-lock
[BAKE-TIME] 0.19s (total of 13.71s): git checkout --force -B master e08749f1a95646702edc84c535ff87ce3e10e1bc
[BAKE-TIME] 0.62s (total of 14.33s): git merge a6fb84fcc4798fdcb1f46c60ff1aa5037c75fe3a
[BAKE-TIME] 5m35s (total of 5m49s): stepPrepare user action
[BAKE-TIME] 1.39s (total of 5m51s): tar -cf ../bake-step-git-4762652644488644249/../bake-step-point-3521543077975254953/result.tar -C ../bake-step-git-4762652644488644249/repo /home/nikita/haskell/snowdrift/dist/build/test/test
[BAKE-TIME] 0.15s (total of 5m51s): tar -xf ../bake-step-git-4762652644488644249/../bake-step-point-3521543077975254953/result.tar -C .
From /home/nikita/haskell/snowdrift
 * [new branch]      bake       -> origin/bake
Reset branch 'master'
tar: Removing leading `/' from member names

Is my assumption incorrect, or did something go wrong?

The other two patches have been in the "Queued" status for 40 minutes
or so, nothing shows up on the server UI or at the logs. The client
(Thomas) has "None" at the "Running" field. What's the problem?

{-# LANGUAGE FlexibleInstances #-}

module Main where

import Prelude

import Control.Monad
import Data.List.Extra
import Data.Maybe
import Data.Tuple.Extra
import Development.Bake
import Development.Shake.Command
import System.Environment.Extra
import System.FilePath

data Platform = Linux {-| Windows-} deriving (Show,Read)
data Action = Compile | Run deriving (Show,Read)

instance Stringy (Platform, Action) where
    stringyTo (a,b) = show a ++ " " ++ show b
    stringyFrom = (read *** read) . word1

platforms :: [Platform]
platforms = [Linux{-,Windows-}]

main :: IO ()
main = do
    let env      = "REPO"
        envError = "You need to set an environment variable named $"
                ++ env ++ " for the Git repo"
    repo <- fromMaybe (error envError) `fmap` lookupEnv env
    bake $
        ovenPretty $
        ovenStepGit (compile repo) repo "master" Nothing $
        ovenNotifyStdout $
        ovenTest (return allTests) (execute repo)
        defaultOven{ovenServer=("127.0.0.1",5000)}

allTests :: [(Platform, Action)]
allTests = [(p,t) | p <- platforms, t <- [Compile,Run]]

exe :: FilePath -> FilePath
exe repo = repo </> "dist/build/test/test"

compile :: FilePath -> IO [FilePath]
compile repo = do unit $ cmd "stack build"; return [exe repo]

execute :: FilePath -> (Platform,Action) -> TestInfo (Platform,Action)
execute repo (p, Compile) =
    require [show p] $ run $ void $ compile repo
execute repo (p, Run) =
    depend [(p,Compile)] $ require [show p] $ run $ cmd $ exe repo

Build output disappears

It seems that after a day build output disappears. When I click on patch/state link in admin I got the odd message:

bake-store/state-2/extra-long.html: openFile: does not exist (No such file or directory)

When I try to go back in time and retrieve link, it does not work either.

Support much bigger files

Related to #8, I should use streaming to send and receive data with Bake, so I can work with much bigger test files. Currently the limit isn't that high - 10Mb is fine, but 30Mb is too much. I think the problem is going via Aeson, which isn't designed for streaming. Perhaps I should send all the JSON on the first line, then switch to just raw data, which I use proper conduit to stream.

Code is built twice

With newer bake versions code is now built twice and I have two lines for each patch on the UI:

screen shot 2015-08-28 at 13 02 59

One titled patch and one titled state. I am not sure I understand what's going on...

Using 'Retry' in admin view adds a quote to patch number preventing it to be merged

In Development.Bake.Server.Web the following line adds a quote in front of patch name when hitting Retry:

     do br_; admin (AddPatch (paAuthor pi) $ toPatch $ '\'' : fromPatch p) $ str_ "Retry"

I understand this ensures Brain enqueues the patch:

update mem@Memory{..} (AddPatch author p) =
    if storeIsPatch store p then
        return $ Left "patch has already been submitted"
     else do
        let queued = storeAlive store `Set.difference` Set.fromList (snd active)
            supersede = filter (\old -> ovenSupersede oven old p) $ Set.toList queued
        store <- storeUpdate store $ IUQueue p author : map IUSupersede supersede
        return $ Right mem{store = store}

But this supernumerary quote prevents proper merging later on in the chain, AFAICT. How about creating a RetryPatch command that will follow roughly same semantic than AddPatch except it will not check the store?

Clients should have a unique identifier

If a client disappears then reappears with the same name, that should be treated as an entirely fresh client, and all their pending jobs should be timed out. Perhaps make client name a random string, with a pretty string to display too?

Can I start using bake if I am ready to contribute?

Hello,
I am really interested in starting using bake for our continuous integration and deployment process, given that:

  1. Our codebase is 90% (and growing) Haskell
  2. CI part is still pretty rough consisting in a post-receive hook on git repo
  3. We are ready to handle issues and generally get over the unavoidable rough edges of an early stage project
  4. I would rather avoid the hassle of installing and managing a jenkins + gerrit infrastructure

What I would like to do is something reminiscent of gerrit's workflow:

  1. dev submit patches
  2. patch must undergo review
  3. patch must build successfully
  4. built and reviewed patches go into a testing branch that triggers system-level testing for each patch in such a way that testing is aborted for all dependent patches of a failed patch (e.g. something that is handled by zuul)
  5. successfully tested patches go into main branch which triggers a deploy

Thanks for your feedback

Fail to addpatch

I managed to get my own ci instance from bake up and running, properly packed in docker containers orchestrated with fig. So far so good... But when I try to push a patch for integration, I got the following somewhat mysterious error:

Preparing by copying from bake-test-7510837679507534341
% GIT: Begin gitCheckout
% GIT: Begin gitInitMirror
% GIT: Finish gitInitMirror
HEAD is now at 917f8b0 [ETET][WIP] start application server inside ETE tests
Already on 'master'
fatal: d734a23fefe6b141db58edf6f7124c115bcdfce4 - not something we can merge
ci: user error (Development.Shake.cmd, system command failed
Command: git merge d734a23fefe6b141db58edf6f7124c115bcdfce4
Current directory: /bake-test-6583846214312572754
Exit code: 128
Stderr:
fatal: d734a23fefe6b141db58edf6f7124c115bcdfce4 - not something we can merge
)

Looking at the details of the patch integration, I got this error:

% GIT: Begin gitPatchExtra Just
% GIT: Begin gitInitMirror
% GIT: Finish gitInitMirror
fatal: Invalid symmetric difference expression 917f8b0701905815cc09ba9588c5e1b4a5aea8a6...d734a23fefe6b141db58edf6f7124c115bcdfce4
ci: user error (Development.Shake.cmd, system command failed
Command: git diff 917f8b0701905815cc09ba9588c5e1b4a5aea8a6...d734a23fefe6b141db58edf6f7124c115bcdfce4
Current directory: /bake-git-5401199084002705030/mirror
Exit code: 128
Stderr:
fatal: Invalid symmetric difference expression 917f8b0701905815cc09ba9588c5e1b4a5aea8a6...d734a23fefe6b141db58edf6f7124c115bcdfce4
)

Any idea what am I doing wrong?

Client crashes due to error 500 when finishing

I got the following recurring error with bake:

 Running CI
 -- Client start ------------------------------------------------------
 Client: client1
 Id: 1
 Test: Prepare
 State: 2c0d93c48129252d146ad78b88ada05a1ebbd0d1
 Patches:
 ----------------------------------------------------------------------

 -- Client stop -------------------------------------------------------
 Client: client1
 Id: 1
 Result: Success
 Duration: 2.61s
 ----------------------------------------------------------------------

 -- Client start ------------------------------------------------------
 Client: client1
 Id: 2
 Test: Dependencies
 State: 2c0d93c48129252d146ad78b88ada05a1ebbd0d1
 Patches:
 ----------------------------------------------------------------------

 -- Client stop -------------------------------------------------------
 Client: client1
 Id: 2
 Result: Success
 Duration: 3.15s
 ----------------------------------------------------------------------

 -- Client start ------------------------------------------------------
 Client: client1
 Id: 3
 Test: Compile
 State: 2c0d93c48129252d146ad78b88ada05a1ebbd0d1
 Patches:
 ----------------------------------------------------------------------

 -- Client stop -------------------------------------------------------
 Client: client1
 Id: 3
 Result: Success
 Duration: 24m13s
 ----------------------------------------------------------------------

 ci: Incorrect code: ((5,0,0),"Internal Server Error ","http://server:5000/api/finish")
 "endOfInput"

Allow tests to create artifacts that are retrievable from server

  • A test should be able to declare generated artifacts (e.g. files) that it can provide on demand
  • When test completes, it sends list of artifacts to server
  • Server can retrieve artifacts from tests when requested, e.g. through GUI or programatically during ovenUpdate phase

Bring up clients as needed? (assuming clients are virtualized)

Couldn't find an answer either in the docs or in the source (admittedly, didn't read too much into latter)

Let's imagine a scenario. I have a Haskell project that I want to test against multiple GHC versions. I also have a beefy server I can use for that. So I create multiple containers for each GHC version I want to test against, and set up bake client in each of those. For the sake of simplicity, let's assume I run bake server on host itself.

Now, I don't want to have containers running 24/7, but only when there's a build to do (assume that those start almost instantaneously compared to build time, so almost no overhead there). So, the question is, is there a way to bring up client instances on demand? (e.g. by shelling out some IO commands from server)

Support multiple Git repositories from a single server?

We use multiple, small (generally package specific) git repositories. It would be ideal to see the collected status of these repositories from a single server. I realize the current design does not accommodate this approach, but I'm curious if there's a reason this type of approach is a bad idea or counter to the Bake philosophy.

GC should not remove data from latest incremental build

We run GC with a space factor of 20% and when the disk is getting full, we cannot even pass a single build as GC removes the latest build in bake-incremental.txt which is then not usable by subsequent builds. GC should never remove directory pointed at bake-incremental.txt nor currently in use directory.

What is the correct deployment topology to use for bake?

I managed to tweak the given Example.hs to suite my own "test", which for the moment is limited to compiling the application. One thing I am struggling with is the topology of server/clients and repositiories to deploy bake. From various experiments, I inferred that:

  • server is started pointing to some git repository which it manages: When patches got submitted with addpatch command, server will merge those patches to "master" (by default) when tests are successful
  • client is started pointing to some git repository which it uses to execute commandes from server. This implies that pointed at repository must have roughly the same state than server
  • both client and server have a working directory to which they clone the REPO they manage, meaning this repo is never touched directly by tests' execution.
  • tests are by default run into the working directory of the client executing the test

Clients are just slaves that are used to execute tests as directed by server, possibly depending on some specific OS configuration as done in Example.hs or some other parameters. Which means that a given patch gets submitted to only one client for checking its correctness.

Am I correct?

Don't send emails until after updating the state

Currently on merge the server takes the state variable, sends emails, does the merge, then updates the state. That can mean there are 5 minutes when the user can visit the web page and it shows the code is not merged, and yet they have an email saying it was merged. Generally, emails should lag the web page.

Solution is probably to replace the emailNotify function in oven with one that queues things up and sends them after. At the same time I can refactor to make emailNotify total and then not worry about error handling.

How to handle multiple branches?

We would like our bake server to be able to handle multiple git branches with different workflows. Is it possible already and if so, what would be the best way to do that?

Build failure with extra-1.5.1

As seen on the stackage build server, building bake-0.4:

[ 4 of 26] Compiling General.Extra    ( src/General/Extra.hs, dist/build/General/Extra.o )

src/General/Extra.hs:16:5: error:
    Ambiguous occurrence ‘eitherToMaybe’
    It could refer to either ‘Data.Either.Extra.eitherToMaybe’,
                             imported from ‘Data.Either.Extra’ at src/General/Extra.hs:45:1-24
                          or ‘General.Extra.eitherToMaybe’,
                             defined at src/General/Extra.hs:116:1

Problems building on ghc-7.8.4

Hi,

I have problems building with ghc-7.8.4 on a couple of different environments. First I tried on an old RH box (you probably know the one). I then tried on my nixos box using stack. In both of these cases I get:

/home/ben/dev/haskell/bake/src/General/HTML.hs:76:15:
    No instance for (Eq
                       (WriterT Rope Data.Functor.Identity.Identity a))
      arising from the 'deriving' clause of a data type declaration
    Possible fix:
      use a standalone 'deriving instance' declaration,
        so you can specify the instance context yourself
    When deriving the instance for (Eq (HTML_ a))

/home/ben/dev/haskell/bake/src/General/HTML.hs:76:18:
    No instance for (Ord
                       (WriterT Rope Data.Functor.Identity.Identity a))
      arising from the 'deriving' clause of a data type declaration
    Possible fix:
      use a standalone 'deriving instance' declaration,
        so you can specify the instance context yourself
    When deriving the instance for (Ord (HTML_ a))

This seems to be needing base-4.9.0.0 to work as base-4.7.0.1 doens't have the Ord1 instance for Identity.

The ghc environment on this machine seem... quirky... though.

Preparing step is failing on a freshly cloned bare repository

When I start bake from scratch pointing it a freshly cloned bare git repository, it fails in the preparing step with the following odd messages:

Running CI server...
% GIT: Begin gitCheckout
% GIT: Begin gitInitMirror
error: packfile ./objects/pack/pack-4e334e50d18177148e5b9004ede64a2fac19b63a.pack size changed
warning: packfile ./objects/pack/pack-4e334e50d18177148e5b9004ede64a2fac19b63a.pack cannot be accessed
error: packfile ./objects/pack/pack-4e334e50d18177148e5b9004ede64a2fac19b63a.pack size changed
warning: packfile ./objects/pack/pack-4e334e50d18177148e5b9004ede64a2fac19b63a.pack cannot be accessed
error: packfile ./objects/pack/pack-4e334e50d18177148e5b9004ede64a2fac19b63a.pack size changed
warning: packfile ./objects/pack/pack-4e334e50d18177148e5b9004ede64a2fac19b63a.pack cannot be accessed
error: packfile ./objects/pack/pack-4e334e50d18177148e5b9004ede64a2fac19b63a.pack size changed
warning: packfile ./objects/pack/pack-4e334e50d18177148e5b9004ede64a2fac19b63a.pack cannot be accessed
error: packfile ./objects/pack/pack-4e334e50d18177148e5b9004ede64a2fac19b63a.pack size changed
warning: packfile ./objects/pack/pack-4e334e50d18177148e5b9004ede64a2fac19b63a.pack cannot be accessed
error: packfile ./objects/pack/pack-4e334e50d18177148e5b9004ede64a2fac19b63a.pack size changed
warning: packfile ./objects/pack/pack-4e334e50d18177148e5b9004ede64a2fac19b63a.pack cannot be accessed
error: packfile ./objects/pack/pack-4e334e50d18177148e5b9004ede64a2fac19b63a.pack size changed
warning: packfile ./objects/pack/pack-4e334e50d18177148e5b9004ede64a2fac19b63a.pack cannot be accessed
error: packfile ./objects/pack/pack-4e334e50d18177148e5b9004ede64a2fac19b63a.pack size changed
warning: packfile ./objects/pack/pack-4e334e50d18177148e5b9004ede64a2fac19b63a.pack cannot be accessed
error: packfile ./objects/pack/pack-4e334e50d18177148e5b9004ede64a2fac19b63a.pack size changed
warning: packfile ./objects/pack/pack-4e334e50d18177148e5b9004ede64a2fac19b63a.pack cannot be accessed
error: packfile ./objects/pack/pack-4e334e50d18177148e5b9004ede64a2fac19b63a.pack size changed
warning: packfile ./objects/pack/pack-4e334e50d18177148e5b9004ede64a2fac19b63a.pack cannot be accessed
error: packfile ./objects/pack/pack-4e334e50d18177148e5b9004ede64a2fac19b63a.pack size changed
warning: packfile ./objects/pack/pack-4e334e50d18177148e5b9004ede64a2fac19b63a.pack cannot be accessed
error: packfile ./objects/pack/pack-4e334e50d18177148e5b9004ede64a2fac19b63a.pack size changed
warning: packfile ./objects/pack/pack-4e334e50d18177148e5b9004ede64a2fac19b63a.pack cannot be accessed

Checking the length of a hash

Two related issues:

  1. README.md suggests that bake addpatch --name=cb3c2a71 should work, but it doesn't because a hash must be 40 chars long (see sha1 in src/Development/Bake/Git.hs).
  2. I can't find a way to retry a patch. If I pass a 40 char hash to addpatch, rowPatch in src/Development/Bake/Server/Web.hs will prepend a quote to it, so the hash will fail the 40 char check in sha1. After that I had to clean all bake files because it failed to start.

Error messages:

Output: bake-test: SHA1 for Git must be 40 characters long, got "'ec1b02295770352e9f4c8ff2b675b1ada898f896"

bake-test: user error (Pattern match failure in do expression at src/Development/Bake/Server/Store.hs:116:9-98)

Steps to reproduce (in the bake source dir):

terminal1$ REPO=$(pwd) dist/build/bake-test/bake-test server
terminal2$ REPO=$(pwd) dist/build/bake-test/bake-test client
terminal3$ dist/build/bake-test/bake-test addpatch --name=$(git rev-parse HEAD)

I've tried changing both sha1 and rowPatch, but neither seems to work. Unfortunately, I have to give up on this for today, but here are the patches. Not sure whether either is a good idea, so I'm just putting them here.

commit 3ad1d26314fb534bb1347658036015b9a525b65d
Author: Nikita Karetnikov <[email protected]>
Date:   Thu Jul 9 18:32:09 2015 +0300

    Do not prepend a quote to a hash on retry

    This causes bake to fail because it expects a hash to be 40 characters
    long.

diff --git a/src/Development/Bake/Server/Web.hs b/src/Development/Bake/Server/Web.hs
index 8d75f27..4b068d1 100644
--- a/src/Development/Bake/Server/Web.hs
+++ b/src/Development/Bake/Server/Web.hs
@@ -334,7 +334,7 @@ rowPatch Shower{..} mem@Memory{..} argsAdmin info = (code, [showTime time, state
                 if paAlive pi then
                     do br_; admin (DelPatch p) $ str_ "Delete"
                 else if isNothing $ paMerge pi then
-                    do br_; admin (AddPatch (paAuthor pi) $ toPatch $ '\'' : fromPatch p) $ str_ "Retry"
+                    do br_; admin (AddPatch (paAuthor pi) p) $ str_ "Retry"
                 else
                     mempty
             | otherwise = mempty
commit a173edc71188ded5dada2c8dfe61e55daf05c021
Author: Nikita Karetnikov <[email protected]>
Date:   Thu Jul 9 18:50:34 2015 +0300

    Do not check the length of a hash

diff --git a/src/Development/Bake/Git.hs b/src/Development/Bake/Git.hs
index 24f739c..a4c30f5 100644
--- a/src/Development/Bake/Git.hs
+++ b/src/Development/Bake/Git.hs
@@ -24,8 +24,9 @@ import Prelude
 newtype SHA1 = SHA1 {fromSHA1 :: String} deriving (Show,Eq)

 sha1 :: String -> SHA1
-sha1 x | length x /= 40 = error $ "SHA1 for Git must be 40 characters long, got " ++ show x
-       | not $ all (`elem` "0123456789abcdef") x = error $ "SHA1 for Git must be all lower case hex, got " ++ show x 
+sha1 x | not $ all (`elem` "0123456789abcdef'") x =
+           error $ "SHA1 for Git must be all lower case hex " ++
+                   "or a quote character ('), got " ++ show x
        | otherwise = SHA1 x

 instance Stringy SHA1 where

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.