Skip to content

Commit 2c0e4db

Browse files
author
Cory Faller
committed
Filter repos and branches
1 parent 9f8603d commit 2c0e4db

File tree

14 files changed

+292
-66
lines changed

14 files changed

+292
-66
lines changed

Gruntfile.js

+14-7
Original file line numberDiff line numberDiff line change
@@ -6,13 +6,20 @@ module.exports = function ( grunt )
66
var env = grunt.option( "env" ) || "local";
77
var envObj = grunt.file.readJSON( "env.json" )[ env ];
88

9-
envObj.apiroot = grunt.option( "apiroot" ) || envObj.apiroot;
10-
envObj.token = grunt.option( "token" ) || envObj.token;
11-
envObj.prtimeout = grunt.option( "prtimeout" ) || envObj.prtimeout;
12-
envObj.prmax = grunt.option( "prmax" ) || envObj.prmax;
13-
envObj.orgname = grunt.option( "orgname" ) || envObj.orgname;
14-
envObj.theme = grunt.option( "theme" ) || envObj.theme;
15-
envObj.colors = JSON.parse( grunt.option( "colors" ) || "null" ) || envObj.colors;
9+
envObj.apiroot = grunt.option( "apiroot" ) || envObj.apiroot;
10+
envObj.token = grunt.option( "token" ) || envObj.token;
11+
12+
envObj.include = grunt.option( "include" ) || envObj.include;
13+
envObj.exclude = grunt.option( "exclude" ) || envObj.exclude;
14+
envObj.mainbranch = grunt.option( "mainbranch" ) || envObj.mainbranch;
15+
16+
envObj.prtimeout = grunt.option( "prtimeout" ) || envObj.prtimeout;
17+
envObj.prmax = grunt.option( "prmax" ) || envObj.prmax;
18+
19+
envObj.orgname = grunt.option( "orgname" ) || envObj.orgname;
20+
envObj.theme = grunt.option( "theme" ) || envObj.theme;
21+
22+
envObj.colors = JSON.parse( grunt.option( "colors" ) || "null" ) || envObj.colors;
1623

1724
grunt.initConfig( {
1825
env: envObj,

README.md

+9-1
Original file line numberDiff line numberDiff line change
@@ -23,6 +23,14 @@ The default values for most of these options can be found in `env.json`, and can
2323

2424
**Be aware:** supplying these values hard-codes them into the deployed JavaScript files, so providing your Drone token here is suitable *only* when you do not plan to deploy the Drone Wall someplace public. If the `apiroot` and `token` values aren't supplied via the command line build process, they will be asked for in the Wall interface itself.
2525

26+
The Drone Wall will display builds from all repos and branches by default, unless filtered using these options:
27+
28+
* **include**: `[String]` Supply a comma-delimited list of repos (ex. `repo-name`), branches (ex. `repo-name/branch-name`), or branch wildcards (ex. `*/branch-name`) to include ONLY these items on the wall, and implicitly exclude all others.
29+
30+
* **exclude**: `[String]` Supply a comma-delimited list in the same format as the `include` option to exclude repos or branches. If you set the `exclude` option and not the `include` option, all repos and branches will be implicitly included EXCEPT for those excluded. If you set the `include` AND `exclude` options, the list will first be filtered to only the inclusion list, and then further filtered by the exclusion list.
31+
32+
* **mainbranch**: `[String]` Defaults to `master`. When pushes are made to this branch on any of the repos on the Wall, that repo will reflect the status of the build (color, avatar). Set to `*` to show build status for all pushes regardless of branch (this is the pre-`3.1.0` behavior).
33+
2634
You can further customize the Wall's default appearance with these options:
2735

2836
* **prtimeout**: `[Number]` Defaults to `48`. The number of hours before an un-merged pull request is hidden in the repo list. Useful for removing stale pull requests that have been closed without being merged.
@@ -37,7 +45,7 @@ You can further customize the Wall's default appearance with these options:
3745

3846
## Local Development
3947

40-
The Drone Wall requires Node.js `4.x` and npm `3.x`.
48+
The Drone Wall requires Node.js `4.x` and npm `3.x` at minimum.
4149

4250
Begin with `npm install`, and then run `npm start` to build the application, start a file-watcher, and run a local server accessible at `localhost:3000`. You can pass Grunt flags through `npm` (as of `2.0.0`) like this:
4351

env.json

+42-30
Original file line numberDiff line numberDiff line change
@@ -1,52 +1,64 @@
11
{
22
"local": {
3-
"apiroot": "",
4-
"token": "",
5-
"prtimeout": 48,
6-
"prmax": 3,
7-
8-
"orgname": "Drone",
9-
"theme": "light",
10-
"colors": {}
3+
"apiroot": "",
4+
"token": "",
5+
"include": "",
6+
"exclude": "",
7+
"mainbranch": "master",
8+
9+
"prtimeout": 48,
10+
"prmax": 3,
11+
"orgname": "Drone",
12+
"theme": "light",
13+
"colors": {}
1114
},
1215

1316
"dev": {
14-
"apiroot": "",
15-
"token": "",
16-
"prtimeout": 48,
17-
"prmax": 3,
17+
"apiroot": "",
18+
"token": "",
19+
"include": "",
20+
"exclude": "",
21+
"mainbranch": "master",
1822

19-
"orgname": "Drone",
20-
"theme": "light",
21-
"colors": {},
23+
"prtimeout": 48,
24+
"prmax": 3,
25+
"orgname": "Drone",
26+
"theme": "light",
27+
"colors": {},
2228

2329
"aws.s3Bucket": "<dev-s3-bucket>",
2430
"aws.distributionId": "<dev-cloudfront-distribution-id>"
2531
},
2632

2733
"staging": {
28-
"apiroot": "",
29-
"token": "",
30-
"prtimeout": 48,
31-
"prmax": 3,
34+
"apiroot": "",
35+
"token": "",
36+
"include": "",
37+
"exclude": "",
38+
"mainbranch": "master",
3239

33-
"orgname": "Drone",
34-
"theme": "light",
35-
"colors": {},
40+
"prtimeout": 48,
41+
"prmax": 3,
42+
"orgname": "Drone",
43+
"theme": "light",
44+
"colors": {},
3645

3746
"aws.s3Bucket": "<staging-s3-bucket>",
3847
"aws.distributionId": "<staging-cloudfront-distribution-id>"
3948
},
4049

4150
"prod": {
42-
"apiroot": "",
43-
"token": "",
44-
"prtimeout": 48,
45-
"prmax": 3,
46-
47-
"orgname": "Drone",
48-
"theme": "light",
49-
"colors": {},
51+
"apiroot": "",
52+
"token": "",
53+
"include": "",
54+
"exclude": "",
55+
"mainbranch": "master",
56+
57+
"prtimeout": 48,
58+
"prmax": 3,
59+
"orgname": "Drone",
60+
"theme": "light",
61+
"colors": {},
5062

5163
"aws.s3Bucket": "<prod-s3-bucket>",
5264
"aws.distributionId": "<prod-cloudfront-distribution-id>"

package.json

+1-1
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
{
22
"name": "drone-wall",
3-
"version": "3.0.0",
3+
"version": "3.1.0",
44
"description": "Wall display component for Drone CI server.",
55
"license": "MIT",
66
"repository": {

source/modules/_app/controllers/wall.js

+2-1
Original file line numberDiff line numberDiff line change
@@ -79,7 +79,8 @@ module.exports = [ "$rootScope", "$timeout", "$interval", "$filter", "$q",
7979
builds = $filter( "orderBy" )( builds, "updatedAt" );
8080

8181
// Record when builds started to be monitored
82-
ctrl.watchTime = ctrl.watchTime || builds[ 0 ].updatedAt * 1000;
82+
ctrl.watchTime = ctrl.watchTime ||
83+
( builds.length && builds[ 0 ].updatedAt * 1000 ) || Date.now();
8384

8485
// Only keep builds that have changed since the last poll
8586
builds = $filter( "filter" )( builds, function ( build )

source/modules/_app/services/droneAPI.js

+74-3
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,10 @@
11
"use strict";
22

3-
module.exports = [ "API", "Settings",
3+
module.exports = [ "$q", "$filter", "API", "Settings",
44

5-
function ( API, Settings )
5+
function ( $q, $filter, API, Settings )
66
{
7+
var filters;
78
var path = Settings.apiRoot;
89
path = path.substr( -1, 1 ) === "/" || path === "" ? path : path + "/";
910

@@ -14,7 +15,77 @@ module.exports = [ "API", "Settings",
1415

1516
apiInterface.setKey( Settings.token );
1617

17-
apiInterface.getLatest = () => apiInterface.$get( "user/feed" );
18+
apiInterface.parseFilters = function ()
19+
{
20+
filters = {
21+
include: Settings.include ? Settings.include.replace( /\s/g, "" ).split( "," ) : [],
22+
exclude: Settings.exclude ? Settings.exclude.replace( /\s/g, "" ).split( "," ) : []
23+
};
24+
};
25+
apiInterface.parseFilters();
26+
27+
var filterBuilds = function ( builds, filterSet, filterType )
28+
{
29+
return $filter( "filter" )( builds, function ( build )
30+
{
31+
for( var i = 0; i < filterSet.length; i++ )
32+
{
33+
var parts = filterSet[ i ].split( "/" );
34+
35+
if( parts.length === 2 )
36+
{
37+
// Match branches
38+
if( ( parts[ 0 ] === "*" || parts[ 0 ] === build.name ) &&
39+
parts[ 1 ] === build.branch )
40+
{
41+
return filterType;
42+
}
43+
}
44+
else
45+
{
46+
// Match repos
47+
if( parts[ 0 ] === build.name )
48+
{
49+
return filterType;
50+
}
51+
}
52+
}
53+
54+
return !filterType;
55+
} );
56+
};
57+
58+
apiInterface.getLatest = function ()
59+
{
60+
var deferred = $q.defer();
61+
62+
apiInterface.$get( "user/feed" ).then( function ( response )
63+
{
64+
var builds = response.data;
65+
66+
if( angular.isArray( builds ) )
67+
{
68+
if( filters.include.length )
69+
{
70+
builds = filterBuilds( builds, filters.include, true );
71+
}
72+
if( filters.exclude.length )
73+
{
74+
builds = filterBuilds( builds, filters.exclude, false );
75+
}
76+
}
77+
78+
response.data = builds;
79+
80+
deferred.resolve( response );
81+
},
82+
function ( response )
83+
{
84+
deferred.reject( response );
85+
} );
86+
87+
return deferred.promise;
88+
};
1889

1990
return apiInterface;
2091
}

source/modules/_app/services/repos.js

+9-4
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,8 @@ module.exports = [ "$rootScope", "Settings",
77
var repos = [];
88

99
var checkMerge = ( build ) => build.event === "push" && build.message.match( /Merge pull request #([0-9]+)/i );
10+
var pushToMain = ( build ) => Settings.mainBranch === "*" ||
11+
build.branch.toUpperCase() === Settings.mainBranch.toUpperCase();
1012

1113
var getPullID = function ( build )
1214
{
@@ -47,7 +49,7 @@ module.exports = [ "$rootScope", "Settings",
4749
owner: build.owner,
4850
pulls: [],
4951
lastMerge: null,
50-
developer: checkMerge( build ) ? developer : {}
52+
developer: checkMerge( build ) && pushToMain( build ) ? developer : {}
5153
};
5254

5355
repos.push( newRepo );
@@ -146,7 +148,10 @@ module.exports = [ "$rootScope", "Settings",
146148
// Remove merged pull request
147149
if( pullIndex !== null )
148150
{
149-
currentRepo.developer = currentRepo.pulls[ pullIndex ].developer;
151+
if( pushToMain( build ) )
152+
{
153+
currentRepo.developer = currentRepo.pulls[ pullIndex ].developer;
154+
}
150155

151156
if( build.status === "running" )
152157
{
@@ -160,8 +165,8 @@ module.exports = [ "$rootScope", "Settings",
160165
}
161166
}
162167

163-
// Update repo with details from latest non-pull build
164-
if( build.status !== "pending" )
168+
// Update repo if latest push is from the configured main branch
169+
if( pushToMain( build ) && build.status !== "pending" )
165170
{
166171
if( !currentRepo.lastMerge || build.startedAt >= currentRepo.lastMerge )
167172
{

source/modules/_app/styles/wall.less

+33-2
Original file line numberDiff line numberDiff line change
@@ -674,14 +674,28 @@ h1.bar {
674674
font-weight: 700;
675675
}
676676
.message {
677+
677678
transition: color ease .3s;
678679
margin-right: 15px;
679-
padding: 0px 0px 3px 105px;
680+
margin-top: -3px;
681+
padding: 3px 0px 3px 105px;
680682
overflow: hidden;
681683
white-space: nowrap;
682684
text-overflow: ellipsis;
683685
font-size: 18px;
684686
color: @shadeDark;
687+
688+
.branch {
689+
position: relative;
690+
top: -2px;
691+
margin-right: 5px;
692+
padding: 3px 5px;
693+
background-color: @shadeDark;
694+
border-radius: 3px;
695+
font-size: 12px;
696+
color: @white;
697+
}
698+
685699
}
686700
.when {
687701
transition: color ease .3s;
@@ -848,7 +862,15 @@ h1.bar {
848862
padding-bottom: 14px;
849863
font-size: 25px;
850864
}
851-
.message { font-size: 15px; }
865+
.message {
866+
867+
font-size: 15px;
868+
869+
.branch {
870+
top: -1px;
871+
}
872+
873+
}
852874

853875
}
854876
}
@@ -1032,6 +1054,7 @@ h1.bar {
10321054
font-size: 18px;
10331055
}
10341056
.message {
1057+
10351058
max-height: 28px;
10361059
margin-right: 10px;
10371060
padding-bottom: 0;
@@ -1040,6 +1063,14 @@ h1.bar {
10401063
font-size: 10px;
10411064
white-space: normal;
10421065
line-height: 13px;
1066+
1067+
.branch {
1068+
top: 0;
1069+
margin-right: 2px;
1070+
padding: 0 3px;
1071+
font-size: 10px;
1072+
}
1073+
10431074
}
10441075
.when {
10451076
top: 4px;

source/modules/_app/templates/wall.html

+4-1
Original file line numberDiff line numberDiff line change
@@ -78,7 +78,10 @@ <h1 class="bar">Latest Builds <i class="fa fa-rocket"></i></h1>
7878
<i class="fa fa-circle-o-notch fa-spin" ng-if="build.status === 'running'"></i>
7979
</div>
8080
<div class="name">{{ build.name }}</div>
81-
<div class="message">{{ build.message }}</div>
81+
<div class="message">
82+
<span class="branch" ng-if="build.branch !== 'master'">{{ build.branch }}</span>
83+
{{ build.message }}
84+
</div>
8285
<div class="when" ng-if="build.status !== 'pending'">{{ build.startedAt * 1000 | from:wall.now }} ago</div>
8386
<div class="when" ng-if="build.status === 'pending'">Build Pending</div>
8487
<div class="duration" ng-if="build.finishedAt > 0">

0 commit comments

Comments
 (0)