mirror of
https://github.com/caprover/caprover
synced 2026-09-25 16:15:34 +00:00
github hooks phase 1
This commit is contained in:
@@ -173,6 +173,8 @@ app.use(function (err, req, res, next) {
|
||||
res.locals.message = err.message;
|
||||
res.locals.error = req.app.get('env') === 'development' ? err : {};
|
||||
|
||||
Logger.e(err);
|
||||
|
||||
// render the error page
|
||||
res.status(err.status || 500);
|
||||
res.render('error');
|
||||
|
||||
Vendored
+124
-119
@@ -464,6 +464,7 @@ angular
|
||||
var volumes = appDefinition.volumes;
|
||||
var ports = appDefinition.ports;
|
||||
var nodeId = appDefinition.nodeId;
|
||||
var appPushWebhook = appDefinition.appPushWebhook;
|
||||
|
||||
$http
|
||||
.post(BASE_API + 'user/appDefinitions/update', {
|
||||
@@ -472,6 +473,7 @@ angular
|
||||
notExposeAsWebApp: notExposeAsWebApp,
|
||||
volumes: volumes,
|
||||
ports: ports,
|
||||
appPushWebhook: appPushWebhook,
|
||||
nodeId: nodeId,
|
||||
envVars: envVars
|
||||
}, createConfig())
|
||||
@@ -650,6 +652,124 @@ angular.module('RDash')
|
||||
}
|
||||
|
||||
});
|
||||
/**
|
||||
* File Upload Read Directive
|
||||
*/
|
||||
|
||||
angular
|
||||
.module('RDash')
|
||||
.directive("fileread", [function () {
|
||||
return {
|
||||
scope: {
|
||||
fileread: "="
|
||||
},
|
||||
link: function (scope, element, attributes) {
|
||||
element.bind("change", function (changeEvent) {
|
||||
scope.$apply(function () {
|
||||
scope.fileread = changeEvent.target.files[0];
|
||||
// or all selected files:
|
||||
// scope.fileread = changeEvent.target.files;
|
||||
});
|
||||
});
|
||||
}
|
||||
}
|
||||
}]);
|
||||
/**
|
||||
* Loading Directive
|
||||
* @see http://tobiasahlin.com/spinkit/
|
||||
*/
|
||||
|
||||
angular
|
||||
.module('RDash')
|
||||
.directive('rdLoading', rdLoading);
|
||||
|
||||
function rdLoading() {
|
||||
var directive = {
|
||||
restrict: 'AE',
|
||||
template: '<div class="loading"><div class="double-bounce1"></div><div class="double-bounce2"></div></div>'
|
||||
};
|
||||
return directive;
|
||||
};
|
||||
/**
|
||||
* Widget Body Directive
|
||||
*/
|
||||
|
||||
angular
|
||||
.module('RDash')
|
||||
.directive('rdWidgetBody', rdWidgetBody);
|
||||
|
||||
function rdWidgetBody() {
|
||||
var directive = {
|
||||
requires: '^rdWidget',
|
||||
scope: {
|
||||
loading: '=?',
|
||||
classes: '@?'
|
||||
},
|
||||
transclude: true,
|
||||
template: '<div class="widget-body" ng-class="classes"><rd-loading ng-show="loading"></rd-loading><div ng-hide="loading" class="widget-content" ng-transclude></div></div>',
|
||||
restrict: 'E'
|
||||
};
|
||||
return directive;
|
||||
};
|
||||
|
||||
/**
|
||||
* Widget Footer Directive
|
||||
*/
|
||||
|
||||
angular
|
||||
.module('RDash')
|
||||
.directive('rdWidgetFooter', rdWidgetFooter);
|
||||
|
||||
function rdWidgetFooter() {
|
||||
var directive = {
|
||||
requires: '^rdWidget',
|
||||
transclude: true,
|
||||
template: '<div class="widget-footer" ng-transclude></div>',
|
||||
restrict: 'E'
|
||||
};
|
||||
return directive;
|
||||
};
|
||||
/**
|
||||
* Widget Header Directive
|
||||
*/
|
||||
|
||||
angular
|
||||
.module('RDash')
|
||||
.directive('rdWidgetHeader', rdWidgetTitle);
|
||||
|
||||
function rdWidgetTitle() {
|
||||
var directive = {
|
||||
requires: '^rdWidget',
|
||||
scope: {
|
||||
title: '@',
|
||||
icon: '@'
|
||||
},
|
||||
transclude: true,
|
||||
template: '<div class="widget-header"><div class="row"><div class="pull-left"><i class="fa" ng-class="icon"></i> {{title}} </div><div class="pull-right col-xs-6 col-sm-4" ng-transclude></div></div></div>',
|
||||
restrict: 'E'
|
||||
};
|
||||
return directive;
|
||||
};
|
||||
/**
|
||||
* Widget Directive
|
||||
*/
|
||||
|
||||
angular
|
||||
.module('RDash')
|
||||
.directive('rdWidget', rdWidget);
|
||||
|
||||
function rdWidget() {
|
||||
var directive = {
|
||||
transclude: true,
|
||||
template: '<div class="widget" ng-transclude></div>',
|
||||
restrict: 'EA'
|
||||
};
|
||||
return directive;
|
||||
|
||||
function link(scope, element, attrs) {
|
||||
/* */
|
||||
}
|
||||
};
|
||||
/**
|
||||
* Alerts Controller
|
||||
*/
|
||||
@@ -685,6 +805,7 @@ angular.module('RDash')
|
||||
function AppDefinitionCtrl($scope, $cookieStore, $rootScope, pageDefinitions,
|
||||
apiManager, captainToast, $uibModal, $state, $location) {
|
||||
|
||||
$scope.rootDomainWithProtocol = window.location.protocol;
|
||||
$scope.loadingState = {};
|
||||
$scope.loadingState.enabled = true;
|
||||
$scope.search = {};
|
||||
@@ -715,6 +836,7 @@ function AppDefinitionCtrl($scope, $cookieStore, $rootScope, pageDefinitions,
|
||||
}
|
||||
|
||||
$scope.rootDomain = data.rootDomain;
|
||||
$scope.rootDomainWithProtocol = window.location.protocol + '//' + data.rootDomain;
|
||||
|
||||
});
|
||||
|
||||
@@ -936,6 +1058,7 @@ function AppDefinitionCtrl($scope, $cookieStore, $rootScope, pageDefinitions,
|
||||
ports: app.ports,
|
||||
nodeId: app.nodeId,
|
||||
notExposeAsWebApp: app.notExposeAsWebApp,
|
||||
appPushWebhook: app.appPushWebhook,
|
||||
volumes: app.volumes
|
||||
}
|
||||
|
||||
@@ -1526,122 +1649,4 @@ function SettingsCtrl($scope, $cookieStore, $rootScope, pageDefinitions,
|
||||
|
||||
}());
|
||||
|
||||
}
|
||||
/**
|
||||
* File Upload Read Directive
|
||||
*/
|
||||
|
||||
angular
|
||||
.module('RDash')
|
||||
.directive("fileread", [function () {
|
||||
return {
|
||||
scope: {
|
||||
fileread: "="
|
||||
},
|
||||
link: function (scope, element, attributes) {
|
||||
element.bind("change", function (changeEvent) {
|
||||
scope.$apply(function () {
|
||||
scope.fileread = changeEvent.target.files[0];
|
||||
// or all selected files:
|
||||
// scope.fileread = changeEvent.target.files;
|
||||
});
|
||||
});
|
||||
}
|
||||
}
|
||||
}]);
|
||||
/**
|
||||
* Loading Directive
|
||||
* @see http://tobiasahlin.com/spinkit/
|
||||
*/
|
||||
|
||||
angular
|
||||
.module('RDash')
|
||||
.directive('rdLoading', rdLoading);
|
||||
|
||||
function rdLoading() {
|
||||
var directive = {
|
||||
restrict: 'AE',
|
||||
template: '<div class="loading"><div class="double-bounce1"></div><div class="double-bounce2"></div></div>'
|
||||
};
|
||||
return directive;
|
||||
};
|
||||
/**
|
||||
* Widget Body Directive
|
||||
*/
|
||||
|
||||
angular
|
||||
.module('RDash')
|
||||
.directive('rdWidgetBody', rdWidgetBody);
|
||||
|
||||
function rdWidgetBody() {
|
||||
var directive = {
|
||||
requires: '^rdWidget',
|
||||
scope: {
|
||||
loading: '=?',
|
||||
classes: '@?'
|
||||
},
|
||||
transclude: true,
|
||||
template: '<div class="widget-body" ng-class="classes"><rd-loading ng-show="loading"></rd-loading><div ng-hide="loading" class="widget-content" ng-transclude></div></div>',
|
||||
restrict: 'E'
|
||||
};
|
||||
return directive;
|
||||
};
|
||||
|
||||
/**
|
||||
* Widget Footer Directive
|
||||
*/
|
||||
|
||||
angular
|
||||
.module('RDash')
|
||||
.directive('rdWidgetFooter', rdWidgetFooter);
|
||||
|
||||
function rdWidgetFooter() {
|
||||
var directive = {
|
||||
requires: '^rdWidget',
|
||||
transclude: true,
|
||||
template: '<div class="widget-footer" ng-transclude></div>',
|
||||
restrict: 'E'
|
||||
};
|
||||
return directive;
|
||||
};
|
||||
/**
|
||||
* Widget Header Directive
|
||||
*/
|
||||
|
||||
angular
|
||||
.module('RDash')
|
||||
.directive('rdWidgetHeader', rdWidgetTitle);
|
||||
|
||||
function rdWidgetTitle() {
|
||||
var directive = {
|
||||
requires: '^rdWidget',
|
||||
scope: {
|
||||
title: '@',
|
||||
icon: '@'
|
||||
},
|
||||
transclude: true,
|
||||
template: '<div class="widget-header"><div class="row"><div class="pull-left"><i class="fa" ng-class="icon"></i> {{title}} </div><div class="pull-right col-xs-6 col-sm-4" ng-transclude></div></div></div>',
|
||||
restrict: 'E'
|
||||
};
|
||||
return directive;
|
||||
};
|
||||
/**
|
||||
* Widget Directive
|
||||
*/
|
||||
|
||||
angular
|
||||
.module('RDash')
|
||||
.directive('rdWidget', rdWidget);
|
||||
|
||||
function rdWidget() {
|
||||
var directive = {
|
||||
transclude: true,
|
||||
template: '<div class="widget" ng-transclude></div>',
|
||||
restrict: 'EA'
|
||||
};
|
||||
return directive;
|
||||
|
||||
function link(scope, element, attrs) {
|
||||
/* */
|
||||
}
|
||||
};
|
||||
}
|
||||
Vendored
+42
@@ -235,6 +235,48 @@
|
||||
<div class="col-lg-3">
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="row">
|
||||
<h4>
|
||||
Deploy from Github/Bitbucket
|
||||
</h4>
|
||||
<p>
|
||||
POST Webhook:
|
||||
<br>
|
||||
<pre>{{app.appPushWebhook.pushWebhookToken?(rootDomainWithProtocol+'/api/v1/webhooks/triggerbuild?token='+app.appPushWebhook.pushWebhookToken):
|
||||
'** Add repo info and save for this webhook to appear **'}}</pre>
|
||||
</p>
|
||||
</div>
|
||||
<br>
|
||||
<div class="row">
|
||||
<div class="form-group col-sm-6">
|
||||
<div class="input-group">
|
||||
<span class="input-group-addon">Username:</span>
|
||||
<input type="text" class="form-control" ng-model="app.appPushWebhook.repoInfo.user" placeholder="githubusername">
|
||||
</div>
|
||||
</div>
|
||||
<div class="col-sm-6 form-group">
|
||||
<div class="input-group">
|
||||
<span class="input-group-addon">Password:</span>
|
||||
<input type="text" class="form-control" ng-model="app.appPushWebhook.repoInfo.password" placeholder="githubpassword">
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="row">
|
||||
<div class="form-group col-sm-6">
|
||||
<div class="input-group">
|
||||
<span class="input-group-addon">Repository:</span>
|
||||
<input type="text" class="form-control" ng-model="app.appPushWebhook.repoInfo.repo" placeholder="githubusername">
|
||||
</div>
|
||||
</div>
|
||||
<div class="col-sm-6 form-group">
|
||||
<div class="input-group">
|
||||
<span class="input-group-addon">Branch:</span>
|
||||
<input type="text" class="form-control" ng-model="app.appPushWebhook.repoInfo.branch" placeholder="master">
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="row" ng-show="app.isAppBuilding">
|
||||
<div class="pull-left">
|
||||
<div class="inline-loader"></div>
|
||||
|
||||
@@ -2,6 +2,7 @@
|
||||
* Created by kasra on 27/06/17.
|
||||
*/
|
||||
const Configstore = require('configstore');
|
||||
const uuid = require('uuid/v4');
|
||||
const isValidPath = require('is-valid-path');
|
||||
const fs = require('fs-extra');
|
||||
const ApiStatusCodes = require('../api/ApiStatusCodes');
|
||||
@@ -392,11 +393,39 @@ class DataStore {
|
||||
});
|
||||
}
|
||||
|
||||
updateAppDefinitionInDb(appName, instanceCount, envVars, volumes, nodeId, notExposeAsWebApp, ports) {
|
||||
updateAppDefinitionInDb(appName, instanceCount, envVars, volumes, nodeId, notExposeAsWebApp, ports, appPushWebhook, authenticator) {
|
||||
const self = this;
|
||||
|
||||
return this.getAppDefinition(appName)
|
||||
.then(function (app) {
|
||||
let app;
|
||||
|
||||
return Promise.resolve()
|
||||
.then(function () {
|
||||
|
||||
return self.getAppDefinition(appName);
|
||||
|
||||
})
|
||||
.then(function (appObj) {
|
||||
|
||||
app = appObj;
|
||||
|
||||
})
|
||||
.then(function () {
|
||||
|
||||
if (appPushWebhook.repoInfo && appPushWebhook.repoInfo.repo && appPushWebhook.repoInfo.branch
|
||||
&& appPushWebhook.repoInfo.user && appPushWebhook.repoInfo.password) {
|
||||
return authenticator
|
||||
.getAppPushWebhookDatastore({
|
||||
repo: appPushWebhook.repoInfo.repo,
|
||||
branch: appPushWebhook.repoInfo.branch,
|
||||
user: appPushWebhook.repoInfo.user,
|
||||
password: appPushWebhook.repoInfo.password
|
||||
})
|
||||
}
|
||||
|
||||
return null;
|
||||
|
||||
})
|
||||
.then(function (appPushWebhookRepoInfo) {
|
||||
|
||||
instanceCount = Number(instanceCount);
|
||||
|
||||
@@ -404,6 +433,22 @@ class DataStore {
|
||||
app.notExposeAsWebApp = !!notExposeAsWebApp;
|
||||
app.nodeId = nodeId;
|
||||
|
||||
if (appPushWebhookRepoInfo) {
|
||||
|
||||
app.appPushWebhook = app.appPushWebhook || {};
|
||||
|
||||
if (!app.appPushWebhook.tokenVersion) {
|
||||
app.appPushWebhook.tokenVersion = uuid();
|
||||
}
|
||||
|
||||
app.appPushWebhook.repoInfo = appPushWebhookRepoInfo;
|
||||
}
|
||||
else {
|
||||
|
||||
app.appPushWebhook = {};
|
||||
|
||||
}
|
||||
|
||||
if (ports) {
|
||||
|
||||
function isPortValid(portNumber) {
|
||||
@@ -471,6 +516,21 @@ class DataStore {
|
||||
}
|
||||
}
|
||||
|
||||
})
|
||||
.then(function () {
|
||||
|
||||
if (app.appPushWebhook.repoInfo) {
|
||||
return authenticator
|
||||
.getAppPushWebhookToken(appName, app.appPushWebhook.tokenVersion)
|
||||
}
|
||||
|
||||
})
|
||||
.then(function (pushWebhookToken) {
|
||||
|
||||
if (pushWebhookToken) {
|
||||
app.appPushWebhook.pushWebhookToken = pushWebhookToken;
|
||||
}
|
||||
|
||||
self.data.set(APP_DEFINITIONS + '.' + appName, app);
|
||||
|
||||
});
|
||||
@@ -687,6 +747,7 @@ class DataStore {
|
||||
envVars: [],
|
||||
volumes: [],
|
||||
ports: [],
|
||||
appPushWebhook: {}, // tokenVersion, repoInfo, pushWebhookToken
|
||||
versions: []
|
||||
};
|
||||
|
||||
|
||||
@@ -4,6 +4,7 @@ const router = express.Router();
|
||||
const BaseApi = require('../api/BaseApi');
|
||||
const ApiStatusCodes = require('../api/ApiStatusCodes');
|
||||
const Logger = require('../utils/Logger');
|
||||
const Authenticator = require('../user/Authenticator');
|
||||
|
||||
// Get a list of oneclickspps
|
||||
router.get('/oneclickapps', function (req, res, next) {
|
||||
@@ -36,19 +37,39 @@ router.get('/', function (req, res, next) {
|
||||
|
||||
let dataStore = res.locals.user.dataStore;
|
||||
let serviceManager = res.locals.user.serviceManager;
|
||||
let appsArray = [];
|
||||
|
||||
dataStore.getAppDefinitions()
|
||||
.then(function (apps) {
|
||||
|
||||
let appsArray = [];
|
||||
let promises = [];
|
||||
|
||||
Object.keys(apps).forEach(function (key, index) {
|
||||
let app = apps[key];
|
||||
app.appName = key;
|
||||
app.isAppBuilding = serviceManager.isAppBuilding(key);
|
||||
app.appPushWebhook = app.appPushWebhook || {};
|
||||
|
||||
let repoInfoEncrypted = app.appPushWebhook ? app.appPushWebhook.repoInfo : null;
|
||||
if (repoInfoEncrypted) {
|
||||
promises.push(
|
||||
Authenticator.get(dataStore.getNameSpace())
|
||||
.decodeAppPushWebhookDatastore(repoInfoEncrypted)
|
||||
.then(function (decryptedData) {
|
||||
app.appPushWebhook.repoInfo = decryptedData;
|
||||
}));
|
||||
}
|
||||
else {
|
||||
app.appPushWebhook.repoInfo = {};
|
||||
}
|
||||
appsArray.push(app);
|
||||
});
|
||||
|
||||
return Promise.all(promises);
|
||||
|
||||
})
|
||||
.then(function () {
|
||||
|
||||
let baseApi = new BaseApi(ApiStatusCodes.STATUS_OK, "App definitions are retrieved.");
|
||||
baseApi.data = appsArray;
|
||||
baseApi.rootDomain = dataStore.getRootDomain();
|
||||
@@ -299,6 +320,7 @@ router.post('/update/', function (req, res, next) {
|
||||
let appName = req.body.appName;
|
||||
let nodeId = req.body.nodeId;
|
||||
let notExposeAsWebApp = req.body.notExposeAsWebApp;
|
||||
let appPushWebhook = req.body.appPushWebhook || {};
|
||||
let envVars = req.body.envVars || [];
|
||||
let volumes = req.body.volumes || [];
|
||||
let ports = req.body.ports || [];
|
||||
@@ -306,7 +328,7 @@ router.post('/update/', function (req, res, next) {
|
||||
|
||||
Logger.d('Updating app started: ' + appName);
|
||||
|
||||
serviceManager.updateAppDefinition(appName, Number(instanceCount), envVars, volumes, nodeId, notExposeAsWebApp, ports)
|
||||
serviceManager.updateAppDefinition(appName, Number(instanceCount), envVars, volumes, nodeId, notExposeAsWebApp, ports, appPushWebhook)
|
||||
.then(function () {
|
||||
|
||||
Logger.d('AppName is updated: ' + appName);
|
||||
|
||||
@@ -10,8 +10,9 @@ const DataStoreProvider = require('../datastore/DataStoreProvider');
|
||||
|
||||
const captainDefaultPassword = EnvVar.DEFAULT_PASSWORD || 'captain42';
|
||||
|
||||
const COOKIE_AUTH_PREFIX = 'cookie-';
|
||||
|
||||
const COOKIE_AUTH_SUFFIX = 'cookie-';
|
||||
const WEBHOOK_APP_PUSH_SUFFIX = '-webhook-app-push';
|
||||
const WEBHOOK_APP_PUSH_DATASTORE_SUFFIX = "-webhook-app-datastore";
|
||||
|
||||
class Authenticator {
|
||||
|
||||
@@ -72,7 +73,7 @@ class Authenticator {
|
||||
}
|
||||
|
||||
getAuthTokenForCookies(password) {
|
||||
return this.getAuthToken(password, COOKIE_AUTH_PREFIX);
|
||||
return this.getAuthToken(password, COOKIE_AUTH_SUFFIX);
|
||||
}
|
||||
|
||||
getAuthToken(password, keySuffix) {
|
||||
@@ -101,7 +102,7 @@ class Authenticator {
|
||||
}
|
||||
|
||||
decodeAuthTokenFromCookies(token) {
|
||||
return this.decodeAuthToken(token, COOKIE_AUTH_PREFIX);
|
||||
return this.decodeAuthToken(token, COOKIE_AUTH_SUFFIX);
|
||||
}
|
||||
|
||||
decodeAuthToken(token, keySuffix) {
|
||||
@@ -135,6 +136,77 @@ class Authenticator {
|
||||
|
||||
});
|
||||
}
|
||||
|
||||
getAppPushWebhookDatastore(dataToSave) {
|
||||
const self = this;
|
||||
|
||||
return self.getGenericToken(dataToSave, WEBHOOK_APP_PUSH_DATASTORE_SUFFIX)
|
||||
}
|
||||
|
||||
decodeAppPushWebhookDatastore(token) {
|
||||
const self = this;
|
||||
|
||||
return self.decodeGenericToken(token, WEBHOOK_APP_PUSH_DATASTORE_SUFFIX)
|
||||
}
|
||||
|
||||
getAppPushWebhookToken(appName, tokenVersion) {
|
||||
const self = this;
|
||||
|
||||
if (!appName) {
|
||||
throw ApiStatusCodes.createError(ApiStatusCodes.STATUS_ERROR_GENERIC, 'App name are required for webhook token..');
|
||||
}
|
||||
|
||||
return self.getGenericToken({
|
||||
tokenVersion: tokenVersion,
|
||||
appName: appName
|
||||
}, WEBHOOK_APP_PUSH_SUFFIX)
|
||||
}
|
||||
|
||||
decodeAppPushWebhookToken(token) {
|
||||
const self = this;
|
||||
|
||||
return self.decodeGenericToken(token, WEBHOOK_APP_PUSH_SUFFIX)
|
||||
}
|
||||
|
||||
getGenericToken(obj, keySuffix) {
|
||||
|
||||
const self = this;
|
||||
obj.namespace = self.namespace;
|
||||
|
||||
return Promise.resolve()
|
||||
.then(function () {
|
||||
return jwt.sign({
|
||||
data: obj
|
||||
}, self.encryptionKey + (keySuffix ? keySuffix : ''));
|
||||
})
|
||||
}
|
||||
|
||||
decodeGenericToken(token, keySuffix) {
|
||||
const self = this;
|
||||
|
||||
return new Promise(function (resolve, reject) {
|
||||
|
||||
jwt.verify(token, self.encryptionKey + (keySuffix ? keySuffix : ''), function (err, rawDecoded) {
|
||||
if (err) {
|
||||
Logger.d(err);
|
||||
reject(ApiStatusCodes.createError(ApiStatusCodes.STATUS_AUTH_TOKEN_INVALID, 'Token corrupted'));
|
||||
return;
|
||||
}
|
||||
|
||||
let decodedData = rawDecoded.data;
|
||||
|
||||
if (decodedData.namespace !== self.namespace) {
|
||||
reject(ApiStatusCodes.createError(ApiStatusCodes.STATUS_AUTH_TOKEN_INVALID,
|
||||
'token does not match the namespace'));
|
||||
return;
|
||||
}
|
||||
|
||||
resolve(decodedData);
|
||||
});
|
||||
|
||||
});
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
const authenticatorCache = {};
|
||||
|
||||
@@ -6,6 +6,7 @@ const path = require('path');
|
||||
const CaptainManager = require('./CaptainManager');
|
||||
const ApiStatusCodes = require('../api/ApiStatusCodes');
|
||||
const TemplateHelper = require('./TemplateHelper');
|
||||
const Authenticator = require('./Authenticator');
|
||||
const uuid = require('uuid/v4');
|
||||
|
||||
const SOURCE_FOLDER_NAME = 'src';
|
||||
@@ -630,7 +631,7 @@ class ServiceManager {
|
||||
});
|
||||
}
|
||||
|
||||
updateAppDefinition(appName, instanceCount, envVars, volumes, nodeId, notExposeAsWebApp, ports) {
|
||||
updateAppDefinition(appName, instanceCount, envVars, volumes, nodeId, notExposeAsWebApp, ports, appPushWebhook) {
|
||||
|
||||
const self = this;
|
||||
const dataStore = this.dataStore;
|
||||
@@ -721,7 +722,8 @@ class ServiceManager {
|
||||
})
|
||||
.then(function () {
|
||||
|
||||
return dataStore.updateAppDefinitionInDb(appName, instanceCount, envVars, volumes, nodeId, notExposeAsWebApp, ports);
|
||||
return dataStore.updateAppDefinitionInDb(appName, instanceCount, envVars, volumes, nodeId,
|
||||
notExposeAsWebApp, ports, appPushWebhook, Authenticator.get(dataStore.getNameSpace()));
|
||||
|
||||
})
|
||||
.then(function () {
|
||||
|
||||
@@ -382,6 +382,7 @@
|
||||
var volumes = appDefinition.volumes;
|
||||
var ports = appDefinition.ports;
|
||||
var nodeId = appDefinition.nodeId;
|
||||
var appPushWebhook = appDefinition.appPushWebhook;
|
||||
|
||||
$http
|
||||
.post(BASE_API + 'user/appDefinitions/update', {
|
||||
@@ -390,6 +391,7 @@
|
||||
notExposeAsWebApp: notExposeAsWebApp,
|
||||
volumes: volumes,
|
||||
ports: ports,
|
||||
appPushWebhook: appPushWebhook,
|
||||
nodeId: nodeId,
|
||||
envVars: envVars
|
||||
}, createConfig())
|
||||
|
||||
@@ -6,6 +6,7 @@ angular.module('RDash')
|
||||
function AppDefinitionCtrl($scope, $cookieStore, $rootScope, pageDefinitions,
|
||||
apiManager, captainToast, $uibModal, $state, $location) {
|
||||
|
||||
$scope.rootDomainWithProtocol = window.location.protocol;
|
||||
$scope.loadingState = {};
|
||||
$scope.loadingState.enabled = true;
|
||||
$scope.search = {};
|
||||
@@ -36,6 +37,7 @@ function AppDefinitionCtrl($scope, $cookieStore, $rootScope, pageDefinitions,
|
||||
}
|
||||
|
||||
$scope.rootDomain = data.rootDomain;
|
||||
$scope.rootDomainWithProtocol = window.location.protocol + '//' + data.rootDomain;
|
||||
|
||||
});
|
||||
|
||||
@@ -257,6 +259,7 @@ function AppDefinitionCtrl($scope, $cookieStore, $rootScope, pageDefinitions,
|
||||
ports: app.ports,
|
||||
nodeId: app.nodeId,
|
||||
notExposeAsWebApp: app.notExposeAsWebApp,
|
||||
appPushWebhook: app.appPushWebhook,
|
||||
volumes: app.volumes
|
||||
}
|
||||
|
||||
|
||||
@@ -236,6 +236,48 @@
|
||||
<div class="col-lg-3">
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="row">
|
||||
<h4>
|
||||
Deploy from Github/Bitbucket
|
||||
</h4>
|
||||
<p>
|
||||
POST Webhook:
|
||||
<br>
|
||||
<pre>{{app.appPushWebhook.pushWebhookToken?(rootDomainWithProtocol+'/api/v1/webhooks/triggerbuild?token='+app.appPushWebhook.pushWebhookToken):
|
||||
'** Add repo info and save for this webhook to appear **'}}</pre>
|
||||
</p>
|
||||
</div>
|
||||
<br/>
|
||||
<div class="row">
|
||||
<div class="form-group col-sm-6">
|
||||
<div class="input-group">
|
||||
<span class="input-group-addon">Username:</span>
|
||||
<input type="text" class="form-control" ng-model="app.appPushWebhook.repoInfo.user" placeholder="githubusername">
|
||||
</div>
|
||||
</div>
|
||||
<div class="col-sm-6 form-group">
|
||||
<div class="input-group">
|
||||
<span class="input-group-addon">Password:</span>
|
||||
<input type="text" class="form-control" ng-model="app.appPushWebhook.repoInfo.password" placeholder="githubpassword">
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="row">
|
||||
<div class="form-group col-sm-6">
|
||||
<div class="input-group">
|
||||
<span class="input-group-addon">Repository:</span>
|
||||
<input type="text" class="form-control" ng-model="app.appPushWebhook.repoInfo.repo" placeholder="githubusername">
|
||||
</div>
|
||||
</div>
|
||||
<div class="col-sm-6 form-group">
|
||||
<div class="input-group">
|
||||
<span class="input-group-addon">Branch:</span>
|
||||
<input type="text" class="form-control" ng-model="app.appPushWebhook.repoInfo.branch" placeholder="master">
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="row" ng-show="app.isAppBuilding">
|
||||
<div class="pull-left">
|
||||
<div class="inline-loader"></div>
|
||||
|
||||
Reference in New Issue
Block a user