Skip to content

Commit

Permalink
os conditional starter (#999)
Browse files Browse the repository at this point in the history
* os conditional starter

* align release process + test fixes

* flaky test
  • Loading branch information
jondot authored Nov 21, 2024
1 parent e82bd7d commit 694a131
Show file tree
Hide file tree
Showing 16 changed files with 181 additions and 39 deletions.
3 changes: 3 additions & 0 deletions .github/workflows/loco-new.yml
Original file line number Diff line number Diff line change
Expand Up @@ -65,6 +65,9 @@ jobs:
- name: Run sccache-cache
uses: mozilla-actions/[email protected]

- name: Install seaorm cli
run: cargo install sea-orm-cli

- name: Run cargo test
run: cargo test --all-features -- --test-threads 1
working-directory: ./loco-new
Expand Down
1 change: 1 addition & 0 deletions loco-gen/.gitattributes
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
src/templates/* text eol=lf
Original file line number Diff line number Diff line change
@@ -1,4 +1,9 @@
[alias]
loco = "run --"
{%- if settings.os == "windows" %}
loco-tool = "run --bin tool --"
{% else %}
loco-tool = "run --"
{%- endif %}

playground = "run --example playground"
2 changes: 2 additions & 0 deletions loco-new/base_template/Cargo.toml.t
Original file line number Diff line number Diff line change
Expand Up @@ -58,10 +58,12 @@ name = "{{settings.module_name}}-cli"
path = "src/bin/main.rs"
required-features = []

{%- if settings.os == "windows" %}
[[bin]]
name = "tool"
path = "src/bin/tool.rs"
required-features = []
{%- endif %}

[dev-dependencies]
loco-rs = { workspace = true, features = ["testing"] }
Expand Down
11 changes: 9 additions & 2 deletions loco-new/setup.rhai
Original file line number Diff line number Diff line change
Expand Up @@ -4,9 +4,11 @@
// Copy core project structure files and directories that are fundamental
// to the Rust environment, GitHub actions, and formatting settings.

gen.copy_dirs([".cargo", ".github"]);
gen.copy_dirs([".github"]);
gen.copy_files([".gitignore", ".rustfmt.toml", "README.md"]);

gen.copy_template_dir(".cargo");

// =====================
// Core Source Files
// =====================
Expand All @@ -20,7 +22,12 @@ gen.copy_template("src/initializers/mod.rs.t"); // initializer module
gen.copy_template("src/app.rs.t"); // App root file
gen.copy_template("src/lib.rs.t"); // Library entry file
gen.copy_template("Cargo.toml.t"); // Project’s cargo configuration
gen.copy_template_dir("src/bin"); // Copies binary directory with templates

// bin
gen.copy_template("src/bin/main.rs.t");
if windows {
gen.copy_template("src/bin/tool.rs.t");
}


// =====================
Expand Down
17 changes: 14 additions & 3 deletions loco-new/src/bin/main.rs
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@ use duct::cmd;
use loco::{
generator::{executer, extract_default_template, Generator},
settings::Settings,
wizard, Result,
wizard, Result, OS,
};
use tracing::level_filters::LevelFilter;
use tracing_subscriber::EnvFilter;
Expand Down Expand Up @@ -51,12 +51,21 @@ enum Commands {
#[arg(long)]
assets: Option<wizard::AssetsOption>,

/// Allows create loco starter in target git repository
/// Create the starter in target git repository
#[arg(short, long)]
allow_in_git_repo: bool,

/// Create a Unix (linux, mac) or Windows optimized starter
#[arg(long, default_value = DEFAULT_OS)]
os: OS,
},
}

#[cfg(unix)]
const DEFAULT_OS: &str = "linux";
#[cfg(not(unix))]
const DEFAULT_OS: &str = "windows";

#[allow(clippy::cognitive_complexity)]
fn main() -> Result<()> {
let cli = Cli::parse();
Expand All @@ -76,7 +85,9 @@ fn main() -> Result<()> {
assets,
name,
allow_in_git_repo,
os,
} => {
tracing::debug!(path = ?path, db = ?db, bg=?bg, assets=?assets,name=?name, allow_in_git_repo=allow_in_git_repo, os=?os, "CLI options");
if !allow_in_git_repo && is_a_git_repo(path.as_path()).unwrap_or(false) {
tracing::debug!("the target directory is a Git repository");
wizard::warn_if_in_git_repo()?;
Expand Down Expand Up @@ -108,7 +119,7 @@ fn main() -> Result<()> {
let executor =
executer::FileSystem::new(generator_tmp_folder.as_path(), to.as_path());

let settings = Settings::from_wizard(&app_name, &user_selection);
let settings = Settings::from_wizard(&app_name, &user_selection, os);

if let Ok(path) = env::var("LOCO_DEV_MODE_PATH") {
println!("⚠️ NOTICE: working in dev mode, pointing to local Loco on '{path}'");
Expand Down
3 changes: 2 additions & 1 deletion loco-new/src/generator/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@ use std::sync::Arc;
use include_dir::{include_dir, Dir};
use rhai::{Engine, Scope};

use crate::settings;
use crate::{settings, OS};

static APP_TEMPLATE: Dir<'_> = include_dir!("base_template");

Expand Down Expand Up @@ -87,6 +87,7 @@ impl Generator {
scope.push("background", self.settings.background.is_some());
scope.push("initializers", self.settings.initializers.is_some());
scope.push("asset", self.settings.asset.is_some());
scope.push("windows", self.settings.os == OS::Windows);

engine.run_with_scope(&mut scope, script)?;
Ok(())
Expand Down
18 changes: 18 additions & 0 deletions loco-new/src/lib.rs
Original file line number Diff line number Diff line change
@@ -1,3 +1,7 @@
use clap::ValueEnum;
use serde::{Deserialize, Serialize};
use strum::Display;

pub mod generator;
pub mod settings;
pub mod wizard;
Expand Down Expand Up @@ -32,3 +36,17 @@ impl Error {
Self::Message(msg.into())
}
}

#[derive(Debug, Clone, Deserialize, Serialize, Display, Default, PartialEq, Eq, ValueEnum)]
pub enum OS {
#[cfg_attr(windows, default)]
#[serde(rename = "windows")]
Windows,

#[cfg_attr(unix, default)]
#[serde(rename = "linux")]
Linux,

#[serde(rename = "macos")]
Macos,
}
7 changes: 5 additions & 2 deletions loco-new/src/settings.rs
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@ use serde::{Deserialize, Serialize};

use crate::{
wizard::{self, AssetsOption, BackgroundOption, DBOption},
LOCO_VERSION,
LOCO_VERSION, OS,
};

/// Represents general application settings.
Expand All @@ -25,6 +25,7 @@ pub struct Settings {
pub initializers: Option<Initializers>,
pub features: Features,
pub loco_version_text: String,
pub os: OS,
}

impl From<DBOption> for Option<Db> {
Expand Down Expand Up @@ -60,7 +61,7 @@ impl From<AssetsOption> for Option<Asset> {
impl Settings {
/// Creates a new [`Settings`] instance based on prompt selections.
#[must_use]
pub fn from_wizard(package_name: &str, prompt_selection: &wizard::Selections) -> Self {
pub fn from_wizard(package_name: &str, prompt_selection: &wizard::Selections, os: OS) -> Self {
let features = if prompt_selection.db.enable() {
Features::default()
} else {
Expand All @@ -87,6 +88,7 @@ impl Settings {
},
features,
loco_version_text: get_loco_version_text(),
os,
}
}
}
Expand All @@ -105,6 +107,7 @@ impl Default for Settings {
initializers: Default::default(),
features: Default::default(),
loco_version_text: get_loco_version_text(),
os: Default::default(),
}
}
}
Expand Down
1 change: 1 addition & 0 deletions loco-new/tests/templates/db.rs
Original file line number Diff line number Diff line change
Expand Up @@ -101,6 +101,7 @@ fn test_src_bin_main_rs(
}

#[rstest]
#[cfg(windows)]
fn test_src_bin_tool_rs(
#[values(DBOption::None, DBOption::Sqlite, DBOption::Postgres)] db: DBOption,
) {
Expand Down
4 changes: 1 addition & 3 deletions loco-new/tests/templates/module_name.rs
Original file line number Diff line number Diff line change
Expand Up @@ -36,9 +36,7 @@ fn test_cargo_toml() {
}

#[rstest]
fn test_use_name(
#[values("src/bin/main.rs", "src/bin/tool.rs", "tests/requests/home.rs")] file: &str,
) {
fn test_use_name(#[values("src/bin/main.rs", "tests/requests/home.rs")] file: &str) {
let generator = run_generator();

let content = std::fs::read_to_string(generator.path(file)).expect("could not open file");
Expand Down
50 changes: 44 additions & 6 deletions loco-new/tests/wizard/new.rs
Original file line number Diff line number Diff line change
Expand Up @@ -3,8 +3,9 @@ use std::{fs, path::PathBuf, sync::Arc};
use duct::cmd;
use loco::{
generator::{executer::FileSystem, Generator},
settings, wizard,
wizard::{AssetsOption, BackgroundOption, DBOption},
settings,
wizard::{self, AssetsOption, BackgroundOption, DBOption},
OS,
};
use uuid::Uuid;

Expand Down Expand Up @@ -43,35 +44,48 @@ fn test_all_combinations(
#[values(AssetsOption::Serverside, AssetsOption::Clientside, AssetsOption::None)]
asset: AssetsOption,
) {
test_combination(db, background, asset);
test_combination(db, background, asset, false);
}

// when running locally set LOCO_DEV_MODE_PATH=<to local loco path>
#[test]
fn test_starter_combinations() {
// lightweight service
test_combination(DBOption::None, BackgroundOption::None, AssetsOption::None);
test_combination(
DBOption::None,
BackgroundOption::None,
AssetsOption::None,
false,
);
// REST API
test_combination(
DBOption::Sqlite,
BackgroundOption::Async,
AssetsOption::None,
true,
);
// SaaS, serverside
test_combination(
DBOption::Sqlite,
BackgroundOption::Async,
AssetsOption::Serverside,
true,
);
// SaaS, clientside
test_combination(
DBOption::Sqlite,
BackgroundOption::Async,
AssetsOption::Clientside,
true,
);
}

fn test_combination(db: DBOption, background: BackgroundOption, asset: AssetsOption) {
fn test_combination(
db: DBOption,
background: BackgroundOption,
asset: AssetsOption,
scaffold: bool,
) {
use std::collections::HashMap;

let test_dir = TestDir::new();
Expand All @@ -83,7 +97,8 @@ fn test_combination(db: DBOption, background: BackgroundOption, asset: AssetsOpt
background,
asset,
};
let settings = settings::Settings::from_wizard("test-loco-template", &wizard_selection);
let settings =
settings::Settings::from_wizard("test-loco-template", &wizard_selection, OS::default());

let res = Generator::new(Arc::new(executor), settings).run();
assert!(res.is_ok());
Expand Down Expand Up @@ -116,4 +131,27 @@ fn test_combination(db: DBOption, background: BackgroundOption, asset: AssetsOpt
.dir(test_dir.path.as_path())
.run()
.expect("run test");

if scaffold {
cmd!(
"cargo",
"loco",
"g",
"scaffold",
"movie",
"title:string",
"--htmx"
)
.full_env(&env_map)
.dir(test_dir.path.as_path())
.run()
.expect("scaffold");
cmd!("cargo", "test")
// .stdout_null()
// .stderr_null()
.full_env(&env_map)
.dir(test_dir.path.as_path())
.run()
.expect("test after scaffold");
}
}
19 changes: 14 additions & 5 deletions src/controller/middleware/secure_headers.rs
Original file line number Diff line number Diff line change
Expand Up @@ -227,12 +227,21 @@ where
mod tests {

use axum::{routing::get, Router};
use hyper::Method;
use hyper::{HeaderMap, Method};
use insta::assert_debug_snapshot;
use tower::ServiceExt;

use super::*;

fn normalize_headers(headers: &HeaderMap) -> BTreeMap<String, String> {
headers
.iter()
.map(|(k, v)| {
let key = k.to_string();
let value = v.to_str().unwrap_or("").to_string();
(key, value)
})
.collect()
}
#[tokio::test]
async fn can_set_headers() {
let config = SecureHeader {
Expand All @@ -250,7 +259,7 @@ mod tests {
.body(Body::empty())
.unwrap();
let response = app.oneshot(req).await.unwrap();
assert_debug_snapshot!(response.headers());
assert_debug_snapshot!(normalize_headers(response.headers()));
}

#[tokio::test]
Expand All @@ -274,7 +283,7 @@ mod tests {
.body(Body::empty())
.unwrap();
let response = app.oneshot(req).await.unwrap();
assert_debug_snapshot!(response.headers());
assert_debug_snapshot!(normalize_headers(response.headers()));
}

#[tokio::test]
Expand All @@ -290,6 +299,6 @@ mod tests {
.body(Body::empty())
.unwrap();
let response = app.oneshot(req).await.unwrap();
assert_debug_snapshot!(response.headers());
assert_debug_snapshot!(normalize_headers(response.headers()));
}
}
Original file line number Diff line number Diff line change
@@ -1,15 +1,16 @@
---
source: src/controller/middleware/secure_headers.rs
expression: res.headers()
expression: normalize_headers(response.headers())
snapshot_kind: text
---
{
"content-length": "0",
"content-security-policy": "default-src 'self' https:; font-src 'self' https: data:; img-src 'self' https: data:; object-src 'none'; script-src https:; style-src 'self' https: 'unsafe-inline'",
"new-header": "baz",
"strict-transport-security": "max-age=631138519",
"x-content-type-options": "nosniff",
"x-download-options": "foobar",
"x-frame-options": "sameorigin",
"x-permitted-cross-domain-policies": "none",
"x-xss-protection": "0",
"new-header": "baz",
}
Loading

0 comments on commit 694a131

Please sign in to comment.