-
Notifications
You must be signed in to change notification settings - Fork 7
Expand file tree
/
Copy pathrake_assets_install.rs
More file actions
142 lines (125 loc) · 5.51 KB
/
Copy pathrake_assets_install.rs
File metadata and controls
142 lines (125 loc) · 5.51 KB
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
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
use crate::rake_task_detect::RakeDetect;
use crate::RubyBuildpack;
use crate::RubyBuildpackError;
use bullet_stream::state::SubBullet;
use bullet_stream::{style, Print};
use commons::cache::{mib, AppCache, CacheConfig, CacheError, CacheState, KeepPath, PathState};
use fun_run::{self, CommandWithName};
use libcnb::build::BuildContext;
use libcnb::Env;
use std::io::Stdout;
use std::process::Command;
pub(crate) fn rake_assets_install(
mut bullet: Print<SubBullet<Stdout>>,
context: &BuildContext<RubyBuildpack>,
env: &Env,
rake_detect: &RakeDetect,
) -> Result<Print<SubBullet<Stdout>>, RubyBuildpackError> {
let help = style::important("HELP");
let cases = asset_cases(rake_detect);
let rake_assets_precompile = style::value("rake assets:precompile");
let rake_assets_clean = style::value("rake assets:clean");
let rake_detect_cmd = style::value("rake -P");
match cases {
AssetCases::None => {
bullet = bullet.sub_bullet(format!(
"Skipping {rake_assets_clean} (task not found via {rake_detect_cmd})",
)).sub_bullet(format!("{help} Enable cleaning assets by ensuring {rake_assets_clean} is present when running the detect command locally"));
}
AssetCases::PrecompileOnly => {
bullet = bullet.sub_bullet(
format!("Compiling assets without cache (Clean task not found via {rake_detect_cmd})"),
).sub_bullet(format!("{help} Enable caching by ensuring {rake_assets_clean} is present when running the detect command locally"));
let mut cmd = Command::new("rake");
cmd.args(["assets:precompile", "--trace"])
.env_clear()
.envs(env);
bullet
.stream_with(
format!("Running {}", style::command(cmd.name())),
|stdout, stderr| cmd.stream_output(stdout, stderr),
)
.map_err(|error| {
fun_run::map_which_problem(error, &mut cmd, env.get("PATH").cloned())
})
.map_err(RubyBuildpackError::RakeAssetsPrecompileFailed)?;
}
AssetCases::PrecompileAndClean => {
bullet = bullet.sub_bullet(format!("Compiling assets with cache (detected {rake_assets_precompile} and {rake_assets_clean} via {rake_detect_cmd})"));
let cache_config = [
CacheConfig {
path: context.app_dir.join("public").join("assets"),
limit: mib(100),
keep_path: KeepPath::Runtime,
},
CacheConfig {
path: context.app_dir.join("tmp").join("cache").join("assets"),
limit: mib(100),
keep_path: KeepPath::BuildOnly,
},
];
let caches = cache_config
.into_iter()
.map(|config| AppCache::new_and_load(context, config))
.collect::<Result<Vec<AppCache>, CacheError>>()
.map_err(RubyBuildpackError::InAppDirCacheError)?;
for store in &caches {
let path = store.path().display();
bullet = bullet.sub_bullet(match store.cache_state() {
CacheState::NewEmpty => format!("Creating cache for {path}"),
CacheState::ExistsEmpty => format!("Loading (empty) cache for {path}"),
CacheState::ExistsWithContents => format!("Loading cache for {path}"),
});
}
let mut cmd = Command::new("rake");
cmd.args(["assets:precompile", "assets:clean", "--trace"])
.env_clear()
.envs(env);
bullet
.stream_with(
format!("Running {}", style::command(cmd.name())),
|stdout, stderr| cmd.stream_output(stdout, stderr),
)
.map_err(|error| {
fun_run::map_which_problem(error, &mut cmd, env.get("PATH").cloned())
})
.map_err(RubyBuildpackError::RakeAssetsPrecompileFailed)?;
for store in caches {
let path = store.path().display();
bullet = bullet.sub_bullet(match store.path_state() {
PathState::Empty => format!("Storing cache for (empty) {path}"),
PathState::HasFiles => format!("Storing cache for {path}"),
});
if let Some(removed) = store
.save_and_clean()
.map_err(RubyBuildpackError::InAppDirCacheError)?
{
let path = store.path().display();
let limit = store.limit();
let removed_len = removed.files.len();
let removed_size = removed.adjusted_bytes();
bullet = bullet.sub_bullet(format!("Detected cache size exceeded (over {limit} limit by {removed_size}) for {path}"))
.sub_bullet(
format!("Removed {removed_len} files from the cache for {path}"),
);
}
}
}
}
Ok(bullet)
}
#[derive(Clone, Debug)]
enum AssetCases {
None,
PrecompileOnly,
PrecompileAndClean,
}
fn asset_cases(rake: &RakeDetect) -> AssetCases {
if !rake.has_task("assets:precompile") {
AssetCases::None
} else if rake.has_task("assets:clean") {
AssetCases::PrecompileAndClean
} else {
AssetCases::PrecompileOnly
}
}