github-actions-0.1.1.0: src/Language/Github/Actions/RunIf.hs
{-# LANGUAGE DeriveGeneric #-}
{-# LANGUAGE DerivingStrategies #-}
{-# LANGUAGE OverloadedStrings #-}
-- |
-- Module : Language.Github.Actions.RunIf
-- Description : Flexible conditional expressions for GitHub Actions
-- Copyright : (c) 2025 Bellroy Pty Ltd
-- License : BSD-3-Clause
-- Maintainer : Bellroy Tech Team <haskell@bellroy.com>
--
-- This module provides the 'RunIf' type for representing conditional expressions
-- in GitHub Actions workflows. GitHub Actions allows both boolean and string
-- expressions in 'if' conditions for jobs and steps.
--
-- Examples of valid 'if' conditions:
-- * @if: false@ - Boolean
-- * @if: "github.ref == 'refs/heads/main'"@ - String
--
-- For more information about GitHub Actions conditional expressions, see:
-- <https://docs.github.com/en/actions/writing-workflows/workflow-syntax-for-github-actions#jobsjob_idif>
module Language.Github.Actions.RunIf
( RunIf (..),
gen,
)
where
import Data.Aeson (FromJSON, ToJSON (..), Value (..))
import qualified Data.Aeson as Aeson
import Data.Text (Text)
import GHC.Generics (Generic)
import Hedgehog (MonadGen)
import qualified Hedgehog.Gen as Gen
import qualified Hedgehog.Range as Range
-- | A conditional expression that can be either a boolean or string.
--
-- GitHub Actions supports flexible 'if' conditions:
--
-- * 'RunIfBool' - Simple boolean values like @true@ or @false@
-- * 'RunIfString' - GitHub expressions like @"github.ref == 'refs/heads/main'"@
--
-- Examples:
--
-- @
-- -- Simple boolean condition
-- simpleFalse :: RunIf
-- simpleFalse = RunIfBool False
--
-- -- GitHub expression condition
-- branchCheck :: RunIf
-- branchCheck = RunIfString "github.ref == 'refs/heads/main'"
-- @
--
-- The type preserves the original format during round-trip serialization,
-- so a boolean input remains a boolean in the output YAML.
data RunIf
= RunIfBool Bool
| RunIfString Text
deriving stock (Eq, Generic, Ord, Show)
instance FromJSON RunIf where
parseJSON (Bool b) = pure $ RunIfBool b
parseJSON (String s) = pure $ RunIfString s
parseJSON v = fail $ "Expected Bool or String for RunIf, got: " ++ show v
instance ToJSON RunIf where
toJSON (RunIfBool b) = Bool b
toJSON (RunIfString s) = String s
gen :: (MonadGen m) => m RunIf
gen =
Gen.choice
[ RunIfBool <$> Gen.bool,
RunIfString <$> Gen.text (Range.linear 5 50) Gen.alphaNum
]