diff --git a/config/local_settings_pretenders.py b/config/local_settings_pretenders.py new file mode 100644 index 0000000..559ecd6 --- /dev/null +++ b/config/local_settings_pretenders.py @@ -0,0 +1,20 @@ +# Settings for pretenders projects + +GITHUB_CONFIG = { + 'organization': 'pretenders', +} + +# GIT_CONFIG = { +# 'feature_breakup_regex': "(?P[a-zA-Z]+)-?(?P[0-9]+)", +# 'branch_finder_template': ".*(?i){project}.*" +# } + +HIERARCHY_REGEXES = [ + 'master', + 'develop', + 'story/{FEATURE_ID}', + 'story/{FEATURE_ID}/[a-z_]*', + '{PARENT}[/_][a-z]*', + 'dev/{FEATURE_ID}/[a-z]*', + '{PARENT}[/_][a-z]*', +] diff --git a/deploystream/apps/feature/lib.py b/deploystream/apps/feature/lib.py index 125e846..7fe7334 100644 --- a/deploystream/apps/feature/lib.py +++ b/deploystream/apps/feature/lib.py @@ -45,13 +45,13 @@ def get_feature_info(feature_provider, feature_id, providers): # First get feature info from the management provider planning_provider = providers[feature_provider] + feature_info = planning_provider.get_feature_info(feature_id) + feature = Feature(planning_provider, **feature_info) - feature = Feature(planning_provider, - **planning_provider.get_feature_info(feature_id)) # Then get any branch info from any source control providers for provider in providers[ISourceCodeControlProvider]: for branch_data in provider.get_repo_branches_involved( - feature_id, app.config['HIERARCHY_REGEXES']): + feature_id, app.config['HIERARCHY_REGEXES']): feature.add_branch(Branch(provider=provider, **branch_data)) # Use that branch info, along with configuration regexes to create a diff --git a/deploystream/apps/feature/models.py b/deploystream/apps/feature/models.py index 6cbf05d..19ce314 100644 --- a/deploystream/apps/feature/models.py +++ b/deploystream/apps/feature/models.py @@ -42,11 +42,13 @@ def __init__(self, provider, project, id, title, self._extras = kwargs self.branches = defaultdict(dict) + self.branch_list = [] self.trees = [] def add_branch(self, branch): assert isinstance(branch, Branch) self.branches[branch.repo_name][branch.branch_name] = branch + self.branch_list.append(branch) def create_hierarchy_trees(self): "Create hierarchy trees - one for each repo." diff --git a/deploystream/apps/feature/views.py b/deploystream/apps/feature/views.py index 28c7bd0..65f0d3e 100644 --- a/deploystream/apps/feature/views.py +++ b/deploystream/apps/feature/views.py @@ -30,7 +30,7 @@ def list_features(providers): return features -@app.route('/features//', methods=['GET']) +@app.route('/features/-', methods=['GET']) @needs_providers @as_json def view_feature(source_id, feature_id, providers): diff --git a/deploystream/static/font-awesome b/deploystream/static/font-awesome new file mode 120000 index 0000000..8a3fd51 --- /dev/null +++ b/deploystream/static/font-awesome @@ -0,0 +1 @@ +../../components/font-awesome/ \ No newline at end of file diff --git a/deploystream/static/github-70.json b/deploystream/static/github-70.json new file mode 100644 index 0000000..8791019 --- /dev/null +++ b/deploystream/static/github-70.json @@ -0,0 +1,154 @@ +{ + "description": "", + "title": "Ability to view the branch hierarchy for a feature, and what is merged into what.", + "url": "https://github.com/pretenders/deploystream/issues/70", + "project": "pretenders/deploystream", + "owner": "alexcouper", + "provider": "github", + "type": "story", + "id": 70, + "repositories": [ + { + "name": "deploystream", + "branches": [ + { + "latest_commit": "9770a5e", + "branch_name": "master", + "health": { + "status": "green", + "details": [ + { + "type": "build", + "provider": "travis-ci", + "status": "green", + "url": "https://travis-ci.org/pretenders/deploystream/builds/8604410" + } + ] + }, + "children": [ + { + "latest_commit": "dfa9217", + "branch_name": "develop", + "health": { + "status": "green", + "details": [ + { + "type": "build", + "provider": "travis-ci", + "status": "green", + "url": "https://travis-ci.org/pretenders/deploystream/builds/8604410" + }, + { + "type": "relevant", + "provider": "git", + "status": "green" + } + ] + }, + "children": [ + { + "latest_commit": "98457ab", + "branch_name": "story/70/view-hierarchy", + "health": { + "status": "red", + "details": [ + { + "type": "build", + "provider": "travis-ci", + "status": "red", + "url": "https://travis-ci.org/pretenders/deploystream/builds/8604410" + }, + { + "type": "relevant", + "provider": "git", + "status": "green" + }, + { + "type": "updated", + "provider": "git", + "status": "yellow", + "message": "this branch is not up to date with develop" + } + ] + }, + "children": [ + { + "latest_commit": "5719681", + "branch_name": "dev/70/alex", + "repo_name": "deploystream", + "health": { + "status": "unknown", + "details": [ + { + "type": "build", + "provider": "travis-ci", + "status": "unknown", + "url": "https://travis-ci.org/pretenders/deploystream/builds/8604410" + } + ] + }, + "children": [] + }, + { + "latest_commit": "aace02c", + "branch_name": "dev/70/carles", + "health": { + "status": "yellow", + "details": [ + { + "type": "build", + "provider": "travis-ci", + "status": "yellow", + "url": "https://travis-ci.org/pretenders/deploystream/builds/8604410" + } + ] + }, + "children": [] + } + ] + } + ] + } + ] + } + ] + }, + { + "name": "somecomponent", + "branches": [ + { + "latest_commit": "7923a5e", + "branch_name": "develop", + "health": { + "status": "green", + "details": [ + { + "type": "build", + "provider": "travis-ci", + "status": "green", + "url": "https://travis-ci.org/pretenders/deploystream/builds/8604410" + } + ] + }, + "children": [ + { + "latest_commit": "e3457ab", + "branch_name": "story/70/view-hierarchy", + "health": { + "status": "green", + "details": [ + { + "type": "build", + "provider": "travis-ci", + "status": "green", + "url": "https://travis-ci.org/pretenders/deploystream/builds/8604410" + } + ] + } + } + ] + } + ] + } + ] +} diff --git a/deploystream/static/js/app.js b/deploystream/static/js/app.js index 2f80d5a..b8c9e11 100644 --- a/deploystream/static/js/app.js +++ b/deploystream/static/js/app.js @@ -1,4 +1,4 @@ -// global angular, FeatureListCtrl +// global angular, FeatureListCtrl, FeatureDetailCtrl 'use strict'; @@ -16,5 +16,9 @@ angular.module('deploystream', [ templateUrl: '/static/partials/features.html', controller: FeatureListCtrl }); + $routeProvider.when('/features/:featureId', { + templateUrl: '/static/partials/feature.html', + controller: FeatureDetailCtrl + }); }] ); diff --git a/deploystream/static/js/controllers.js b/deploystream/static/js/controllers.js index 0a0ec52..a6a08dc 100644 --- a/deploystream/static/js/controllers.js +++ b/deploystream/static/js/controllers.js @@ -11,4 +11,21 @@ function FeatureListCtrl($scope, Feature) { $scope.features = features; }); } + + +function FeatureDetailCtrl($scope, $routeParams, Feature) { + + var featureId = $routeParams.featureId; + + Feature.query('', function (features) { + $scope.features = features; + }); + + Feature.get({featureId: featureId}, function (feature) { + $scope.feature = feature; + $scope.root = 'master'; + }); +} + + //FeatureListCtrl.$inject = []; diff --git a/deploystream/static/js/directives.js b/deploystream/static/js/directives.js index 6424c97..eb4c097 100644 --- a/deploystream/static/js/directives.js +++ b/deploystream/static/js/directives.js @@ -1,4 +1,4 @@ -// global angular +/* global angular */ 'use strict'; /* Directives */ @@ -6,7 +6,9 @@ angular.module('deploystream.directives', []) .directive('appVersion', ['version', function (version) { - return function (scope, elm, attrs) { - elm.text(version); + return function ($scope, $element) { + $element.text(version); }; }]); +// .directive('featureHealth', function() { +// }); diff --git a/deploystream/static/js/services.js b/deploystream/static/js/services.js index f5d1635..b2c4ede 100644 --- a/deploystream/static/js/services.js +++ b/deploystream/static/js/services.js @@ -10,12 +10,12 @@ angular.module('deploystream.services', ['ngResource']) .value('version', '0.1') .factory('Feature', function ($resource) { return $resource( - '/features/:featureId', + //'/features/:featureId', + '/static/:featureId.json', {}, { query: { method: 'GET', - params: {featureId: ''}, isArray: true } }); diff --git a/deploystream/static/less/colours.less b/deploystream/static/less/colours.less index b023896..ab0ede5 100644 --- a/deploystream/static/less/colours.less +++ b/deploystream/static/less/colours.less @@ -35,3 +35,9 @@ @altDarkBackground: darken(@color5, 30%); @btnPrimaryColor: @color5; +@secondaryTitle: @color5; + +@statusGreen: @color1; +@statusRed: @color4; +@statusYellow: @yellow; +@statusUnknown: #888; diff --git a/deploystream/static/less/features.less b/deploystream/static/less/features.less new file mode 100644 index 0000000..0d20744 --- /dev/null +++ b/deploystream/static/less/features.less @@ -0,0 +1,100 @@ +.feature { + header { + border-bottom: 1px solid @grayLight; + margin-bottom: 20px; + .box-shadow(0 10px 8px -8px @grayLight); + p { + float: right; + font-size: 80%; + font-weight: normal; + font-style: italic; + font-family: @baseFontFamily; + margin-top: 8px; + .opacity(70); + } + } +} +.repo { + margin-top: 8px; + h4 { + min-width: 150px; + float: left; + font-size: 140%; + color: @secondaryTitle; + text-align: right; + clear: left; + } + .branches { + float: left; + border-left: 6px solid @secondaryTitle; + padding-left: 8px; + margin-left: 8px; + i.menu { + cursor: pointer; + } + .popover-content { + padding: 0; + } + .dropdown { + display: inline; + } + .dropdown-menu { + left: -18px; + width: 220px; + font-size: 90%; + padding: 8px 0; + li { + padding: 0 16px; + &:hover { + background-color: #eee; + cursor: pointer; + } + } + &:before { + content: ''; + position: absolute; + top: -7px; + left: 15px; + display: inline-block; + border-left: 7px solid transparent; + border-right: 7px solid transparent; + border-bottom: 7px solid #ccc; + border-bottom-color: rgba(0, 0, 0, 0.2); + } + &:after { + content: ''; + position: absolute; + top: -6px; + left: 16px; + display: inline-block; + border-right: 6px solid transparent; + border-bottom: 6px solid white; + border-left: 6px solid transparent; + } + } + } + ul { + margin-top: 10px; + list-style: none; + } + .tool:hover { + color: @linkColor; + } +} + +.health-green { + color: @statusGreen; +} + +.health-yellow { + color: @statusYellow; +} + +.health-red { + color: @statusRed; +} + +.health-unknown { + color: @statusUnknown; +} + diff --git a/deploystream/static/less/font-awesome b/deploystream/static/less/font-awesome deleted file mode 120000 index a45a4c5..0000000 --- a/deploystream/static/less/font-awesome +++ /dev/null @@ -1 +0,0 @@ -../../../components/font-awesome/less/ \ No newline at end of file diff --git a/deploystream/static/less/site.less b/deploystream/static/less/site.less index 70c429c..4bd7c7b 100644 --- a/deploystream/static/less/site.less +++ b/deploystream/static/less/site.less @@ -12,9 +12,6 @@ @import "variables.less"; @import "bootstrap-modules.less"; -// Iconic font-awesome -@import "font-awesome/font-awesome.less"; - // Custom Site-wide styles @@ -52,7 +49,7 @@ body { height: auto !important; height: 100%; /* Negative indent footer by it's height */ - margin: 0 auto -120px; + margin: 0 auto -154px; } /* Set the fixed height of the footer here */ @@ -140,3 +137,8 @@ body { height: 16px; background-image: url("../img/loading.gif"); } + + +// TODO: structure properly... + +@import "features.less"; diff --git a/deploystream/static/partials/feature.html b/deploystream/static/partials/feature.html new file mode 100644 index 0000000..043e25a --- /dev/null +++ b/deploystream/static/partials/feature.html @@ -0,0 +1,61 @@ +
+ +
+

+ + #{{feature.id}} + + {{feature.title}} +

+ +

+ {{feature.project}} + {{feature.type}} + {{feature.owner}} +

+
+ + + + + +
+

{{repo.name}}

+
    +
  • +
+
+ +
+

+ Loading... +

diff --git a/deploystream/static/partials/features.html b/deploystream/static/partials/features.html index 9fe8b8b..2b6b386 100644 --- a/deploystream/static/partials/features.html +++ b/deploystream/static/partials/features.html @@ -15,7 +15,7 @@

Features

#{{feature.id}} {{feature.type}} {{feature.owner}} - {{feature.title}} + {{feature.title}} (+) diff --git a/deploystream/templates/base.html b/deploystream/templates/base.html index e36bb90..6805a53 100644 --- a/deploystream/templates/base.html +++ b/deploystream/templates/base.html @@ -16,6 +16,7 @@ + {% block extrahead %} diff --git a/scripts/test b/scripts/test index 5593898..7b8a835 100755 --- a/scripts/test +++ b/scripts/test @@ -1,4 +1,5 @@ #!/bin/bash +set -e coverage erase CONFIG=test coverage run --branch --omit="*/tests/*,${HOME}/*virtualenv*" -m nose.core --verbosity=2 $* coverage report --show-missing diff --git a/scripts/watch-less.sh b/scripts/watch-less.sh deleted file mode 100755 index dc0d8e7..0000000 --- a/scripts/watch-less.sh +++ /dev/null @@ -1,4 +0,0 @@ -#!/bin/bash -# Dynamically compile site.less when LESS files in 'less' folder change - -recess less/site.less:css/site.css --watch less/