1use steps::{Step, Context, error::StepError};
3use cmd::*;
4
5const NO_PREV_ERR_MSG: &str = "Can't rollback because there is no release to rollback to.";
6
7pub struct CanRollBack;
9
10impl Step for CanRollBack {
13
14 fn execute (&self, context: &Context) -> Result<(), StepError> {
15 context.prev_release_path.as_ref().ok_or(StepError::Critical(NO_PREV_ERR_MSG.into())).map(|_| ())
16 }
17
18 fn get_name(&self) -> &str {
19 "rollback:check"
20 }
21}
22
23pub struct RemoveCurrentRelease;
27
28impl Step for RemoveCurrentRelease {
30
31 fn execute (&self, context: &Context) -> Result<(), StepError> {
32
33 let release_path = &context.release_path;
34 let cmd = format!("rm -rf {}", release_path);
35 let output = exec_remote_cmd(&context.config.host, &cmd)?;
36
37 match output.status.success() {
38 true => Ok(()),
39 false => {
40 let err_msg = format!("Failed to remove current release at {}", release_path);
41 Err(StepError::Critical(err_msg))
42 }
43 }
44 }
45
46 fn get_name(&self) -> &str {
47 "rollback:rm:latest"
48 }
49}
50
51pub struct SymlinkPreviousRelease;
53
54impl Step for SymlinkPreviousRelease {
55
56 fn execute (&self, context: &Context) -> Result<(), StepError> {
57
58 let current_symlink_path = format!("{}/current", context.config.deploy_path);
59 let current_symlink_exist = exec_remote_file_exists(&context.config.host, ¤t_symlink_path, FSResourceType::Symlink)?;
60
61 if current_symlink_exist {
63 let remove_current_command = format!("rm {}", current_symlink_path);
64
65 let status = exec_remote_cmd(&context.config.host, &remove_current_command)?.status;
66
67 if !status.success() {
68 return Err(StepError::from_failed_command(&remove_current_command, status.code()));
69 }
70 }
71
72 let prev_release_path = context.prev_release_path.as_ref().unwrap();
73 let create_current_symlink_cmd = format!("ln -s {} {}", prev_release_path.trim(), current_symlink_path);
74 let status = exec_remote_cmd(&context.config.host, &create_current_symlink_cmd)?.status;
75
76 if !status.success() {
77 return Err(StepError::from_failed_command(&create_current_symlink_cmd, status.code()));
78 }
79
80 Ok(())
81 }
82
83 fn get_name(&self) -> &str {
84 "rollback:symlink:previous"
85 }
86}