{-# LANGUAGE DeriveGeneric #-}
{-# LANGUAGE DerivingStrategies #-}
{-# LANGUAGE GeneralizedNewtypeDeriving #-}

-- |
-- Module      : Language.Github.Actions.Job.Id
-- Description : Job identifiers for GitHub Actions workflows
-- Copyright   : (c) 2025 Bellroy Pty Ltd
-- License     : BSD-3-Clause
-- Maintainer  : Bellroy Tech Team <haskell@bellroy.com>
--
-- This module provides the 'JobId' type for uniquely identifying jobs within
-- GitHub Actions workflows.
--
-- Job IDs are used to reference jobs in dependency declarations (needs), outputs,
-- and other cross-job references. They must be unique within a workflow and follow
-- specific naming conventions.
--
-- For more information about GitHub Actions job IDs, see:
-- <https://docs.github.com/en/actions/writing-workflows/workflow-syntax-for-github-actions#jobsjob_id>
module Language.Github.Actions.Job.Id
  ( JobId (..),
    gen,
    render,
  )
where

import Data.Aeson (FromJSON, FromJSONKey, ToJSON (..), ToJSONKey)
import Data.Text (Text)
import GHC.Generics (Generic)
import Hedgehog (MonadGen)
import qualified Hedgehog.Gen as Gen
import qualified Hedgehog.Range as Range

-- | A unique identifier for a job within a GitHub Actions workflow.
--
-- Job IDs are used to:
-- * Reference jobs in dependency declarations (needs)
-- * Access job outputs from other jobs
-- * Identify jobs in workflow run logs and API responses
--
-- Job IDs must be unique within a workflow and should follow these conventions:
-- * Start with a letter or underscore
-- * Contain only alphanumeric characters, hyphens, and underscores
-- * Be descriptive of the job's purpose
--
-- Example usage:
--
-- @
-- import Language.Github.Actions.Job.Id
--
-- -- Simple job IDs
-- buildJobId :: JobId
-- buildJobId = JobId "build"
--
-- testJobId :: JobId
-- testJobId = JobId "test"
--
-- -- More descriptive job IDs
-- deployProdJobId :: JobId
-- deployProdJobId = JobId "deploy-production"
-- @
--
-- For more details, see: <https://docs.github.com/en/actions/writing-workflows/workflow-syntax-for-github-actions#jobsjob_id>
newtype JobId = JobId Text
  deriving stock (JobId -> JobId -> Bool
(JobId -> JobId -> Bool) -> (JobId -> JobId -> Bool) -> Eq JobId
forall a. (a -> a -> Bool) -> (a -> a -> Bool) -> Eq a
$c== :: JobId -> JobId -> Bool
== :: JobId -> JobId -> Bool
$c/= :: JobId -> JobId -> Bool
/= :: JobId -> JobId -> Bool
Eq, (forall x. JobId -> Rep JobId x)
-> (forall x. Rep JobId x -> JobId) -> Generic JobId
forall x. Rep JobId x -> JobId
forall x. JobId -> Rep JobId x
forall a.
(forall x. a -> Rep a x) -> (forall x. Rep a x -> a) -> Generic a
$cfrom :: forall x. JobId -> Rep JobId x
from :: forall x. JobId -> Rep JobId x
$cto :: forall x. Rep JobId x -> JobId
to :: forall x. Rep JobId x -> JobId
Generic, Eq JobId
Eq JobId =>
(JobId -> JobId -> Ordering)
-> (JobId -> JobId -> Bool)
-> (JobId -> JobId -> Bool)
-> (JobId -> JobId -> Bool)
-> (JobId -> JobId -> Bool)
-> (JobId -> JobId -> JobId)
-> (JobId -> JobId -> JobId)
-> Ord JobId
JobId -> JobId -> Bool
JobId -> JobId -> Ordering
JobId -> JobId -> JobId
forall a.
Eq a =>
(a -> a -> Ordering)
-> (a -> a -> Bool)
-> (a -> a -> Bool)
-> (a -> a -> Bool)
-> (a -> a -> Bool)
-> (a -> a -> a)
-> (a -> a -> a)
-> Ord a
$ccompare :: JobId -> JobId -> Ordering
compare :: JobId -> JobId -> Ordering
$c< :: JobId -> JobId -> Bool
< :: JobId -> JobId -> Bool
$c<= :: JobId -> JobId -> Bool
<= :: JobId -> JobId -> Bool
$c> :: JobId -> JobId -> Bool
> :: JobId -> JobId -> Bool
$c>= :: JobId -> JobId -> Bool
>= :: JobId -> JobId -> Bool
$cmax :: JobId -> JobId -> JobId
max :: JobId -> JobId -> JobId
$cmin :: JobId -> JobId -> JobId
min :: JobId -> JobId -> JobId
Ord, Int -> JobId -> ShowS
[JobId] -> ShowS
JobId -> String
(Int -> JobId -> ShowS)
-> (JobId -> String) -> ([JobId] -> ShowS) -> Show JobId
forall a.
(Int -> a -> ShowS) -> (a -> String) -> ([a] -> ShowS) -> Show a
$cshowsPrec :: Int -> JobId -> ShowS
showsPrec :: Int -> JobId -> ShowS
$cshow :: JobId -> String
show :: JobId -> String
$cshowList :: [JobId] -> ShowS
showList :: [JobId] -> ShowS
Show)
  deriving newtype (Maybe JobId
Value -> Parser [JobId]
Value -> Parser JobId
(Value -> Parser JobId)
-> (Value -> Parser [JobId]) -> Maybe JobId -> FromJSON JobId
forall a.
(Value -> Parser a)
-> (Value -> Parser [a]) -> Maybe a -> FromJSON a
$cparseJSON :: Value -> Parser JobId
parseJSON :: Value -> Parser JobId
$cparseJSONList :: Value -> Parser [JobId]
parseJSONList :: Value -> Parser [JobId]
$comittedField :: Maybe JobId
omittedField :: Maybe JobId
FromJSON, FromJSONKeyFunction [JobId]
FromJSONKeyFunction JobId
FromJSONKeyFunction JobId
-> FromJSONKeyFunction [JobId] -> FromJSONKey JobId
forall a.
FromJSONKeyFunction a -> FromJSONKeyFunction [a] -> FromJSONKey a
$cfromJSONKey :: FromJSONKeyFunction JobId
fromJSONKey :: FromJSONKeyFunction JobId
$cfromJSONKeyList :: FromJSONKeyFunction [JobId]
fromJSONKeyList :: FromJSONKeyFunction [JobId]
FromJSONKey, [JobId] -> Value
[JobId] -> Encoding
JobId -> Bool
JobId -> Value
JobId -> Encoding
(JobId -> Value)
-> (JobId -> Encoding)
-> ([JobId] -> Value)
-> ([JobId] -> Encoding)
-> (JobId -> Bool)
-> ToJSON JobId
forall a.
(a -> Value)
-> (a -> Encoding)
-> ([a] -> Value)
-> ([a] -> Encoding)
-> (a -> Bool)
-> ToJSON a
$ctoJSON :: JobId -> Value
toJSON :: JobId -> Value
$ctoEncoding :: JobId -> Encoding
toEncoding :: JobId -> Encoding
$ctoJSONList :: [JobId] -> Value
toJSONList :: [JobId] -> Value
$ctoEncodingList :: [JobId] -> Encoding
toEncodingList :: [JobId] -> Encoding
$comitField :: JobId -> Bool
omitField :: JobId -> Bool
ToJSON, ToJSONKeyFunction [JobId]
ToJSONKeyFunction JobId
ToJSONKeyFunction JobId
-> ToJSONKeyFunction [JobId] -> ToJSONKey JobId
forall a.
ToJSONKeyFunction a -> ToJSONKeyFunction [a] -> ToJSONKey a
$ctoJSONKey :: ToJSONKeyFunction JobId
toJSONKey :: ToJSONKeyFunction JobId
$ctoJSONKeyList :: ToJSONKeyFunction [JobId]
toJSONKeyList :: ToJSONKeyFunction [JobId]
ToJSONKey)

gen :: (MonadGen m) => m JobId
gen :: forall (m :: * -> *). MonadGen m => m JobId
gen = Text -> JobId
JobId (Text -> JobId) -> m Text -> m JobId
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> Range Int -> m Char -> m Text
forall (m :: * -> *). MonadGen m => Range Int -> m Char -> m Text
Gen.text (Int -> Int -> Range Int
forall a. Integral a => a -> a -> Range a
Range.linear Int
1 Int
5) m Char
forall (m :: * -> *). MonadGen m => m Char
Gen.alphaNum

render :: JobId -> Text
render :: JobId -> Text
render (JobId Text
t) = Text
t