Completed
Pull Request — master (#627)
by Stig
07:45 queued 02:57
created

DeployDispatcher::log()   C

Complexity

Conditions 7
Paths 6

Size

Total Lines 26
Code Lines 18

Duplication

Lines 0
Ratio 0 %

Importance

Changes 1
Bugs 0 Features 1
Metric Value
c 1
b 0
f 1
dl 0
loc 26
rs 6.7272
cc 7
eloc 18
nc 6
nop 1
1
<?php
2
3
/**
4
 * This dispatcher takes care of updating and returning information about this
5
 * projects git repository
6
 */
7
class DeployDispatcher extends Dispatcher {
8
9
	const ACTION_DEPLOY = 'deploy';
10
11
	/**
12
	 * @var array
13
	 */
14
	private static $action_types = [
15
		self::ACTION_DEPLOY
16
	];
17
18
	/**
19
	 * @var array
20
	 */
21
	public static $allowed_actions = [
22
		'history',
23
		'start',
24
		'log'
25
	];
26
27
	/**
28
	 * @var \DNProject
29
	 */
30
	protected $project = null;
31
32
	/**
33
	 * @var \DNEnvironment
34
	 */
35
	protected $environment = null;
36
37 View Code Duplication
	public function init() {
0 ignored issues
show
Duplication introduced by
This method seems to be duplicated in your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
38
		parent::init();
39
40
		$this->project = $this->getCurrentProject();
41
42
		if(!$this->project) {
43
			return $this->project404Response();
44
		}
45
46
		// Performs canView permission check by limiting visible projects
47
		$this->environment = $this->getCurrentEnvironment($this->project);
48
		if(!$this->environment) {
49
			return $this->environment404Response();
50
		}
51
	}
52
53
	/**
54
	 *
55
	 * @param \SS_HTTPRequest $request
56
	 *
57
	 * @return \HTMLText|\SS_HTTPResponse
58
	 */
59
	public function index(\SS_HTTPRequest $request) {
60
		return $this->redirect(\Controller::join_links($this->Link(), 'history'), 302);
61
	}
62
63
	/**
64
	 * @return SS_HTTPResponse
65
	 */
66
	public function history(SS_HTTPRequest $request) {
67
		$data = [];
68
		$list = $this->DeployHistory();
69
		$page = $request->getVar('page') ?: 1;
70
		if ($page > $list->TotalPages()) {
71
			$page = 1;
72
		}
73
		if ($page < 1) {
74
			$page = 1;
75
		}
76
		$start = ($page - 1) * $list->getPageLength();
77
		$list->setPageStart((int) $start);
78
		if (empty($list)) {
79
			return $this->getAPIResponse(['message' => 'No deploy history'], 404);
80
		}
81
82
		foreach ($list as $deployment) {
83
			$data[] = [
84
				'CreatedDate' => $deployment->Created,
85
				'Branch' => $deployment->Branch,
86
				'Tags' => $deployment->getTags()->toArray(),
87
				'Changes' => $deployment->getDeploymentStrategy()->getChanges(),
88
				'CommitMessage' => $deployment->getCommitMessage(),
89
				'Deployer' => $deployment->Deployer()->getName(),
90
				'Approver' => $deployment->Approver()->getName(),
91
				'State' => $deployment->State,
92
			];
93
		}
94
95
		return $this->getAPIResponse(
96
			[
97
				'list' => $data,
98
				'pagelength' => $list->getPageLength(),
99
				'totalpages' => $list->TotalPages(),
100
				'currentpage' => $list->CurrentPage()
101
			],
102
			200
103
		);
104
	}
105
106
	/**
107
	 *
108
	 * @param SS_HTTPRequest $request
109
	 *
110
	 * @return SS_HTTPResponse
111
	 * @throws ValidationException
112
	 * @throws null
113
	 */
114
	public function start(SS_HTTPRequest $request) {
115
		$this->checkSecurityToken();
116
117
		if(!$this->environment->canDeploy(Member::currentUser())) {
0 ignored issues
show
Bug introduced by
It seems like \Member::currentUser() targeting Member::currentUser() can also be of type object<DataObject>; however, DNEnvironment::canDeploy() does only seem to accept object<Member>|null, maybe add an additional type check?

This check looks at variables that are passed out again to other methods.

If the outgoing method call has stricter type requirements than the method itself, an issue is raised.

An additional type check may prevent trouble.

Loading history...
118
			return $this->getAPIResponse(['message' => 'You are not authorized to deploy this environment'], 403);
119
		}
120
121
		// Initiate the deployment
122
		// The extension point should pass in: Project, Environment, SelectRelease, buildName
123
		// @todo: compat breakage: check what extends this in DNRoot and switch it to this dispatcher
124
		$this->extend('doDeploy', $this->project, $this->environment, $buildName, $data);
125
126
		$options = [
127
			'sha' => $request->requestVar('sha'),
128
		];
129
130
		// @todo replan and check if it's changed compared since it was originally planned?
131
		$strategy = $this->environment->Backend()->planDeploy($this->environment, $options);
132
133
		$strategy->fromArray($request->requestVars());
134
		$deployment = $strategy->createDeployment();
135
		// Skip through the approval state for now.
136
		$deployment->getMachine()->apply(DNDeployment::TR_SUBMIT);
137
		$deployment->getMachine()->apply(DNDeployment::TR_QUEUE);
138
139
		$output = [
140
			'message' => 'deployed queued',
141
			'deployID' => $deployment->ID,
142
		];
143
144
		return $this->getAPIResponse($output, 201);
145
	}
146
147
	/**
148
	    * Action - Get the latest deploy log
149
	    *
150
	    * @param SS_HTTPRequest $request
151
	    *
152
	    * @return string
153
	    * @throws SS_HTTPResponse_Exception
154
	    */
155
	public function log(SS_HTTPRequest $request) {
156
		$params = $request->params();
157
		$deployment = DNDeployment::get()->byId($params['ID']);
158
		if(!$deployment || !$deployment->ID) {
159
			throw new SS_HTTPResponse_Exception('Deployment not found', 404);
160
		}
161
		if(!$deployment->canView()) {
162
			return Security::permissionFailure();
163
		}
164
		if($this->environment->Name != $params['Environment']) {
165
			throw new LogicException("Environment in URL doesn't match this deploy");
166
		}
167
		if($this->project->Name != $params['Project']) {
168
			throw new LogicException("Project in URL doesn't match this deploy");
169
		}
170
		$log = $deployment->log();
171
		if($log->exists()) {
172
			$content = $log->content();
173
		} else {
174
			$content = 'Waiting for action to start';
175
		}
176
177
		$lines = explode(PHP_EOL, $content);
178
179
		return $this->getAPIResponse(['message' => $lines, 'status' => $deployment->ResqueStatus()], 200);
180
	}
181
182
183
	/**
184
	 * @return string
185
	 */
186
	public function Link() {
187
		return \Controller::join_links($this->project->Link(), self::ACTION_DEPLOY);
188
	}
189
190
	/**
191
	 * @param string $name
192
	 *
193
	 * @return array
194
	 */
195
	public function getModel($name = '') {
196
		return [];
197
	}
198
199
}
200