Skip to content
Projects
Groups
Snippets
Help
Loading...
Help
Support
Keyboard shortcuts
?
Submit feedback
Contribute to GitLab
Sign in / Register
Toggle navigation
G
gitlab-ce
Project overview
Project overview
Details
Activity
Releases
Repository
Repository
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Issues
0
Issues
0
List
Boards
Labels
Milestones
Merge Requests
0
Merge Requests
0
Analytics
Analytics
Repository
Value Stream
Wiki
Wiki
Snippets
Snippets
Members
Members
Collapse sidebar
Close sidebar
Activity
Graph
Create a new issue
Commits
Issue Boards
Open sidebar
Boxiang Sun
gitlab-ce
Commits
bd8d4d2e
Commit
bd8d4d2e
authored
Nov 18, 2016
by
Kamil Trzcinski
Browse files
Options
Browse Files
Download
Plain Diff
Merge branch '22539-display-folders' of gitlab.com:gitlab-org/gitlab-ce into 22539-display-folders
parents
8d001844
25f99d84
Changes
20
Expand all
Hide whitespace changes
Inline
Side-by-side
Showing
20 changed files
with
326 additions
and
359 deletions
+326
-359
app/assets/javascripts/environments/components/environment.js.es6
...ts/javascripts/environments/components/environment.js.es6
+51
-33
app/assets/javascripts/environments/components/environment_actions.js.es6
...cripts/environments/components/environment_actions.js.es6
+7
-6
app/assets/javascripts/environments/components/environment_item.js.es6
...vascripts/environments/components/environment_item.js.es6
+69
-28
app/assets/javascripts/environments/components/environment_stop.js.es6
...vascripts/environments/components/environment_stop.js.es6
+1
-1
app/assets/javascripts/environments/stores/environments_store.js.es6
...javascripts/environments/stores/environments_store.js.es6
+5
-13
app/assets/javascripts/vue_common_component/commit.js.es6
app/assets/javascripts/vue_common_component/commit.js.es6
+0
-2
app/assets/stylesheets/pages/environments.scss
app/assets/stylesheets/pages/environments.scss
+2
-0
app/serializers/build_entity.rb
app/serializers/build_entity.rb
+8
-8
app/serializers/commit_entity.rb
app/serializers/commit_entity.rb
+2
-2
app/serializers/deployment_entity.rb
app/serializers/deployment_entity.rb
+2
-2
app/serializers/environment_entity.rb
app/serializers/environment_entity.rb
+2
-2
app/views/projects/environments/index.html.haml
app/views/projects/environments/index.html.haml
+2
-1
spec/features/environment_spec.rb
spec/features/environment_spec.rb
+67
-13
spec/features/environments_spec.rb
spec/features/environments_spec.rb
+88
-227
spec/javascripts/environments/mock_data.js.es6
spec/javascripts/environments/mock_data.js.es6
+10
-11
spec/serializers/build_entity_spec.rb
spec/serializers/build_entity_spec.rb
+5
-5
spec/serializers/commit_entity_spec.rb
spec/serializers/commit_entity_spec.rb
+2
-2
spec/serializers/deployment_entity_spec.rb
spec/serializers/deployment_entity_spec.rb
+1
-1
spec/serializers/environment_entity_spec.rb
spec/serializers/environment_entity_spec.rb
+1
-1
spec/serializers/environment_serializer_spec.rb
spec/serializers/environment_serializer_spec.rb
+1
-1
No files found.
app/assets/javascripts/environments/components/environment.js.es6
View file @
bd8d4d2e
...
@@ -6,15 +6,36 @@
...
@@ -6,15 +6,36 @@
/* globals Vue, EnvironmentsService */
/* globals Vue, EnvironmentsService */
/* eslint-disable no-param-reassign */
/* eslint-disable no-param-reassign */
$(() => {
(() => { // eslint-disable-line
window.gl = window.gl || {};
window.gl = window.gl || {};
const filterState = state => environment => environment.state === state && environment;
/**
* Given the visibility prop provided by the url query parameter and which
* changes according to the active tab we need to filter which environments
* should be visible.
*
* The environments array is a recursive tree structure and we need to filter
* both root level environments and children environments.
*
* In order to acomplish that, both `filterState` and `filterEnvironmnetsByState`
* functions work together.
* The first one works as the filter that verifies if the given environment matches
* the given state.
* The second guarantees both root level and children elements are filtered as well.
*/
// recursiveMap :: (Function, Array) -> Array
const filterState = state => environment => environment.state === state && environment;
const recursiveMap = (fn, arr) => arr.map((item) => {
/**
* Given the filter function and the array of environments will return only
* the environments that match the state provided to the filter function.
*
* @param {Function} fn
* @param {Array} array
* @return {Array}
*/
const filterEnvironmnetsByState = (fn, arr) => arr.map((item) => {
if (item.children) {
if (item.children) {
const filteredChildren =
recursiveMap
(fn, item.children).filter(Boolean);
const filteredChildren =
filterEnvironmnetsByState
(fn, item.children).filter(Boolean);
if (filteredChildren.length) {
if (filteredChildren.length) {
item.children = filteredChildren;
item.children = filteredChildren;
return item;
return item;
...
@@ -37,26 +58,27 @@ $(() => {
...
@@ -37,26 +58,27 @@ $(() => {
},
},
data() {
data() {
const environments
ListApp = document.querySelector('#environments-list-view')
;
const environments
Data = document.querySelector('#environments-list-view').dataset
;
return {
return {
state: this.store.state,
state: this.store.state,
endpoint: environmentsListApp.dataset.environmentsDataEndpoint,
canCreateDeployment: environmentsListApp.dataset.canCreateDeployment,
canReadEnvironment: environmentsListApp.dataset.canReadEnvironment,
canCreateEnvironment: environmentsListApp.dataset.canCreateEnvironment,
projectEnvironmentsPath: environmentsListApp.dataset.projectEnvironmentsPath,
projectStoppedEnvironmentsPath: environmentsListApp.dataset.projectStoppedEnvironmentsPath,
newEnvironmentPath: environmentsListApp.dataset.newEnvironmentPath,
helpPagePath: environmentsListApp.dataset.helpPagePath,
visibility: 'available',
visibility: 'available',
isLoading: false,
isLoading: false,
cssContainerClass: environmentsData.cssClass,
endpoint: environmentsData.environmentsDataEndpoint,
canCreateDeployment: environmentsData.canCreateDeployment,
canReadEnvironment: environmentsData.canReadEnvironment,
canCreateEnvironment: environmentsData.canCreateEnvironment,
projectEnvironmentsPath: environmentsData.projectEnvironmentsPath,
projectStoppedEnvironmentsPath: environmentsData.projectStoppedEnvironmentsPath,
newEnvironmentPath: environmentsData.newEnvironmentPath,
helpPagePath: environmentsData.helpPagePath,
};
};
},
},
computed: {
computed: {
filteredEnvironments() {
filteredEnvironments() {
return
recursiveMap
(filterState(this.visibility), this.state.environments);
return
filterEnvironmnetsByState
(filterState(this.visibility), this.state.environments);
},
},
scope() {
scope() {
...
@@ -81,7 +103,7 @@ $(() => {
...
@@ -81,7 +103,7 @@ $(() => {
* Toggles loading property.
* Toggles loading property.
*/
*/
created() {
created() {
window.
gl.environmentsService = new EnvironmentsService(this.endpoint);
gl.environmentsService = new EnvironmentsService(this.endpoint);
const scope = this.$options.getQueryParameter('scope');
const scope = this.$options.getQueryParameter('scope');
if (scope) {
if (scope) {
...
@@ -90,7 +112,7 @@ $(() => {
...
@@ -90,7 +112,7 @@ $(() => {
this.isLoading = true;
this.isLoading = true;
return
window.
gl.environmentsService.all()
return gl.environmentsService.all()
.then(resp => resp.json())
.then(resp => resp.json())
.then((json) => {
.then((json) => {
this.store.storeEnvironments(json);
this.store.storeEnvironments(json);
...
@@ -119,10 +141,7 @@ $(() => {
...
@@ -119,10 +141,7 @@ $(() => {
* @returns {Boolean}
* @returns {Boolean}
*/
*/
convertPermissionToBoolean(string) {
convertPermissionToBoolean(string) {
if (string === 'true') {
return string === 'true';
return true;
}
return false;
},
},
methods: {
methods: {
...
@@ -132,10 +151,10 @@ $(() => {
...
@@ -132,10 +151,10 @@ $(() => {
},
},
template: `
template: `
<div
class="container-fluid container-limited
">
<div
:class="cssContainerClass
">
<div class="top-area">
<div class="top-area">
<ul v-if="!isLoading" class="nav-links">
<ul v-if="!isLoading" class="nav-links">
<li v-bind:class="{ 'active': scope === undefined}">
<li v-bind:class="{ 'active': scope === undefined
}">
<a :href="projectEnvironmentsPath">
<a :href="projectEnvironmentsPath">
Available
Available
<span
<span
...
@@ -143,7 +162,7 @@ $(() => {
...
@@ -143,7 +162,7 @@ $(() => {
v-html="state.availableCounter"></span>
v-html="state.availableCounter"></span>
</a>
</a>
</li>
</li>
<li v-bind:class="{ 'active' : scope === 'stopped'}">
<li v-bind:class="{ 'active' : scope === 'stopped'
}">
<a :href="projectStoppedEnvironmentsPath">
<a :href="projectStoppedEnvironmentsPath">
Stopped
Stopped
<span
<span
...
@@ -172,19 +191,18 @@ $(() => {
...
@@ -172,19 +191,18 @@ $(() => {
</h2>
</h2>
<p class="blank-state-text">
<p class="blank-state-text">
Environments are places where code gets deployed, such as staging or production.
Environments are places where code gets deployed, such as staging or production.
<br />
<br />
<a :href="helpPagePath">
<a :href="helpPagePath">
Read more about environments
Read more about environments
</a>
</a>
<a
v-if="canCreateEnvironmentParsed"
:href="newEnvironmentPath"
class="btn btn-create">
New Environment
</a>
</p>
</p>
<a
v-if="canCreateEnvironmentParsed"
:href="newEnvironmentPath"
class="btn btn-create">
New Environment
</a>
</div>
</div>
<div
<div
...
@@ -227,4 +245,4 @@ $(() => {
...
@@ -227,4 +245,4 @@ $(() => {
</div>
</div>
`,
`,
});
});
});
})
()
;
app/assets/javascripts/environments/components/environment_actions.js.es6
View file @
bd8d4d2e
...
@@ -44,18 +44,19 @@
...
@@ -44,18 +44,19 @@
<div class="dropdown">
<div class="dropdown">
<a class="dropdown-new btn btn-default" data-toggle="dropdown">
<a class="dropdown-new btn btn-default" data-toggle="dropdown">
<span class="dropdown-play-icon-container">
<span class="dropdown-play-icon-container">
<!-- svg goes here -->
</span>
</span>
<i class="fa fa-caret-down"></i>
<i class="fa fa-caret-down"></i>
</a>
</a>
<ul class="dropdown-menu dropdown-menu-align-right">
<ul class="dropdown-menu dropdown-menu-align-right">
<li v-for="action in actions">
<li v-for="action in actions">
<a :href="action.play_url" data-method="post" data-rel="nofollow" class="js-manual-action-link">
<a :href="action.play_path"
<span class="action-play-icon-container">
data-method="post"
<!-- svg goes here -->
rel="nofollow"
</span>
class="js-manual-action-link">
<span v-html="action.name"></span>
<span class="action-play-icon-container">
</span>
<span v-html="action.name"></span>
</a>
</a>
</li>
</li>
</ul>
</ul>
...
...
app/assets/javascripts/environments/components/environment_item.js.es6
View file @
bd8d4d2e
...
@@ -76,8 +76,7 @@
...
@@ -76,8 +76,7 @@
* @returns {Boolean|Undefined}
* @returns {Boolean|Undefined}
*/
*/
isFolder() {
isFolder() {
return this.model.children &&
return this.model.children && this.model.children.length > 0;
this.model.children.length > 0;
},
},
/**
/**
...
@@ -97,8 +96,7 @@
...
@@ -97,8 +96,7 @@
* @returns {Number|Undefined} The number of environments for the current folder.
* @returns {Number|Undefined} The number of environments for the current folder.
*/
*/
childrenCounter() {
childrenCounter() {
return this.model.children &&
return this.model.children && this.model.children.length;
this.model.children.length;
},
},
/**
/**
...
@@ -109,7 +107,8 @@
...
@@ -109,7 +107,8 @@
* @returns {Boolean}
* @returns {Boolean}
*/
*/
hasLastDeploymentKey() {
hasLastDeploymentKey() {
if (this.model.last_deployment && this.model.last_deployment !== {}) {
if (this.model.last_deployment &&
!this.$options.isObjectEmpty(this.model.last_deployment)) {
return true;
return true;
}
}
return false;
return false;
...
@@ -168,7 +167,7 @@
...
@@ -168,7 +167,7 @@
return this.model.last_deployment.manual_actions.map((action) => {
return this.model.last_deployment.manual_actions.map((action) => {
const parsedAction = {
const parsedAction = {
name: gl.text.humanize(action.name),
name: gl.text.humanize(action.name),
play_
url: action.play_url
,
play_
path: action.play_path
,
};
};
return parsedAction;
return parsedAction;
});
});
...
@@ -209,8 +208,7 @@
...
@@ -209,8 +208,7 @@
* @returns {Object|Undefined}
* @returns {Object|Undefined}
*/
*/
commitRef() {
commitRef() {
if (this.model.last_deployment &&
if (this.model.last_deployment && this.model.last_deployment.ref) {
this.model.last_deployment.ref) {
return this.model.last_deployment.ref;
return this.model.last_deployment.ref;
}
}
return undefined;
return undefined;
...
@@ -224,8 +222,8 @@
...
@@ -224,8 +222,8 @@
commitUrl() {
commitUrl() {
if (this.model.last_deployment &&
if (this.model.last_deployment &&
this.model.last_deployment.commit &&
this.model.last_deployment.commit &&
this.model.last_deployment.commit.commit_
url
) {
this.model.last_deployment.commit.commit_
path
) {
return this.model.last_deployment.commit.commit_
url
;
return this.model.last_deployment.commit.commit_
path
;
}
}
return undefined;
return undefined;
},
},
...
@@ -274,15 +272,15 @@
...
@@ -274,15 +272,15 @@
},
},
/**
/**
* Verifies if the `retry_
url
` key is present and returns its value.
* Verifies if the `retry_
path
` key is present and returns its value.
*
*
* @returns {String|Undefined}
* @returns {String|Undefined}
*/
*/
retryUrl() {
retryUrl() {
if (this.model.last_deployment &&
if (this.model.last_deployment &&
this.model.last_deployment.deployable &&
this.model.last_deployment.deployable &&
this.model.last_deployment.deployable.retry_
url
) {
this.model.last_deployment.deployable.retry_
path
) {
return this.model.last_deployment.deployable.retry_
url
;
return this.model.last_deployment.deployable.retry_
path
;
}
}
return undefined;
return undefined;
},
},
...
@@ -328,11 +326,8 @@
...
@@ -328,11 +326,8 @@
* @returns {Boolean}
* @returns {Boolean}
*/
*/
deploymentHasUser() {
deploymentHasUser() {
if (this.model.last_deployment &&
return !this.$options.isObjectEmpty(this.model.last_deployment) &&
this.model.last_deployment.user) {
!this.$options.isObjectEmpty(this.model.last_deployment.user);
return true;
}
return false;
},
},
/**
/**
...
@@ -342,11 +337,53 @@
...
@@ -342,11 +337,53 @@
* @returns {Object}
* @returns {Object}
*/
*/
deploymentUser() {
deploymentUser() {
if (this.model.last_deployment && this.model.last_deployment.user) {
if (!this.$options.isObjectEmpty(this.model.last_deployment) &&
!this.$options.isObjectEmpty(this.model.last_deployment.user)) {
return this.model.last_deployment.user;
return this.model.last_deployment.user;
}
}
return {};
return {};
},
},
/**
* Verifies if the build name column should be rendered by verifing
* if all the information needed is present
* and if the environment is not a folder.
*
* @returns {Boolean}
*/
shouldRenderBuildName() {
return !this.isFolder &&
!this.$options.isObjectEmpty(this.model.last_deployment) &&
!this.$options.isObjectEmpty(this.model.last_deployment.deployable);
},
/**
* Verifies if deplyment internal ID should be rendered by verifing
* if all the information needed is present
* and if the environment is not a folder.
*
* @returns {Boolean}
*/
shouldRenderDeploymentID() {
return !this.isFolder &&
!this.$options.isObjectEmpty(this.model.last_deployment) &&
this.model.last_deployment.iid !== undefined;
},
},
/**
* Helper to verify if certain given object are empty.
* Should be replaced by lodash _.isEmpty - https://lodash.com/docs/4.17.2#isEmpty
* @param {Object} object
* @returns {Bollean}
*/
isObjectEmpty(object) {
for (const key in object) { // eslint-disable-line
if (hasOwnProperty.call(object, key)) {
return false;
}
}
return true;
},
},
template: `
template: `
...
@@ -355,7 +392,7 @@
...
@@ -355,7 +392,7 @@
<a
<a
v-if="!isFolder"
v-if="!isFolder"
class="environment-name"
class="environment-name"
:href="model.environment_
url
"
:href="model.environment_
path
"
v-html="model.name">
v-html="model.name">
</a>
</a>
<span v-else v-on:click="toggleRow(model)" class="folder-name">
<span v-else v-on:click="toggleRow(model)" class="folder-name">
...
@@ -372,7 +409,7 @@
...
@@ -372,7 +409,7 @@
<td class="deployment-column">
<td class="deployment-column">
<span
<span
v-if="
!isFolder && model.last_deployment && model.last_deployment.iid
"
v-if="
shouldRenderDeploymentID
"
v-html="deploymentInternalId">
v-html="deploymentInternalId">
</span>
</span>
...
@@ -388,9 +425,9 @@
...
@@ -388,9 +425,9 @@
</td>
</td>
<td>
<td>
<a v-if="
!isFolder && model.last_deployment && model.last_deployment.deployabl
e"
<a v-if="
shouldRenderBuildNam
e"
class="build-link"
class="build-link"
:href="model.last_deployment.deployable.build_
url
"
:href="model.last_deployment.deployable.build_
path
"
v-html="buildName">
v-html="buildName">
</a>
</a>
</td>
</td>
...
@@ -421,25 +458,29 @@
...
@@ -421,25 +458,29 @@
<td class="hidden-xs">
<td class="hidden-xs">
<div v-if="!isFolder">
<div v-if="!isFolder">
<div v-if="hasManualActions && canCreateDeployment" class="inline js-manual-actions-container">
<div v-if="hasManualActions && canCreateDeployment"
class="inline js-manual-actions-container">
<actions-component
<actions-component
:actions="manualActions">
:actions="manualActions">
</actions-component>
</actions-component>
</div>
</div>
<div v-if="model.external_url && canReadEnvironment" class="inline js-external-url-container">
<div v-if="model.external_url && canReadEnvironment"
class="inline js-external-url-container">
<external-url-component
<external-url-component
:external_url="model.external_url">
:external_url="model.external_url">
</external_url-component>
</external_url-component>
</div>
</div>
<div v-if="isStoppable && canCreateDeployment" class="inline js-stop-component-container">
<div v-if="isStoppable && canCreateDeployment"
class="inline js-stop-component-container">
<stop-component
<stop-component
:stop_url="model.environment_
url
">
:stop_url="model.environment_
path
">
</stop-component>
</stop-component>
</div>
</div>
<div v-if="canRetry && canCreateDeployment" class="inline js-rollback-component-container">
<div v-if="canRetry && canCreateDeployment"
class="inline js-rollback-component-container">
<rollback-component
<rollback-component
:is_last_deployment="isLastDeployment"
:is_last_deployment="isLastDeployment"
:retry_url="retryUrl">
:retry_url="retryUrl">
...
...
app/assets/javascripts/environments/components/environment_stop.js.es6
View file @
bd8d4d2e
...
@@ -30,7 +30,7 @@
...
@@ -30,7 +30,7 @@
class="btn stop-env-link"
class="btn stop-env-link"
:href="stopUrl"
:href="stopUrl"
data-method="post"
data-method="post"
data-
rel="nofollow">
rel="nofollow">
<i class="fa fa-stop stop-env-icon"></i>
<i class="fa fa-stop stop-env-icon"></i>
</a>
</a>
`,
`,
...
...
app/assets/javascripts/environments/stores/environments_store.js.es6
View file @
bd8d4d2e
...
@@ -89,17 +89,17 @@
...
@@ -89,17 +89,17 @@
toggleFolder(envType) {
toggleFolder(envType) {
const environments = this.state.environments;
const environments = this.state.environments;
const environm
ne
tsCopy = environments.map((env) => {
const environm
en
tsCopy = environments.map((env) => {
if (env['vue-isChildren']
=== true
&& env.name === envType) {
if (env['vue-isChildren'] && env.name === envType) {
env.isOpen = !env.isOpen;
env.isOpen = !env.isOpen;
}
}
return env;
return env;
});
});
this.state.environments = environm
ne
tsCopy;
this.state.environments = environm
en
tsCopy;
return environm
ne
tsCopy;
return environm
en
tsCopy;
},
},
/**
/**
...
@@ -125,15 +125,7 @@
...
@@ -125,15 +125,7 @@
const nameA = a.name.toUpperCase();
const nameA = a.name.toUpperCase();
const nameB = b.name.toUpperCase();
const nameB = b.name.toUpperCase();
if (nameA < nameB) {
return nameA < nameB ? -1 : nameA > nameB ? 1 : 0; // eslint-disable-line
return -1;
}
if (nameA > nameB) {
return 1;
}
return 0;
},
},
};
};
})();
})();
app/assets/javascripts/vue_common_component/commit.js.es6
View file @
bd8d4d2e
...
@@ -143,7 +143,6 @@
...
@@ -143,7 +143,6 @@
</a>
</a>
<div class="icon-container commit-icon commit-icon-container">
<div class="icon-container commit-icon commit-icon-container">
<!-- svg goes here -->
</div>
</div>
<a class="commit-id monospace"
<a class="commit-id monospace"
...
@@ -153,7 +152,6 @@
...
@@ -153,7 +152,6 @@
<p class="commit-title">
<p class="commit-title">
<span v-if="title">
<span v-if="title">
<!-- commit author info-->
<a v-if="hasAuthor"
<a v-if="hasAuthor"
class="avatar-image-container"
class="avatar-image-container"
:href="author.web_url">
:href="author.web_url">
...
...
app/assets/stylesheets/pages/environments.scss
View file @
bd8d4d2e
...
@@ -16,6 +16,8 @@
...
@@ -16,6 +16,8 @@
}
}
.environments
{
.environments
{
table-layout
:
fixed
;
.deployment-column
{
.deployment-column
{
.avatar
{
.avatar
{
float
:
none
;
float
:
none
;
...
...
app/serializers/build_entity.rb
View file @
bd8d4d2e
...
@@ -4,21 +4,21 @@ class BuildEntity < Grape::Entity
...
@@ -4,21 +4,21 @@ class BuildEntity < Grape::Entity
expose
:id
expose
:id
expose
:name
expose
:name
expose
:build_
url
do
|
build
|
expose
:build_
path
do
|
build
|
url
_to
(
:namespace_project_build
,
build
)
path
_to
(
:namespace_project_build
,
build
)
end
end
expose
:retry_
url
do
|
build
|
expose
:retry_
path
do
|
build
|
url
_to
(
:retry_namespace_project_build
,
build
)
path
_to
(
:retry_namespace_project_build
,
build
)
end
end
expose
:play_
url
,
if:
->
(
build
,
_
)
{
build
.
manual?
}
do
|
build
|
expose
:play_
path
,
if:
->
(
build
,
_
)
{
build
.
manual?
}
do
|
build
|
url
_to
(
:play_namespace_project_build
,
build
)
path
_to
(
:play_namespace_project_build
,
build
)
end
end
private
private
def
url
_to
(
route
,
build
)
def
path
_to
(
route
,
build
)
send
(
"
#{
route
}
_
url
"
,
build
.
project
.
namespace
,
build
.
project
,
build
)
send
(
"
#{
route
}
_
path
"
,
build
.
project
.
namespace
,
build
.
project
,
build
)
end
end
end
end
app/serializers/commit_entity.rb
View file @
bd8d4d2e
...
@@ -3,8 +3,8 @@ class CommitEntity < API::Entities::RepoCommit
...
@@ -3,8 +3,8 @@ class CommitEntity < API::Entities::RepoCommit
expose
:author
,
using:
UserEntity
expose
:author
,
using:
UserEntity
expose
:commit_
url
do
|
commit
|
expose
:commit_
path
do
|
commit
|
namespace_project_tree_
url
(
namespace_project_tree_
path
(
request
.
project
.
namespace
,
request
.
project
.
namespace
,
request
.
project
,
request
.
project
,
id:
commit
.
id
)
id:
commit
.
id
)
...
...
app/serializers/deployment_entity.rb
View file @
bd8d4d2e
...
@@ -10,8 +10,8 @@ class DeploymentEntity < Grape::Entity
...
@@ -10,8 +10,8 @@ class DeploymentEntity < Grape::Entity
deployment
.
ref
deployment
.
ref
end
end
expose
:ref_
url
do
|
deployment
|
expose
:ref_
path
do
|
deployment
|
namespace_project_tree_
url
(
namespace_project_tree_
path
(
deployment
.
project
.
namespace
,
deployment
.
project
.
namespace
,
deployment
.
project
,
deployment
.
project
,
id:
deployment
.
ref
)
id:
deployment
.
ref
)
...
...
app/serializers/environment_entity.rb
View file @
bd8d4d2e
...
@@ -9,8 +9,8 @@ class EnvironmentEntity < Grape::Entity
...
@@ -9,8 +9,8 @@ class EnvironmentEntity < Grape::Entity
expose
:last_deployment
,
using:
DeploymentEntity
expose
:last_deployment
,
using:
DeploymentEntity
expose
:stoppable?
expose
:stoppable?
expose
:environment_
url
do
|
environment
|
expose
:environment_
path
do
|
environment
|
namespace_project_environment_
url
(
namespace_project_environment_
path
(
environment
.
project
.
namespace
,
environment
.
project
.
namespace
,
environment
.
project
,
environment
.
project
,
environment
)
environment
)
...
...
app/views/projects/environments/index.html.haml
View file @
bd8d4d2e
...
@@ -16,4 +16,5 @@
...
@@ -16,4 +16,5 @@
"project-environments-path"
=>
project_environments_path
(
@project
),
"project-environments-path"
=>
project_environments_path
(
@project
),
"project-stopped-environments-path"
=>
project_environments_path
(
@project
,
scope: :stopped
),
"project-stopped-environments-path"
=>
project_environments_path
(
@project
,
scope: :stopped
),
"new-environment-path"
=>
new_namespace_project_environment_path
(
@project
.
namespace
,
@project
),
"new-environment-path"
=>
new_namespace_project_environment_path
(
@project
.
namespace
,
@project
),
"help-page-path"
=>
help_page_path
(
"ci/environments"
)},
class:
container_class
}
"help-page-path"
=>
help_page_path
(
"ci/environments"
),
"css-class"
=>
container_class
}}
spec/features/environment_spec.rb
View file @
bd8d4d2e
require
'spec_helper'
require
'spec_helper'
feature
'Environment
s'
,
feature:
tru
e
do
feature
'Environment
'
,
:featur
e
do
given
(
:project
)
{
create
(
:empty_project
)
}
given
(
:project
)
{
create
(
:empty_project
)
}
given
(
:user
)
{
create
(
:user
)
}
given
(
:user
)
{
create
(
:user
)
}
given
(
:role
)
{
:developer
}
given
(
:role
)
{
:developer
}
...
@@ -10,13 +10,13 @@ feature 'Environments', feature: true do
...
@@ -10,13 +10,13 @@ feature 'Environments', feature: true do
project
.
team
<<
[
user
,
role
]
project
.
team
<<
[
user
,
role
]
end
end
describe
'when showing the environment
'
do
feature
'environment details page
'
do
given
(
:environment
)
{
create
(
:environment
,
project:
project
)
}
given
!
(
:environment
)
{
create
(
:environment
,
project:
project
)
}
given!
(
:deployment
)
{
}
given!
(
:deployment
)
{
}
given!
(
:manual
)
{
}
given!
(
:manual
)
{
}
before
do
before
do
visit
namespace_project_environment_path
(
project
.
namespace
,
project
,
environment
)
visit
_environment
(
environment
)
end
end
context
'without deployments'
do
context
'without deployments'
do
...
@@ -26,20 +26,27 @@ feature 'Environments', feature: true do
...
@@ -26,20 +26,27 @@ feature 'Environments', feature: true do
end
end
context
'with deployments'
do
context
'with deployments'
do
given
(
:deployment
)
{
create
(
:deployment
,
environment:
environment
)
}
context
'when there is no related deployable'
do
given
(
:deployment
)
do
create
(
:deployment
,
environment:
environment
,
deployable:
nil
)
end
scenario
'does show deployment SHA'
do
scenario
'does show deployment SHA'
do
expect
(
page
).
to
have_link
(
deployment
.
short_sha
)
expect
(
page
).
to
have_link
(
deployment
.
short_sha
)
end
end
scenario
'does not show a re-deploy button for deployment without build'
do
scenario
'does not show a re-deploy button for deployment without build'
do
expect
(
page
).
not_to
have_link
(
'Re-deploy'
)
expect
(
page
).
not_to
have_link
(
'Re-deploy'
)
end
end
end
context
'with
build
'
do
context
'with
related deployable present
'
do
given
(
:pipeline
)
{
create
(
:ci_pipeline
,
project:
project
)
}
given
(
:pipeline
)
{
create
(
:ci_pipeline
,
project:
project
)
}
given
(
:build
)
{
create
(
:ci_build
,
pipeline:
pipeline
)
}
given
(
:build
)
{
create
(
:ci_build
,
pipeline:
pipeline
)
}
given
(
:deployment
)
{
create
(
:deployment
,
environment:
environment
,
deployable:
build
)
}
given
(
:deployment
)
do
create
(
:deployment
,
environment:
environment
,
deployable:
build
)
end
scenario
'does show build name'
do
scenario
'does show build name'
do
expect
(
page
).
to
have_link
(
"
#{
build
.
name
}
(#
#{
build
.
id
}
)"
)
expect
(
page
).
to
have_link
(
"
#{
build
.
name
}
(#
#{
build
.
id
}
)"
)
...
@@ -57,7 +64,6 @@ feature 'Environments', feature: true do
...
@@ -57,7 +64,6 @@ feature 'Environments', feature: true do
given
(
:manual
)
{
create
(
:ci_build
,
:manual
,
pipeline:
pipeline
,
name:
'deploy to production'
)
}
given
(
:manual
)
{
create
(
:ci_build
,
:manual
,
pipeline:
pipeline
,
name:
'deploy to production'
)
}
scenario
'does show a play button'
do
scenario
'does show a play button'
do
expect
(
page
).
to
have_link
(
manual
.
name
.
humanize
)
expect
(
page
).
to
have_link
(
manual
.
name
.
humanize
)
end
end
...
@@ -104,4 +110,52 @@ feature 'Environments', feature: true do
...
@@ -104,4 +110,52 @@ feature 'Environments', feature: true do
end
end
end
end
end
end
feature
'auto-close environment when branch is deleted'
do
given
(
:project
)
{
create
(
:project
)
}
given!
(
:environment
)
do
create
(
:environment
,
:with_review_app
,
project:
project
,
ref:
'feature'
)
end
scenario
'user visits environment page'
do
visit_environment
(
environment
)
expect
(
page
).
to
have_link
(
'Stop'
)
end
scenario
'user deletes the branch with running environment'
do
visit
namespace_project_branches_path
(
project
.
namespace
,
project
)
remove_branch_with_hooks
(
project
,
user
,
'feature'
)
do
page
.
within
(
'.js-branch-feature'
)
{
find
(
'a.btn-remove'
).
click
}
end
visit_environment
(
environment
)
expect
(
page
).
to
have_no_link
(
'Stop'
)
end
##
# This is a workaround for problem described in #24543
#
def
remove_branch_with_hooks
(
project
,
user
,
branch
)
params
=
{
oldrev:
project
.
commit
(
branch
).
id
,
newrev:
Gitlab
::
Git
::
BLANK_SHA
,
ref:
"refs/heads/
#{
branch
}
"
}
yield
GitPushService
.
new
(
project
,
user
,
params
).
execute
end
end
def
visit_environment
(
environment
)
visit
namespace_project_environment_path
(
environment
.
project
.
namespace
,
environment
.
project
,
environment
)
end
end
end
spec/features/environments_spec.rb
View file @
bd8d4d2e
This diff is collapsed.
Click to expand it.
spec/javascripts/environments/mock_data.js.es6
View file @
bd8d4d2e
...
@@ -40,18 +40,18 @@ const environmentsList = [
...
@@ -40,18 +40,18 @@ const environmentsList = [
avatar_url: 'http://www.gravatar.com/avatar/e64c7d89f26bd1972efa854d13d7dd61?s=80\u0026d=identicon',
avatar_url: 'http://www.gravatar.com/avatar/e64c7d89f26bd1972efa854d13d7dd61?s=80\u0026d=identicon',
web_url: 'http://localhost:3000/root',
web_url: 'http://localhost:3000/root',
},
},
commit_
url: 'http://localhost:3000
/root/ci-folders/tree/500aabcb17c97bdcf2d0c410b70cb8556f0362dd',
commit_
path: '
/root/ci-folders/tree/500aabcb17c97bdcf2d0c410b70cb8556f0362dd',
},
},
deployable: {
deployable: {
id: 1278,
id: 1278,
name: 'build',
name: 'build',
build_
url: 'http://localhost:3000
/root/ci-folders/builds/1278',
build_
path: '
/root/ci-folders/builds/1278',
retry_
url: 'http://localhost:3000
/root/ci-folders/builds/1278/retry',
retry_
path: '
/root/ci-folders/builds/1278/retry',
},
},
manual_actions: [],
manual_actions: [],
},
},
'stoppable?': true,
'stoppable?': true,
environment_
url: 'http://localhost:3000
/root/ci-folders/environments/31',
environment_
path: '
/root/ci-folders/environments/31',
created_at: '2016-11-07T11:11:16.525Z',
created_at: '2016-11-07T11:11:16.525Z',
updated_at: '2016-11-07T11:11:16.525Z',
updated_at: '2016-11-07T11:11:16.525Z',
},
},
...
@@ -95,18 +95,18 @@ const environmentsList = [
...
@@ -95,18 +95,18 @@ const environmentsList = [
avatar_url: 'http://www.gravatar.com/avatar/e64c7d89f26bd1972efa854d13d7dd61?s=80\u0026d=identicon',
avatar_url: 'http://www.gravatar.com/avatar/e64c7d89f26bd1972efa854d13d7dd61?s=80\u0026d=identicon',
web_url: 'http://localhost:3000/root',
web_url: 'http://localhost:3000/root',
},
},
commit_
url: 'http://localhost:3000
/root/ci-folders/tree/500aabcb17c97bdcf2d0c410b70cb8556f0362dd',
commit_
path: '
/root/ci-folders/tree/500aabcb17c97bdcf2d0c410b70cb8556f0362dd',
},
},
deployable: {
deployable: {
id: 1278,
id: 1278,
name: 'build',
name: 'build',
build_
url: 'http://localhost:3000
/root/ci-folders/builds/1278',
build_
path: '
/root/ci-folders/builds/1278',
retry_
url: 'http://localhost:3000
/root/ci-folders/builds/1278/retry',
retry_
path: '
/root/ci-folders/builds/1278/retry',
},
},
manual_actions: [],
manual_actions: [],
},
},
'stoppable?': false,
'stoppable?': false,
environment_
url: 'http://localhost:3000
/root/ci-folders/environments/31',
environment_
path: '
/root/ci-folders/environments/31',
created_at: '2016-11-07T11:11:16.525Z',
created_at: '2016-11-07T11:11:16.525Z',
updated_at: '2016-11-07T11:11:16.525Z',
updated_at: '2016-11-07T11:11:16.525Z',
},
},
...
@@ -117,7 +117,7 @@ const environmentsList = [
...
@@ -117,7 +117,7 @@ const environmentsList = [
environment_type: 'review',
environment_type: 'review',
last_deployment: null,
last_deployment: null,
'stoppable?': true,
'stoppable?': true,
environment_
url: 'http://localhost:3000
/root/ci-folders/environments/31',
environment_
path: '
/root/ci-folders/environments/31',
created_at: '2016-11-07T11:11:16.525Z',
created_at: '2016-11-07T11:11:16.525Z',
updated_at: '2016-11-07T11:11:16.525Z',
updated_at: '2016-11-07T11:11:16.525Z',
},
},
...
@@ -128,9 +128,8 @@ const environmentsList = [
...
@@ -128,9 +128,8 @@ const environmentsList = [
environment_type: 'review',
environment_type: 'review',
last_deployment: null,
last_deployment: null,
'stoppable?': true,
'stoppable?': true,
environment_
url: 'http://localhost:3000
/root/ci-folders/environments/31',
environment_
path: '
/root/ci-folders/environments/31',
created_at: '2016-11-07T11:11:16.525Z',
created_at: '2016-11-07T11:11:16.525Z',
updated_at: '2016-11-07T11:11:16.525Z',
updated_at: '2016-11-07T11:11:16.525Z',
},
},
];
];
spec/serializers/build_entity_spec.rb
View file @
bd8d4d2e
...
@@ -10,9 +10,9 @@ describe BuildEntity do
...
@@ -10,9 +10,9 @@ describe BuildEntity do
context
'when build is a regular job'
do
context
'when build is a regular job'
do
let
(
:build
)
{
create
(
:ci_build
)
}
let
(
:build
)
{
create
(
:ci_build
)
}
it
'contains
url
to build page and retry action'
do
it
'contains
paths
to build page and retry action'
do
expect
(
subject
).
to
include
(
:build_
url
,
:retry_url
)
expect
(
subject
).
to
include
(
:build_
path
,
:retry_path
)
expect
(
subject
).
not_to
include
(
:play_
url
)
expect
(
subject
).
not_to
include
(
:play_
path
)
end
end
it
'does not contain sensitive information'
do
it
'does not contain sensitive information'
do
...
@@ -24,8 +24,8 @@ describe BuildEntity do
...
@@ -24,8 +24,8 @@ describe BuildEntity do
context
'when build is a manual action'
do
context
'when build is a manual action'
do
let
(
:build
)
{
create
(
:ci_build
,
:manual
)
}
let
(
:build
)
{
create
(
:ci_build
,
:manual
)
}
it
'contains
url
to play action'
do
it
'contains
path
to play action'
do
expect
(
subject
).
to
include
(
:play_
url
)
expect
(
subject
).
to
include
(
:play_
path
)
end
end
end
end
end
end
spec/serializers/commit_entity_spec.rb
View file @
bd8d4d2e
...
@@ -31,8 +31,8 @@ describe CommitEntity do
...
@@ -31,8 +31,8 @@ describe CommitEntity do
end
end
end
end
it
'contains
commit URL
'
do
it
'contains
path to commit
'
do
expect
(
subject
).
to
include
(
:commit_
url
)
expect
(
subject
).
to
include
(
:commit_
path
)
end
end
it
'needs to receive project in the request'
do
it
'needs to receive project in the request'
do
...
...
spec/serializers/deployment_entity_spec.rb
View file @
bd8d4d2e
...
@@ -15,6 +15,6 @@ describe DeploymentEntity do
...
@@ -15,6 +15,6 @@ describe DeploymentEntity do
it
'exposes nested information about branch'
do
it
'exposes nested information about branch'
do
expect
(
subject
[
:ref
][
:name
]).
to
eq
'master'
expect
(
subject
[
:ref
][
:name
]).
to
eq
'master'
expect
(
subject
[
:ref
][
:ref_
url
]).
not_to
be_empty
expect
(
subject
[
:ref
][
:ref_
path
]).
not_to
be_empty
end
end
end
end
spec/serializers/environment_entity_spec.rb
View file @
bd8d4d2e
...
@@ -13,6 +13,6 @@ describe EnvironmentEntity do
...
@@ -13,6 +13,6 @@ describe EnvironmentEntity do
end
end
it
'exposes core elements of environment'
do
it
'exposes core elements of environment'
do
expect
(
subject
).
to
include
(
:id
,
:name
,
:state
,
:environment_
url
)
expect
(
subject
).
to
include
(
:id
,
:name
,
:state
,
:environment_
path
)
end
end
end
end
spec/serializers/environment_serializer_spec.rb
View file @
bd8d4d2e
...
@@ -33,7 +33,7 @@ describe EnvironmentSerializer do
...
@@ -33,7 +33,7 @@ describe EnvironmentSerializer do
it
'contains important elements of environment'
do
it
'contains important elements of environment'
do
expect
(
json
)
expect
(
json
)
.
to
include
(
:name
,
:external_url
,
:environment_
url
,
:last_deployment
)
.
to
include
(
:name
,
:external_url
,
:environment_
path
,
:last_deployment
)
end
end
it
'contains relevant information about last deployment'
do
it
'contains relevant information about last deployment'
do
...
...
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment