From c25390646bf9289dbba78a6d54f7e9a71fda3dc2 Mon Sep 17 00:00:00 2001 From: Ben Sima Date: Sat, 28 Nov 2020 19:20:57 -0500 Subject: Use weekly branch names in pie, and small refactors --- Alpha.hs | 7 ++++ Biz/Bild.hs | 5 --- Biz/Pie.hs | 107 +++++++++++++++++++++++++++++++++--------------------------- 3 files changed, 66 insertions(+), 53 deletions(-) diff --git a/Alpha.hs b/Alpha.hs index 556f8df..f95d234 100644 --- a/Alpha.hs +++ b/Alpha.hs @@ -43,6 +43,9 @@ module Alpha -- * String capitalize, + -- * Data Validation + require, + -- * Debugging tools say, ) @@ -115,3 +118,7 @@ instance CanSnakeCase Text where capitalize :: String -> String capitalize [] = [] capitalize str = (Char.toUpper <| List.head str) : (Char.toLower Maybe a -> a +require _ (Just x) = x +require s Nothing = panic <| s <> " not found" diff --git a/Biz/Bild.hs b/Biz/Bild.hs index 35ba7f0..2526395 100644 --- a/Biz/Bild.hs +++ b/Biz/Bild.hs @@ -265,7 +265,6 @@ build target@Target {..} = do putText <| show target Nix -> do putText <| "bild: nix: " <> Text.pack namespace - cwd <- Dir.getCurrentDirectory let outDir = root "_/bild/nix" Dir.createDirectoryIfMissing True outDir putText <| "bild: nix: remote: " <> Text.pack builder @@ -302,10 +301,6 @@ metaDep = Regex.string "-- : dep " *> Regex.many (Regex.psym Char.isAlpha) metaOut :: Regex.RE Char Out metaOut = Regex.string "-- : out " *> Regex.many (Regex.psym (/= ' ')) -require :: Text -> Maybe a -> a -require _ (Just x) = x -require s Nothing = panic <| s <> " not found" - -- | Replace 'a' in 's' with 'b'. reps :: String -> String -> String -> String reps a b s@(x : xs) = diff --git a/Biz/Pie.hs b/Biz/Pie.hs index d414a12..d3fca5f 100644 --- a/Biz/Pie.hs +++ b/Biz/Pie.hs @@ -45,12 +45,14 @@ where import Alpha import qualified Data.Aeson as Aeson +import qualified Data.List as List import qualified Data.Maybe as Maybe import qualified Data.Text as Text -import qualified Data.Time.Clock as Clock +import qualified Data.Time as Time import Options.Applicative.Simple import qualified System.Console.Haskeline as Haskeline import qualified System.Directory as Directory +import qualified System.Environment as Env import qualified System.Exit as Exit import qualified System.Process as Process import qualified Text.Parsec as Parsec @@ -63,80 +65,89 @@ main = do "dev" "[P]roduct [I]mprovement [E]ngine" "manages .pie files, records data from product build sprints and user testing" - ( strArgument - <| help "the namespace of the app you are working on" - <> metavar "NAMESPACE" - <> value "Devalloc" - ) + (pure mempty) <| do addCommand - "start" - "start a sprint" - (const . move Start) + "new" + "start new a weekly sprint" + (const . move New) (pure mempty) addCommand "update" - "submit update" - (const . move Update) - (pure mempty) + "submit weekly update for a namespace" + (move . Update) + (optNamespace) addCommand "feedback" - "submit user feedback" - (const . move Feedback) - (pure mempty) - form <- loadForm ns - newForm <- mov form {namespace = ns} - saveForm ns newForm - -type Namespace = String - -data Form = Form {namespace :: Namespace, roll :: [Entry]} + "submit user feedback for a namespace" + (move . Feedback) + (optNamespace) + cwd <- Directory.getCurrentDirectory + root <- Env.getEnv "BIZ_ROOT" + let fullNamespace = + require "namespace" <| List.stripPrefix "/" + <| ((cwd List.\\ root) <> "/" <> Text.unpack ns) + putText <| "ns:" <> ns + putText <| "fullNamespace:" <> ns + oldForm <- loadForm fullNamespace + newForm <- mov oldForm + saveForm (Text.unpack ns) newForm + +optNamespace :: Parser String +optNamespace = + strOption + <| help "the namespace of the app you are working on" + <> long "namespace" + <> short 'n' + <> value "Devalloc" + +data Form = Form {roll :: [Entry]} deriving (Generic, Aeson.ToJSON, Aeson.FromJSON, Show) instance Monoid Form where - mempty = Form "" [] + mempty = Form [] instance Semigroup Form where - a <> b = Form (namespace a <> namespace b) (roll a <> roll b) + a <> b = Form (roll a <> roll b) formFile :: String -> FilePath formFile ns = ns ++ ".pie" -loadForm :: Namespace -> IO Form +loadForm :: String -> IO Form loadForm ns = Directory.doesFileExist file >>= \case - False -> touch file >> return mempty + False -> return mempty True -> Aeson.decodeFileStrict file >>= \case Nothing -> panic <| Text.pack <| "could not decode: " ++ file Just x -> return x where file = formFile ns - touch f = writeFile f "" -saveForm :: Namespace -> Form -> IO () -saveForm ns = Aeson.encodeFile (formFile ns) +saveForm :: String -> Form -> IO () +saveForm "" _ = pure () +saveForm namespace form = Aeson.encodeFile (formFile namespace) form data Move - = Start - | Update - | Feedback + = New + | Update String + | Feedback String move :: Move -> Form -> IO Form move mov form = case mov of - Start -> - let branch = namespace form ++ "/sprint" - in Process.spawnProcess "git" ["show-ref", branch] - >>= Process.waitForProcess - >>= \case - Exit.ExitSuccess -> - Process.callProcess "git" ["switch", branch] - Exit.ExitFailure _ -> - Process.callProcess "git" ["switch", "-c", branch] - >> return form - Update -> + New -> do + week <- Time.getCurrentTime >>= return . Time.formatTime Time.defaultTimeLocale "%V" + let branch = "sprint-" <> week + proc <- Process.spawnProcess "git" ["show-ref", branch] + Process.waitForProcess proc >>= \case + Exit.ExitSuccess -> + Process.callProcess "git" ["switch", branch] + Exit.ExitFailure _ -> + Process.callProcess "git" ["switch", "-c", branch] + >> return form + Update namespace -> Haskeline.runInputT Haskeline.defaultSettings <| do - timestamp <- liftIO Clock.getCurrentTime + timestamp <- liftIO Time.getCurrentTime onTrack <- parseBool + Feedback namespace -> Haskeline.runInputT Haskeline.defaultSettings <| do - timestamp <- liftIO Clock.getCurrentTime + timestamp <- liftIO Time.getCurrentTime user <- parseText