Skip to content

Commit

Permalink
Add support for production builds for Haskell projects
Browse files Browse the repository at this point in the history
  • Loading branch information
sd234678 committed Apr 29, 2024
1 parent 72d0cbe commit 76aa5ac
Show file tree
Hide file tree
Showing 32 changed files with 397 additions and 124 deletions.
2 changes: 1 addition & 1 deletion .last-exported-commit
Original file line number Diff line number Diff line change
@@ -1 +1 @@
Last exported commit from parent repo: 05f63cbae6025640025eed5554804f2c06b4cd29
Last exported commit from parent repo: e2e8453069a3817288b59e66e3931415f3829638
2 changes: 1 addition & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -37,7 +37,7 @@ The following symbols are used throughout this page to indicate support status:
| :----------------------------------------: | :-------------------------------------------------------------------------: | :-----------------------------------------------------------------------------: | :-------: | :-----------------------------: | :---------------------------------------------------------------------------------------: |
| Elm | ✅ <br>Either as a standalone app or as part of a Node project with Parcel. | ✅ <br>With the Elm extension installed. ||||
| Golang || ✅ <br>With the official Go extension installed. ||| 🟠 <br>Support is currently considered _experimental_. |
| Haskell | ✅ <br>Either as a simple project or just a place to run a repl. | ✅ <br>With the haskell.haskell extension installed. ||| 🕓 |
| Haskell | ✅ <br>Either as a simple project or just a place to run a repl. | ✅ <br>With the haskell.haskell extension installed. ||| |
| Java | ✅ <br>With maven, google-java-format, and optionally minishift. | ✅ <br>With the official Java, and optionally the Lombok, extensions installed. ||| 🟠 <br>Only supports Spring applications. Support is currently considered _experimental_. |
| Minimal (With no project-specific tooling) |||| 🟠 ||
| NodeJS | ✅ <br>With latest stable node, AWS CLI, and optionally PNPm/Yarn. |||||
Expand Down
3 changes: 2 additions & 1 deletion nix-bootstrap.cabal
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@ cabal-version: 2.0
-- see: https://github.com/sol/hpack

name: nix-bootstrap
version: 1.5.7.3
version: 1.6.0.0
author: gchquser
maintainer: [email protected]
copyright: Crown Copyright
Expand Down Expand Up @@ -84,6 +84,7 @@ library
Bootstrap.Nix.Expr.Python
Bootstrap.Nix.Expr.ReproducibleBuild
Bootstrap.Nix.Expr.ReproducibleBuild.Go
Bootstrap.Nix.Expr.ReproducibleBuild.Haskell
Bootstrap.Nix.Expr.ReproducibleBuild.Java
Bootstrap.Nix.Expr.ReproducibleBuild.Rust
Bootstrap.Nix.Flake
Expand Down
2 changes: 1 addition & 1 deletion package.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@
# See the License for the specific language governing permissions and
# limitations under the License.
name: nix-bootstrap
version: 1.5.7.3
version: 1.6.0.0
author: gchquser
maintainer: [email protected]
copyright: Crown Copyright
Expand Down
20 changes: 4 additions & 16 deletions src/Bootstrap.hs
Original file line number Diff line number Diff line change
Expand Up @@ -117,9 +117,9 @@ import Bootstrap.Data.ProjectType
PythonVersion (Python39),
SetUpGoBuild (SetUpGoBuild),
SetUpJavaBuild (NoJavaBuild, SetUpJavaBuild),
haskellProjectTypeName,
nodePackageManagerName,
projectSuperTypeName,
promptHaskellProjectType,
)
import Bootstrap.Data.Version (MajorVersion (MajorVersion), displayMajorVersion)
import Bootstrap.Error (CanDieOnError (dieOnError', dieOnErrorWithPrefix))
Expand All @@ -129,10 +129,10 @@ import Bootstrap.Niv (initialiseNiv)
import Bootstrap.Nix.Evaluate (NixBinaryPaths, getAvailableGHCVersions, getNixBinaryPaths, getNixConfig, getNixVersion)
import Bootstrap.Nix.Flake (generateIntermediateFlake)
import Bootstrap.Terminal
( promptChoice,
( askIfReproducibleBuildRequired,
promptChoice,
promptNonemptyText,
promptYesNo,
promptYesNoWithCustomPrompt,
promptYesNoWithDefault,
putErrorLn,
withAttribute,
Expand Down Expand Up @@ -411,7 +411,7 @@ promptProjectType nixBinaryPaths runConfig devContainerConfig = do
availableGHCVersions <- getAvailableGHCVersions nixBinaryPaths runConfig
case nonEmpty $ toList availableGHCVersions of
Just availableGHCVersions' -> do
haskellProjectType <- promptChoice "What kind of Haskell project would you like?" universeNonEmpty haskellProjectTypeName
haskellProjectType <- promptHaskellProjectType
ghcVersion <- promptChoice "Select a version of the Glasgow Haskell Compiler:" availableGHCVersions' printGHCVersion
pure . Haskell $ HaskellOptions ghcVersion haskellProjectType
Nothing -> putErrorLn "Could not find any versions of GHC in nixpkgs" *> exitFailure
Expand All @@ -437,18 +437,6 @@ promptProjectType nixBinaryPaths runConfig devContainerConfig = do
pure . Java $ JavaOptions installMinishift installLombok setUpJavaBuild
PSTPython -> pure $ Python Python39
PSTRust -> pure Rust
where
askIfReproducibleBuildRequired :: m Bool
askIfReproducibleBuildRequired = promptYesNoWithCustomPrompt do
let (part1, part2, part3) =
( "Would you like to set up a reproducible build for this project ",
"(EXPERIMENTAL)",
"?"
)
withAttribute (foreground blue) $ putText part1
withAttributes [bold, foreground yellow] $ putText part2
withAttribute (foreground blue) $ putText part3
pure $ sum $ T.length <$> [part1, part2, part3]

data MakeBuildPlanArgs = MakeBuildPlanArgs
{ mbpNixBinaryPaths :: NixBinaryPaths,
Expand Down
29 changes: 17 additions & 12 deletions src/Bootstrap/Data/Bootstrappable.hs
Original file line number Diff line number Diff line change
Expand Up @@ -149,18 +149,23 @@ bootstrapContentNix a = do
)
<$> writeExprFormatted ShowComments expr
Left (i1 :| iRest) ->
pure . Left $
"Nix expression is incorrectly scoped; it references the out of scope "
<> ( if null iRest
then "identifier " <> toString (unIdentifier i1)
else
"identifiers "
<> toString
( foldr (\i acc -> unIdentifier i <> ", " <> acc) ("and " <> unIdentifier i1) iRest
)
)
<> ". This is a bug in nix-bootstrap; please "
<> "contact the nix-bootstrap team to report it."
Left
. ( ( "Nix expression is incorrectly scoped; it references the out of scope "
<> ( if null iRest
then "identifier " <> toString (unIdentifier i1)
else
"identifiers "
<> toString
( foldr (\i acc -> unIdentifier i <> ", " <> acc) ("and " <> unIdentifier i1) iRest
)
)
<> ". This is a bug in nix-bootstrap; please "
<> "contact the nix-bootstrap team to report it.\nBad expr was: "
)
<>
)
. show
<$> writeExprFormatted ShowComments expr

-- | A helper function when the generated file should be JSON
--
Expand Down
14 changes: 11 additions & 3 deletions src/Bootstrap/Data/Bootstrappable/DefaultNix.hs
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,9 @@ import Bootstrap.Data.Bootstrappable
)
import Bootstrap.Data.ProjectName (ProjectName)
import Bootstrap.Data.ProjectType
( JavaOptions (JavaOptions),
( HaskellOptions (HaskellOptions),
HaskellProjectType (HaskellProjectTypeBasic),
JavaOptions (JavaOptions),
ProjectType
( Elm,
Go,
Expand All @@ -27,6 +29,7 @@ import Bootstrap.Data.ProjectType
Rust
),
SetUpGoBuild (SetUpGoBuild),
SetUpHaskellBuild (SetUpHaskellBuild),
SetUpJavaBuild (SetUpJavaBuild),
)
import Bootstrap.Nix.Expr
Expand All @@ -40,10 +43,12 @@ import Bootstrap.Nix.Expr
import Bootstrap.Nix.Expr.Nixpkgs (nixpkgsFromNiv)
import Bootstrap.Nix.Expr.ReproducibleBuild
( ReproducibleBuildExpr (ReproducibleBuildExpr, rbeExpr, rbeRequirements),
ReproducibleBuildRequirement (RBRNixpkgs),
ReproducibleBuildRequirement (RBRHaskellPackages, RBRNixpkgs),
reproducibleBuildRequirementIdentifier,
sortRbeRequirements,
)
import Bootstrap.Nix.Expr.ReproducibleBuild.Go (reproducibleGoBuild)
import Bootstrap.Nix.Expr.ReproducibleBuild.Haskell (reproducibleHaskellBuild)
import Bootstrap.Nix.Expr.ReproducibleBuild.Java (reproducibleJavaBuild)
import Bootstrap.Nix.Expr.ReproducibleBuild.Rust (reproducibleRustBuild)

Expand All @@ -56,12 +61,13 @@ instance Bootstrappable DefaultNix where

instance IsNixExpr DefaultNix where
toNixExpr (DefaultNix ReproducibleBuildExpr {..}) =
ELetIn (bindingFor <$> rbeRequirements) rbeExpr
ELetIn (bindingFor <$> sortRbeRequirements rbeRequirements) rbeExpr
where
bindingFor :: ReproducibleBuildRequirement -> Binding
bindingFor r =
PIdent (reproducibleBuildRequirementIdentifier r) |= case r of
RBRNixpkgs -> nixpkgsFromNiv
RBRHaskellPackages -> [nix|import nix/haskell-packages.nix { inherit nixpkgs; }|]

-- | The source directory for the build
data SrcDir
Expand All @@ -79,6 +85,8 @@ defaultNixFor :: SrcDir -> ProjectName -> ProjectType -> Maybe DefaultNix
defaultNixFor srcDir projectName = \case
Minimal -> Nothing
Elm _ -> Nothing
Haskell (HaskellOptions _ (HaskellProjectTypeBasic (SetUpHaskellBuild True))) ->
Just . DefaultNix . reproducibleHaskellBuild projectName $ srcDirExpr srcDir
Haskell _ -> Nothing
Node _ -> Nothing
Go (SetUpGoBuild True) -> Just . DefaultNix $ reproducibleGoBuild projectName
Expand Down
8 changes: 6 additions & 2 deletions src/Bootstrap/Data/Bootstrappable/FlakeNix.hs
Original file line number Diff line number Diff line change
Expand Up @@ -59,7 +59,7 @@ import Bootstrap.Nix.Expr.MkShell
)
import Bootstrap.Nix.Expr.PreCommitHooks (ImportPreCommitHooksArgs (ImportPreCommitHooksArgs, passNixpkgsThrough, passSystemThrough), importPreCommitHooks)
import Bootstrap.Nix.Expr.Python (machNixFlakeInput, pythonPackagesBinding)
import Bootstrap.Nix.Expr.ReproducibleBuild (ReproducibleBuildExpr (rbeRequirements), ReproducibleBuildRequirement (RBRNixpkgs), reproducibleBuildRequirementIdentifier)
import Bootstrap.Nix.Expr.ReproducibleBuild (ReproducibleBuildExpr (rbeRequirements), ReproducibleBuildRequirement (RBRHaskellPackages, RBRNixpkgs), reproducibleBuildRequirementIdentifier, sortRbeRequirements)
import Control.Lens
( Field2 (_2),
filtered,
Expand Down Expand Up @@ -208,6 +208,7 @@ instance IsNixExpr FlakeNix where
( toList
. unsafeSimplifyBindings
. fmap toBuildRequirementBinding
. sortRbeRequirements
. rbeRequirements
$ unBuildNix buildNix
)
Expand All @@ -224,7 +225,10 @@ instance IsNixExpr FlakeNix where
-- Note: When adding bindings here, check they are not interdependent as they will
-- be passed through `unsafeSimplifyBindings`.
\case
RBRNixpkgs -> BInherit . one $ reproducibleBuildRequirementIdentifier RBRNixpkgs
RBRNixpkgs -> buildRequirementBindingInherit RBRNixpkgs
RBRHaskellPackages -> buildRequirementBindingInherit RBRHaskellPackages
buildRequirementBindingInherit :: ReproducibleBuildRequirement -> Binding
buildRequirementBindingInherit = BInherit . one . reproducibleBuildRequirementIdentifier
runChecksDerivation :: [Binding]
runChecksDerivation =
[ [nixbinding|# runChecks is a hack required to allow checks to run on a single system|],
Expand Down
2 changes: 1 addition & 1 deletion src/Bootstrap/Data/Bootstrappable/Haskell/LibHs.hs
Original file line number Diff line number Diff line change
Expand Up @@ -49,5 +49,5 @@ libHsFor :: ProjectType -> Maybe LibHs
libHsFor = \case
Haskell (HaskellOptions _ haskellProjectType) -> case haskellProjectType of
HaskellProjectTypeReplOnly -> Nothing
HaskellProjectTypeBasic -> Just LibHs
HaskellProjectTypeBasic _ -> Just LibHs
_ -> Nothing
2 changes: 1 addition & 1 deletion src/Bootstrap/Data/Bootstrappable/Haskell/MainHs.hs
Original file line number Diff line number Diff line change
Expand Up @@ -51,5 +51,5 @@ mainHsFor :: ProjectType -> Maybe MainHs
mainHsFor = \case
Haskell (HaskellOptions _ haskellProjectType) -> case haskellProjectType of
HaskellProjectTypeReplOnly -> Nothing
HaskellProjectTypeBasic -> Just MainHs
HaskellProjectTypeBasic _ -> Just MainHs
_ -> Nothing
4 changes: 2 additions & 2 deletions src/Bootstrap/Data/Bootstrappable/Haskell/PackageYaml.hs
Original file line number Diff line number Diff line change
Expand Up @@ -38,7 +38,7 @@ instance Bootstrappable PackageYaml where
. getHaskellDependencyVersions nbps rc opts
$ case haskellOptionsHaskellProjectType of
HaskellProjectTypeReplOnly -> []
HaskellProjectTypeBasic -> [$(hdep "base"), $(hdep "relude")]
HaskellProjectTypeBasic _ -> [$(hdep "base"), $(hdep "relude")]
pure . bootstrapContentYaml $ PackageYamlWithDependencies n dependencies

data PackageYamlWithDependencies = PackageYamlWithDependencies ProjectName [HaskellDependency 'VersionKnown]
Expand Down Expand Up @@ -128,5 +128,5 @@ packageYamlFor :: NixBinaryPaths -> RunConfig -> ProjectName -> ProjectType -> M
packageYamlFor nbps rc projectName = \case
Haskell haskellOptions@(HaskellOptions _ haskellProjectType) -> case haskellProjectType of
HaskellProjectTypeReplOnly -> Nothing
HaskellProjectTypeBasic -> Just $ PackageYaml nbps rc projectName haskellOptions
HaskellProjectTypeBasic _ -> Just $ PackageYaml nbps rc projectName haskellOptions
_ -> Nothing
2 changes: 1 addition & 1 deletion src/Bootstrap/Data/Bootstrappable/Haskell/PreludeHs.hs
Original file line number Diff line number Diff line change
Expand Up @@ -36,5 +36,5 @@ preludeHsFor :: ProjectType -> Maybe PreludeHs
preludeHsFor = \case
Haskell (HaskellOptions _ haskellProjectType) -> case haskellProjectType of
HaskellProjectTypeReplOnly -> Nothing
HaskellProjectTypeBasic -> Just PreludeHs
HaskellProjectTypeBasic _ -> Just PreludeHs
_ -> Nothing
Original file line number Diff line number Diff line change
Expand Up @@ -142,7 +142,7 @@ nixPreCommitHookConfigFor RunConfig {rcUseFlakes} projectType =
Minimal -> []
Elm _ -> [elmFormat, elmReview, prettier]
Haskell (HaskellOptions _ HaskellProjectTypeReplOnly) -> []
Haskell (HaskellOptions _ HaskellProjectTypeBasic) -> [hlint, hpack, ormolu]
Haskell (HaskellOptions _ (HaskellProjectTypeBasic _)) -> [hlint, hpack, ormolu]
Node _ -> [prettier]
Go _ -> [goFmt, goTest]
Java {} -> [googleJavaFormat]
Expand Down
2 changes: 1 addition & 1 deletion src/Bootstrap/Data/Bootstrappable/NixShell.hs
Original file line number Diff line number Diff line change
Expand Up @@ -125,7 +125,7 @@ nixShellFor RunConfig {rcUseFlakes} projectType preCommitHooksConfig nixPreCommi
|= ghcWithPackages
( case haskellProjectType of
HaskellProjectTypeReplOnly -> [[nixident|cabal-install|]]
HaskellProjectTypeBasic -> [[nixident|cabal-install|], [nixident|haskell-language-server|]]
HaskellProjectTypeBasic _ -> [[nixident|cabal-install|], [nixident|haskell-language-server|]]
)
]
Node _ -> []
Expand Down
28 changes: 17 additions & 11 deletions src/Bootstrap/Data/Bootstrappable/Readme.hs
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,7 @@ import Bootstrap.Data.ProjectType
HaskellProjectType (HaskellProjectTypeBasic, HaskellProjectTypeReplOnly),
ProjectType (Elm, Go, Haskell, Python),
SetUpGoBuild (SetUpGoBuild),
SetUpHaskellBuild (SetUpHaskellBuild),
)
import Bootstrap.Nix.Command
( NixCommand (NixCommand),
Expand All @@ -46,6 +47,19 @@ instance Bootstrappable Readme where
bootstrapReason = const "This helpfully explains to you what each file (including itself) does!"
bootstrapContent Readme {..} = do
let commandStyle = if readmeUseFlakes then NCSNew else NCSOld
buildFileName = if readmeUseFlakes then "nix/build.nix" else "default.nix"
buildingForProduction =
[ "",
"## Building for Production",
"",
"To produce a production build as defined in `"
<> buildFileName
<> "`, run `"
<> writeNixCommand (NixCommand commandStyle NCVBuild)
<> "`.",
"",
"This will produce a `result` directory with built artefacts."
]
pure . Right . unlines $
intersperse
""
Expand Down Expand Up @@ -179,24 +193,16 @@ instance Bootstrappable Readme where
"",
"You can use the provided Haskell repl by running `cabal repl` in the dev shell."
]
HaskellProjectTypeBasic ->
HaskellProjectTypeBasic (SetUpHaskellBuild withBuild) ->
[ "",
"## Using your project",
"",
"1. Generate a cabal file by running `hpack`",
"2. `cabal build` will build your application",
"3. `cabal run app` will run your application. **Note:** this will initially fail until you replace the body of the `lib` function in `src/Lib.hs`."
]
Go (SetUpGoBuild True) ->
[ "",
"## Building for Production",
"",
"To produce a production build as defined in `default.nix`, run `"
<> writeNixCommand (NixCommand commandStyle NCVBuild)
<> "`.",
"",
"This will produce a `result` directory with built artefacts."
]
<> if withBuild then buildingForProduction else []
Go (SetUpGoBuild True) -> buildingForProduction
Python _ ->
[ "",
"## Adding Python Dependencies",
Expand Down
8 changes: 4 additions & 4 deletions src/Bootstrap/Data/Config.hs
Original file line number Diff line number Diff line change
Expand Up @@ -32,8 +32,8 @@ import Bootstrap.Data.Config.Internal
LoadConfigResultFound,
LoadConfigResultNotFound
),
VersionedConfig (VersionedConfigV5),
VersionedProjectType (VPT5),
VersionedConfig (VersionedConfigV6),
VersionedProjectType (VPT6),
configV3ProjectName,
configV3ProjectType,
configV3SetUpContinuousIntegration,
Expand Down Expand Up @@ -65,5 +65,5 @@ configFor ::
Bool ->
Config
configFor a1 a2 a3 a4 a5 a6 =
VersionedConfigV5 $
ConfigV3Plus a1 (VPT5 a2) a3 a4 a5 a6
VersionedConfigV6 $
ConfigV3Plus a1 (VPT6 a2) a3 a4 a5 a6
Loading

0 comments on commit 76aa5ac

Please sign in to comment.