module Hix.Managed.BuildOutput where

import qualified Data.Aeson as Aeson
import Data.List.Extra (nubSortOn)
import qualified Data.Text as Text
import Data.These.Combinators (justThere)

import Hix.Data.Monad (M)
import Hix.Data.OutputFormat (OutputFormat (..))
import Hix.Data.OutputTarget (OutputTarget (..))
import Hix.Data.PackageName (PackageName (PackageName))
import Hix.Managed.BuildOutput.CommitMsg (formatCommit)
import Hix.Managed.BuildOutput.GithubActionsPr (githubActionsPr)
import qualified Hix.Managed.Data.BuildOutput
import Hix.Managed.Data.BuildOutput (BuildOutput (BuildOutput), ModifiedId (ModifiedId))
import Hix.Managed.Data.Mutable (MutableDep, depName)
import qualified Hix.Managed.Data.Mutation
import Hix.Managed.Data.ProjectResult (ProjectResult)
import qualified Hix.Managed.EnvResult
import Hix.Managed.EnvResult (
  DepModification (DepAdded, DepUpdated),
  DepResult,
  DepResultDetail (DepModified),
  DepResults (DepResults),
  )
import qualified Hix.Managed.ProjectResult as ProjectResult
import qualified Hix.OutputWriter
import Hix.OutputWriter (outputWriterGlobal)

outputResult :: BuildOutput -> OutputTarget -> OutputFormat -> M ()
outputResult :: BuildOutput -> OutputTarget -> OutputFormat -> M ()
outputResult BuildOutput
output OutputTarget
target = \case
  OutputFormat
OutputNone -> M ()
forall (f :: * -> *). Applicative f => f ()
unit
  OutputFormat
OutputJson -> OutputWriter
writer.bytes (ByteString -> ByteString
forall l s. LazyStrict l s => l -> s
toStrict (BuildOutput -> ByteString
forall a. ToJSON a => a -> ByteString
Aeson.encode BuildOutput
output))
  OutputFormat
OutputCommitMsg -> (Text -> M ()) -> Maybe Text -> M ()
forall (t :: * -> *) (f :: * -> *) a b.
(Foldable t, Applicative f) =>
(a -> f b) -> t a -> f ()
traverse_ OutputWriter
writer.text (BuildOutput -> Maybe Text
formatCommit BuildOutput
output)
  OutputFormat
OutputGaPr -> BuildOutput -> OutputTarget -> M ()
githubActionsPr BuildOutput
output OutputTarget
target
  where
    writer :: OutputWriter
writer = OutputTarget -> OutputWriter
outputWriterGlobal OutputTarget
target

buildOutputFromLists :: [ModifiedId] -> [MutableDep] -> [MutableDep] -> BuildOutput
buildOutputFromLists :: [ModifiedId] -> [MutableDep] -> [MutableDep] -> BuildOutput
buildOutputFromLists [ModifiedId]
modified [MutableDep]
unmodified [MutableDep]
failed =
  BuildOutput {
    [ModifiedId]
modified :: [ModifiedId]
$sel:modified:BuildOutput :: [ModifiedId]
modified,
    [MutableDep]
unmodified :: [MutableDep]
$sel:unmodified:BuildOutput :: [MutableDep]
unmodified,
    [MutableDep]
failed :: [MutableDep]
$sel:failed:BuildOutput :: [MutableDep]
failed,
    $sel:modifiedNames:BuildOutput :: Maybe Text
modifiedNames = [MutableDep] -> Maybe Text
comma ((.package) (ModifiedId -> MutableDep) -> [ModifiedId] -> [MutableDep]
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> [ModifiedId]
modified),
    $sel:unmodifiedNames:BuildOutput :: Maybe Text
unmodifiedNames = [MutableDep] -> Maybe Text
comma [MutableDep]
unmodified,
    $sel:failedNames:BuildOutput :: Maybe Text
failedNames = [MutableDep] -> Maybe Text
comma [MutableDep]
failed
  }
  where
    comma :: [MutableDep] -> Maybe Text
comma = (NonEmpty MutableDep -> Text)
-> Maybe (NonEmpty MutableDep) -> Maybe Text
forall a b. (a -> b) -> Maybe a -> Maybe b
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
fmap (Text -> [Text] -> Text
Text.intercalate Text
", " ([Text] -> Text)
-> (NonEmpty MutableDep -> [Text]) -> NonEmpty MutableDep -> Text
forall b c a. (b -> c) -> (a -> b) -> a -> c
. (MutableDep -> Text) -> [MutableDep] -> [Text]
forall a b. (a -> b) -> [a] -> [b]
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
fmap (PackageName -> Text
forall a b. Coercible a b => a -> b
coerce (PackageName -> Text)
-> (MutableDep -> PackageName) -> MutableDep -> Text
forall b c a. (b -> c) -> (a -> b) -> a -> c
. MutableDep -> PackageName
depName) ([MutableDep] -> [Text])
-> (NonEmpty MutableDep -> [MutableDep])
-> NonEmpty MutableDep
-> [Text]
forall b c a. (b -> c) -> (a -> b) -> a -> c
. NonEmpty MutableDep -> [MutableDep]
forall a. NonEmpty a -> [a]
forall (t :: * -> *) a. Foldable t => t a -> [a]
toList) (Maybe (NonEmpty MutableDep) -> Maybe Text)
-> ([MutableDep] -> Maybe (NonEmpty MutableDep))
-> [MutableDep]
-> Maybe Text
forall b c a. (b -> c) -> (a -> b) -> a -> c
. [MutableDep] -> Maybe (NonEmpty MutableDep)
forall a. [a] -> Maybe (NonEmpty a)
nonEmpty

modifiedId :: DepResult -> ModifiedId
modifiedId :: DepResult -> ModifiedId
modifiedId DepResult
result =
  ModifiedId {$sel:package:ModifiedId :: MutableDep
package = DepResult
result.package, $sel:version:ModifiedId :: Version
version = DepResult
result.version, Maybe VersionBounds
range :: Maybe VersionBounds
$sel:range:ModifiedId :: Maybe VersionBounds
range}
  where
    range :: Maybe VersionBounds
range = case DepResult
result.detail of
      DepModified (DepUpdated (These Version BoundsModification -> Maybe BoundsModification
forall a b. These a b -> Maybe b
justThere -> Just BoundsModification
_)) -> VersionBounds -> Maybe VersionBounds
forall a. a -> Maybe a
Just DepResult
result.bounds
      DepModified (DepAdded Maybe BoundsModification
_) -> VersionBounds -> Maybe VersionBounds
forall a. a -> Maybe a
Just DepResult
result.bounds
      DepResultDetail
_ -> Maybe VersionBounds
forall a. Maybe a
Nothing

buildOutput :: ProjectResult -> BuildOutput
buildOutput :: ProjectResult -> BuildOutput
buildOutput ProjectResult
result =
  [ModifiedId] -> [MutableDep] -> [MutableDep] -> BuildOutput
buildOutputFromLists [ModifiedId]
modified ((.package) (DepResult -> MutableDep) -> [DepResult] -> [MutableDep]
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> [DepResult]
unmodified) [MutableDep]
failed
  where
    modified :: [ModifiedId]
modified = DepResult -> ModifiedId
modifiedId (DepResult -> ModifiedId) -> [DepResult] -> [ModifiedId]
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> (DepResult -> MutableDep) -> [DepResult] -> [DepResult]
forall b a. Ord b => (a -> b) -> [a] -> [a]
nubSortOn (.package) ([DepResult]
added [DepResult] -> [DepResult] -> [DepResult]
forall a. [a] -> [a] -> [a]
++ [DepResult]
updated)
    failed :: [MutableDep]
failed = (.package) (FailedMutation -> MutableDep) -> [FailedMutation] -> [MutableDep]
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> ProjectResult -> [FailedMutation]
ProjectResult.failures ProjectResult
result
    DepResults {[DepResult]
unmodified :: [DepResult]
added :: [DepResult]
updated :: [DepResult]
$sel:added:DepResults :: DepResults -> [DepResult]
$sel:updated:DepResults :: DepResults -> [DepResult]
$sel:unmodified:DepResults :: DepResults -> [DepResult]
..} = ProjectResult -> DepResults
ProjectResult.grouped ProjectResult
result