Client Github Server Implementation
This commit is contained in:
1 parent
6d67490942
commit
37d70849ec
13 files changed
+843
-535
No files matched your search
@@ -0,0 +1,73 @@
|
||||
exports.newMultiProject = function () {
|
||||
|
||||
let thisObject = {
|
||||
initialize: initialize
|
||||
}
|
||||
|
||||
return thisObject;
|
||||
|
||||
function initialize() {
|
||||
/*
|
||||
First thing is to load the project schema file.
|
||||
*/
|
||||
let PROJECTS_SCHEMA = require(global.env.PATH_TO_PROJECTS_REQUIRED + '/' + 'ProjectsSchema.json')
|
||||
|
||||
/*
|
||||
Here we will setup the CL object, with all the
|
||||
projects and modules that will have inside.
|
||||
*/
|
||||
global.CL = {
|
||||
projects: {}
|
||||
}
|
||||
for (let i = 0; i < PROJECTS_SCHEMA.length; i++) {
|
||||
let projectDefinition = PROJECTS_SCHEMA[i]
|
||||
global.CL.projects[projectDefinition.propertyName] = {}
|
||||
let projectInstance = global.CL.projects[projectDefinition.propertyName]
|
||||
|
||||
projectInstance.utilities = {}
|
||||
projectInstance.globals = {}
|
||||
projectInstance.functionLibraries = {}
|
||||
projectInstance.taskModules = {}
|
||||
projectInstance.processModules = {}
|
||||
projectInstance.botModules = {}
|
||||
|
||||
if (projectDefinition.CL === undefined) { continue }
|
||||
|
||||
/* Set up Utilities of this Project */
|
||||
if (projectDefinition.CL.utilities !== undefined) {
|
||||
for (let j = 0; j < projectDefinition.CL.utilities.length; j++) {
|
||||
let utilityDefinition = projectDefinition.CL.utilities[j]
|
||||
let path = global.env.PATH_TO_PROJECTS_REQUIRED + '/' + projectDefinition.name + '/' + 'CL' + '/' + 'Utilities' + '/' + utilityDefinition.fileName
|
||||
|
||||
let requiredObject = require(path)
|
||||
let requiredFunction = requiredObject[utilityDefinition.functionName]
|
||||
projectInstance.utilities[utilityDefinition.propertyName] = requiredFunction.call()
|
||||
}
|
||||
}
|
||||
|
||||
/* Set up Globals of this Project */
|
||||
if (projectDefinition.CL.globals !== undefined) {
|
||||
for (let j = 0; j < projectDefinition.CL.globals.length; j++) {
|
||||
let globalDefinition = projectDefinition.CL.globals[j]
|
||||
let path = global.env.PATH_TO_PROJECTS_REQUIRED + '/' + projectDefinition.name + '/' + 'CL' + '/' + 'Globals' + '/' + globalDefinition.fileName
|
||||
|
||||
let requiredObject = require(path)
|
||||
let requiredFunction = requiredObject[globalDefinition.functionName]
|
||||
projectInstance.globals[globalDefinition.propertyName] = requiredFunction.call()
|
||||
}
|
||||
}
|
||||
|
||||
/* Set up Function Libraries of this Project */
|
||||
if (projectDefinition.CL.functionLibraries !== undefined) {
|
||||
for (let j = 0; j < projectDefinition.CL.functionLibraries.length; j++) {
|
||||
let functionLibraryDefinition = projectDefinition.CL.functionLibraries[j]
|
||||
let path = global.env.PATH_TO_PROJECTS_REQUIRED + '/' + projectDefinition.name + '/' + 'CL' + '/' + 'Function-Libraries' + '/' + functionLibraryDefinition.fileName
|
||||
|
||||
let requiredObject = require(path)
|
||||
let requiredFunction = requiredObject[functionLibraryDefinition.functionName]
|
||||
projectInstance.functionLibraries[functionLibraryDefinition.propertyName] = requiredFunction.call()
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
+23
-3
@@ -64,12 +64,18 @@ let EVENT_SERVER = require('./eventServer.js')
|
||||
let TASK_MANAGER_SERVER = require('./taskManagerServer.js')
|
||||
let CCXT_SERVER = require('./ccxtServer.js')
|
||||
let WEB3_SERVER = require('./web3Server.js')
|
||||
let GITHUB_SERVER = require('./githubServer.js')
|
||||
|
||||
/* Network Interfaces */
|
||||
let WEB_SOCKETS_INTERFACE = require('./webSocketsServer.js')
|
||||
let HTTP_INTERFACE = require('./httpInterface.js')
|
||||
|
||||
try {
|
||||
/* Setting up the modules that will be available for the Servers Running inside this Client */
|
||||
let MULTI_PROJECT = require('./MultiProject.js');
|
||||
let MULTI_PROJECT_MODULE = MULTI_PROJECT.newMultiProject()
|
||||
MULTI_PROJECT_MODULE.initialize()
|
||||
|
||||
console.log('CLIENT SERVERS:')
|
||||
console.log('')
|
||||
|
||||
@@ -87,7 +93,7 @@ try {
|
||||
PROJECT_FILE_SERVER.initialize()
|
||||
PROJECT_FILE_SERVER.run()
|
||||
console.log('Project File Server ......................................... Started')
|
||||
|
||||
|
||||
PLUGIN_SERVER = PLUGIN_SERVER.newPluginServer()
|
||||
PLUGIN_SERVER.initialize()
|
||||
PLUGIN_SERVER.run()
|
||||
@@ -112,12 +118,17 @@ try {
|
||||
CCXT_SERVER.initialize()
|
||||
CCXT_SERVER.run()
|
||||
console.log('CCXT Server ................................................. Started')
|
||||
|
||||
|
||||
WEB3_SERVER = WEB3_SERVER.newWeb3Server()
|
||||
WEB3_SERVER.initialize()
|
||||
WEB3_SERVER.run()
|
||||
console.log('WEB3 Server ................................................. Started')
|
||||
|
||||
GITHUB_SERVER = GITHUB_SERVER.newGithubServer()
|
||||
GITHUB_SERVER.initialize()
|
||||
GITHUB_SERVER.run()
|
||||
console.log('Github Server ............................................... Started')
|
||||
|
||||
console.log('')
|
||||
console.log('CLIENT INTERFACES:')
|
||||
console.log('')
|
||||
@@ -127,7 +138,16 @@ try {
|
||||
WEB_SOCKETS_INTERFACE.run()
|
||||
console.log('Web Sockets Interface ....................................... Listening at port ' + global.env.WEB_SOCKETS_INTERFACE_PORT)
|
||||
|
||||
HTTP_INTERFACE = HTTP_INTERFACE.newHttpInterface(WEB_SERVER, DATA_FILE_SERVER, PROJECT_FILE_SERVER, UI_FILE_SERVER, PLUGIN_SERVER, CCXT_SERVER, WEB3_SERVER)
|
||||
HTTP_INTERFACE = HTTP_INTERFACE.newHttpInterface(
|
||||
WEB_SERVER,
|
||||
DATA_FILE_SERVER,
|
||||
PROJECT_FILE_SERVER,
|
||||
UI_FILE_SERVER,
|
||||
PLUGIN_SERVER,
|
||||
CCXT_SERVER,
|
||||
WEB3_SERVER,
|
||||
GITHUB_SERVER
|
||||
)
|
||||
HTTP_INTERFACE.initialize()
|
||||
HTTP_INTERFACE.run()
|
||||
console.log('Http Interface .............................................. Listening at port ' + global.env.HTTP_INTERFACE_PORT)
|
||||
|
||||
@@ -0,0 +1,484 @@
|
||||
exports.newGithubServer = function newGithubServer() {
|
||||
|
||||
const MODULE = "Github Server"
|
||||
|
||||
let thisObject = {
|
||||
getGithubStars: getGithubStars,
|
||||
getGithubWatchers: getGithubWatchers,
|
||||
getGithubForks: getGithubForks,
|
||||
mergePullRequests: mergePullRequests,
|
||||
initialize: initialize,
|
||||
finalize: finalize,
|
||||
run: run
|
||||
}
|
||||
|
||||
const GITHUB_API_WAITING_TIME = 250
|
||||
return thisObject
|
||||
|
||||
function finalize() {
|
||||
|
||||
}
|
||||
|
||||
function initialize() {
|
||||
|
||||
}
|
||||
|
||||
function run() {
|
||||
|
||||
}
|
||||
|
||||
async function getGithubStars(repository, username, token) {
|
||||
return await getGithubUsernames('activity', 'listStargazersForRepo', repository, username, token)
|
||||
}
|
||||
|
||||
async function getGithubWatchers(repository, username, token) {
|
||||
return await getGithubUsernames('activity', 'listWatchersForRepo', repository, username, token)
|
||||
}
|
||||
|
||||
async function getGithubForks(repository, username, token) {
|
||||
return await getGithubUsernames('repos', 'listForks', repository, username, token)
|
||||
}
|
||||
|
||||
async function mergePullRequests(commitMessage, username, token) {
|
||||
return await mergeGithubPullRequests(commitMessage, username, token)
|
||||
}
|
||||
|
||||
async function getGithubUsernames(endpoint, method, repository, username, token) {
|
||||
try {
|
||||
|
||||
repository = unescape(repository)
|
||||
username = unescape(username)
|
||||
token = unescape(token)
|
||||
let error
|
||||
let githubListArray = []
|
||||
|
||||
return await getRepoInfo()
|
||||
|
||||
async function getRepoInfo() {
|
||||
await doGithub()
|
||||
if (error !== undefined) {
|
||||
|
||||
let docs = {
|
||||
project: 'Governance',
|
||||
category: 'Topic',
|
||||
type: 'Gov Error - Get Repository Information',
|
||||
anchor: undefined,
|
||||
placeholder: {}
|
||||
}
|
||||
|
||||
return respondWithDocsObject(docs, error)
|
||||
}
|
||||
|
||||
return {
|
||||
result: global.DEFAULT_OK_RESPONSE.result,
|
||||
githubListArray: githubListArray
|
||||
}
|
||||
}
|
||||
|
||||
async function doGithub() {
|
||||
|
||||
const { Octokit } = require("@octokit/rest")
|
||||
|
||||
const octokit = new Octokit({
|
||||
auth: token,
|
||||
userAgent: 'Superalgos Beta 11'
|
||||
})
|
||||
await getList()
|
||||
|
||||
async function getList() {
|
||||
const repo = repository
|
||||
const owner = 'Superalgos'
|
||||
const per_page = 100 // Max
|
||||
let page = 0
|
||||
let lastPage = false
|
||||
|
||||
while (lastPage === false) {
|
||||
try {
|
||||
page++
|
||||
await CL.projects.foundations.utilities.asyncFunctions.sleep(GITHUB_API_WAITING_TIME)
|
||||
let listResponse = await octokit[endpoint][method]({
|
||||
owner,
|
||||
repo,
|
||||
per_page,
|
||||
page
|
||||
});
|
||||
|
||||
if (listResponse.data.length < 100) {
|
||||
lastPage = true
|
||||
}
|
||||
|
||||
for (let i = 0; i < listResponse.data.length; i++) {
|
||||
let listItem = listResponse.data[i]
|
||||
let githubUsername
|
||||
switch (endpoint) {
|
||||
case 'activity': {
|
||||
githubUsername = listItem.login
|
||||
break
|
||||
}
|
||||
case 'repos': {
|
||||
githubUsername = listItem.owner.login
|
||||
break
|
||||
}
|
||||
}
|
||||
//console.log(listItem)
|
||||
|
||||
githubListArray.push(githubUsername)
|
||||
}
|
||||
console.log('[INFO] Github Server -> getRepoInfo -> doGithub -> getList -> ' + method + ' Page = ' + page)
|
||||
console.log('[INFO] Github Server -> getRepoInfo -> doGithub -> getList -> ' + method + ' Received = ' + listResponse.data.length)
|
||||
|
||||
} catch (err) {
|
||||
console.log(err)
|
||||
|
||||
if (err.stack.indexOf('last page') >= 0) {
|
||||
return
|
||||
} else {
|
||||
console.log('[ERROR] Github Server -> getRepoInfo -> doGithub -> getList ->Method call produced an error.')
|
||||
console.log('[ERROR] Github Server -> getRepoInfo -> doGithub -> getList ->err.stack = ' + err.stack)
|
||||
console.log('[ERROR] Github Server -> getRepoInfo -> doGithub -> getList ->repository = ' + repository)
|
||||
console.log('[ERROR] Github Server -> getRepoInfo -> doGithub -> getList ->username = ' + username)
|
||||
console.log('[ERROR] Github Server -> getRepoInfo -> doGithub -> getList ->token starts with = ' + token.substring(0, 10) + '...')
|
||||
console.log('[ERROR] Github Server -> getRepoInfo -> doGithub -> getList ->token ends with = ' + '...' + token.substring(token.length - 10))
|
||||
error = err
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
} catch (err) {
|
||||
console.log('[ERROR] Github Server -> getRepoInfo -> Method call produced an error.')
|
||||
console.log('[ERROR] Github Server -> getRepoInfo -> err.stack = ' + err.stack)
|
||||
console.log('[ERROR] Github Server -> getRepoInfo -> repository = ' + repository)
|
||||
console.log('[ERROR] Github Server -> getRepoInfo -> username = ' + username)
|
||||
console.log('[ERROR] Github Server -> getRepoInfo -> token starts with = ' + token.substring(0, 10) + '...')
|
||||
console.log('[ERROR] Github Server -> getRepoInfo -> token ends with = ' + '...' + token.substring(token.length - 10))
|
||||
|
||||
let error = {
|
||||
result: 'Fail Because',
|
||||
message: err.message,
|
||||
stack: err.stack
|
||||
}
|
||||
return error
|
||||
}
|
||||
}
|
||||
|
||||
async function mergeGithubPullRequests(commitMessage, username, token) {
|
||||
try {
|
||||
commitMessage = unescape(commitMessage)
|
||||
username = unescape(username)
|
||||
token = unescape(token)
|
||||
const repository = 'Superalgos'
|
||||
|
||||
/* Unsavping # */
|
||||
for (let i = 0; i < 10; i++) {
|
||||
commitMessage = commitMessage.replace('_SLASH_', '/')
|
||||
commitMessage = commitMessage.replace('_HASHTAG_', '#')
|
||||
}
|
||||
|
||||
let error
|
||||
let githubPrListArray = []
|
||||
|
||||
return await processOpenPullRequests()
|
||||
|
||||
async function processOpenPullRequests() {
|
||||
await doGithub()
|
||||
if (error !== undefined) {
|
||||
|
||||
let docs = {
|
||||
project: 'Governance',
|
||||
category: 'Topic',
|
||||
type: 'Gov Error - Merge Pull Requests',
|
||||
anchor: undefined,
|
||||
placeholder: {}
|
||||
}
|
||||
|
||||
return respondWithDocsObject(docs, error)
|
||||
}
|
||||
|
||||
return {
|
||||
result: global.DEFAULT_OK_RESPONSE.result
|
||||
}
|
||||
}
|
||||
|
||||
async function doGithub() {
|
||||
try {
|
||||
const repo = repository
|
||||
const owner = 'Superalgos'
|
||||
const { Octokit } = require("@octokit/rest")
|
||||
const octokit = new Octokit({
|
||||
auth: token,
|
||||
userAgent: 'Superalgos Beta 11'
|
||||
})
|
||||
await getPrList()
|
||||
await mergePrs()
|
||||
|
||||
async function getPrList() {
|
||||
|
||||
const per_page = 100 // Max
|
||||
let page = 0
|
||||
let lastPage = false
|
||||
|
||||
while (lastPage === false) {
|
||||
try {
|
||||
page++
|
||||
|
||||
await CL.projects.foundations.utilities.asyncFunctions.sleep(GITHUB_API_WAITING_TIME)
|
||||
|
||||
let listResponse = await octokit.rest.pulls.list({
|
||||
owner: owner,
|
||||
repo: repo,
|
||||
state: 'open',
|
||||
head: 'develop',
|
||||
base: 'develop',
|
||||
sort: undefined,
|
||||
direction: undefined,
|
||||
per_page: per_page,
|
||||
page: page
|
||||
});
|
||||
|
||||
if (listResponse.data.length < 100) {
|
||||
lastPage = true
|
||||
}
|
||||
console.log('[INFO] Github Server -> mergeGithubPullRequests -> doGithub -> getPrList -> Receiving Page = ' + page)
|
||||
for (let i = 0; i < listResponse.data.length; i++) {
|
||||
let pullRequest = listResponse.data[i]
|
||||
console.log('[INFO] Github Server -> mergeGithubPullRequests -> doGithub -> getPrList -> Pull Request "' + pullRequest.title + '" found and added to the list to validate. ')
|
||||
githubPrListArray.push(pullRequest)
|
||||
}
|
||||
console.log('[INFO] Github Server -> mergeGithubPullRequests -> doGithub -> getPrList -> Received = ' + listResponse.data.length)
|
||||
|
||||
} catch (err) {
|
||||
console.log(err)
|
||||
|
||||
if (err.stack.indexOf('last page') >= 0) {
|
||||
return
|
||||
} else {
|
||||
console.log('[ERROR] Github Server -> mergeGithubPullRequests -> doGithub -> getPrList ->Method call produced an error.')
|
||||
console.log('[ERROR] Github Server -> mergeGithubPullRequests -> doGithub -> getPrList ->err.stack = ' + err.stack)
|
||||
console.log('[ERROR] Github Server -> mergeGithubPullRequests -> doGithub -> getPrList ->repository = ' + repository)
|
||||
console.log('[ERROR] Github Server -> mergeGithubPullRequests -> doGithub -> getPrList ->username = ' + username)
|
||||
console.log('[ERROR] Github Server -> mergeGithubPullRequests -> doGithub -> getPrList ->token starts with = ' + token.substring(0, 10) + '...')
|
||||
console.log('[ERROR] Github Server -> mergeGithubPullRequests -> doGithub -> getPrList ->token ends with = ' + '...' + token.substring(token.length - 10))
|
||||
error = err
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
async function mergePrs() {
|
||||
/*
|
||||
In order to automatically merge a PRs we will run several validations first.
|
||||
We want to automate specifically the merging of Profile File changes at the
|
||||
Governance System done by the same Github user name that matches the profile
|
||||
changed. We will also not do the merge if there are more than one file at the
|
||||
PR.
|
||||
|
||||
We will go through the list of open PRs and run the validations at each one of them.
|
||||
*/
|
||||
console.log('[INFO] Github Server -> mergeGithubPullRequests -> Ready to Validate ' + githubPrListArray.length + ' pull requests. ')
|
||||
|
||||
for (let i = 0; i < githubPrListArray.length; i++) {
|
||||
let pullRequest = githubPrListArray[i]
|
||||
/*
|
||||
Lets get the files changed at this Pull Request.
|
||||
*/
|
||||
await CL.projects.foundations.utilities.asyncFunctions.sleep(GITHUB_API_WAITING_TIME)
|
||||
let listResponse = await octokit.rest.pulls.listFiles({
|
||||
owner: owner,
|
||||
repo: repo,
|
||||
pull_number: pullRequest.number
|
||||
});
|
||||
/*
|
||||
Validation #1: If the PR has more than one file, then we will not automatically
|
||||
merge it.
|
||||
*/
|
||||
if (listResponse.data.length !== 1) {
|
||||
console.log('[INFO] Github Server -> mergeGithubPullRequests -> Validation #1 Failed -> Pull Request "' + pullRequest.title + '" not merged because it contains more than 1 file. -> fileCount = ' + listResponse.data.length)
|
||||
/*
|
||||
We will close PRs that contains any User Profile file together with other files in the same Pull Request.
|
||||
This will avoid manual merges to include User Profile files.
|
||||
*/
|
||||
for (j = 0; j < listResponse.data.length; j++) {
|
||||
let pullRequestFile = listResponse.data[j]
|
||||
let fileContentUrl = pullRequestFile.raw_url
|
||||
if (fileContentUrl.indexOf('Governance/Plugins/User-Profiles') >= 0) {
|
||||
await CL.projects.foundations.utilities.asyncFunctions.sleep(GITHUB_API_WAITING_TIME)
|
||||
await octokit.rest.issues.createComment({
|
||||
owner: owner,
|
||||
repo: repo,
|
||||
issue_number: pullRequest.number,
|
||||
body: 'This Pull Request could not be automatically merged and was closed by the Superalgos Governance System because it was detected that a User Profile file... \n\n' + fileContentUrl + '\n\n...was submitted together with ' + (listResponse.data.length - 1) + ' other file/s. User Profiles files as per the Governance System rules, must be the only file present at a Pull Request in order to pass all the validations and be automatically merged.'
|
||||
});
|
||||
|
||||
await CL.projects.foundations.utilities.asyncFunctions.sleep(GITHUB_API_WAITING_TIME)
|
||||
await octokit.rest.pulls.update({
|
||||
owner: owner,
|
||||
repo: repo,
|
||||
pull_number: pullRequest.number,
|
||||
state: 'closed'
|
||||
});
|
||||
break
|
||||
}
|
||||
}
|
||||
continue
|
||||
}
|
||||
let pullRequestFile = listResponse.data[0]
|
||||
/*
|
||||
Validation #2: File Name must be the same to the Github Username of the PR owner.
|
||||
*/
|
||||
let fileContentUrl = pullRequestFile.raw_url
|
||||
|
||||
if (fileContentUrl.indexOf('Governance/Plugins/User-Profiles') < 0) {
|
||||
/*
|
||||
If it is not a user profile then there is no need to auto merge.
|
||||
*/
|
||||
console.log('[INFO] Github Server -> mergeGithubPullRequests -> Validation #2 Failed -> Pull Request "' + pullRequest.title + '" not merged because the file modified at the Pull Request is not a User Profile file. -> fileContentUrl = ' + fileContentUrl)
|
||||
continue
|
||||
}
|
||||
|
||||
let splittedURL = fileContentUrl.split('/')
|
||||
let fileName = splittedURL[splittedURL.length - 1]
|
||||
let splittedFileName = fileName.split('.')
|
||||
fileName = splittedFileName[0]
|
||||
let githubUsername = pullRequest.user.login
|
||||
|
||||
if (githubUsername !== fileName) {
|
||||
console.log('[INFO] Github Server -> mergeGithubPullRequests -> Validation #2 Failed -> Pull Request "' + pullRequest.title + '" not merged because the Github Username is not equal to the File Name. -> Github Username = ' + githubUsername + '-> fileName = ' + fileName)
|
||||
|
||||
await CL.projects.foundations.utilities.asyncFunctions.sleep(GITHUB_API_WAITING_TIME)
|
||||
await octokit.rest.issues.createComment({
|
||||
owner: owner,
|
||||
repo: repo,
|
||||
issue_number: pullRequest.number,
|
||||
body: 'This Pull Request could not be automatically merged and was closed by the Superalgos Governance System because it was detected that the Github User "' + githubUsername + '" who submitted it, is not equal to the name of the User Profile Plugin File.\n\n File Name = "' + fileName + '"'
|
||||
});
|
||||
|
||||
await CL.projects.foundations.utilities.asyncFunctions.sleep(GITHUB_API_WAITING_TIME)
|
||||
await octokit.rest.pulls.update({
|
||||
owner: owner,
|
||||
repo: repo,
|
||||
pull_number: pullRequest.number,
|
||||
state: 'closed'
|
||||
});
|
||||
continue
|
||||
}
|
||||
await CL.projects.foundations.utilities.asyncFunctions.sleep(GITHUB_API_WAITING_TIME)
|
||||
let fileContent = await fetchAPIDataFile(fileContentUrl)
|
||||
|
||||
let userProfile = JSON.parse(fileContent)
|
||||
/*
|
||||
Validation #3: The file changed at the PR is a User Profile.
|
||||
*/
|
||||
if (userProfile.type !== 'User Profile') {
|
||||
console.log('[INFO] Github Server -> mergeGithubPullRequests -> Validation #3 Failed -> Pull Request "' + pullRequest.title + '" not merged because the file modified is not a User Profile. -> Type = ' + userProfile.type)
|
||||
continue
|
||||
}
|
||||
/*
|
||||
Validation #4: The message signed at the config is not the Github Username.
|
||||
*/
|
||||
let config = JSON.parse(userProfile.config)
|
||||
let messageSigned = config.signature.message
|
||||
if (messageSigned !== githubUsername) {
|
||||
console.log('[INFO] Github Server -> mergeGithubPullRequests -> Validation #4 Failed -> Pull Request "' + pullRequest.title + '" not merged because the Github Username is not equal to the Message Signed at the User Profile. -> Github Username = ' + githubUsername + '-> messageSigned = ' + messageSigned)
|
||||
|
||||
await CL.projects.foundations.utilities.asyncFunctions.sleep(GITHUB_API_WAITING_TIME)
|
||||
await octokit.rest.issues.createComment({
|
||||
owner: owner,
|
||||
repo: repo,
|
||||
issue_number: pullRequest.number,
|
||||
body: 'This Pull Request could not be automatically merged and was closed by the Superalgos Governance System because it was detected that the Github User "' + githubUsername + '" who submitted it, is not equal to the Message Signed at the User Profile.\n\n Message Signed = "' + messageSigned + '"'
|
||||
});
|
||||
|
||||
await CL.projects.foundations.utilities.asyncFunctions.sleep(GITHUB_API_WAITING_TIME)
|
||||
await octokit.rest.pulls.update({
|
||||
owner: owner,
|
||||
repo: repo,
|
||||
pull_number: pullRequest.number,
|
||||
state: 'closed'
|
||||
});
|
||||
continue
|
||||
}
|
||||
/*
|
||||
All validations passed, we will proceed an merge this Pull Request.
|
||||
*/
|
||||
await CL.projects.foundations.utilities.asyncFunctions.sleep(GITHUB_API_WAITING_TIME)
|
||||
let mergeResponse = await octokit.rest.pulls.merge({
|
||||
owner: owner,
|
||||
repo: repo,
|
||||
pull_number: pullRequest.number,
|
||||
commit_title: 'Changes in User Profile done by Profile Owner ' + githubUsername + ' automatically merged by Superalgos.'
|
||||
});
|
||||
|
||||
if (mergeResponse.data.merged !== true) {
|
||||
console.log('[WARN] Github Server -> mergeGithubPullRequests -> Merge Failed -> Pull Request "' + pullRequest.title + '" not merged because Github could not merge it. -> mergeResponse.message = ' + mergeResponse.data.message)
|
||||
continue
|
||||
} else {
|
||||
console.log('[INFO] Github Server -> mergeGithubPullRequests -> Merge Succed -> Pull Request "' + pullRequest.title + '" successfully merged. -> mergeResponse.message = ' + mergeResponse.data.message)
|
||||
await CL.projects.foundations.utilities.asyncFunctions.sleep(GITHUB_API_WAITING_TIME)
|
||||
await octokit.rest.issues.createComment({
|
||||
owner: owner,
|
||||
repo: repo,
|
||||
issue_number: pullRequest.number,
|
||||
body: 'This Pull Request was automatically merged by the Superalgos Governance System because it was detected that the Github User " ' + githubUsername + '" who submitted it, modified its own User Profile Plugin File and nothning else but that file. All validations were successfull.'
|
||||
});
|
||||
continue
|
||||
}
|
||||
}
|
||||
}
|
||||
} catch (err) {
|
||||
console.log('[ERROR] Github Server -> mergeGithubPullRequests -> doGithub -> err.stack = ' + err.stack)
|
||||
}
|
||||
}
|
||||
|
||||
} catch (err) {
|
||||
console.log('[ERROR] Github Server -> mergeGithubPullRequests -> Method call produced an error.')
|
||||
console.log('[ERROR] Github Server -> mergeGithubPullRequests -> err.stack = ' + err.stack)
|
||||
console.log('[ERROR] Github Server -> mergeGithubPullRequests -> repository = ' + repository)
|
||||
console.log('[ERROR] Github Server -> mergeGithubPullRequests -> username = ' + username)
|
||||
console.log('[ERROR] Github Server -> mergeGithubPullRequests -> token starts with = ' + token.substring(0, 10) + '...')
|
||||
console.log('[ERROR] Github Server -> mergeGithubPullRequests -> token ends with = ' + '...' + token.substring(token.length - 10))
|
||||
|
||||
let error = {
|
||||
result: 'Fail Because',
|
||||
message: err.message,
|
||||
stack: err.stack
|
||||
}
|
||||
return error
|
||||
}
|
||||
}
|
||||
|
||||
function respondWithDocsObject(docs, error) {
|
||||
|
||||
if (error.message !== undefined) {
|
||||
docs.placeholder.errorMessage = {
|
||||
style: 'Error',
|
||||
text: error.message
|
||||
}
|
||||
}
|
||||
if (error.stack !== undefined) {
|
||||
docs.placeholder.errorStack = {
|
||||
style: 'Javascript',
|
||||
text: error.stack
|
||||
}
|
||||
}
|
||||
if (error.code !== undefined) {
|
||||
docs.placeholder.errorCode = {
|
||||
style: 'Json',
|
||||
text: error.code
|
||||
}
|
||||
}
|
||||
|
||||
docs.placeholder.errorDetails = {
|
||||
style: 'Json',
|
||||
text: JSON.stringify(error, undefined, 4)
|
||||
}
|
||||
|
||||
let customResponse = {
|
||||
result: global.CUSTOM_FAIL_RESPONSE.result,
|
||||
docs: docs
|
||||
}
|
||||
|
||||
return customResponse
|
||||
}
|
||||
}
|
||||
+72
-447
@@ -1,4 +1,13 @@
|
||||
exports.newHttpInterface = function newHttpInterface(WEB_SERVER, DATA_FILE_SERVER, PROJECT_FILE_SERVER, UI_FILE_SERVER, PLUGIN_SERVER, CCXT_SERVER, WEB3_SERVER) {
|
||||
exports.newHttpInterface = function newHttpInterface(
|
||||
WEB_SERVER,
|
||||
DATA_FILE_SERVER,
|
||||
PROJECT_FILE_SERVER,
|
||||
UI_FILE_SERVER,
|
||||
PLUGIN_SERVER,
|
||||
CCXT_SERVER,
|
||||
WEB3_SERVER,
|
||||
GITHUB_SERVER
|
||||
) {
|
||||
|
||||
/*
|
||||
IMPORTANT: If you are reviewing the code of the project please note
|
||||
@@ -366,6 +375,7 @@ exports.newHttpInterface = function newHttpInterface(WEB_SERVER, DATA_FILE_SERVE
|
||||
}
|
||||
break
|
||||
}
|
||||
|
||||
case 'Save-Concept-Schema': {
|
||||
getBody(processRequest)
|
||||
|
||||
@@ -396,6 +406,7 @@ exports.newHttpInterface = function newHttpInterface(WEB_SERVER, DATA_FILE_SERVE
|
||||
}
|
||||
break
|
||||
}
|
||||
|
||||
case 'Save-Topic-Schema': {
|
||||
getBody(processRequest)
|
||||
|
||||
@@ -426,6 +437,7 @@ exports.newHttpInterface = function newHttpInterface(WEB_SERVER, DATA_FILE_SERVE
|
||||
}
|
||||
break
|
||||
}
|
||||
|
||||
case 'Save-Tutorial-Schema': {
|
||||
getBody(processRequest)
|
||||
|
||||
@@ -456,6 +468,7 @@ exports.newHttpInterface = function newHttpInterface(WEB_SERVER, DATA_FILE_SERVE
|
||||
}
|
||||
break
|
||||
}
|
||||
|
||||
case 'Save-Review-Schema': {
|
||||
getBody(processRequest)
|
||||
|
||||
@@ -486,6 +499,7 @@ exports.newHttpInterface = function newHttpInterface(WEB_SERVER, DATA_FILE_SERVE
|
||||
}
|
||||
break
|
||||
}
|
||||
|
||||
case 'Save-Book-Schema': {
|
||||
getBody(processRequest)
|
||||
|
||||
@@ -1019,138 +1033,80 @@ exports.newHttpInterface = function newHttpInterface(WEB_SERVER, DATA_FILE_SERVE
|
||||
}
|
||||
break
|
||||
|
||||
case 'Gov': {
|
||||
switch (requestParameters[2]) { // switch by command
|
||||
case 'getGithubStars': {
|
||||
getGithubUsernames('activity', 'listStargazersForRepo')
|
||||
break
|
||||
}
|
||||
case 'getGithubWatchers': {
|
||||
getGithubUsernames('activity', 'listWatchersForRepo')
|
||||
break
|
||||
}
|
||||
case 'getGithubForks': {
|
||||
getGithubUsernames('repos', 'listForks')
|
||||
break
|
||||
}
|
||||
case 'PRs': {
|
||||
mergeGithubPullRequests()
|
||||
break
|
||||
}
|
||||
case 'Pay': {
|
||||
payToContributors()
|
||||
break
|
||||
}
|
||||
}
|
||||
case 'GOV': {
|
||||
/*
|
||||
This is the Governance endpoint at the Http Interface. All methods
|
||||
related to the Governance System are implemented here and routed
|
||||
to the backend Servers that can process them.
|
||||
*/
|
||||
getBody(processRequest)
|
||||
|
||||
function getGithubUsernames(endpoint, method) {
|
||||
async function processRequest(body) {
|
||||
try {
|
||||
const GITHUB_API_WAITING_TIME = 250
|
||||
const repository = unescape(requestParameters[3])
|
||||
const username = unescape(requestParameters[4])
|
||||
const token = unescape(requestParameters[5])
|
||||
let error
|
||||
let githubListArray = []
|
||||
let params = JSON.parse(body)
|
||||
|
||||
getRepoInfo()
|
||||
switch (params.method) {
|
||||
case 'getGithubStars': {
|
||||
|
||||
async function getRepoInfo() {
|
||||
await doGithub()
|
||||
if (error !== undefined) {
|
||||
let serverResponse = await GITHUB_SERVER.getGithubStars(
|
||||
params.repository,
|
||||
params.username,
|
||||
params.token
|
||||
)
|
||||
|
||||
let docs = {
|
||||
project: 'Governance',
|
||||
category: 'Topic',
|
||||
type: 'Gov Error - Get Repository Information',
|
||||
anchor: undefined,
|
||||
placeholder: {}
|
||||
}
|
||||
|
||||
respondWithDocsObject(docs, error)
|
||||
respondWithContent(JSON.stringify(serverResponse), httpResponse)
|
||||
return
|
||||
}
|
||||
case 'getGithubWatchers': {
|
||||
|
||||
respondWithContent(JSON.stringify(githubListArray), httpResponse)
|
||||
}
|
||||
let serverResponse = await GITHUB_SERVER.getGithubWatchers(
|
||||
params.repository,
|
||||
params.username,
|
||||
params.token
|
||||
)
|
||||
|
||||
async function doGithub() {
|
||||
respondWithContent(JSON.stringify(serverResponse), httpResponse)
|
||||
return
|
||||
}
|
||||
case 'getGithubForks': {
|
||||
|
||||
const { Octokit } = require("@octokit/rest")
|
||||
let serverResponse = await GITHUB_SERVER.getGithubForks(
|
||||
params.repository,
|
||||
params.username,
|
||||
params.token
|
||||
)
|
||||
|
||||
const octokit = new Octokit({
|
||||
auth: token,
|
||||
userAgent: 'Superalgos Beta 11'
|
||||
})
|
||||
await getList()
|
||||
respondWithContent(JSON.stringify(serverResponse), httpResponse)
|
||||
return
|
||||
}
|
||||
case 'mergePullRequests': {
|
||||
|
||||
async function getList() {
|
||||
const repo = repository
|
||||
const owner = 'Superalgos'
|
||||
const per_page = 100 // Max
|
||||
let page = 0
|
||||
let lastPage = false
|
||||
let serverResponse = await GITHUB_SERVER.mergePullRequests(
|
||||
params.commitMessage,
|
||||
params.username,
|
||||
params.token
|
||||
)
|
||||
|
||||
while (lastPage === false) {
|
||||
try {
|
||||
page++
|
||||
await sleep(GITHUB_API_WAITING_TIME)
|
||||
let listResponse = await octokit[endpoint][method]({
|
||||
owner,
|
||||
repo,
|
||||
per_page,
|
||||
page
|
||||
});
|
||||
respondWithContent(JSON.stringify(serverResponse), httpResponse)
|
||||
return
|
||||
}
|
||||
case 'payContributors': {
|
||||
|
||||
if (listResponse.data.length < 100) {
|
||||
lastPage = true
|
||||
}
|
||||
let serverResponse = await WEB3_SERVER.payContributors(
|
||||
params.signature
|
||||
)
|
||||
|
||||
for (let i = 0; i < listResponse.data.length; i++) {
|
||||
let listItem = listResponse.data[i]
|
||||
let githubUsername
|
||||
switch (endpoint) {
|
||||
case 'activity': {
|
||||
githubUsername = listItem.login
|
||||
break
|
||||
}
|
||||
case 'repos': {
|
||||
githubUsername = listItem.owner.login
|
||||
break
|
||||
}
|
||||
}
|
||||
//console.log(listItem)
|
||||
|
||||
githubListArray.push(githubUsername)
|
||||
}
|
||||
console.log('[INFO] httpInterface -> Gov -> getRepoInfo -> doGithub -> getList -> ' + method + ' Page = ' + page)
|
||||
console.log('[INFO] httpInterface -> Gov -> getRepoInfo -> doGithub -> getList -> ' + method + ' Received = ' + listResponse.data.length)
|
||||
|
||||
} catch (err) {
|
||||
console.log(err)
|
||||
|
||||
if (err.stack.indexOf('last page') >= 0) {
|
||||
return
|
||||
} else {
|
||||
console.log('[ERROR] httpInterface -> Gov -> getRepoInfo -> doGithub -> getList ->Method call produced an error.')
|
||||
console.log('[ERROR] httpInterface -> Gov -> getRepoInfo -> doGithub -> getList ->err.stack = ' + err.stack)
|
||||
console.log('[ERROR] httpInterface -> Gov -> getRepoInfo -> doGithub -> getList ->repository = ' + repository)
|
||||
console.log('[ERROR] httpInterface -> Gov -> getRepoInfo -> doGithub -> getList ->username = ' + username)
|
||||
console.log('[ERROR] httpInterface -> Gov -> getRepoInfo -> doGithub -> getList ->token starts with = ' + token.substring(0, 10) + '...')
|
||||
console.log('[ERROR] httpInterface -> Gov -> getRepoInfo -> doGithub -> getList ->token ends with = ' + '...' + token.substring(token.length - 10))
|
||||
error = err
|
||||
}
|
||||
}
|
||||
}
|
||||
respondWithContent(JSON.stringify(serverResponse), httpResponse)
|
||||
return
|
||||
}
|
||||
default: {
|
||||
respondWithContent(JSON.stringify({ error: 'Method ' + params.method + ' is invalid.' }), httpResponse)
|
||||
}
|
||||
}
|
||||
|
||||
} catch (err) {
|
||||
console.log('[ERROR] httpInterface -> Gov -> getRepoInfo -> Method call produced an error.')
|
||||
console.log('[ERROR] httpInterface -> Gov -> getRepoInfo -> err.stack = ' + err.stack)
|
||||
console.log('[ERROR] httpInterface -> Gov -> getRepoInfo -> repository = ' + repository)
|
||||
console.log('[ERROR] httpInterface -> Gov -> getRepoInfo -> username = ' + username)
|
||||
console.log('[ERROR] httpInterface -> Gov -> getRepoInfo -> token starts with = ' + token.substring(0, 10) + '...')
|
||||
console.log('[ERROR] httpInterface -> Gov -> getRepoInfo -> token ends with = ' + '...' + token.substring(token.length - 10))
|
||||
console.log('[ERROR] httpInterface -> GOV -> Method call produced an error.')
|
||||
console.log('[ERROR] httpInterface -> GOV -> err.stack = ' + err.stack)
|
||||
console.log('[ERROR] httpInterface -> GOV -> Params Received = ' + body)
|
||||
|
||||
let error = {
|
||||
result: 'Fail Because',
|
||||
@@ -1160,333 +1116,8 @@ exports.newHttpInterface = function newHttpInterface(WEB_SERVER, DATA_FILE_SERVE
|
||||
respondWithContent(JSON.stringify(error), httpResponse)
|
||||
}
|
||||
}
|
||||
|
||||
function respondWithDocsObject(docs, error) {
|
||||
|
||||
if (error.message !== undefined) {
|
||||
docs.placeholder.errorMessage = {
|
||||
style: 'Error',
|
||||
text: error.message
|
||||
}
|
||||
}
|
||||
if (error.stack !== undefined) {
|
||||
docs.placeholder.errorStack = {
|
||||
style: 'Javascript',
|
||||
text: error.stack
|
||||
}
|
||||
}
|
||||
if (error.code !== undefined) {
|
||||
docs.placeholder.errorCode = {
|
||||
style: 'Json',
|
||||
text: error.code
|
||||
}
|
||||
}
|
||||
|
||||
docs.placeholder.errorDetails = {
|
||||
style: 'Json',
|
||||
text: JSON.stringify(error, undefined, 4)
|
||||
}
|
||||
|
||||
let customResponse = {
|
||||
result: global.CUSTOM_FAIL_RESPONSE.result,
|
||||
docs: docs
|
||||
}
|
||||
|
||||
respondWithContent(JSON.stringify(customResponse), httpResponse)
|
||||
|
||||
}
|
||||
|
||||
function mergeGithubPullRequests() {
|
||||
try {
|
||||
let commitMessage = unescape(requestParameters[3])
|
||||
|
||||
/* Unsavping # */
|
||||
for (let i = 0; i < 10; i++) {
|
||||
commitMessage = commitMessage.replace('_SLASH_', '/')
|
||||
commitMessage = commitMessage.replace('_HASHTAG_', '#')
|
||||
}
|
||||
|
||||
const GITHUB_API_WAITING_TIME = 250
|
||||
const repository = 'Superalgos'
|
||||
const username = unescape(requestParameters[4])
|
||||
const token = unescape(requestParameters[5])
|
||||
|
||||
let error
|
||||
let githubPrListArray = []
|
||||
|
||||
processOpenPullRequests()
|
||||
|
||||
async function processOpenPullRequests() {
|
||||
await doGithub()
|
||||
if (error !== undefined) {
|
||||
|
||||
let docs = {
|
||||
project: 'Governance',
|
||||
category: 'Topic',
|
||||
type: 'Gov Error - Merge Pull Requests',
|
||||
anchor: undefined,
|
||||
placeholder: {}
|
||||
}
|
||||
|
||||
respondWithDocsObject(docs, error)
|
||||
return
|
||||
}
|
||||
|
||||
respondWithContent(JSON.stringify(global.DEFAULT_OK_RESPONSE), httpResponse)
|
||||
}
|
||||
|
||||
async function doGithub() {
|
||||
try {
|
||||
const repo = repository
|
||||
const owner = 'Superalgos'
|
||||
const { Octokit } = require("@octokit/rest")
|
||||
const octokit = new Octokit({
|
||||
auth: token,
|
||||
userAgent: 'Superalgos Beta 11'
|
||||
})
|
||||
await getPrList()
|
||||
await mergePrs()
|
||||
|
||||
async function getPrList() {
|
||||
|
||||
const per_page = 100 // Max
|
||||
let page = 0
|
||||
let lastPage = false
|
||||
|
||||
while (lastPage === false) {
|
||||
try {
|
||||
page++
|
||||
|
||||
await sleep(GITHUB_API_WAITING_TIME)
|
||||
let listResponse = await octokit.rest.pulls.list({
|
||||
owner: owner,
|
||||
repo: repo,
|
||||
state: 'open',
|
||||
head: 'develop',
|
||||
base: 'develop',
|
||||
sort: undefined,
|
||||
direction: undefined,
|
||||
per_page: per_page,
|
||||
page: page
|
||||
});
|
||||
|
||||
if (listResponse.data.length < 100) {
|
||||
lastPage = true
|
||||
}
|
||||
console.log('[INFO] httpInterface -> Gov -> mergeGithubPullRequests -> doGithub -> getPrList -> Receiving Page = ' + page)
|
||||
for (let i = 0; i < listResponse.data.length; i++) {
|
||||
let pullRequest = listResponse.data[i]
|
||||
console.log('[INFO] httpInterface -> Gov -> mergeGithubPullRequests -> doGithub -> getPrList -> Pull Request "' + pullRequest.title + '" found and added to the list to validate. ')
|
||||
githubPrListArray.push(pullRequest)
|
||||
}
|
||||
console.log('[INFO] httpInterface -> Gov -> mergeGithubPullRequests -> doGithub -> getPrList -> Received = ' + listResponse.data.length)
|
||||
|
||||
} catch (err) {
|
||||
console.log(err)
|
||||
|
||||
if (err.stack.indexOf('last page') >= 0) {
|
||||
return
|
||||
} else {
|
||||
console.log('[ERROR] httpInterface -> Gov -> mergeGithubPullRequests -> doGithub -> getPrList ->Method call produced an error.')
|
||||
console.log('[ERROR] httpInterface -> Gov -> mergeGithubPullRequests -> doGithub -> getPrList ->err.stack = ' + err.stack)
|
||||
console.log('[ERROR] httpInterface -> Gov -> mergeGithubPullRequests -> doGithub -> getPrList ->repository = ' + repository)
|
||||
console.log('[ERROR] httpInterface -> Gov -> mergeGithubPullRequests -> doGithub -> getPrList ->username = ' + username)
|
||||
console.log('[ERROR] httpInterface -> Gov -> mergeGithubPullRequests -> doGithub -> getPrList ->token starts with = ' + token.substring(0, 10) + '...')
|
||||
console.log('[ERROR] httpInterface -> Gov -> mergeGithubPullRequests -> doGithub -> getPrList ->token ends with = ' + '...' + token.substring(token.length - 10))
|
||||
error = err
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
async function mergePrs() {
|
||||
/*
|
||||
In order to automatically merge a PRs we will run several validations first.
|
||||
We want to automate specifically the merging of Profile File changes at the
|
||||
Governance System done by the same Github user name that matches the profile
|
||||
changed. We will also not do the merge if there are more than one file at the
|
||||
PR.
|
||||
|
||||
We will go through the list of open PRs and run the validations at each one of them.
|
||||
*/
|
||||
console.log('[INFO] httpInterface -> Gov -> mergeGithubPullRequests -> Ready to Validate ' + githubPrListArray.length + ' pull requests. ')
|
||||
|
||||
for (let i = 0; i < githubPrListArray.length; i++) {
|
||||
let pullRequest = githubPrListArray[i]
|
||||
/*
|
||||
Lets get the files changed at this Pull Request.
|
||||
*/
|
||||
await sleep(GITHUB_API_WAITING_TIME)
|
||||
let listResponse = await octokit.rest.pulls.listFiles({
|
||||
owner: owner,
|
||||
repo: repo,
|
||||
pull_number: pullRequest.number
|
||||
});
|
||||
/*
|
||||
Validation #1: If the PR has more than one file, then we will not automatically
|
||||
merge it.
|
||||
*/
|
||||
if (listResponse.data.length !== 1) {
|
||||
console.log('[INFO] httpInterface -> Gov -> mergeGithubPullRequests -> Validation #1 Failed -> Pull Request "' + pullRequest.title + '" not merged because it contains more than 1 file. -> fileCount = ' + listResponse.data.length)
|
||||
/*
|
||||
We will close PRs that contains any User Profile file together with other files in the same Pull Request.
|
||||
This will avoid manual merges to include User Profile files.
|
||||
*/
|
||||
for (j = 0; j < listResponse.data.length; j++) {
|
||||
let pullRequestFile = listResponse.data[j]
|
||||
let fileContentUrl = pullRequestFile.raw_url
|
||||
if (fileContentUrl.indexOf('Governance/Plugins/User-Profiles') >= 0) {
|
||||
await sleep(GITHUB_API_WAITING_TIME)
|
||||
await octokit.rest.issues.createComment({
|
||||
owner: owner,
|
||||
repo: repo,
|
||||
issue_number: pullRequest.number,
|
||||
body: 'This Pull Request could not be automatically merged and was closed by the Superalgos Governance System because it was detected that a User Profile file... \n\n' + fileContentUrl + '\n\n...was submitted together with ' + (listResponse.data.length - 1) + ' other file/s. User Profiles files as per the Governance System rules, must be the only file present at a Pull Request in order to pass all the validations and be automatically merged.'
|
||||
});
|
||||
|
||||
await sleep(GITHUB_API_WAITING_TIME)
|
||||
await octokit.rest.pulls.update({
|
||||
owner: owner,
|
||||
repo: repo,
|
||||
pull_number: pullRequest.number,
|
||||
state: 'closed'
|
||||
});
|
||||
break
|
||||
}
|
||||
}
|
||||
continue
|
||||
}
|
||||
let pullRequestFile = listResponse.data[0]
|
||||
/*
|
||||
Validation #2: File Name must be the same to the Github Username of the PR owner.
|
||||
*/
|
||||
let fileContentUrl = pullRequestFile.raw_url
|
||||
|
||||
if (fileContentUrl.indexOf('Governance/Plugins/User-Profiles') < 0) {
|
||||
/*
|
||||
If it is not a user profile then there is no need to auto merge.
|
||||
*/
|
||||
console.log('[INFO] httpInterface -> Gov -> mergeGithubPullRequests -> Validation #2 Failed -> Pull Request "' + pullRequest.title + '" not merged because the file modified at the Pull Request is not a User Profile file. -> fileContentUrl = ' + fileContentUrl)
|
||||
continue
|
||||
}
|
||||
|
||||
let splittedURL = fileContentUrl.split('/')
|
||||
let fileName = splittedURL[splittedURL.length - 1]
|
||||
let splittedFileName = fileName.split('.')
|
||||
fileName = splittedFileName[0]
|
||||
let githubUsername = pullRequest.user.login
|
||||
|
||||
if (githubUsername !== fileName) {
|
||||
console.log('[INFO] httpInterface -> Gov -> mergeGithubPullRequests -> Validation #2 Failed -> Pull Request "' + pullRequest.title + '" not merged because the Github Username is not equal to the File Name. -> Github Username = ' + githubUsername + '-> fileName = ' + fileName)
|
||||
|
||||
await sleep(GITHUB_API_WAITING_TIME)
|
||||
await octokit.rest.issues.createComment({
|
||||
owner: owner,
|
||||
repo: repo,
|
||||
issue_number: pullRequest.number,
|
||||
body: 'This Pull Request could not be automatically merged and was closed by the Superalgos Governance System because it was detected that the Github User "' + githubUsername + '" who submitted it, is not equal to the name of the User Profile Plugin File.\n\n File Name = "' + fileName + '"'
|
||||
});
|
||||
|
||||
await sleep(GITHUB_API_WAITING_TIME)
|
||||
await octokit.rest.pulls.update({
|
||||
owner: owner,
|
||||
repo: repo,
|
||||
pull_number: pullRequest.number,
|
||||
state: 'closed'
|
||||
});
|
||||
continue
|
||||
}
|
||||
await sleep(GITHUB_API_WAITING_TIME)
|
||||
let fileContent = await fetchAPIDataFile(fileContentUrl)
|
||||
|
||||
let userProfile = JSON.parse(fileContent)
|
||||
/*
|
||||
Validation #3: The file changed at the PR is a User Profile.
|
||||
*/
|
||||
if (userProfile.type !== 'User Profile') {
|
||||
console.log('[INFO] httpInterface -> Gov -> mergeGithubPullRequests -> Validation #3 Failed -> Pull Request "' + pullRequest.title + '" not merged because the file modified is not a User Profile. -> Type = ' + userProfile.type)
|
||||
continue
|
||||
}
|
||||
/*
|
||||
Validation #4: The message signed at the config is not the Github Username.
|
||||
*/
|
||||
let config = JSON.parse(userProfile.config)
|
||||
let messageSigned = config.signature.message
|
||||
if (messageSigned !== githubUsername) {
|
||||
console.log('[INFO] httpInterface -> Gov -> mergeGithubPullRequests -> Validation #4 Failed -> Pull Request "' + pullRequest.title + '" not merged because the Github Username is not equal to the Message Signed at the User Profile. -> Github Username = ' + githubUsername + '-> messageSigned = ' + messageSigned)
|
||||
|
||||
await sleep(GITHUB_API_WAITING_TIME)
|
||||
await octokit.rest.issues.createComment({
|
||||
owner: owner,
|
||||
repo: repo,
|
||||
issue_number: pullRequest.number,
|
||||
body: 'This Pull Request could not be automatically merged and was closed by the Superalgos Governance System because it was detected that the Github User "' + githubUsername + '" who submitted it, is not equal to the Message Signed at the User Profile.\n\n Message Signed = "' + messageSigned + '"'
|
||||
});
|
||||
|
||||
await sleep(GITHUB_API_WAITING_TIME)
|
||||
await octokit.rest.pulls.update({
|
||||
owner: owner,
|
||||
repo: repo,
|
||||
pull_number: pullRequest.number,
|
||||
state: 'closed'
|
||||
});
|
||||
continue
|
||||
}
|
||||
/*
|
||||
All validations passed, we will proceed an merge this Pull Request.
|
||||
*/
|
||||
await sleep(GITHUB_API_WAITING_TIME)
|
||||
let mergeResponse = await octokit.rest.pulls.merge({
|
||||
owner: owner,
|
||||
repo: repo,
|
||||
pull_number: pullRequest.number,
|
||||
commit_title: 'Changes in User Profile done by Profile Owner ' + githubUsername + ' automatically merged by Superalgos.'
|
||||
});
|
||||
|
||||
if (mergeResponse.data.merged !== true) {
|
||||
console.log('[WARN] httpInterface -> Gov -> mergeGithubPullRequests -> Merge Failed -> Pull Request "' + pullRequest.title + '" not merged because Github could not merge it. -> mergeResponse.message = ' + mergeResponse.data.message)
|
||||
continue
|
||||
} else {
|
||||
console.log('[INFO] httpInterface -> Gov -> mergeGithubPullRequests -> Merge Succed -> Pull Request "' + pullRequest.title + '" successfully merged. -> mergeResponse.message = ' + mergeResponse.data.message)
|
||||
await sleep(GITHUB_API_WAITING_TIME)
|
||||
await octokit.rest.issues.createComment({
|
||||
owner: owner,
|
||||
repo: repo,
|
||||
issue_number: pullRequest.number,
|
||||
body: 'This Pull Request was automatically merged by the Superalgos Governance System because it was detected that the Github User " ' + githubUsername + '" who submitted it, modified its own User Profile Plugin File and nothning else but that file. All validations were successfull.'
|
||||
});
|
||||
continue
|
||||
}
|
||||
}
|
||||
}
|
||||
} catch (err) {
|
||||
console.log('[ERROR] httpInterface -> Gov -> mergeGithubPullRequests -> doGithub -> err.stack = ' + err.stack)
|
||||
}
|
||||
}
|
||||
|
||||
} catch (err) {
|
||||
console.log('[ERROR] httpInterface -> Gov -> mergeGithubPullRequests -> Method call produced an error.')
|
||||
console.log('[ERROR] httpInterface -> Gov -> mergeGithubPullRequests -> err.stack = ' + err.stack)
|
||||
console.log('[ERROR] httpInterface -> Gov -> mergeGithubPullRequests -> repository = ' + repository)
|
||||
console.log('[ERROR] httpInterface -> Gov -> mergeGithubPullRequests -> username = ' + username)
|
||||
console.log('[ERROR] httpInterface -> Gov -> mergeGithubPullRequests -> token starts with = ' + token.substring(0, 10) + '...')
|
||||
console.log('[ERROR] httpInterface -> Gov -> mergeGithubPullRequests -> token ends with = ' + '...' + token.substring(token.length - 10))
|
||||
|
||||
let error = {
|
||||
result: 'Fail Because',
|
||||
message: err.message,
|
||||
stack: err.stack
|
||||
}
|
||||
respondWithContent(JSON.stringify(error), httpResponse)
|
||||
}
|
||||
}
|
||||
|
||||
function payToContributors() {
|
||||
|
||||
}
|
||||
}
|
||||
break
|
||||
|
||||
}
|
||||
case 'LegacyPlotter.js':
|
||||
{
|
||||
respondWithFile(global.env.PATH_TO_CLIENT + 'WebServer/LegacyPlotter.js', httpResponse)
|
||||
@@ -2432,12 +2063,6 @@ exports.newHttpInterface = function newHttpInterface(WEB_SERVER, DATA_FILE_SERVE
|
||||
}
|
||||
}
|
||||
|
||||
function sleep(ms) {
|
||||
return new Promise((resolve) => {
|
||||
setTimeout(resolve, ms)
|
||||
})
|
||||
}
|
||||
|
||||
async function fetchAPIDataFile(url) {
|
||||
let promise = new Promise((resolve, reject) => {
|
||||
|
||||
|
||||
@@ -0,0 +1,14 @@
|
||||
exports.newFoundationsUtilitiesAsyncFunctions = function () {
|
||||
|
||||
let thisObject = {
|
||||
sleep: sleep
|
||||
}
|
||||
|
||||
return thisObject
|
||||
|
||||
function sleep(ms) {
|
||||
return new Promise((resolve) => {
|
||||
setTimeout(resolve, ms)
|
||||
})
|
||||
}
|
||||
}
|
||||
@@ -157,7 +157,10 @@ function newWorkspace() {
|
||||
let workspace = UI.projects.foundations.spaces.designSpace.workspace.workspaceNode
|
||||
|
||||
/* Validation if it is too early to save. */
|
||||
if (thisObject.isInitialized === false) { return }
|
||||
if (thisObject.isInitialized === false) {
|
||||
console.log('Workspace not saved because it has not been initialized. =')
|
||||
return
|
||||
}
|
||||
|
||||
/* Validation of 2 sessions opened at the same time. */
|
||||
let savedSessionTimestamp = window.localStorage.getItem('Session Timestamp')
|
||||
|
||||
@@ -81,12 +81,12 @@
|
||||
"id": "bda21833-11b8-49d3-8c79-ff8e1c667dcc",
|
||||
"savedPayload": {
|
||||
"position": {
|
||||
"x": 31000.07168984726,
|
||||
"y": 23974.264068711924
|
||||
"x": 30936.297332942388,
|
||||
"y": 24042.62315256192
|
||||
},
|
||||
"targetPosition": {
|
||||
"x": 30787.939655491296,
|
||||
"y": 23762.13203435596
|
||||
"x": 30747.501215627435,
|
||||
"y": 23809.47936412483
|
||||
},
|
||||
"floatingObject": {
|
||||
"isPinned": false,
|
||||
@@ -114,7 +114,7 @@
|
||||
"floatingObject": {
|
||||
"isPinned": false,
|
||||
"isFrozen": false,
|
||||
"isCollapsed": true,
|
||||
"isCollapsed": false,
|
||||
"angleToParent": 3,
|
||||
"distanceToParent": 3,
|
||||
"arrangementStyle": 0
|
||||
|
||||
@@ -31,7 +31,7 @@ function newGovernanceFunctionLibraryProfileConstructor() {
|
||||
entropy: node.id + (new Date()).valueOf()
|
||||
}
|
||||
|
||||
let url = 'WEB3' // we don't need to ask this to any specific superalgos node.
|
||||
let url = 'WEB3' // We will access the default Client WEB3 endpoint.
|
||||
|
||||
httpRequest(JSON.stringify(params), url, onResponse)
|
||||
|
||||
|
||||
@@ -41,6 +41,10 @@ function newGovernanceReportsCommmandInterface() {
|
||||
message = 'Automated PR merging process.'
|
||||
}
|
||||
|
||||
/* Closing the Governance Tab */
|
||||
UI.projects.governance.spaces.reportsSpace.sidePanelTab.close()
|
||||
UI.projects.education.spaces.docsSpace.sidePanelTab.open()
|
||||
|
||||
/* Find the Username and Password */
|
||||
let apisNode = UI.projects.foundations.spaces.designSpace.workspace.getHierarchyHeadByNodeType('APIs')
|
||||
if (apisNode === undefined) {
|
||||
@@ -62,36 +66,53 @@ function newGovernanceReportsCommmandInterface() {
|
||||
return
|
||||
}
|
||||
|
||||
UI.projects.education.spaces.docsSpace.navigateTo('Governance', 'Topic', 'Gov Message - Processing Pull Requests')
|
||||
|
||||
message = message.replaceAll('#', '_HASHTAG_')
|
||||
message = message.replaceAll('/', '_SLASH_')
|
||||
|
||||
httpRequest(
|
||||
undefined,
|
||||
'Gov/PRs/' +
|
||||
message + '/' +
|
||||
config.username + '/' +
|
||||
config.token + '/' +
|
||||
UI.projects.education.spaces.docsSpace.currentBranch + '/' +
|
||||
UI.projects.education.spaces.docsSpace.contributionsBranch
|
||||
, onResponse)
|
||||
/* Lets execute this command against the Client */
|
||||
|
||||
UI.projects.education.spaces.docsSpace.navigateTo('Governance', 'Topic', 'Gov Message - Processing Pull Requests')
|
||||
let params = {
|
||||
method: 'mergePullRequests',
|
||||
commitMessage: message,
|
||||
username: config.username,
|
||||
token: config.token
|
||||
}
|
||||
|
||||
return
|
||||
let url = 'GOV' // We will access the default Client GOV endpoint.
|
||||
|
||||
httpRequest(JSON.stringify(params), url, onResponse)
|
||||
|
||||
function onResponse(err, data) {
|
||||
|
||||
/* Lets check the result of the call through the http interface */
|
||||
data = JSON.parse(data)
|
||||
if (err.result === GLOBAL.DEFAULT_OK_RESPONSE.result && data.result === GLOBAL.DEFAULT_OK_RESPONSE.result) {
|
||||
if (err.result !== GLOBAL.DEFAULT_OK_RESPONSE.result) {
|
||||
console.log('[ERROR] Call via HTTP Interface failed.' + err.stack)
|
||||
console.log('[ERROR] Params = ' + JSON.stringify(params))
|
||||
return
|
||||
}
|
||||
|
||||
let response = JSON.parse(data)
|
||||
|
||||
/* Lets check the result of the method call */
|
||||
if (response.result !== GLOBAL.DEFAULT_OK_RESPONSE.result) {
|
||||
console.log('[ERROR] Call to Client Github Server failed.' + err.stack)
|
||||
console.log('[ERROR] Params = ' + JSON.stringify(params))
|
||||
}
|
||||
|
||||
/* Successful Call */
|
||||
|
||||
if (response.result === GLOBAL.DEFAULT_OK_RESPONSE.result) {
|
||||
UI.projects.education.spaces.docsSpace.navigateTo('Governance', 'Topic', 'Gov Message - Pull Requests Processed')
|
||||
} else {
|
||||
UI.projects.education.spaces.docsSpace.navigateTo(
|
||||
data.docs.project,
|
||||
data.docs.category,
|
||||
data.docs.type,
|
||||
data.docs.anchor,
|
||||
response.docs.project,
|
||||
response.docs.category,
|
||||
response.docs.type,
|
||||
response.docs.anchor,
|
||||
undefined,
|
||||
data.docs.placeholder
|
||||
response.docs.placeholder
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -231,15 +231,6 @@ function newGobernanceReportsSpace() {
|
||||
'width: ' + thisObject.container.frame.width + 'px;' +
|
||||
'height: ' + thisObject.container.frame.height + 'px'
|
||||
}
|
||||
|
||||
/*
|
||||
Monitor the Docs Space to see if its tab is opened, to close this space tab.
|
||||
*/
|
||||
if (UI.projects.education.spaces.docsSpace.sidePanelTab.isOpen === true &&
|
||||
thisObject.sidePanelTab.isOpen === true
|
||||
) {
|
||||
thisObject.sidePanelTab.close()
|
||||
}
|
||||
}
|
||||
|
||||
function getContainer(point, purpose) {
|
||||
|
||||
@@ -37,7 +37,7 @@ function newGovernanceUserProfileSpace() {
|
||||
If the workspace is not related to governance, then we exit the Intialize Function
|
||||
*/
|
||||
let resultsArary = UI.projects.foundations.spaces.designSpace.workspace.getHierarchyHeadsByNodeType('User Profile')
|
||||
if (resultsArary.length === 0 || resultsArary.length === 1) { return }
|
||||
if (resultsArary.length === 0) { return }
|
||||
|
||||
/* Find the Username and Password */
|
||||
|
||||
@@ -68,69 +68,135 @@ function newGovernanceUserProfileSpace() {
|
||||
requestStars()
|
||||
|
||||
function requestStars() {
|
||||
httpRequest(
|
||||
undefined,
|
||||
'Gov/getGithubStars/' +
|
||||
'Superalgos' + '/' +
|
||||
config.username + '/' +
|
||||
config.token
|
||||
, onGithubStarsResponse)
|
||||
|
||||
let params = {
|
||||
method: 'getGithubStars',
|
||||
repository: 'Superalgos',
|
||||
username: config.username,
|
||||
token: config.token
|
||||
}
|
||||
|
||||
let url = 'GOV' // We will access the default Client GOV endpoint.
|
||||
|
||||
httpRequest(JSON.stringify(params), url, onResponse)
|
||||
|
||||
function onResponse(err, data) {
|
||||
|
||||
/* Lets check the result of the call through the http interface */
|
||||
if (err.result !== GLOBAL.DEFAULT_OK_RESPONSE.result) {
|
||||
console.log('[ERROR] Call via HTTP Interface failed. err.stack = ' + err.stack)
|
||||
console.log('[ERROR] params = ' + JSON.stringify(params))
|
||||
return
|
||||
}
|
||||
|
||||
let response = JSON.parse(data)
|
||||
|
||||
/* Lets check the result of the method call */
|
||||
if (response.result !== GLOBAL.DEFAULT_OK_RESPONSE.result) {
|
||||
console.log('[ERROR] Call to Client Github Server failed. err.stack = ' + err.stack)
|
||||
console.log('[ERROR] params = ' + JSON.stringify(params))
|
||||
console.log('[ERROR] response = ' + JSON.stringify(response))
|
||||
return
|
||||
}
|
||||
|
||||
/* Successful Call */
|
||||
|
||||
let githubStarsArray = response.githubListArray
|
||||
|
||||
for (let i = 0; i < githubStarsArray.length; i++) {
|
||||
let githubUsername = githubStarsArray[i]
|
||||
thisObject.githubStars.set(githubUsername, 1)
|
||||
}
|
||||
|
||||
requestWatchers()
|
||||
}
|
||||
}
|
||||
|
||||
function requestWatchers() {
|
||||
httpRequest(
|
||||
undefined,
|
||||
'Gov/getGithubWatchers/' +
|
||||
'Superalgos' + '/' +
|
||||
config.username + '/' +
|
||||
config.token
|
||||
, onGithubWatchersResponse)
|
||||
|
||||
let params = {
|
||||
method: 'getGithubWatchers',
|
||||
repository: 'Superalgos',
|
||||
username: config.username,
|
||||
token: config.token
|
||||
}
|
||||
|
||||
let url = 'GOV' // We will access the default Client GOV endpoint.
|
||||
|
||||
httpRequest(JSON.stringify(params), url, onResponse)
|
||||
|
||||
function onResponse(err, data) {
|
||||
|
||||
/* Lets check the result of the call through the http interface */
|
||||
if (err.result !== GLOBAL.DEFAULT_OK_RESPONSE.result) {
|
||||
console.log('[ERROR] Call via HTTP Interface failed. err.stack = ' + err.stack)
|
||||
console.log('[ERROR] params = ' + JSON.stringify(params))
|
||||
return
|
||||
}
|
||||
|
||||
let response = JSON.parse(data)
|
||||
|
||||
/* Lets check the result of the method call */
|
||||
if (response.result !== GLOBAL.DEFAULT_OK_RESPONSE.result) {
|
||||
console.log('[ERROR] Call to Client Github Server failed. err.stack = ' + err.stack)
|
||||
console.log('[ERROR] params = ' + JSON.stringify(params))
|
||||
console.log('[ERROR] response = ' + JSON.stringify(response))
|
||||
return
|
||||
}
|
||||
|
||||
/* Successful Call */
|
||||
|
||||
let githubWatchersArray = response.githubListArray
|
||||
|
||||
for (let i = 0; i < githubWatchersArray.length; i++) {
|
||||
let githubUsername = githubWatchersArray[i]
|
||||
thisObject.githubWatchers.set(githubUsername, 1)
|
||||
}
|
||||
|
||||
requestForks()
|
||||
}
|
||||
}
|
||||
|
||||
function requestForks() {
|
||||
httpRequest(
|
||||
undefined,
|
||||
'Gov/getGithubForks/' +
|
||||
'Superalgos' + '/' +
|
||||
config.username + '/' +
|
||||
config.token
|
||||
, onGithubForksResponse)
|
||||
}
|
||||
|
||||
function onGithubStarsResponse(err, githubData) {
|
||||
//console.log(githubData)
|
||||
/* Lets check the result of the call through the http interface */
|
||||
let githubStarsArray = JSON.parse(githubData)
|
||||
|
||||
for (let i = 0; i < githubStarsArray.length; i++) {
|
||||
let githubUsername = githubStarsArray[i]
|
||||
thisObject.githubStars.set(githubUsername, 1)
|
||||
let params = {
|
||||
method: 'getGithubForks',
|
||||
repository: 'Superalgos',
|
||||
username: config.username,
|
||||
token: config.token
|
||||
}
|
||||
|
||||
requestWatchers()
|
||||
}
|
||||
let url = 'GOV' // We will access the default Client GOV endpoint.
|
||||
|
||||
function onGithubWatchersResponse(err, githubData) {
|
||||
//console.log(githubData)
|
||||
/* Lets check the result of the call through the http interface */
|
||||
let githubWatchersArray = JSON.parse(githubData)
|
||||
httpRequest(JSON.stringify(params), url, onResponse)
|
||||
|
||||
for (let i = 0; i < githubWatchersArray.length; i++) {
|
||||
let githubUsername = githubWatchersArray[i]
|
||||
thisObject.githubWatchers.set(githubUsername, 1)
|
||||
}
|
||||
function onResponse(err, data) {
|
||||
|
||||
requestForks()
|
||||
}
|
||||
/* Lets check the result of the call through the http interface */
|
||||
if (err.result !== GLOBAL.DEFAULT_OK_RESPONSE.result) {
|
||||
console.log('[ERROR] Call via HTTP Interface failed. err.stack = ' + err.stack)
|
||||
console.log('[ERROR] params = ' + JSON.stringify(params))
|
||||
return
|
||||
}
|
||||
|
||||
function onGithubForksResponse(err, githubData) {
|
||||
//console.log(githubData)
|
||||
/* Lets check the result of the call through the http interface */
|
||||
let githubForksArray = JSON.parse(githubData)
|
||||
let response = JSON.parse(data)
|
||||
|
||||
for (let i = 0; i < githubForksArray.length; i++) {
|
||||
let githubUsername = githubForksArray[i]
|
||||
thisObject.githubForks.set(githubUsername, 1)
|
||||
/* Lets check the result of the method call */
|
||||
if (response.result !== GLOBAL.DEFAULT_OK_RESPONSE.result) {
|
||||
console.log('[ERROR] Call to Client Github Server failed. err.stack = ' + err.stack)
|
||||
console.log('[ERROR] params = ' + JSON.stringify(params))
|
||||
console.log('[ERROR] response = ' + JSON.stringify(response))
|
||||
return
|
||||
}
|
||||
|
||||
/* Successful Call */
|
||||
|
||||
let githubForksArray = response.githubListArray
|
||||
|
||||
for (let i = 0; i < githubForksArray.length; i++) {
|
||||
let githubUsername = githubForksArray[i]
|
||||
thisObject.githubForks.set(githubUsername, 1)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -871,7 +871,16 @@
|
||||
}
|
||||
]
|
||||
},
|
||||
"CL": {},
|
||||
"CL": {
|
||||
"utilities": [
|
||||
{
|
||||
"name": "Async Function",
|
||||
"propertyName": "asyncFunctions",
|
||||
"functionName": "newFoundationsUtilitiesAsyncFunctions",
|
||||
"fileName": "AsyncFunctions.js"
|
||||
}
|
||||
]
|
||||
},
|
||||
"plugins": [
|
||||
"Data Mines",
|
||||
"Trading Mines",
|
||||
|
||||
@@ -31,6 +31,8 @@ exports.newMultiProject = function () {
|
||||
projectInstance.processModules = {}
|
||||
projectInstance.botModules = {}
|
||||
|
||||
if (projectDefinition.TS === undefined) { continue }
|
||||
|
||||
/* Set up Utilities of this Project */
|
||||
if (projectDefinition.TS.utilities !== undefined) {
|
||||
for (let j = 0; j < projectDefinition.TS.utilities.length; j++) {
|
||||
|
||||
Reference in new issue
Block a user