1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
use super::Provider;
use crate::nixpacks::{
    app::App,
    environment::{Environment, EnvironmentVariables},
    nix::pkg::Pkg,
    plan::{
        phase::{Phase, StartPhase},
        BuildPlan,
    },
};
use anyhow::{Context, Result};

pub struct FSharpProvider {}

pub const ARTIFACT_DIR: &str = "out";

impl Provider for FSharpProvider {
    fn name(&self) -> &str {
        "f#"
    }

    fn detect(&self, app: &App, _env: &Environment) -> Result<bool> {
        Ok(!app.find_files("*.fsproj")?.is_empty())
    }

    fn get_build_plan(&self, app: &App, _env: &Environment) -> Result<Option<BuildPlan>> {
        let setup = Phase::setup(Some(vec![Pkg::new("dotnet-sdk")]));
        let install = Phase::install(Some("dotnet restore".to_string()));
        let build = Phase::build(Some(format!(
            "dotnet publish --no-restore -c Release -o {}",
            ARTIFACT_DIR
        )));

        let fsproj = &app.find_files("*.fsproj")?[0].with_extension("");
        let project_name = fsproj
            .file_name()
            .context("Invalid file_name")?
            .to_str()
            .context("Invalid project_name")?;
        let start = StartPhase::new(format!("./{ARTIFACT_DIR}/{project_name}"));

        let mut plan = BuildPlan::new(&vec![setup, install, build], Some(start));
        plan.add_variables(EnvironmentVariables::from([
            (
                "ASPNETCORE_ENVIRONMENT".to_string(),
                "Production".to_string(),
            ),
            (
                "ASPNETCORE_URLS".to_string(),
                "http://0.0.0.0:3000".to_string(),
            ),
            (
                "DOTNET_ROOT".to_string(),
                "/nix/var/nix/profiles/default/".to_string(),
            ),
        ]));

        Ok(Some(plan))
    }
}