Merge branch 'master', remote-tracking branch 'origin'
This commit is contained in:
commit
040ef6f8ab
20 changed files with 1211 additions and 1198 deletions
2
AUTHORS
2
AUTHORS
|
@ -3,4 +3,6 @@
|
||||||
|
|
||||||
Artur Rodrigues <arturhoo@gmail.com>
|
Artur Rodrigues <arturhoo@gmail.com>
|
||||||
Brad Rydzewski <brad@drone.io>
|
Brad Rydzewski <brad@drone.io>
|
||||||
|
Martin Charles <martincharles07@gmail.com>
|
||||||
Thomas Burke <burke@drone.io>
|
Thomas Burke <burke@drone.io>
|
||||||
|
|
||||||
|
|
|
@ -1,14 +1,14 @@
|
||||||
body {
|
body {
|
||||||
background: #FFF;
|
background: #FFF;
|
||||||
}
|
}
|
||||||
.container {
|
.container {
|
||||||
max-width: none !important;
|
max-width: none !important;
|
||||||
width: 940px;
|
width: 940px;
|
||||||
padding: 0px;
|
padding: 0;
|
||||||
}
|
}
|
||||||
.row {
|
.row {
|
||||||
margin: 0px;
|
margin: 0;
|
||||||
padding: 0px;
|
padding: 0;
|
||||||
}
|
}
|
||||||
.col-xs-1,
|
.col-xs-1,
|
||||||
.col-xs-2,
|
.col-xs-2,
|
||||||
|
@ -19,7 +19,7 @@
|
||||||
.col-xs-7,
|
.col-xs-7,
|
||||||
.col-xs-8,
|
.col-xs-8,
|
||||||
.col-xs-9 {
|
.col-xs-9 {
|
||||||
padding: 0px;
|
padding: 0;
|
||||||
}
|
}
|
||||||
.row > .col-xs-2:last-child,
|
.row > .col-xs-2:last-child,
|
||||||
.row > .col-xs-3:last-child,
|
.row > .col-xs-3:last-child,
|
||||||
|
@ -36,7 +36,7 @@
|
||||||
margin-bottom: 0px;
|
margin-bottom: 0px;
|
||||||
}
|
}
|
||||||
.navbar-inverse .container {
|
.navbar-inverse .container {
|
||||||
padding-right: 0px;
|
padding-right: 0;
|
||||||
}
|
}
|
||||||
.navbar-fixed-top,
|
.navbar-fixed-top,
|
||||||
.navbar-fixed-bottom {
|
.navbar-fixed-bottom {
|
||||||
|
@ -53,7 +53,7 @@
|
||||||
}
|
}
|
||||||
.navbar .nav {
|
.navbar .nav {
|
||||||
float: right;
|
float: right;
|
||||||
margin-right: 0px;
|
margin-right: 0;
|
||||||
}
|
}
|
||||||
.navbar .nav > li > a {
|
.navbar .nav > li > a {
|
||||||
padding: 18px 20px;
|
padding: 18px 20px;
|
||||||
|
@ -63,10 +63,9 @@
|
||||||
margin: 0px;
|
margin: 0px;
|
||||||
margin-top: 11px;
|
margin-top: 11px;
|
||||||
border-radius: 4px;
|
border-radius: 4px;
|
||||||
-webkit-border-radius: 4px;
|
|
||||||
-moz-border-radius: 4px;
|
|
||||||
background: #363839;
|
background: #363839;
|
||||||
border: none;
|
border: none;
|
||||||
|
-webkit-box-shadow: none;
|
||||||
box-shadow: none;
|
box-shadow: none;
|
||||||
text-shadow: none;
|
text-shadow: none;
|
||||||
color: #DDD;
|
color: #DDD;
|
||||||
|
@ -82,7 +81,6 @@
|
||||||
border: none;
|
border: none;
|
||||||
position: relative;
|
position: relative;
|
||||||
-webkit-box-shadow: none;
|
-webkit-box-shadow: none;
|
||||||
-moz-box-shadow: none;
|
|
||||||
box-shadow: none;
|
box-shadow: none;
|
||||||
}
|
}
|
||||||
.subhead h1 {
|
.subhead h1 {
|
||||||
|
@ -110,8 +108,6 @@
|
||||||
width: 42px;
|
width: 42px;
|
||||||
height: 42px;
|
height: 42px;
|
||||||
border-radius: 50%;
|
border-radius: 50%;
|
||||||
-webkit-border-radius: 50%;
|
|
||||||
-moz-border-radius: 50%;
|
|
||||||
}
|
}
|
||||||
.subhead h1.user small {
|
.subhead h1.user small {
|
||||||
color: #777;
|
color: #777;
|
||||||
|
@ -119,14 +115,14 @@
|
||||||
}
|
}
|
||||||
.subhead .container {
|
.subhead .container {
|
||||||
position: relative;
|
position: relative;
|
||||||
padding: 0px;
|
padding: 0;
|
||||||
}
|
}
|
||||||
.subhead .nav-tabs {
|
.subhead .nav-tabs {
|
||||||
position: absolute;
|
position: absolute;
|
||||||
right: 0px;
|
right: 0;
|
||||||
bottom: 0px;
|
bottom: 0;
|
||||||
margin: 0px;
|
margin: 0;
|
||||||
padding: 0px;
|
padding: 0;
|
||||||
border-bottom: none;
|
border-bottom: none;
|
||||||
}
|
}
|
||||||
.subhead .nav-tabs > li {
|
.subhead .nav-tabs > li {
|
||||||
|
@ -136,11 +132,11 @@
|
||||||
color: #999;
|
color: #999;
|
||||||
padding: 10px 20px;
|
padding: 10px 20px;
|
||||||
line-height: 20px;
|
line-height: 20px;
|
||||||
border: 0px;
|
border: 0;
|
||||||
}
|
}
|
||||||
.subhead .nav-tabs > li.active > a {
|
.subhead .nav-tabs > li.active > a {
|
||||||
color: #777;
|
color: #777;
|
||||||
border: 0px;
|
border: 0;
|
||||||
}
|
}
|
||||||
.nav-repos,
|
.nav-repos,
|
||||||
.nav-branches {
|
.nav-branches {
|
||||||
|
@ -154,11 +150,9 @@
|
||||||
padding: 5px 15px;
|
padding: 5px 15px;
|
||||||
padding: 10px 15px;
|
padding: 10px 15px;
|
||||||
border: none;
|
border: none;
|
||||||
margin: 0px !IMPORTANT;
|
margin: 0 !IMPORTANT;
|
||||||
font-size: 15px;
|
font-size: 15px;
|
||||||
border-radius: 0px;
|
border-radius: 0;
|
||||||
-moz-border-radius: 0px;
|
|
||||||
-webkit-border-radius: 0px;
|
|
||||||
overflow: hidden;
|
overflow: hidden;
|
||||||
white-space: nowrap;
|
white-space: nowrap;
|
||||||
text-overflow: ellipsis;
|
text-overflow: ellipsis;
|
||||||
|
@ -200,7 +194,7 @@
|
||||||
.nav-repos li a,
|
.nav-repos li a,
|
||||||
.nav-branches li a {
|
.nav-branches li a {
|
||||||
padding: 12px 15px;
|
padding: 12px 15px;
|
||||||
margin-bottom: 0px;
|
margin-bottom: 0;
|
||||||
color: #777;
|
color: #777;
|
||||||
}
|
}
|
||||||
.nav-pills.nav-repos > li > a,
|
.nav-pills.nav-repos > li > a,
|
||||||
|
@ -233,12 +227,12 @@
|
||||||
margin-top: -10px;
|
margin-top: -10px;
|
||||||
}
|
}
|
||||||
.alert .thumbnails {
|
.alert .thumbnails {
|
||||||
margin: 0px;
|
margin: 0;
|
||||||
padding: 0px;
|
padding: 0;
|
||||||
}
|
}
|
||||||
.alert .thumbnails li {
|
.alert .thumbnails li {
|
||||||
margin: 0px;
|
margin: 0;
|
||||||
padding: 0px;
|
padding: 0;
|
||||||
margin-left: 20px;
|
margin-left: 20px;
|
||||||
margin-top: 20px;
|
margin-top: 20px;
|
||||||
}
|
}
|
||||||
|
@ -261,9 +255,9 @@
|
||||||
font-weight: normal;
|
font-weight: normal;
|
||||||
}
|
}
|
||||||
.alert.alert-feed .thumbnails > li {
|
.alert.alert-feed .thumbnails > li {
|
||||||
margin: 0px;
|
margin: 0;
|
||||||
margin-left: 5px;
|
margin-left: 5px;
|
||||||
padding: 0px;
|
padding: 0;
|
||||||
display: inline-block;
|
display: inline-block;
|
||||||
}
|
}
|
||||||
.alert.alert-feed .thumbnails > li a {
|
.alert.alert-feed .thumbnails > li a {
|
||||||
|
@ -272,8 +266,6 @@
|
||||||
}
|
}
|
||||||
.alert.alert-feed .thumbnails > li a img {
|
.alert.alert-feed .thumbnails > li a img {
|
||||||
border-radius: 50%;
|
border-radius: 50%;
|
||||||
-moz-border-radius: 50%;
|
|
||||||
-webkit-border-radius: 50%;
|
|
||||||
width: 32px;
|
width: 32px;
|
||||||
height: 32px;
|
height: 32px;
|
||||||
margin-top: 10px;
|
margin-top: 10px;
|
||||||
|
@ -296,11 +288,11 @@
|
||||||
}
|
}
|
||||||
.commit-list {
|
.commit-list {
|
||||||
list-style: none;
|
list-style: none;
|
||||||
margin: 0px;
|
margin: 0;
|
||||||
padding-left: 0px;
|
padding-left: 0;
|
||||||
}
|
}
|
||||||
.commit-list > li {
|
.commit-list > li {
|
||||||
margin: 0px;
|
margin: 0;
|
||||||
position: relative;
|
position: relative;
|
||||||
padding: 25px 20px;
|
padding: 25px 20px;
|
||||||
padding-left: 25px;
|
padding-left: 25px;
|
||||||
|
@ -310,8 +302,6 @@
|
||||||
position: absolute;
|
position: absolute;
|
||||||
right: 20px;
|
right: 20px;
|
||||||
top: 20px;
|
top: 20px;
|
||||||
-webkit-border-radius: 50%;
|
|
||||||
-moz-border-radius: 50%;
|
|
||||||
border-radius: 50%;
|
border-radius: 50%;
|
||||||
width: 48px;
|
width: 48px;
|
||||||
height: 48px;
|
height: 48px;
|
||||||
|
@ -359,8 +349,8 @@
|
||||||
.commit-list > li > h3 p {
|
.commit-list > li > h3 p {
|
||||||
font-size: 14px;
|
font-size: 14px;
|
||||||
color: #999;
|
color: #999;
|
||||||
margin: 0px;
|
margin: 0;
|
||||||
padding: 0px;
|
padding: 0;
|
||||||
padding-top: 2px;
|
padding-top: 2px;
|
||||||
display: block;
|
display: block;
|
||||||
overflow: hidden;
|
overflow: hidden;
|
||||||
|
@ -378,6 +368,7 @@
|
||||||
background: #BBB;
|
background: #BBB;
|
||||||
color: #FFF;
|
color: #FFF;
|
||||||
text-shadow: none;
|
text-shadow: none;
|
||||||
|
-webkit-box-shadow: none;
|
||||||
box-shadow: none;
|
box-shadow: none;
|
||||||
padding: 10px 15px;
|
padding: 10px 15px;
|
||||||
min-width: 75px;
|
min-width: 75px;
|
||||||
|
@ -395,8 +386,6 @@
|
||||||
min-width: 48px;
|
min-width: 48px;
|
||||||
max-width: 48px;
|
max-width: 48px;
|
||||||
border-radius: 50%;
|
border-radius: 50%;
|
||||||
-webkit-border-radius: 50%;
|
|
||||||
-moz-border-radius: 50%;
|
|
||||||
}
|
}
|
||||||
.btn.btn-success,
|
.btn.btn-success,
|
||||||
.btn.btn-Success {
|
.btn.btn-Success {
|
||||||
|
@ -436,8 +425,6 @@
|
||||||
background: #f7f7f7;
|
background: #f7f7f7;
|
||||||
width: 75px;
|
width: 75px;
|
||||||
border-radius: 0px;
|
border-radius: 0px;
|
||||||
-webkit-border-radius: 0px;
|
|
||||||
-moz-border-radius: 0px;
|
|
||||||
text-align: center;
|
text-align: center;
|
||||||
font-size: 22px;
|
font-size: 22px;
|
||||||
text-decoration: none;
|
text-decoration: none;
|
||||||
|
@ -460,9 +447,6 @@
|
||||||
color: #FFF;
|
color: #FFF;
|
||||||
display: inline-block;
|
display: inline-block;
|
||||||
-webkit-animation: spin 1.5s infinite linear;
|
-webkit-animation: spin 1.5s infinite linear;
|
||||||
-moz-animation: spin 1.5s infinite linear;
|
|
||||||
-ms-animation: spin 1.5s infinite linear;
|
|
||||||
-o-animation: spin 1.5s infinite linear;
|
|
||||||
animation: spin 1.5s infinite linear;
|
animation: spin 1.5s infinite linear;
|
||||||
}
|
}
|
||||||
.btn.btn-mini {
|
.btn.btn-mini {
|
||||||
|
@ -482,31 +466,6 @@
|
||||||
line-height: 24px !IMPORTANT;
|
line-height: 24px !IMPORTANT;
|
||||||
font-size: 14px !IMPORTANT;
|
font-size: 14px !IMPORTANT;
|
||||||
}
|
}
|
||||||
@-webkit-keyframes spin {
|
|
||||||
to {
|
|
||||||
-webkit-transform: rotate(360deg);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@-moz-keyframes spin {
|
|
||||||
to {
|
|
||||||
-moz-transform: rotate(360deg);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@-ms-keyframes spin {
|
|
||||||
to {
|
|
||||||
-ms-transform: rotate(360deg);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@-o-keyframes spin {
|
|
||||||
to {
|
|
||||||
-o-transform: rotate(360deg);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@keyframes spin {
|
|
||||||
to {
|
|
||||||
transform: rotate(360deg);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
.btn.btn-None {
|
.btn.btn-None {
|
||||||
background: rgba(81, 163, 81, 0.75);
|
background: rgba(81, 163, 81, 0.75);
|
||||||
border-bottom: 2px solid #51a351;
|
border-bottom: 2px solid #51a351;
|
||||||
|
@ -539,6 +498,18 @@
|
||||||
background: rgba(189, 54, 47, 0.9);
|
background: rgba(189, 54, 47, 0.9);
|
||||||
border-bottom: 2px solid #bd362f;
|
border-bottom: 2px solid #bd362f;
|
||||||
}
|
}
|
||||||
|
@-webkit-keyframes spin {
|
||||||
|
to {
|
||||||
|
-webkit-transform: rotate(360deg);
|
||||||
|
transform: rotate(360deg);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
@keyframes spin {
|
||||||
|
to {
|
||||||
|
-webkit-transform: rotate(360deg);
|
||||||
|
transform: rotate(360deg);
|
||||||
|
}
|
||||||
|
}
|
||||||
.nav-pills > li a {
|
.nav-pills > li a {
|
||||||
padding: 7px 15px;
|
padding: 7px 15px;
|
||||||
color: #777777;
|
color: #777777;
|
||||||
|
@ -546,14 +517,10 @@
|
||||||
.nav-pills > li > a,
|
.nav-pills > li > a,
|
||||||
.nav-pills > li > a:hover,
|
.nav-pills > li > a:hover,
|
||||||
.nav-pills > li > a:focus {
|
.nav-pills > li > a:focus {
|
||||||
border-radius: 0px;
|
border-radius: 0;
|
||||||
-webkit-border-radius: 0px;
|
|
||||||
-moz-border-radius: 0px;
|
|
||||||
}
|
}
|
||||||
.nav-pills > .active {
|
.nav-pills > .active {
|
||||||
border-radius: 0px;
|
border-radius: 0;
|
||||||
-webkit-border-radius: 0px;
|
|
||||||
-moz-border-radius: 0px;
|
|
||||||
}
|
}
|
||||||
.nav-pills > li.active > a,
|
.nav-pills > li.active > a,
|
||||||
.nav-pills > li.active > a:hover,
|
.nav-pills > li.active > a:hover,
|
||||||
|
@ -561,10 +528,8 @@
|
||||||
.nav-pills > .active > a,
|
.nav-pills > .active > a,
|
||||||
.nav-pills > .active > a:hover,
|
.nav-pills > .active > a:hover,
|
||||||
.nav-pills > .active > a:focus {
|
.nav-pills > .active > a:focus {
|
||||||
border-radius: 0px;
|
border-radius: 0;
|
||||||
-webkit-border-radius: 0px;
|
margin-top: 0;
|
||||||
-moz-border-radius: 0px;
|
|
||||||
margin-top: 0px;
|
|
||||||
background-color: #f4f4f4;
|
background-color: #f4f4f4;
|
||||||
color: #777777;
|
color: #777777;
|
||||||
}
|
}
|
||||||
|
@ -578,12 +543,12 @@ form label {
|
||||||
display: block;
|
display: block;
|
||||||
}
|
}
|
||||||
form label:first-child {
|
form label:first-child {
|
||||||
margin-top: 0px;
|
margin-top: 0;
|
||||||
}
|
}
|
||||||
form .form-actions {
|
form .form-actions {
|
||||||
background: transparent;
|
background: transparent;
|
||||||
padding: 30px 0px;
|
padding: 30px 0px;
|
||||||
margin: 0px;
|
margin: 0;
|
||||||
border: none;
|
border: none;
|
||||||
}
|
}
|
||||||
form .form-actions .btn {
|
form .form-actions .btn {
|
||||||
|
@ -601,8 +566,6 @@ select.form-control {
|
||||||
font-size: 14px;
|
font-size: 14px;
|
||||||
line-height: 20px;
|
line-height: 20px;
|
||||||
color: #555555;
|
color: #555555;
|
||||||
-webkit-border-radius: 4px;
|
|
||||||
-moz-border-radius: 4px;
|
|
||||||
border-radius: 4px;
|
border-radius: 4px;
|
||||||
vertical-align: middle;
|
vertical-align: middle;
|
||||||
width: 270px;
|
width: 270px;
|
||||||
|
@ -624,7 +587,6 @@ span.form-control {
|
||||||
background-color: #fcfcfc;
|
background-color: #fcfcfc;
|
||||||
border-color: #cccccc;
|
border-color: #cccccc;
|
||||||
-webkit-box-shadow: inset 0 1px 2px rgba(0, 0, 0, 0.025);
|
-webkit-box-shadow: inset 0 1px 2px rgba(0, 0, 0, 0.025);
|
||||||
-moz-box-shadow: inset 0 1px 2px rgba(0, 0, 0, 0.025);
|
|
||||||
box-shadow: inset 0 1px 2px rgba(0, 0, 0, 0.025);
|
box-shadow: inset 0 1px 2px rgba(0, 0, 0, 0.025);
|
||||||
cursor: not-allowed;
|
cursor: not-allowed;
|
||||||
}
|
}
|
||||||
|
@ -666,22 +628,21 @@ textarea {
|
||||||
font-size: 16px;
|
font-size: 16px;
|
||||||
}
|
}
|
||||||
.row.gravatar-list {
|
.row.gravatar-list {
|
||||||
margin-left: 0px;
|
margin-left: 0;
|
||||||
}
|
}
|
||||||
.row.gravatar-list .col-xs-3 {
|
.row.gravatar-list .col-xs-3 {
|
||||||
width: 23.404255319148934%;
|
width: 23.404255319148934%;
|
||||||
margin: 0px;
|
margin: 0;
|
||||||
padding: 0px;
|
padding: 0;
|
||||||
margin-right: 2.127659574468085%;
|
margin-right: 2.127659574468085%;
|
||||||
}
|
}
|
||||||
.row.gravatar-list .col-xs-3:nth-child(4) {
|
.row.gravatar-list .col-xs-3:nth-child(4) {
|
||||||
margin-right: 0px;
|
margin-right: 0;
|
||||||
}
|
}
|
||||||
.row.gravatar-list .col-xs-3 a.thumbnail,
|
.row.gravatar-list .col-xs-3 a.thumbnail,
|
||||||
.row.gravatar-list .col-xs-3 a.thumbnail:hover {
|
.row.gravatar-list .col-xs-3 a.thumbnail:hover {
|
||||||
border-radius: 0px;
|
border-radius: 0;
|
||||||
-webkit-border-radius: 0px;
|
-webkit-box-shadow: none;
|
||||||
-moz-border-radius: 0px;
|
|
||||||
box-shadow: none;
|
box-shadow: none;
|
||||||
border: none;
|
border: none;
|
||||||
text-decoration: none;
|
text-decoration: none;
|
||||||
|
@ -721,7 +682,11 @@ textarea {
|
||||||
.row.gravatar-list .col-xs-3 a.thumbnail:hover.team-add .caption > h3 {
|
.row.gravatar-list .col-xs-3 a.thumbnail:hover.team-add .caption > h3 {
|
||||||
color: #999;
|
color: #999;
|
||||||
}
|
}
|
||||||
/* Checkbox hack */
|
.switch {
|
||||||
|
height: 40px;
|
||||||
|
position: relative;
|
||||||
|
width: 100px;
|
||||||
|
}
|
||||||
.switch input,
|
.switch input,
|
||||||
.switch a {
|
.switch a {
|
||||||
cursor: pointer;
|
cursor: pointer;
|
||||||
|
@ -731,25 +696,18 @@ textarea {
|
||||||
width: 100%;
|
width: 100%;
|
||||||
z-index: 100;
|
z-index: 100;
|
||||||
}
|
}
|
||||||
/* Container */
|
|
||||||
.switch {
|
|
||||||
height: 40px;
|
|
||||||
position: relative;
|
|
||||||
width: 100px;
|
|
||||||
}
|
|
||||||
/* Background unchecked */
|
|
||||||
.switch label {
|
.switch label {
|
||||||
background: rgba(189, 54, 47, 0.8);
|
background: rgba(189, 54, 47, 0.8);
|
||||||
border-radius: 2px;
|
border-radius: 2px;
|
||||||
display: block;
|
display: block;
|
||||||
height: 100%;
|
height: 100%;
|
||||||
position: relative;
|
position: relative;
|
||||||
|
-webkit-transition: all .15s ease;
|
||||||
transition: all .15s ease;
|
transition: all .15s ease;
|
||||||
width: 100%;
|
width: 100%;
|
||||||
border-radius: 5px;
|
border-radius: 5px;
|
||||||
color: #FFF;
|
color: #FFF;
|
||||||
}
|
}
|
||||||
/* Slider unchecked */
|
|
||||||
.switch label div {
|
.switch label div {
|
||||||
background: #fff;
|
background: #fff;
|
||||||
border-radius: 2px;
|
border-radius: 2px;
|
||||||
|
@ -758,12 +716,12 @@ textarea {
|
||||||
left: 6px;
|
left: 6px;
|
||||||
position: absolute;
|
position: absolute;
|
||||||
top: 6px;
|
top: 6px;
|
||||||
|
-webkit-transition: all .15s ease;
|
||||||
transition: all .15s ease;
|
transition: all .15s ease;
|
||||||
width: 35px;
|
width: 35px;
|
||||||
z-index: 3;
|
z-index: 3;
|
||||||
border-radius: 5px;
|
border-radius: 5px;
|
||||||
}
|
}
|
||||||
/* Vertical lines on slider */
|
|
||||||
.switch label div:before {
|
.switch label div:before {
|
||||||
bottom: 0;
|
bottom: 0;
|
||||||
content: '';
|
content: '';
|
||||||
|
@ -774,10 +732,10 @@ textarea {
|
||||||
position: absolute;
|
position: absolute;
|
||||||
right: 0;
|
right: 0;
|
||||||
top: 0;
|
top: 0;
|
||||||
|
-webkit-transition: all .15s ease;
|
||||||
transition: all .15s ease;
|
transition: all .15s ease;
|
||||||
width: 3px;
|
width: 3px;
|
||||||
}
|
}
|
||||||
/* Icon styles */
|
|
||||||
.switch .fontawesome-ok {
|
.switch .fontawesome-ok {
|
||||||
font-size: 18px;
|
font-size: 18px;
|
||||||
left: 15px;
|
left: 15px;
|
||||||
|
@ -802,7 +760,6 @@ textarea {
|
||||||
content: "\f00d";
|
content: "\f00d";
|
||||||
opacity: 0.8;
|
opacity: 0.8;
|
||||||
}
|
}
|
||||||
/* Checked States */
|
|
||||||
.switch input:checked ~ label {
|
.switch input:checked ~ label {
|
||||||
background: rgba(81, 163, 81, 0.75);
|
background: rgba(81, 163, 81, 0.75);
|
||||||
}
|
}
|
||||||
|
@ -832,8 +789,6 @@ pre {
|
||||||
font-size: 15px;
|
font-size: 15px;
|
||||||
padding: 15px 20px;
|
padding: 15px 20px;
|
||||||
border-radius: 5px;
|
border-radius: 5px;
|
||||||
-webkit-border-radius: 5px;
|
|
||||||
-moz-border-radius: 5px;
|
|
||||||
}
|
}
|
||||||
.alert.alert-build-Success span,
|
.alert.alert-build-Success span,
|
||||||
.alert.alert-build-Error span,
|
.alert.alert-build-Error span,
|
||||||
|
@ -870,6 +825,14 @@ pre {
|
||||||
font-size: 22px !IMPORTANT;
|
font-size: 22px !IMPORTANT;
|
||||||
line-height: 32px !IMPORTANT;
|
line-height: 32px !IMPORTANT;
|
||||||
}
|
}
|
||||||
|
.alert.alert-build-Success .actions,
|
||||||
|
.alert.alert-build-Error .actions,
|
||||||
|
.alert.alert-build-Failure .actions,
|
||||||
|
.alert.alert-build-Pending .actions,
|
||||||
|
.alert.alert-build-Started .actions {
|
||||||
|
float: right;
|
||||||
|
margin-top: -2px;
|
||||||
|
}
|
||||||
.build-details {
|
.build-details {
|
||||||
background: #FFF;
|
background: #FFF;
|
||||||
margin-bottom: 40px;
|
margin-bottom: 40px;
|
||||||
|
@ -894,8 +857,6 @@ pre {
|
||||||
}
|
}
|
||||||
.build-details img {
|
.build-details img {
|
||||||
float: left;
|
float: left;
|
||||||
-webkit-border-radius: 50%;
|
|
||||||
-moz-border-radius: 50%;
|
|
||||||
border-radius: 50%;
|
border-radius: 50%;
|
||||||
margin-right: 30px;
|
margin-right: 30px;
|
||||||
width: 58px;
|
width: 58px;
|
||||||
|
@ -936,7 +897,7 @@ pre {
|
||||||
margin-bottom: 30px;
|
margin-bottom: 30px;
|
||||||
}
|
}
|
||||||
.form-repo .field-group label {
|
.form-repo .field-group label {
|
||||||
margin-top: 0px;
|
margin-top: 0;
|
||||||
}
|
}
|
||||||
.form-repo .field-separator {
|
.form-repo .field-separator {
|
||||||
display: inline-block;
|
display: inline-block;
|
||||||
|
@ -944,11 +905,11 @@ pre {
|
||||||
}
|
}
|
||||||
.form-repo ul {
|
.form-repo ul {
|
||||||
padding-top: 15px;
|
padding-top: 15px;
|
||||||
margin-bottom: 0px;
|
margin-bottom: 0;
|
||||||
padding-bottom: 0px;
|
padding-bottom: 0;
|
||||||
list-style: none;
|
list-style: none;
|
||||||
padding-left: 0px;
|
padding-left: 0;
|
||||||
margin-left: 0px;
|
margin-left: 0;
|
||||||
}
|
}
|
||||||
.form-repo ul li {
|
.form-repo ul li {
|
||||||
padding-bottom: 10px;
|
padding-bottom: 10px;
|
||||||
|
@ -957,18 +918,16 @@ pre {
|
||||||
width: 32px;
|
width: 32px;
|
||||||
height: 32px;
|
height: 32px;
|
||||||
border-radius: 50%;
|
border-radius: 50%;
|
||||||
-webkit-border-radius: 50%;
|
|
||||||
-moz-border-radius: 50%;
|
|
||||||
margin-left: 10px;
|
margin-left: 10px;
|
||||||
margin-right: 10px;
|
margin-right: 10px;
|
||||||
}
|
}
|
||||||
ul.account-radio-group {
|
ul.account-radio-group {
|
||||||
padding-top: 15px;
|
padding-top: 15px;
|
||||||
margin-bottom: 0px;
|
margin-bottom: 0;
|
||||||
padding-bottom: 0px;
|
padding-bottom: 0;
|
||||||
list-style: none;
|
list-style: none;
|
||||||
padding-left: 0px;
|
padding-left: 0;
|
||||||
margin-left: 0px;
|
margin-left: 0;
|
||||||
}
|
}
|
||||||
ul.account-radio-group li {
|
ul.account-radio-group li {
|
||||||
padding-bottom: 10px;
|
padding-bottom: 10px;
|
||||||
|
@ -977,8 +936,6 @@ ul.account-radio-group li img {
|
||||||
width: 32px;
|
width: 32px;
|
||||||
height: 32px;
|
height: 32px;
|
||||||
border-radius: 50%;
|
border-radius: 50%;
|
||||||
-webkit-border-radius: 50%;
|
|
||||||
-moz-border-radius: 50%;
|
|
||||||
margin-left: 10px;
|
margin-left: 10px;
|
||||||
margin-right: 10px;
|
margin-right: 10px;
|
||||||
}
|
}
|
||||||
|
@ -991,8 +948,6 @@ ul.account-radio-group li img {
|
||||||
margin-top: 40px;
|
margin-top: 40px;
|
||||||
padding: 0px 0px 20px 0px;
|
padding: 0px 0px 20px 0px;
|
||||||
border-radius: 5px;
|
border-radius: 5px;
|
||||||
-webkit-border-radius: 5px;
|
|
||||||
-moz-border-radius: 5px;
|
|
||||||
}
|
}
|
||||||
.form-centered h1 {
|
.form-centered h1 {
|
||||||
background-color: #262829;
|
background-color: #262829;
|
||||||
|
@ -1003,7 +958,7 @@ ul.account-radio-group li img {
|
||||||
font-weight: normal;
|
font-weight: normal;
|
||||||
font-size: 18px;
|
font-size: 18px;
|
||||||
padding: 25px 10px;
|
padding: 25px 10px;
|
||||||
margin-top: 0px;
|
margin-top: 0;
|
||||||
margin-bottom: 30px;
|
margin-bottom: 30px;
|
||||||
}
|
}
|
||||||
.form-centered input[type="submit"] {
|
.form-centered input[type="submit"] {
|
||||||
|
@ -1016,8 +971,6 @@ ul.account-radio-group li img {
|
||||||
width: 280px;
|
width: 280px;
|
||||||
background: #AAA;
|
background: #AAA;
|
||||||
border-radius: 5px;
|
border-radius: 5px;
|
||||||
-webkit-border-radius: 5px;
|
|
||||||
-moz-border-radius: 5px;
|
|
||||||
}
|
}
|
||||||
.form-centered input[type="text"],
|
.form-centered input[type="text"],
|
||||||
.form-centered input[type="email"],
|
.form-centered input[type="email"],
|
||||||
|
@ -1044,6 +997,7 @@ ul.account-radio-group li img {
|
||||||
.form-centered input[type="text"][disabled],
|
.form-centered input[type="text"][disabled],
|
||||||
.form-centered input[type="email"][disabled],
|
.form-centered input[type="email"][disabled],
|
||||||
.form-centered input[type="password"][disabled] {
|
.form-centered input[type="password"][disabled] {
|
||||||
|
-webkit-box-shadow: none;
|
||||||
box-shadow: none;
|
box-shadow: none;
|
||||||
background: #f7f7f7;
|
background: #f7f7f7;
|
||||||
color: #999;
|
color: #999;
|
||||||
|
|
File diff suppressed because it is too large
Load diff
|
@ -122,7 +122,7 @@ func setupStatic() {
|
||||||
w.Header().Add("Cache-Control", "no-cache")
|
w.Header().Add("Cache-Control", "no-cache")
|
||||||
}
|
}
|
||||||
|
|
||||||
// serce images
|
// serve images
|
||||||
images.ServeHTTP(w, r)
|
images.ServeHTTP(w, r)
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
@ -136,6 +136,7 @@ func setupHandlers() {
|
||||||
github = handler.NewGithubHandler(queue)
|
github = handler.NewGithubHandler(queue)
|
||||||
gitlab = handler.NewGitlabHandler(queue)
|
gitlab = handler.NewGitlabHandler(queue)
|
||||||
bitbucket = handler.NewBitbucketHandler(queue)
|
bitbucket = handler.NewBitbucketHandler(queue)
|
||||||
|
rebuild = handler.NewCommitRebuildHandler(queue)
|
||||||
)
|
)
|
||||||
|
|
||||||
m := pat.New()
|
m := pat.New()
|
||||||
|
@ -226,7 +227,9 @@ func setupHandlers() {
|
||||||
|
|
||||||
// handlers for repository, commits and build details
|
// handlers for repository, commits and build details
|
||||||
m.Get("/:host/:owner/:name/commit/:commit/build/:label/out.txt", handler.RepoHandler(handler.BuildOut))
|
m.Get("/:host/:owner/:name/commit/:commit/build/:label/out.txt", handler.RepoHandler(handler.BuildOut))
|
||||||
|
m.Post("/:host/:owner/:name/commit/:commit/build/:label/rebuild", handler.RepoAdminHandler(rebuild.CommitRebuild))
|
||||||
m.Get("/:host/:owner/:name/commit/:commit/build/:label", handler.RepoHandler(handler.CommitShow))
|
m.Get("/:host/:owner/:name/commit/:commit/build/:label", handler.RepoHandler(handler.CommitShow))
|
||||||
|
m.Post("/:host/:owner/:name/commit/:commit/rebuild", handler.RepoAdminHandler(rebuild.CommitRebuild))
|
||||||
m.Get("/:host/:owner/:name/commit/:commit", handler.RepoHandler(handler.CommitShow))
|
m.Get("/:host/:owner/:name/commit/:commit", handler.RepoHandler(handler.CommitShow))
|
||||||
m.Get("/:host/:owner/:name/tree", handler.RepoHandler(handler.RepoDashboard))
|
m.Get("/:host/:owner/:name/tree", handler.RepoHandler(handler.RepoDashboard))
|
||||||
m.Get("/:host/:owner/:name/status.svg", handler.ErrorHandler(handler.Badge))
|
m.Get("/:host/:owner/:name/status.svg", handler.ErrorHandler(handler.Badge))
|
||||||
|
|
|
@ -10,7 +10,7 @@ const buildTable = "builds"
|
||||||
|
|
||||||
// SQL Queries to retrieve a list of all Commits belonging to a Repo.
|
// SQL Queries to retrieve a list of all Commits belonging to a Repo.
|
||||||
const buildStmt = `
|
const buildStmt = `
|
||||||
SELECT id, commit_id, slug, status, started, finished, duration, created, updated, stdout
|
SELECT id, commit_id, slug, status, started, finished, duration, created, updated, stdout, buildscript
|
||||||
FROM builds
|
FROM builds
|
||||||
WHERE commit_id = ?
|
WHERE commit_id = ?
|
||||||
ORDER BY slug ASC
|
ORDER BY slug ASC
|
||||||
|
@ -18,7 +18,7 @@ ORDER BY slug ASC
|
||||||
|
|
||||||
// SQL Queries to retrieve a Build by id.
|
// SQL Queries to retrieve a Build by id.
|
||||||
const buildFindStmt = `
|
const buildFindStmt = `
|
||||||
SELECT id, commit_id, slug, status, started, finished, duration, created, updated, stdout
|
SELECT id, commit_id, slug, status, started, finished, duration, created, updated, stdout, buildscript
|
||||||
FROM builds
|
FROM builds
|
||||||
WHERE id = ?
|
WHERE id = ?
|
||||||
LIMIT 1
|
LIMIT 1
|
||||||
|
@ -26,7 +26,7 @@ LIMIT 1
|
||||||
|
|
||||||
// SQL Queries to retrieve a Commit by name and repo id.
|
// SQL Queries to retrieve a Commit by name and repo id.
|
||||||
const buildFindSlugStmt = `
|
const buildFindSlugStmt = `
|
||||||
SELECT id, commit_id, slug, status, started, finished, duration, created, updated, stdout
|
SELECT id, commit_id, slug, status, started, finished, duration, created, updated, stdout, buildscript
|
||||||
FROM builds
|
FROM builds
|
||||||
WHERE slug = ? AND commit_id = ?
|
WHERE slug = ? AND commit_id = ?
|
||||||
LIMIT 1
|
LIMIT 1
|
||||||
|
|
20
pkg/database/migrate/20140522205400_save_drone_yml.go
Normal file
20
pkg/database/migrate/20140522205400_save_drone_yml.go
Normal file
|
@ -0,0 +1,20 @@
|
||||||
|
package migrate
|
||||||
|
|
||||||
|
type rev20140522205400 struct{}
|
||||||
|
|
||||||
|
var SaveDroneYml = &rev20140522205400{}
|
||||||
|
|
||||||
|
func (r *rev20140522205400) Revision() int64 {
|
||||||
|
return 20140522205400
|
||||||
|
}
|
||||||
|
|
||||||
|
func (r *rev20140522205400) Up(mg *MigrationDriver) error {
|
||||||
|
_, err := mg.AddColumn("builds", "buildscript TEXT")
|
||||||
|
_, err = mg.Tx.Exec("UPDATE builds SET buildscript = '' WHERE buildscript IS NULL")
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
func (r *rev20140522205400) Down(mg *MigrationDriver) error {
|
||||||
|
_, err := mg.DropColumns("builds", "buildscript")
|
||||||
|
return err
|
||||||
|
}
|
|
@ -13,6 +13,7 @@ func (m *Migration) All() *Migration {
|
||||||
m.Add(GitHubEnterpriseSupport)
|
m.Add(GitHubEnterpriseSupport)
|
||||||
m.Add(AddOpenInvitationColumn)
|
m.Add(AddOpenInvitationColumn)
|
||||||
m.Add(AddGitlabColumns)
|
m.Add(AddGitlabColumns)
|
||||||
|
m.Add(SaveDroneYml)
|
||||||
|
|
||||||
// m.Add(...)
|
// m.Add(...)
|
||||||
// ...
|
// ...
|
||||||
|
|
|
@ -90,3 +90,18 @@ func ListReposTeam(id int64) ([]*Repo, error) {
|
||||||
err := meddler.QueryAll(db, &repos, repoTeamStmt, id)
|
err := meddler.QueryAll(db, &repos, repoTeamStmt, id)
|
||||||
return repos, err
|
return repos, err
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Checks whether a user is admin of a repo
|
||||||
|
// Returns true if user owns repo or is on team that owns repo
|
||||||
|
// Returns true if the user is an admin member of the team.
|
||||||
|
func IsRepoAdmin(user *User, repo *Repo) (bool, error) {
|
||||||
|
if user == nil {
|
||||||
|
return false, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
if user.ID == repo.UserID {
|
||||||
|
return true, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
return IsMemberAdmin(user.ID, repo.TeamID)
|
||||||
|
}
|
||||||
|
|
|
@ -43,26 +43,29 @@ func Badge(w http.ResponseWriter, r *http.Request) error {
|
||||||
// get the latest commit from the database
|
// get the latest commit from the database
|
||||||
// for the requested branch
|
// for the requested branch
|
||||||
commit, err := database.GetBranch(repo.ID, branchParam)
|
commit, err := database.GetBranch(repo.ID, branchParam)
|
||||||
if err == nil {
|
if err != nil {
|
||||||
switch {
|
http.NotFound(w, r)
|
||||||
case commit.Status == "Success" && len(successParam) == 0:
|
return nil
|
||||||
// if no success image is provided, we serve a
|
}
|
||||||
// badge using the shields.io service
|
|
||||||
badge = badgeSuccess
|
switch {
|
||||||
case commit.Status == "Success" && len(successParam) != 0:
|
case commit.Status == "Success" && len(successParam) == 0:
|
||||||
// otherwise we serve the user defined success badge
|
// if no success image is provided, we serve a
|
||||||
badge = successParam
|
// badge using the shields.io service
|
||||||
case commit.Status == "Failure" && len(failureParam) == 0:
|
badge = badgeSuccess
|
||||||
// if no failure image is provided, we serve a
|
case commit.Status == "Success" && len(successParam) != 0:
|
||||||
// badge using the shields.io service
|
// otherwise we serve the user defined success badge
|
||||||
badge = badgeFailure
|
badge = successParam
|
||||||
case commit.Status == "Failure" && len(failureParam) != 0:
|
case commit.Status == "Failure" && len(failureParam) == 0:
|
||||||
// otherwise we serve the user defined failure badge
|
// if no failure image is provided, we serve a
|
||||||
badge = failureParam
|
// badge using the shields.io service
|
||||||
default:
|
badge = badgeFailure
|
||||||
// otherwise load unknown image
|
case commit.Status == "Failure" && len(failureParam) != 0:
|
||||||
badge = badgeUnknown
|
// otherwise we serve the user defined failure badge
|
||||||
}
|
badge = failureParam
|
||||||
|
default:
|
||||||
|
// otherwise load unknown image
|
||||||
|
badge = badgeUnknown
|
||||||
}
|
}
|
||||||
|
|
||||||
http.Redirect(w, r, badge, http.StatusSeeOther)
|
http.Redirect(w, r, badge, http.StatusSeeOther)
|
||||||
|
|
|
@ -5,7 +5,6 @@ import (
|
||||||
"net/http"
|
"net/http"
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
"github.com/drone/drone/pkg/build/script"
|
|
||||||
"github.com/drone/drone/pkg/database"
|
"github.com/drone/drone/pkg/database"
|
||||||
. "github.com/drone/drone/pkg/model"
|
. "github.com/drone/drone/pkg/model"
|
||||||
"github.com/drone/drone/pkg/queue"
|
"github.com/drone/drone/pkg/queue"
|
||||||
|
@ -83,16 +82,6 @@ func (h *BitbucketHandler) Hook(w http.ResponseWriter, r *http.Request) error {
|
||||||
return RenderText(w, http.StatusText(http.StatusNotFound), http.StatusNotFound)
|
return RenderText(w, http.StatusText(http.StatusNotFound), http.StatusNotFound)
|
||||||
}
|
}
|
||||||
|
|
||||||
// parse the build script
|
|
||||||
buildscript, err := script.ParseBuild([]byte(raw.Data), repo.Params)
|
|
||||||
if err != nil {
|
|
||||||
msg := "Could not parse your .drone.yml file. It needs to be a valid drone yaml file.\n\n" + err.Error() + "\n"
|
|
||||||
if err := saveFailedBuild(commit, msg); err != nil {
|
|
||||||
return RenderText(w, http.StatusText(http.StatusInternalServerError), http.StatusInternalServerError)
|
|
||||||
}
|
|
||||||
return RenderText(w, http.StatusText(http.StatusBadRequest), http.StatusBadRequest)
|
|
||||||
}
|
|
||||||
|
|
||||||
// save the commit to the database
|
// save the commit to the database
|
||||||
if err := database.SaveCommit(commit); err != nil {
|
if err := database.SaveCommit(commit); err != nil {
|
||||||
return RenderText(w, http.StatusText(http.StatusInternalServerError), http.StatusInternalServerError)
|
return RenderText(w, http.StatusText(http.StatusInternalServerError), http.StatusInternalServerError)
|
||||||
|
@ -104,12 +93,13 @@ func (h *BitbucketHandler) Hook(w http.ResponseWriter, r *http.Request) error {
|
||||||
build.CommitID = commit.ID
|
build.CommitID = commit.ID
|
||||||
build.Created = time.Now().UTC()
|
build.Created = time.Now().UTC()
|
||||||
build.Status = "Pending"
|
build.Status = "Pending"
|
||||||
|
build.BuildScript = raw.Data
|
||||||
if err := database.SaveBuild(build); err != nil {
|
if err := database.SaveBuild(build); err != nil {
|
||||||
return RenderText(w, http.StatusText(http.StatusInternalServerError), http.StatusInternalServerError)
|
return RenderText(w, http.StatusText(http.StatusInternalServerError), http.StatusInternalServerError)
|
||||||
}
|
}
|
||||||
|
|
||||||
// send the build to the queue
|
// send the build to the queue
|
||||||
h.queue.Add(&queue.BuildTask{Repo: repo, Commit: commit, Build: build, Script: buildscript})
|
h.queue.Add(&queue.BuildTask{Repo: repo, Commit: commit, Build: build})
|
||||||
|
|
||||||
// OK!
|
// OK!
|
||||||
return RenderText(w, http.StatusText(http.StatusOK), http.StatusOK)
|
return RenderText(w, http.StatusText(http.StatusOK), http.StatusOK)
|
||||||
|
|
|
@ -8,6 +8,7 @@ import (
|
||||||
"github.com/drone/drone/pkg/channel"
|
"github.com/drone/drone/pkg/channel"
|
||||||
"github.com/drone/drone/pkg/database"
|
"github.com/drone/drone/pkg/database"
|
||||||
. "github.com/drone/drone/pkg/model"
|
. "github.com/drone/drone/pkg/model"
|
||||||
|
"github.com/drone/drone/pkg/queue"
|
||||||
)
|
)
|
||||||
|
|
||||||
// Display a specific Commit.
|
// Display a specific Commit.
|
||||||
|
@ -33,14 +34,20 @@ func CommitShow(w http.ResponseWriter, r *http.Request, u *User, repo *Repo) err
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
|
admin, err := database.IsRepoAdmin(u, repo)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
data := struct {
|
data := struct {
|
||||||
User *User
|
User *User
|
||||||
Repo *Repo
|
Repo *Repo
|
||||||
Commit *Commit
|
Commit *Commit
|
||||||
Build *Build
|
Build *Build
|
||||||
Builds []*Build
|
Builds []*Build
|
||||||
Token string
|
Token string
|
||||||
}{u, repo, commit, builds[0], builds, ""}
|
IsAdmin bool
|
||||||
|
}{u, repo, commit, builds[0], builds, "", admin}
|
||||||
|
|
||||||
// get the specific build requested by the user. instead
|
// get the specific build requested by the user. instead
|
||||||
// of a database round trip, we can just loop through the
|
// of a database round trip, we can just loop through the
|
||||||
|
@ -94,3 +101,70 @@ func saveFailedBuild(commit *Commit, msg string) error {
|
||||||
return nil
|
return nil
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
type CommitRebuildHandler struct {
|
||||||
|
queue *queue.Queue
|
||||||
|
}
|
||||||
|
|
||||||
|
func NewCommitRebuildHandler(queue *queue.Queue) *CommitRebuildHandler {
|
||||||
|
return &CommitRebuildHandler{
|
||||||
|
queue: queue,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// CommitRebuild re-queues a previously built commit. It finds the existing
|
||||||
|
// commit and build and injects them back into the queue. If the commit
|
||||||
|
// doesn't exist or has no builds, or if a build label has been passed but
|
||||||
|
// can't be located, it prints an error. Otherwise, it adds the build/commit
|
||||||
|
// to the queue and redirects back to the commit page.
|
||||||
|
func (h *CommitRebuildHandler) CommitRebuild(w http.ResponseWriter, r *http.Request, u *User, repo *Repo) error {
|
||||||
|
hash := r.FormValue(":commit")
|
||||||
|
labl := r.FormValue(":label")
|
||||||
|
host := r.FormValue(":host")
|
||||||
|
branch := r.FormValue("branch")
|
||||||
|
if branch == "" {
|
||||||
|
branch = "master"
|
||||||
|
}
|
||||||
|
|
||||||
|
// get the commit from the database
|
||||||
|
commit, err := database.GetCommitBranchHash(branch, hash, repo.ID)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
// get the builds from the database. a commit can have
|
||||||
|
// multiple sub-builds (or matrix builds)
|
||||||
|
builds, err := database.ListBuilds(commit.ID)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
build := builds[0]
|
||||||
|
|
||||||
|
if labl != "" {
|
||||||
|
// get the specific build requested by the user. instead
|
||||||
|
// of a database round trip, we can just loop through the
|
||||||
|
// list and extract the requested build.
|
||||||
|
build = nil
|
||||||
|
for _, b := range builds {
|
||||||
|
if b.Slug == labl {
|
||||||
|
build = b
|
||||||
|
break
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if build == nil {
|
||||||
|
return fmt.Errorf("Could not find build: %s", labl)
|
||||||
|
}
|
||||||
|
|
||||||
|
h.queue.Add(&queue.BuildTask{Repo: repo, Commit: commit, Build: build})
|
||||||
|
|
||||||
|
if labl != "" {
|
||||||
|
http.Redirect(w, r, fmt.Sprintf("/%s/%s/%s/commit/%s/build/%s?branch=%s", host, repo.Owner, repo.Name, hash, labl, branch), http.StatusSeeOther)
|
||||||
|
} else {
|
||||||
|
http.Redirect(w, r, fmt.Sprintf("/%s/%s/%s/commit/%s?branch=%s", host, repo.Owner, repo.Name, hash, branch), http.StatusSeeOther)
|
||||||
|
}
|
||||||
|
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
|
@ -6,7 +6,6 @@ import (
|
||||||
"strconv"
|
"strconv"
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
"github.com/drone/drone/pkg/build/script"
|
|
||||||
"github.com/drone/drone/pkg/database"
|
"github.com/drone/drone/pkg/database"
|
||||||
. "github.com/drone/drone/pkg/model"
|
. "github.com/drone/drone/pkg/model"
|
||||||
"github.com/drone/drone/pkg/queue"
|
"github.com/drone/drone/pkg/queue"
|
||||||
|
@ -131,22 +130,8 @@ func (h *GithubHandler) Hook(w http.ResponseWriter, r *http.Request) error {
|
||||||
}
|
}
|
||||||
|
|
||||||
// decode the content. Note: Not sure this will ever happen...it basically means a GitHub API issue
|
// decode the content. Note: Not sure this will ever happen...it basically means a GitHub API issue
|
||||||
raw, err := content.DecodeContent()
|
buildscript, err := content.DecodeContent()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
msg := "Could not decode the yaml from GitHub. Check that your .drone.yml is a valid yaml file.\n"
|
|
||||||
if err := saveFailedBuild(commit, msg); err != nil {
|
|
||||||
return RenderText(w, http.StatusText(http.StatusInternalServerError), http.StatusInternalServerError)
|
|
||||||
}
|
|
||||||
return RenderText(w, http.StatusText(http.StatusBadRequest), http.StatusBadRequest)
|
|
||||||
}
|
|
||||||
|
|
||||||
// parse the build script
|
|
||||||
buildscript, err := script.ParseBuild(raw, repo.Params)
|
|
||||||
if err != nil {
|
|
||||||
msg := "Could not parse your .drone.yml file. It needs to be a valid drone yaml file.\n\n" + err.Error() + "\n"
|
|
||||||
if err := saveFailedBuild(commit, msg); err != nil {
|
|
||||||
return RenderText(w, http.StatusText(http.StatusInternalServerError), http.StatusInternalServerError)
|
|
||||||
}
|
|
||||||
return RenderText(w, http.StatusText(http.StatusBadRequest), http.StatusBadRequest)
|
return RenderText(w, http.StatusText(http.StatusBadRequest), http.StatusBadRequest)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -161,6 +146,7 @@ func (h *GithubHandler) Hook(w http.ResponseWriter, r *http.Request) error {
|
||||||
build.CommitID = commit.ID
|
build.CommitID = commit.ID
|
||||||
build.Created = time.Now().UTC()
|
build.Created = time.Now().UTC()
|
||||||
build.Status = "Pending"
|
build.Status = "Pending"
|
||||||
|
build.BuildScript = string(buildscript)
|
||||||
if err := database.SaveBuild(build); err != nil {
|
if err := database.SaveBuild(build); err != nil {
|
||||||
return RenderText(w, http.StatusText(http.StatusInternalServerError), http.StatusInternalServerError)
|
return RenderText(w, http.StatusText(http.StatusInternalServerError), http.StatusInternalServerError)
|
||||||
}
|
}
|
||||||
|
@ -169,7 +155,7 @@ func (h *GithubHandler) Hook(w http.ResponseWriter, r *http.Request) error {
|
||||||
//realtime.CommitPending(repo.UserID, repo.TeamID, repo.ID, commit.ID, repo.Private)
|
//realtime.CommitPending(repo.UserID, repo.TeamID, repo.ID, commit.ID, repo.Private)
|
||||||
//realtime.BuildPending(repo.UserID, repo.TeamID, repo.ID, commit.ID, build.ID, repo.Private)
|
//realtime.BuildPending(repo.UserID, repo.TeamID, repo.ID, commit.ID, build.ID, repo.Private)
|
||||||
|
|
||||||
h.queue.Add(&queue.BuildTask{Repo: repo, Commit: commit, Build: build, Script: buildscript}) //Push(repo, commit, build, buildscript)
|
h.queue.Add(&queue.BuildTask{Repo: repo, Commit: commit, Build: build}) //Push(repo, commit, build)
|
||||||
|
|
||||||
// OK!
|
// OK!
|
||||||
return RenderText(w, http.StatusText(http.StatusOK), http.StatusOK)
|
return RenderText(w, http.StatusText(http.StatusOK), http.StatusOK)
|
||||||
|
@ -250,22 +236,12 @@ func (h *GithubHandler) PullRequestHook(w http.ResponseWriter, r *http.Request)
|
||||||
}
|
}
|
||||||
|
|
||||||
// decode the content
|
// decode the content
|
||||||
raw, err := content.DecodeContent()
|
buildscript, err := content.DecodeContent()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
RenderText(w, http.StatusText(http.StatusBadRequest), http.StatusBadRequest)
|
RenderText(w, http.StatusText(http.StatusBadRequest), http.StatusBadRequest)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
// parse the build script
|
|
||||||
buildscript, err := script.ParseBuild(raw, repo.Params)
|
|
||||||
if err != nil {
|
|
||||||
// TODO if the YAML is invalid we should create a commit record
|
|
||||||
// with an ERROR status so that the user knows why a build wasn't
|
|
||||||
// triggered in the system
|
|
||||||
RenderText(w, http.StatusText(http.StatusBadRequest), http.StatusBadRequest)
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
// save the commit to the database
|
// save the commit to the database
|
||||||
if err := database.SaveCommit(commit); err != nil {
|
if err := database.SaveCommit(commit); err != nil {
|
||||||
RenderText(w, http.StatusText(http.StatusInternalServerError), http.StatusInternalServerError)
|
RenderText(w, http.StatusText(http.StatusInternalServerError), http.StatusInternalServerError)
|
||||||
|
@ -278,6 +254,7 @@ func (h *GithubHandler) PullRequestHook(w http.ResponseWriter, r *http.Request)
|
||||||
build.CommitID = commit.ID
|
build.CommitID = commit.ID
|
||||||
build.Created = time.Now().UTC()
|
build.Created = time.Now().UTC()
|
||||||
build.Status = "Pending"
|
build.Status = "Pending"
|
||||||
|
build.BuildScript = string(buildscript)
|
||||||
if err := database.SaveBuild(build); err != nil {
|
if err := database.SaveBuild(build); err != nil {
|
||||||
RenderText(w, http.StatusText(http.StatusInternalServerError), http.StatusInternalServerError)
|
RenderText(w, http.StatusText(http.StatusInternalServerError), http.StatusInternalServerError)
|
||||||
return
|
return
|
||||||
|
@ -285,7 +262,7 @@ func (h *GithubHandler) PullRequestHook(w http.ResponseWriter, r *http.Request)
|
||||||
|
|
||||||
// notify websocket that a new build is pending
|
// notify websocket that a new build is pending
|
||||||
// TODO we should, for consistency, just put this inside Queue.Add()
|
// TODO we should, for consistency, just put this inside Queue.Add()
|
||||||
h.queue.Add(&queue.BuildTask{Repo: repo, Commit: commit, Build: build, Script: buildscript})
|
h.queue.Add(&queue.BuildTask{Repo: repo, Commit: commit, Build: build})
|
||||||
|
|
||||||
// OK!
|
// OK!
|
||||||
RenderText(w, http.StatusText(http.StatusOK), http.StatusOK)
|
RenderText(w, http.StatusText(http.StatusOK), http.StatusOK)
|
||||||
|
|
|
@ -9,7 +9,6 @@ import (
|
||||||
"strings"
|
"strings"
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
"github.com/drone/drone/pkg/build/script"
|
|
||||||
"github.com/drone/drone/pkg/database"
|
"github.com/drone/drone/pkg/database"
|
||||||
. "github.com/drone/drone/pkg/model"
|
. "github.com/drone/drone/pkg/model"
|
||||||
"github.com/drone/drone/pkg/queue"
|
"github.com/drone/drone/pkg/queue"
|
||||||
|
@ -207,7 +206,7 @@ func (g *GitlabHandler) Hook(w http.ResponseWriter, r *http.Request) error {
|
||||||
// get the drone.yml file from GitHub
|
// get the drone.yml file from GitHub
|
||||||
client := gogitlab.NewGitlab(settings.GitlabApiUrl, g.apiPath, user.GitlabToken)
|
client := gogitlab.NewGitlab(settings.GitlabApiUrl, g.apiPath, user.GitlabToken)
|
||||||
|
|
||||||
content, err := client.RepoRawFile(ns(repo.Owner, repo.Name), commit.Hash, ".drone.yml")
|
buildscript, err := client.RepoRawFile(ns(repo.Owner, repo.Name), commit.Hash, ".drone.yml")
|
||||||
if err != nil {
|
if err != nil {
|
||||||
msg := "No .drone.yml was found in this repository. You need to add one.\n"
|
msg := "No .drone.yml was found in this repository. You need to add one.\n"
|
||||||
if err := saveFailedBuild(commit, msg); err != nil {
|
if err := saveFailedBuild(commit, msg); err != nil {
|
||||||
|
@ -216,16 +215,6 @@ func (g *GitlabHandler) Hook(w http.ResponseWriter, r *http.Request) error {
|
||||||
return RenderText(w, http.StatusText(http.StatusBadRequest), http.StatusBadRequest)
|
return RenderText(w, http.StatusText(http.StatusBadRequest), http.StatusBadRequest)
|
||||||
}
|
}
|
||||||
|
|
||||||
// parse the build script
|
|
||||||
buildscript, err := script.ParseBuild(content, repo.Params)
|
|
||||||
if err != nil {
|
|
||||||
msg := "Could not parse your .drone.yml file. It needs to be a valid drone yaml file.\n\n" + err.Error() + "\n"
|
|
||||||
if err := saveFailedBuild(commit, msg); err != nil {
|
|
||||||
return RenderText(w, http.StatusText(http.StatusInternalServerError), http.StatusInternalServerError)
|
|
||||||
}
|
|
||||||
return RenderText(w, http.StatusText(http.StatusBadRequest), http.StatusBadRequest)
|
|
||||||
}
|
|
||||||
|
|
||||||
// save the commit to the database
|
// save the commit to the database
|
||||||
if err := database.SaveCommit(commit); err != nil {
|
if err := database.SaveCommit(commit); err != nil {
|
||||||
return RenderText(w, http.StatusText(http.StatusInternalServerError), http.StatusInternalServerError)
|
return RenderText(w, http.StatusText(http.StatusInternalServerError), http.StatusInternalServerError)
|
||||||
|
@ -237,11 +226,12 @@ func (g *GitlabHandler) Hook(w http.ResponseWriter, r *http.Request) error {
|
||||||
build.CommitID = commit.ID
|
build.CommitID = commit.ID
|
||||||
build.Created = time.Now().UTC()
|
build.Created = time.Now().UTC()
|
||||||
build.Status = "Pending"
|
build.Status = "Pending"
|
||||||
|
build.BuildScript = string(buildscript)
|
||||||
if err := database.SaveBuild(build); err != nil {
|
if err := database.SaveBuild(build); err != nil {
|
||||||
return RenderText(w, http.StatusText(http.StatusInternalServerError), http.StatusInternalServerError)
|
return RenderText(w, http.StatusText(http.StatusInternalServerError), http.StatusInternalServerError)
|
||||||
}
|
}
|
||||||
|
|
||||||
g.queue.Add(&queue.BuildTask{Repo: repo, Commit: commit, Build: build, Script: buildscript})
|
g.queue.Add(&queue.BuildTask{Repo: repo, Commit: commit, Build: build})
|
||||||
|
|
||||||
// OK!
|
// OK!
|
||||||
return RenderText(w, http.StatusText(http.StatusOK), http.StatusOK)
|
return RenderText(w, http.StatusText(http.StatusOK), http.StatusOK)
|
||||||
|
@ -287,7 +277,7 @@ func (g *GitlabHandler) PullRequestHook(p *gogitlab.HookPayload, repo *Repo, use
|
||||||
commit.Timestamp = src.Commit.AuthoredDateRaw
|
commit.Timestamp = src.Commit.AuthoredDateRaw
|
||||||
commit.SetAuthor(src.Commit.Author.Email)
|
commit.SetAuthor(src.Commit.Author.Email)
|
||||||
|
|
||||||
content, err := client.RepoRawFile(strconv.Itoa(obj.SourceProjectId), commit.Hash, ".drone.yml")
|
buildscript, err := client.RepoRawFile(strconv.Itoa(obj.SourceProjectId), commit.Hash, ".drone.yml")
|
||||||
if err != nil {
|
if err != nil {
|
||||||
msg := "No .drone.yml was found in this repository. You need to add one.\n"
|
msg := "No .drone.yml was found in this repository. You need to add one.\n"
|
||||||
if err := saveFailedBuild(commit, msg); err != nil {
|
if err := saveFailedBuild(commit, msg); err != nil {
|
||||||
|
@ -296,16 +286,6 @@ func (g *GitlabHandler) PullRequestHook(p *gogitlab.HookPayload, repo *Repo, use
|
||||||
return fmt.Errorf("Error to fetch build script: %q", err)
|
return fmt.Errorf("Error to fetch build script: %q", err)
|
||||||
}
|
}
|
||||||
|
|
||||||
// parse the build script
|
|
||||||
buildscript, err := script.ParseBuild(content, repo.Params)
|
|
||||||
if err != nil {
|
|
||||||
msg := "Could not parse your .drone.yml file. It needs to be a valid drone yaml file.\n\n" + err.Error() + "\n"
|
|
||||||
if err := saveFailedBuild(commit, msg); err != nil {
|
|
||||||
return fmt.Errorf("Failed to save build: %q", err)
|
|
||||||
}
|
|
||||||
return fmt.Errorf("Failed to parse build script: %q", err)
|
|
||||||
}
|
|
||||||
|
|
||||||
// save the commit to the database
|
// save the commit to the database
|
||||||
if err := database.SaveCommit(commit); err != nil {
|
if err := database.SaveCommit(commit); err != nil {
|
||||||
return fmt.Errorf("Failed to save commit: %q", err)
|
return fmt.Errorf("Failed to save commit: %q", err)
|
||||||
|
@ -317,11 +297,12 @@ func (g *GitlabHandler) PullRequestHook(p *gogitlab.HookPayload, repo *Repo, use
|
||||||
build.CommitID = commit.ID
|
build.CommitID = commit.ID
|
||||||
build.Created = time.Now().UTC()
|
build.Created = time.Now().UTC()
|
||||||
build.Status = "Pending"
|
build.Status = "Pending"
|
||||||
|
build.BuildScript = string(buildscript)
|
||||||
if err := database.SaveBuild(build); err != nil {
|
if err := database.SaveBuild(build); err != nil {
|
||||||
return fmt.Errorf("Failed to save build: %q", err)
|
return fmt.Errorf("Failed to save build: %q", err)
|
||||||
}
|
}
|
||||||
|
|
||||||
g.queue.Add(&queue.BuildTask{Repo: repo, Commit: commit, Build: build, Script: buildscript})
|
g.queue.Add(&queue.BuildTask{Repo: repo, Commit: commit, Build: build})
|
||||||
|
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
|
@ -142,11 +142,9 @@ func (h RepoAdminHandler) ServeHTTP(w http.ResponseWriter, r *http.Request) {
|
||||||
|
|
||||||
// The User must own the repository OR be a member
|
// The User must own the repository OR be a member
|
||||||
// of the Team that owns the repository.
|
// of the Team that owns the repository.
|
||||||
if user.ID != repo.UserID {
|
if admin, _ := database.IsRepoAdmin(user, repo); admin == false {
|
||||||
if admin, _ := database.IsMemberAdmin(user.ID, repo.TeamID); admin == false {
|
RenderNotFound(w)
|
||||||
RenderNotFound(w)
|
return
|
||||||
return
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if err = h(w, r, user, repo); err != nil {
|
if err = h(w, r, user, repo); err != nil {
|
||||||
|
|
|
@ -45,7 +45,7 @@ func TestRepoHandler(t *testing.T) {
|
||||||
So(rec.Code, ShouldEqual, 303)
|
So(rec.Code, ShouldEqual, 303)
|
||||||
})
|
})
|
||||||
Convey("Private repo can not be viewed by a non team member", func() {
|
Convey("Private repo can not be viewed by a non team member", func() {
|
||||||
req, err := http.NewRequest("GET", "/github.com/drone/drone", nil)
|
req, err := http.NewRequest("GET", "/github.com/drone/drone", nil)
|
||||||
So(err, ShouldBeNil)
|
So(err, ShouldBeNil)
|
||||||
rec := httptest.NewRecorder()
|
rec := httptest.NewRecorder()
|
||||||
setUserSession(rec, req, "rick@el.to.ro")
|
setUserSession(rec, req, "rick@el.to.ro")
|
||||||
|
@ -61,7 +61,7 @@ func dummyUserRepo(w http.ResponseWriter, r *http.Request, u *User, repo *Repo)
|
||||||
|
|
||||||
func setUserSession(w http.ResponseWriter, r *http.Request, username string) {
|
func setUserSession(w http.ResponseWriter, r *http.Request, username string) {
|
||||||
handler.SetCookie(w, r, "_sess", username)
|
handler.SetCookie(w, r, "_sess", username)
|
||||||
resp := http.Response{Header: w.Header()}
|
resp := http.Response{Header: w.Header()}
|
||||||
for _, v := range resp.Cookies() {
|
for _, v := range resp.Cookies() {
|
||||||
r.AddCookie(v)
|
r.AddCookie(v)
|
||||||
}
|
}
|
||||||
|
|
|
@ -15,16 +15,17 @@ const (
|
||||||
)
|
)
|
||||||
|
|
||||||
type Build struct {
|
type Build struct {
|
||||||
ID int64 `meddler:"id,pk" json:"id"`
|
ID int64 `meddler:"id,pk" json:"id"`
|
||||||
CommitID int64 `meddler:"commit_id" json:"-"`
|
CommitID int64 `meddler:"commit_id" json:"-"`
|
||||||
Slug string `meddler:"slug" json:"slug"`
|
Slug string `meddler:"slug" json:"slug"`
|
||||||
Status string `meddler:"status" json:"status"`
|
Status string `meddler:"status" json:"status"`
|
||||||
Started time.Time `meddler:"started,utctime" json:"started"`
|
Started time.Time `meddler:"started,utctime" json:"started"`
|
||||||
Finished time.Time `meddler:"finished,utctime" json:"finished"`
|
Finished time.Time `meddler:"finished,utctime" json:"finished"`
|
||||||
Duration int64 `meddler:"duration" json:"duration"`
|
Duration int64 `meddler:"duration" json:"duration"`
|
||||||
Created time.Time `meddler:"created,utctime" json:"created"`
|
Created time.Time `meddler:"created,utctime" json:"created"`
|
||||||
Updated time.Time `meddler:"updated,utctime" json:"updated"`
|
Updated time.Time `meddler:"updated,utctime" json:"updated"`
|
||||||
Stdout string `meddler:"stdout" json:"-"`
|
Stdout string `meddler:"stdout" json:"-"`
|
||||||
|
BuildScript string `meddler:"buildscript" json:"-"`
|
||||||
}
|
}
|
||||||
|
|
||||||
// HumanDuration returns a human-readable approximation of a duration
|
// HumanDuration returns a human-readable approximation of a duration
|
||||||
|
|
|
@ -2,6 +2,7 @@ package publish
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"fmt"
|
"fmt"
|
||||||
|
"strings"
|
||||||
|
|
||||||
"github.com/drone/drone/pkg/build/buildfile"
|
"github.com/drone/drone/pkg/build/buildfile"
|
||||||
)
|
)
|
||||||
|
@ -37,12 +38,18 @@ type Swift struct {
|
||||||
}
|
}
|
||||||
|
|
||||||
func (s *Swift) Write(f *buildfile.Buildfile) {
|
func (s *Swift) Write(f *buildfile.Buildfile) {
|
||||||
|
var target string
|
||||||
// All options are required, so ensure they are present
|
// All options are required, so ensure they are present
|
||||||
if len(s.Username) == 0 || len(s.Password) == 0 || len(s.AuthURL) == 0 || len(s.Region) == 0 || len(s.Source) == 0 || len(s.Container) == 0 || len(s.Target) == 0 {
|
if len(s.Username) == 0 || len(s.Password) == 0 || len(s.AuthURL) == 0 || len(s.Region) == 0 || len(s.Source) == 0 || len(s.Container) == 0 {
|
||||||
f.WriteCmdSilent(`echo "Swift: Missing argument(s)"`)
|
f.WriteCmdSilent(`echo "Swift: Missing argument(s)"`)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// If a target was provided, prefix it with a /
|
||||||
|
if len(s.Target) > 0 {
|
||||||
|
target = fmt.Sprintf("/%s", strings.TrimPrefix(s.Target, "/"))
|
||||||
|
}
|
||||||
|
|
||||||
// debugging purposes so we can see if / where something is failing
|
// debugging purposes so we can see if / where something is failing
|
||||||
f.WriteCmdSilent(`echo "Swift: Publishing..."`)
|
f.WriteCmdSilent(`echo "Swift: Publishing..."`)
|
||||||
|
|
||||||
|
@ -56,5 +63,5 @@ func (s *Swift) Write(f *buildfile.Buildfile) {
|
||||||
f.WriteEnv("SWIFTLY_AUTH_KEY", s.Password)
|
f.WriteEnv("SWIFTLY_AUTH_KEY", s.Password)
|
||||||
f.WriteEnv("SWIFTLY_REGION", s.Region)
|
f.WriteEnv("SWIFTLY_REGION", s.Region)
|
||||||
|
|
||||||
f.WriteCmd(fmt.Sprintf(`swiftly put -i %s %s/%s`, s.Source, s.Container, s.Target))
|
f.WriteCmd(fmt.Sprintf(`swiftly put -i %s %s%s`, s.Source, s.Container, target))
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,7 +1,6 @@
|
||||||
package queue
|
package queue
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"github.com/drone/drone/pkg/build/script"
|
|
||||||
. "github.com/drone/drone/pkg/model"
|
. "github.com/drone/drone/pkg/model"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
@ -16,10 +15,6 @@ type BuildTask struct {
|
||||||
Repo *Repo
|
Repo *Repo
|
||||||
Commit *Commit
|
Commit *Commit
|
||||||
Build *Build
|
Build *Build
|
||||||
|
|
||||||
// Build instructions from the .drone.yml
|
|
||||||
// file, unmarshalled.
|
|
||||||
Script *script.Build
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Start N workers with the given build runner.
|
// Start N workers with the given build runner.
|
||||||
|
|
|
@ -5,6 +5,7 @@ import (
|
||||||
"fmt"
|
"fmt"
|
||||||
"github.com/drone/drone/pkg/build/git"
|
"github.com/drone/drone/pkg/build/git"
|
||||||
r "github.com/drone/drone/pkg/build/repo"
|
r "github.com/drone/drone/pkg/build/repo"
|
||||||
|
"github.com/drone/drone/pkg/build/script"
|
||||||
"github.com/drone/drone/pkg/channel"
|
"github.com/drone/drone/pkg/channel"
|
||||||
"github.com/drone/drone/pkg/database"
|
"github.com/drone/drone/pkg/database"
|
||||||
. "github.com/drone/drone/pkg/model"
|
. "github.com/drone/drone/pkg/model"
|
||||||
|
@ -83,9 +84,16 @@ func (w *worker) execute(task *BuildTask) error {
|
||||||
Host: settings.URL().String(),
|
Host: settings.URL().String(),
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// parse the build script
|
||||||
|
buildscript, err := script.ParseBuild([]byte(task.Build.BuildScript), task.Repo.Params)
|
||||||
|
if err != nil {
|
||||||
|
log.Printf("Could not parse your .drone.yml file. It needs to be a valid drone yaml file.\n\n" + err.Error() + "\n")
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
// send all "started" notifications
|
// send all "started" notifications
|
||||||
if task.Script.Notifications != nil {
|
if buildscript.Notifications != nil {
|
||||||
task.Script.Notifications.Send(context)
|
buildscript.Notifications.Send(context)
|
||||||
}
|
}
|
||||||
|
|
||||||
// Send "started" notification to Github
|
// Send "started" notification to Github
|
||||||
|
@ -113,7 +121,7 @@ func (w *worker) execute(task *BuildTask) error {
|
||||||
// this is not a pull request (for security purposes)
|
// this is not a pull request (for security purposes)
|
||||||
if task.Repo.Params != nil && len(task.Commit.PullRequest) == 0 {
|
if task.Repo.Params != nil && len(task.Commit.PullRequest) == 0 {
|
||||||
for k, v := range task.Repo.Params {
|
for k, v := range task.Repo.Params {
|
||||||
task.Script.Env = append(task.Script.Env, k+"="+v)
|
buildscript.Env = append(buildscript.Env, k+"="+v)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -126,7 +134,7 @@ func (w *worker) execute(task *BuildTask) error {
|
||||||
}()
|
}()
|
||||||
|
|
||||||
// execute the build
|
// execute the build
|
||||||
passed, buildErr := w.runBuild(task, buf)
|
passed, buildErr := w.runBuild(task, buildscript, buf)
|
||||||
|
|
||||||
task.Build.Finished = time.Now().UTC()
|
task.Build.Finished = time.Now().UTC()
|
||||||
task.Commit.Finished = time.Now().UTC()
|
task.Commit.Finished = time.Now().UTC()
|
||||||
|
@ -162,14 +170,14 @@ func (w *worker) execute(task *BuildTask) error {
|
||||||
channel.Close(consoleslug)
|
channel.Close(consoleslug)
|
||||||
|
|
||||||
// send all "finished" notifications
|
// send all "finished" notifications
|
||||||
if task.Script.Notifications != nil {
|
if buildscript.Notifications != nil {
|
||||||
task.Script.Notifications.Send(context)
|
buildscript.Notifications.Send(context)
|
||||||
}
|
}
|
||||||
|
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (w *worker) runBuild(task *BuildTask, buf io.Writer) (bool, error) {
|
func (w *worker) runBuild(task *BuildTask, buildscript *script.Build, buf io.Writer) (bool, error) {
|
||||||
repo := &r.Repo{
|
repo := &r.Repo{
|
||||||
Name: task.Repo.Slug,
|
Name: task.Repo.Slug,
|
||||||
Path: task.Repo.URL,
|
Path: task.Repo.URL,
|
||||||
|
@ -177,11 +185,11 @@ func (w *worker) runBuild(task *BuildTask, buf io.Writer) (bool, error) {
|
||||||
Commit: task.Commit.Hash,
|
Commit: task.Commit.Hash,
|
||||||
PR: task.Commit.PullRequest,
|
PR: task.Commit.PullRequest,
|
||||||
Dir: filepath.Join("/var/cache/drone/src", task.Repo.Slug),
|
Dir: filepath.Join("/var/cache/drone/src", task.Repo.Slug),
|
||||||
Depth: git.GitDepth(task.Script.Git),
|
Depth: git.GitDepth(buildscript.Git),
|
||||||
}
|
}
|
||||||
|
|
||||||
return w.runner.Run(
|
return w.runner.Run(
|
||||||
task.Script,
|
buildscript,
|
||||||
repo,
|
repo,
|
||||||
[]byte(task.Repo.PrivateKey),
|
[]byte(task.Repo.PrivateKey),
|
||||||
task.Repo.Privileged,
|
task.Repo.Privileged,
|
||||||
|
|
|
@ -24,6 +24,18 @@
|
||||||
{{ else }}
|
{{ else }}
|
||||||
<span>commit <span>{{ .Commit.HashShort }}</span> to <span>{{.Commit.Branch}}</span> branch</span>
|
<span>commit <span>{{ .Commit.HashShort }}</span> to <span>{{.Commit.Branch}}</span> branch</span>
|
||||||
{{ end }}
|
{{ end }}
|
||||||
|
|
||||||
|
<div class="actions">
|
||||||
|
{{ if .IsAdmin }}
|
||||||
|
{{ if not .Build.IsRunning }}
|
||||||
|
<form action="/{{.Repo.Slug}}/commit/{{.Commit.Hash}}/rebuild?branch={{ .Commit.Branch }}"
|
||||||
|
method="POST">
|
||||||
|
<input class="btn btn-default" type="submit" value="Rebuild"/>
|
||||||
|
</form>
|
||||||
|
{{ end }}
|
||||||
|
{{ end }}
|
||||||
|
</div>
|
||||||
|
|
||||||
</div>
|
</div>
|
||||||
<div class="build-details container affix-top" data-spy="affix" data-offset-top="248">
|
<div class="build-details container affix-top" data-spy="affix" data-offset-top="248">
|
||||||
<div class="build-summary">
|
<div class="build-summary">
|
||||||
|
|
Loading…
Reference in a new issue