From 3432bb3b8242934e22f1dedb0d974881b77a2ff4 Mon Sep 17 00:00:00 2001 From: kdsbatra Date: Thu, 8 Jul 2021 15:20:00 -0400 Subject: [PATCH 01/21] allowing multiple repo push --- index.js | 264 ++++++++++++++++++++++++++++++++++++------------- repos.js | 12 +++ studentList.js | 38 ++++--- 3 files changed, 226 insertions(+), 88 deletions(-) create mode 100644 repos.js diff --git a/index.js b/index.js index a3f6042..1c4966d 100644 --- a/index.js +++ b/index.js @@ -3,15 +3,21 @@ const { studentList } = require("./studentList"); +let { + repoDetails +} = require("./repos.js"); + // Import inquirer to make shell interactive const inquirer = require("inquirer"); // Import env file and all variables -require("dotenv").config(); -const assignmentUrl = process.env.ASSIGNMENT; -const repoName = process.env.REPONAME; +const dotenv = require('dotenv') +dotenv.config(); + +const opt = { debug: true } +//const assignments = JSON.parse(dotenv.parse(Buffer.from(process.env.ASSIGNMENTS), opt)["REPOS"]); const token = process.env.TOKEN; -const githubUser = process.env.USERNAME; +const githubUser = process.env.GITUSER; const slackToken = process.env.SLACKTOKEN; // Import Axios for HTTP requests @@ -26,100 +32,224 @@ const { } = require("@slack/web-api"); const slack = new WebClient(slackToken); -const checkReposSilent = () => { - // create for loop to check all student repos and see if they exist - studentList.forEach((student) => { - // Do an HTTP get on each students supposed repo - axios.get(`https://github.com/${student.github}/${repoName}`).then( +repoDetails = repoDetails.filter(repoDetail => !repoDetail.skip); + +function matchedRepoDetails(repos, selectedRepos) { + + let allReposFiltered = []; + selectedRepos.forEach(repoName => { + let reposFiltered = repos.filter(repo => repo.name === repoName); + if (reposFiltered.length === 1) { + allReposFiltered.push(reposFiltered[0]); + } else { + console.log(`repo details for ${repoName} not found`); + } + }) + return allReposFiltered; +} + +const checkRepo = (student, repoName, slackAlert, callback, failureCallBack) => { + return axios.get(`https://github.com/${student.github}/${repoName}`) + .then( (response) => { - console.log(`\x1b[32m ${student.github} has made their repo!`) + console.log(`\x1b[32m ${student.github} has made their '${repoName}' repo!`); + if (callback) { + callback(); + } }, (error) => { - console.log(`\x1b[31m ${student.github} has not made the repo yet.`); + if (slackAlert) { + sendMessage(student.slack, repoName); + } + console.log(`\x1b[31m ${student.github} has not made their '${repoName}' repo yet.` + (slackAlert ? ' Alert sent.' : '')); + if (failureCallBack) { + failureCallBack(); + } } - ); - }); -}; + ) +} -const checkReposAlert = () => { +const checkRepos = (reposSelected, i, slackAlert) => { // create for loop to check all student repos and see if they exist + + const repoName = reposSelected[i].name; + + console.log(`\x1b[33m ======= checking if '${repoName}' repo exists =======\n`); + + let promises = []; studentList.forEach((student) => { // Do an HTTP get on each students supposed repo - axios.get(`https://github.com/${student.github}/${repoName}`).then( - (response) => { - console.log(`\x1b[32m ${student.github} has made their repo!`); - }, - (error) => { - sendMessage(student.slack); - console.log(`\x1b[31m ${student.github} has not made the repo yet. Alert sent.`); + promises.push(checkRepo(student, repoName, slackAlert)); + }); + + // continue to next repo + Promise.allSettled(promises).then((results) => { + i++; + if (reposSelected[i]) { + checkRepos(reposSelected, i, slackAlert); + } else { + console.log(`\n\x1b[33m =============== FINISHED ==============`); + } + + }); +}; + +const cloneAndPushAssignments = (allSelectedRepos, i) => { + + let repoName = allSelectedRepos[i].name; + let repoUrl = allSelectedRepos[i].url; + + console.log(`\n ==================================================`); + console.log(`\n===== Going to try cloning repo '${repoName}' ====`); + + let { stdoutClone, stderrClone, codeClone } = shell.exec(`git clone ${repoUrl}`, { silent: true }); + if (stderrClone) { + console.log(`Could not clone ${repoUrl}`, stderrClone); + } + + // Change branch to main as this is new Github default + shell.cd(`${repoName}`); + let { stdoutCheckout, stderrCheckout, codeCheckout } = shell.exec("git checkout -b main", { silent: true }); + if (stderrCheckout) { + console.log(`Could not crete and switch to main branch`, stderrCheckout); + } + + console.log(`\n===== Going to try pushing repo '${repoName}' ====`); + pushRepoToStudents(repoName, allSelectedRepos[i + 1]); + + shell.exec("cd .."); + + // continue to next repo + i++ + if (allSelectedRepos[i]) { + cloneAndPushAssignments(allSelectedRepos, i); + } +} + + +const pushRepoToStudents = (repoName, hasNext) => { + + // Create a forloop to go through each student + let promises = []; + studentList.forEach((student) => { + + promises.push(checkRepo(student, repoName, false, () => { + // First create a URL using the student's username and the repo name + const studentUrl = `https://github.com/${student.github}/${repoName}.git`; + + // Force a push of the assignment main repo + + let { stdout, stderr, code } = shell.exec(`git push ${studentUrl} --force`, { silent: true }); + if (stderr) { + console.log(`\x1b[31m Could not push code to ${student.github} at ${studentUrl}. Error: ${stderr}`); + //console.log(`\x1b[31m Could not push code to ${student.github} at ${studentUrl}, Maybe they have not yet made the repo yet or you are not collabator on it`); } - ); + })); + + }); + + Promise.allSettled(promises).then((result) => { + if (!hasNext) { + console.log(`\n \x1b[32m ============ FINISHED pushing ${repoName} ============`); + } }); }; // Function to clone assignment locally -const cloneAssignment = () => { +const setupRepos = (allSelectedRepos) => { + // Setup github authentication so you have access to stack education shell.exec(`git config --global user.name "${githubUser}"`); shell.exec(`git config --global user.password "${token}"`); // First remove the repo folder and remake it empty - shell.exec("rm -rf repo"); + shell.rm("-rf", "repo"); shell.exec("mkdir repo"); - // Now clone the repo into that folder + // Now clone the repo into repo folder shell.cd("repo"); - shell.exec(`git clone ${assignmentUrl}`); - // Change branch to main as this is new Github default - shell.cd(`${repoName}`); - shell.exec("git checkout -b main"); -}; - -const pushToStudents = () => { - // Create a forloop to go through each student - studentList.forEach((student) => { - // First create a URL using the student's username and the repo name - const studentUrl = `https://github.com/${student.github}/${repoName}.git`; - - // Force a push of the assignment main repo - shell.exec(`git push ${studentUrl} --force`); - }); + cloneAndPushAssignments(allSelectedRepos, 0); }; // Function that controls interactivity const promptUser = () => { // Prompt the user to see what kind of app needs to run inquirer - .prompt([{ - name: "option", - type: "list", - message: "Please select your operation.", - choices: [ - "1: Privately check if student repos exist. (No Slack message reminder).", - "2: Check if student repos exist. (With Slack message reminder).", - "3: Push assignment repo to students.", - "4: Exit application.", - ], - }, ]) + .prompt([ + { + name: "repoOptions", + type: "checkbox", + message: "Please select repos you want to check", + choices: ["exit", "all", new inquirer.Separator()].concat(repoDetails), + default: ["all"] + }, + { + name: "option", + type: "list", + message: "Please select your operation.", + when: (answers) => { + if (answers.repoOptions == "none" || !answers.repoOptions.length) { + return false; + } + return true; + }, + choices: [ + "1: Privately check if student repos exist. (No Slack message reminder).", + "2: Check if student repos exist. (With Slack message reminder).", + "3: Push assignment repo to students.", + "4: Exit application.", + ], + },]) // Then either check the repos or clone/push the assignment - .then((answer) => { + .then((answers) => { + + let reposSelectedByName = answers.repoOptions; + let allReposFiltered = repoDetails; + + console.log(` Repos selected: ${answers.repoOptions}\n`); // If option 1 is selected so a silent check. + if (reposSelectedByName == "exit") { + return; + + } else if (!reposSelectedByName.length) { + console.log(`\x1b[33m Nothing was selected, Exiting`); + return; + + } else if (reposSelectedByName.indexOf("all") > -1) { + if (reposSelectedByName.length > 1) { + console.log(`\x1b[33m All Repos selected, will ignore other options`); + } + + } else { + let exitSelected = reposSelectedByName.indexOf("exit"); + if (exitSelected > -1 && reposSelectedByName.length > 1) {//dont really need to check size here again + console.log(`\x1b[33m Exit was selected along specific repos, ignoring Exit`); + + reposSelectedByName.splice(exitSelected, 1); + } + + allReposFiltered = matchedRepoDetails(repoDetails, reposSelectedByName); + + if (allReposFiltered.length !== reposSelectedByName.length) { + console.log(`Some repo URL is not found, found items include: [${allReposFiltered}] and repoNames selected were [${reposSelectedByName}]`) + return; + } + } + + if ( - answer.option == - "1: Privately check if student repos exist. (No Slack message reminder)." - ) { - checkReposSilent(); + answers.option == "1: Privately check if student repos exist. (No Slack message reminder).") { + checkRepos(allReposFiltered, 0, false); + // If Option 2 is selected do an alerting check. - } else if ( - answer.option == - "2: Check if student repos exist. (With Slack message reminder)." - ) { - checkReposAlert(); + } else if (answers.option == "2: Check if student repos exist. (With Slack message reminder).") { + checkRepos(allReposFiltered, 0, true); + // If option 3 is selected then clone the assignment then push. - } else if (answer.option == "3: Push assignment repo to students.") { - cloneAssignment(); - pushToStudents(); + } else if (answers.option == "3: Push assignment repo to students.") { + setupRepos(allReposFiltered); + // If option 4 is selected then exit the app. } else { return; @@ -127,12 +257,12 @@ const promptUser = () => { }); }; -const sendMessage = (slackId) => { +const sendMessage = (slackId, repoName) => { // Connect to slack and post the reminder message using the slackId provided. (async () => { const result = await slack.chat.postMessage({ channel: slackId, - text: `Your repo was not found. Please create the following repo on Github. If you have created the repo please check the spelling or make the repo public. \n \n *Repo Name:* \n \`${repoName}\``, + text: `Your repo was not found. Please create the following repo on Github. If you have created the repo please check the spelling or make the repo public. \n \n *Repo Name:* \n \`${repoName}\` \n \n Then please add \`${githubUser}\` as a collaborator`, }); })(); }; diff --git a/repos.js b/repos.js new file mode 100644 index 0000000..1af3cc7 --- /dev/null +++ b/repos.js @@ -0,0 +1,12 @@ +const repoDetails = [{ + url: "https://github.com/stackeducation/fantasy-scoring.git", + name: "fantasy-scoring", + skip: false + }, + { + url: "https://github.com/stackeducation/order-book.git", + name: "order-book", + skip: true + }]; + +module.exports = {repoDetails}; \ No newline at end of file diff --git a/studentList.js b/studentList.js index 37fb747..7e0e77c 100644 --- a/studentList.js +++ b/studentList.js @@ -1,25 +1,21 @@ const studentList = [ - { github: "andyschachter", slack: "U01NMC0SZ27" }, - { github: "annie-i0", slack: "U01NECMJMJS" }, - { github: "smithci1", slack: "U01NMC0DDQB" }, - { github: "bellusvulpes", slack: "U01PB1A0Q64" }, - { github: "Danielamoateng1989", slack: "U01N6CNM8GP" }, - { github: "davepenaloza", slack: "U01NMC0FBFV" }, - { github: "firizarry-coder", slack: "U01PFUUJY8G" }, - { github: "gioaceto", slack: "U01NJ6LMVNJ" }, - { github: "jeraldina", slack: "U01NECMLJKG" }, - { github: "grimmi5894", slack: "U01NECMNP54" }, - { github: "keefers1030", slack: "U01NMC0USAF" }, - { github: "kolbycamp211", slack: "U01NMC16NUT" }, - { github: "lamsa01", slack: "U01NMC12ZB5" }, - { github: "mardany126", slack: "U01NECMDXE2" }, - { github: "misheline", slack: "U01NMC0PD51" }, - { github: "oaklanz", slack: "U01NMC0LBBM" }, - { github: "robinmalkus", slack: "U01NQUVF85Q" }, - { github: "pathou80", slack: "U01PB1ATD5W" }, - { github: "larocque-m", slack: "U01NECKHL4E" }, - { github: "markh82581", slack: "U01NMC0GUV9" }, - { github: "marnie-k", slack: "U01NMC0GUV9" }, + { github: "kdsbatra", slack: "U0246KNS2KB" }, + { github: "brnjackson", slack: "U023U8NK89Z" }, + { github: "Cpluchak", slack: "U0246LJV90R" }, + { github: "Forensicrose", slack: "U0246LKG6E5" }, + { github: "jeraldina", slack: "U0246LK6D33" }, + { github: "kjmatt91", slack: "U0246LJTD97" }, + { github: "katskurka", slack: "U023Z44D690" }, + { github: "KevinSalina", slack: "U023V2RJA7P" }, + { github: "mhafez1978", slack: "U023R04GK1B" }, + { github: "RubyDF", slack: "U0246LKC43T" }, + { github: "sherryliztynan", slack: "U0246LJAMS5" }, + + // { github: "reinhal", slack: "U023U7T8RD1" }, + // { github: "StandyMerizier", slack: "U023QUP3KEZ" }, + // { github: "josephpjacobi", slack: "U0246KP1XL1" }, + // { github: "itsdanielguerrero@gmail.com" , slack: "U023D89UMAT" } + // { github: "hollisjamison", slack: "U01NMC0RD3M" }, // { github: "mikaelacurrier", slack: "U01N6CM60UX" }, // { github: "sebastian-vivas", slack: "U01NECMH4T0" }, From 4bbc9b41c7d2655c0d7b8eb1b7574e359aab43a4 Mon Sep 17 00:00:00 2001 From: kdsbatra Date: Thu, 8 Jul 2021 15:25:24 -0400 Subject: [PATCH 02/21] renaming variables and funtion --- index.js | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/index.js b/index.js index 1c4966d..8227bc7 100644 --- a/index.js +++ b/index.js @@ -34,7 +34,7 @@ const slack = new WebClient(slackToken); repoDetails = repoDetails.filter(repoDetail => !repoDetail.skip); -function matchedRepoDetails(repos, selectedRepos) { +function findRepoDetailsByName(repos, selectedRepos) { let allReposFiltered = []; selectedRepos.forEach(repoName => { @@ -229,7 +229,7 @@ const promptUser = () => { reposSelectedByName.splice(exitSelected, 1); } - allReposFiltered = matchedRepoDetails(repoDetails, reposSelectedByName); + allReposFiltered = findRepoDetailsByName(repoDetails, reposSelectedByName); if (allReposFiltered.length !== reposSelectedByName.length) { console.log(`Some repo URL is not found, found items include: [${allReposFiltered}] and repoNames selected were [${reposSelectedByName}]`) From a1ff3ffa229a631095de2637a4071b69e3d503ec Mon Sep 17 00:00:00 2001 From: kdsbatra Date: Thu, 8 Jul 2021 15:27:52 -0400 Subject: [PATCH 03/21] renaming variables and funtion --- index.js | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/index.js b/index.js index 8227bc7..9c8e635 100644 --- a/index.js +++ b/index.js @@ -34,10 +34,10 @@ const slack = new WebClient(slackToken); repoDetails = repoDetails.filter(repoDetail => !repoDetail.skip); -function findRepoDetailsByName(repos, selectedRepos) { +function findRepoDetailsByName(repos, repoNames) { let allReposFiltered = []; - selectedRepos.forEach(repoName => { + repoNames.forEach(repoName => { let reposFiltered = repos.filter(repo => repo.name === repoName); if (reposFiltered.length === 1) { allReposFiltered.push(reposFiltered[0]); @@ -69,7 +69,7 @@ const checkRepo = (student, repoName, slackAlert, callback, failureCallBack) => ) } -const checkRepos = (reposSelected, i, slackAlert) => { +const checkReposContinuously = (reposSelected, i, slackAlert) => { // create for loop to check all student repos and see if they exist const repoName = reposSelected[i].name; @@ -86,7 +86,7 @@ const checkRepos = (reposSelected, i, slackAlert) => { Promise.allSettled(promises).then((results) => { i++; if (reposSelected[i]) { - checkRepos(reposSelected, i, slackAlert); + checkReposContinuously(reposSelected, i, slackAlert); } else { console.log(`\n\x1b[33m =============== FINISHED ==============`); } @@ -240,11 +240,11 @@ const promptUser = () => { if ( answers.option == "1: Privately check if student repos exist. (No Slack message reminder).") { - checkRepos(allReposFiltered, 0, false); + checkReposContinuously(allReposFiltered, 0, false); // If Option 2 is selected do an alerting check. } else if (answers.option == "2: Check if student repos exist. (With Slack message reminder).") { - checkRepos(allReposFiltered, 0, true); + checkReposContinuously(allReposFiltered, 0, true); // If option 3 is selected then clone the assignment then push. } else if (answers.option == "3: Push assignment repo to students.") { From 3fe860884e19c470175080d2893a2fe2d7ee91c8 Mon Sep 17 00:00:00 2001 From: kdsbatra Date: Thu, 8 Jul 2021 15:28:32 -0400 Subject: [PATCH 04/21] renaming variables and funtion --- index.js | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/index.js b/index.js index 9c8e635..d1e5f3c 100644 --- a/index.js +++ b/index.js @@ -94,7 +94,7 @@ const checkReposContinuously = (reposSelected, i, slackAlert) => { }); }; -const cloneAndPushAssignments = (allSelectedRepos, i) => { +const cloneAndPushRepos = (allSelectedRepos, i) => { let repoName = allSelectedRepos[i].name; let repoUrl = allSelectedRepos[i].url; @@ -122,7 +122,7 @@ const cloneAndPushAssignments = (allSelectedRepos, i) => { // continue to next repo i++ if (allSelectedRepos[i]) { - cloneAndPushAssignments(allSelectedRepos, i); + cloneAndPushRepos(allSelectedRepos, i); } } @@ -169,7 +169,7 @@ const setupRepos = (allSelectedRepos) => { // Now clone the repo into repo folder shell.cd("repo"); - cloneAndPushAssignments(allSelectedRepos, 0); + cloneAndPushRepos(allSelectedRepos, 0); }; // Function that controls interactivity From 72cac48171fa4f8c82b91d8c8d8c0171e96bc4b8 Mon Sep 17 00:00:00 2001 From: kdsbatra Date: Thu, 8 Jul 2021 15:32:18 -0400 Subject: [PATCH 05/21] ignore scoring by default, refactor minor --- index.js | 39 +++++++++++++++++++++------------------ repos.js | 4 ++-- 2 files changed, 23 insertions(+), 20 deletions(-) diff --git a/index.js b/index.js index d1e5f3c..b974870 100644 --- a/index.js +++ b/index.js @@ -172,6 +172,25 @@ const setupRepos = (allSelectedRepos) => { cloneAndPushRepos(allSelectedRepos, 0); }; + +const execute = (option, allReposFiltered) => { + if ( + option == "1: Privately check if student repos exist. (No Slack message reminder).") { + checkReposContinuously(allReposFiltered, 0, false); + + // If Option 2 is selected do an alerting check. + } else if (option == "2: Check if student repos exist. (With Slack message reminder).") { + checkReposContinuously(allReposFiltered, 0, true); + + // If option 3 is selected then clone the assignment then push. + } else if (option == "3: Push assignment repo to students.") { + setupRepos(allReposFiltered); + + // If option 4 is selected then exit the app. + } + return; +} + // Function that controls interactivity const promptUser = () => { // Prompt the user to see what kind of app needs to run @@ -236,24 +255,8 @@ const promptUser = () => { return; } } - - - if ( - answers.option == "1: Privately check if student repos exist. (No Slack message reminder).") { - checkReposContinuously(allReposFiltered, 0, false); - - // If Option 2 is selected do an alerting check. - } else if (answers.option == "2: Check if student repos exist. (With Slack message reminder).") { - checkReposContinuously(allReposFiltered, 0, true); - - // If option 3 is selected then clone the assignment then push. - } else if (answers.option == "3: Push assignment repo to students.") { - setupRepos(allReposFiltered); - - // If option 4 is selected then exit the app. - } else { - return; - } + + execute(answers.option, allReposFiltered); }); }; diff --git a/repos.js b/repos.js index 1af3cc7..a939240 100644 --- a/repos.js +++ b/repos.js @@ -1,12 +1,12 @@ const repoDetails = [{ url: "https://github.com/stackeducation/fantasy-scoring.git", name: "fantasy-scoring", - skip: false + skip: true }, { url: "https://github.com/stackeducation/order-book.git", name: "order-book", - skip: true + skip: false }]; module.exports = {repoDetails}; \ No newline at end of file From 5d39583168da8898a1d1b5431c029dec5a7448c6 Mon Sep 17 00:00:00 2001 From: kdsbatra Date: Thu, 8 Jul 2021 15:32:45 -0400 Subject: [PATCH 06/21] renaming variables and funtion --- index.js | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/index.js b/index.js index b974870..f712c9e 100644 --- a/index.js +++ b/index.js @@ -173,7 +173,7 @@ const setupRepos = (allSelectedRepos) => { }; -const execute = (option, allReposFiltered) => { +const process = (option, allReposFiltered) => { if ( option == "1: Privately check if student repos exist. (No Slack message reminder).") { checkReposContinuously(allReposFiltered, 0, false); @@ -256,7 +256,7 @@ const promptUser = () => { } } - execute(answers.option, allReposFiltered); + process(answers.option, allReposFiltered); }); }; From 5f28c042988179a4a2711c72420e27e22e627a44 Mon Sep 17 00:00:00 2001 From: kdsbatra Date: Thu, 8 Jul 2021 15:55:46 -0400 Subject: [PATCH 07/21] renaming variables and funtion --- index.js | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/index.js b/index.js index f712c9e..2623056 100644 --- a/index.js +++ b/index.js @@ -16,9 +16,9 @@ dotenv.config(); const opt = { debug: true } //const assignments = JSON.parse(dotenv.parse(Buffer.from(process.env.ASSIGNMENTS), opt)["REPOS"]); -const token = process.env.TOKEN; -const githubUser = process.env.GITUSER; -const slackToken = process.env.SLACKTOKEN; +const token = processByOption.env.TOKEN; +const githubUser = processByOption.env.GITUSER; +const slackToken = processByOption.env.SLACKTOKEN; // Import Axios for HTTP requests const axios = require("axios"); @@ -173,7 +173,7 @@ const setupRepos = (allSelectedRepos) => { }; -const process = (option, allReposFiltered) => { +const processByOption = (option, allReposFiltered) => { if ( option == "1: Privately check if student repos exist. (No Slack message reminder).") { checkReposContinuously(allReposFiltered, 0, false); @@ -256,7 +256,7 @@ const promptUser = () => { } } - process(answers.option, allReposFiltered); + processByOption(answers.option, allReposFiltered); }); }; From 54ed152b9b77adc7d55eaf4a026ec525817c6668 Mon Sep 17 00:00:00 2001 From: kdsbatra Date: Thu, 8 Jul 2021 15:56:36 -0400 Subject: [PATCH 08/21] renaming variables and funtion --- index.js | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/index.js b/index.js index 2623056..97ebcb9 100644 --- a/index.js +++ b/index.js @@ -16,9 +16,9 @@ dotenv.config(); const opt = { debug: true } //const assignments = JSON.parse(dotenv.parse(Buffer.from(process.env.ASSIGNMENTS), opt)["REPOS"]); -const token = processByOption.env.TOKEN; -const githubUser = processByOption.env.GITUSER; -const slackToken = processByOption.env.SLACKTOKEN; +const token = process.env.TOKEN; +const githubUser = process.env.GITUSER; +const slackToken = process.env.SLACKTOKEN; // Import Axios for HTTP requests const axios = require("axios"); From 0a165f652bc58859d9584ef1c6164b4b9cbbd31d Mon Sep 17 00:00:00 2001 From: kdsbatra Date: Thu, 8 Jul 2021 18:53:52 -0400 Subject: [PATCH 09/21] small refactor for prompt answering and checks --- index.js | 92 +++++++++++++++++++++++++++++--------------------------- 1 file changed, 47 insertions(+), 45 deletions(-) diff --git a/index.js b/index.js index 97ebcb9..243bfa0 100644 --- a/index.js +++ b/index.js @@ -74,7 +74,7 @@ const checkReposContinuously = (reposSelected, i, slackAlert) => { const repoName = reposSelected[i].name; - console.log(`\x1b[33m ======= checking if '${repoName}' repo exists =======\n`); + console.log(`\n\x1b[33m ======= checking if '${repoName}' repo exists =======\n`); let promises = []; studentList.forEach((student) => { @@ -88,7 +88,7 @@ const checkReposContinuously = (reposSelected, i, slackAlert) => { if (reposSelected[i]) { checkReposContinuously(reposSelected, i, slackAlert); } else { - console.log(`\n\x1b[33m =============== FINISHED ==============`); + console.log(`\n\x1b[33m =============== FINISHED ==============\n`); } }); @@ -100,7 +100,7 @@ const cloneAndPushRepos = (allSelectedRepos, i) => { let repoUrl = allSelectedRepos[i].url; console.log(`\n ==================================================`); - console.log(`\n===== Going to try cloning repo '${repoName}' ====`); + console.log(`\n ===== Going to try cloning repo '${repoName}' ====`); let { stdoutClone, stderrClone, codeClone } = shell.exec(`git clone ${repoUrl}`, { silent: true }); if (stderrClone) { @@ -114,7 +114,7 @@ const cloneAndPushRepos = (allSelectedRepos, i) => { console.log(`Could not crete and switch to main branch`, stderrCheckout); } - console.log(`\n===== Going to try pushing repo '${repoName}' ====`); + console.log(`\n ===== Going to try pushing repo '${repoName}' ====`); pushRepoToStudents(repoName, allSelectedRepos[i + 1]); shell.exec("cd .."); @@ -130,10 +130,10 @@ const cloneAndPushRepos = (allSelectedRepos, i) => { const pushRepoToStudents = (repoName, hasNext) => { // Create a forloop to go through each student - let promises = []; + let repoCheckPromisesPerStudent = []; studentList.forEach((student) => { - promises.push(checkRepo(student, repoName, false, () => { + repoCheckPromisesPerStudent.push(checkRepo(student, repoName, false, () => { // First create a URL using the student's username and the repo name const studentUrl = `https://github.com/${student.github}/${repoName}.git`; @@ -148,7 +148,7 @@ const pushRepoToStudents = (repoName, hasNext) => { }); - Promise.allSettled(promises).then((result) => { + Promise.allSettled(repoCheckPromisesPerStudent).then((result) => { if (!hasNext) { console.log(`\n \x1b[32m ============ FINISHED pushing ${repoName} ============`); } @@ -187,10 +187,48 @@ const processByOption = (option, allReposFiltered) => { setupRepos(allReposFiltered); // If option 4 is selected then exit the app. - } + } return; } +const handlePromptAnswer = (answers) => { + + let reposSelectedByName = answers.repoOptions; + let allReposFiltered = repoDetails; + + console.log(` Repos selected: ${answers.repoOptions}\n`); + // If option 1 is selected so a silent check. + if (reposSelectedByName == "exit") { + return; + + } else if (!reposSelectedByName.length) { + console.log(`\x1b[33m Nothing was selected, Exiting`); + return; + + } else if (reposSelectedByName.indexOf("all") > -1) { + if (reposSelectedByName.length > 1) { + console.log(`\x1b[33m All Repos selected, will ignore other options`); + } + + } else { + let exitSelected = reposSelectedByName.indexOf("exit"); + if (exitSelected > -1 && reposSelectedByName.length > 1) {//dont really need to check size here again + console.log(`\x1b[33m Exit was selected along specific repos, ignoring Exit`); + + reposSelectedByName.splice(exitSelected, 1); + } + + allReposFiltered = findRepoDetailsByName(repoDetails, reposSelectedByName); + + if (allReposFiltered.length !== reposSelectedByName.length) { + console.log(`Some repo URL is not found, found items include: [${allReposFiltered}] and repoNames selected were [${reposSelectedByName}]`) + return; + } + } + + processByOption(answers.option, allReposFiltered); +} + // Function that controls interactivity const promptUser = () => { // Prompt the user to see what kind of app needs to run @@ -221,43 +259,7 @@ const promptUser = () => { ], },]) // Then either check the repos or clone/push the assignment - .then((answers) => { - - let reposSelectedByName = answers.repoOptions; - let allReposFiltered = repoDetails; - - console.log(` Repos selected: ${answers.repoOptions}\n`); - // If option 1 is selected so a silent check. - if (reposSelectedByName == "exit") { - return; - - } else if (!reposSelectedByName.length) { - console.log(`\x1b[33m Nothing was selected, Exiting`); - return; - - } else if (reposSelectedByName.indexOf("all") > -1) { - if (reposSelectedByName.length > 1) { - console.log(`\x1b[33m All Repos selected, will ignore other options`); - } - - } else { - let exitSelected = reposSelectedByName.indexOf("exit"); - if (exitSelected > -1 && reposSelectedByName.length > 1) {//dont really need to check size here again - console.log(`\x1b[33m Exit was selected along specific repos, ignoring Exit`); - - reposSelectedByName.splice(exitSelected, 1); - } - - allReposFiltered = findRepoDetailsByName(repoDetails, reposSelectedByName); - - if (allReposFiltered.length !== reposSelectedByName.length) { - console.log(`Some repo URL is not found, found items include: [${allReposFiltered}] and repoNames selected were [${reposSelectedByName}]`) - return; - } - } - - processByOption(answers.option, allReposFiltered); - }); + .then(handlePromptAnswer); }; const sendMessage = (slackId, repoName) => { From 3e5d29d87ee87e958a11a50ce24fa35b194d61f1 Mon Sep 17 00:00:00 2001 From: kdsbatra Date: Thu, 8 Jul 2021 18:55:19 -0400 Subject: [PATCH 10/21] small refactor for prompt answering and checks --- index.js | 52 +++++++++++++++++++++++++++------------------------- 1 file changed, 27 insertions(+), 25 deletions(-) diff --git a/index.js b/index.js index 243bfa0..38d3d7f 100644 --- a/index.js +++ b/index.js @@ -229,35 +229,37 @@ const handlePromptAnswer = (answers) => { processByOption(answers.option, allReposFiltered); } +const promptsTypes = [ + { + name: "repoOptions", + type: "checkbox", + message: "Please select repos you want to check", + choices: ["exit", "all", new inquirer.Separator()].concat(repoDetails), + default: ["all"] + }, + { + name: "option", + type: "list", + message: "Please select your operation.", + when: (answers) => { + if (answers.repoOptions == "none" || !answers.repoOptions.length) { + return false; + } + return true; + }, + choices: [ + "1: Privately check if student repos exist. (No Slack message reminder).", + "2: Check if student repos exist. (With Slack message reminder).", + "3: Push assignment repo to students.", + "4: Exit application.", + ], + }] + // Function that controls interactivity const promptUser = () => { // Prompt the user to see what kind of app needs to run inquirer - .prompt([ - { - name: "repoOptions", - type: "checkbox", - message: "Please select repos you want to check", - choices: ["exit", "all", new inquirer.Separator()].concat(repoDetails), - default: ["all"] - }, - { - name: "option", - type: "list", - message: "Please select your operation.", - when: (answers) => { - if (answers.repoOptions == "none" || !answers.repoOptions.length) { - return false; - } - return true; - }, - choices: [ - "1: Privately check if student repos exist. (No Slack message reminder).", - "2: Check if student repos exist. (With Slack message reminder).", - "3: Push assignment repo to students.", - "4: Exit application.", - ], - },]) + .prompt(promptsTypes) // Then either check the repos or clone/push the assignment .then(handlePromptAnswer); }; From fe513a0af07fe0e301794b3237791637937af606 Mon Sep 17 00:00:00 2001 From: kdsbatra Date: Thu, 8 Jul 2021 18:56:19 -0400 Subject: [PATCH 11/21] code reorg --- index.js | 13 ++++--------- 1 file changed, 4 insertions(+), 9 deletions(-) diff --git a/index.js b/index.js index 38d3d7f..f4254e2 100644 --- a/index.js +++ b/index.js @@ -1,11 +1,7 @@ // Import Student List -const { - studentList -} = require("./studentList"); +const { studentList } = require("./studentList"); -let { - repoDetails -} = require("./repos.js"); +let { repoDetails } = require("./repos.js"); // Import inquirer to make shell interactive const inquirer = require("inquirer"); @@ -27,9 +23,8 @@ const axios = require("axios"); const shell = require("shelljs"); // Import Slack API to send messages to students -const { - WebClient -} = require("@slack/web-api"); +const { WebClient } = require("@slack/web-api"); + const slack = new WebClient(slackToken); repoDetails = repoDetails.filter(repoDetail => !repoDetail.skip); From 39bf6cb1ea6509760b73c3250426c12ecaa871aa Mon Sep 17 00:00:00 2001 From: kdsbatra Date: Thu, 8 Jul 2021 19:27:12 -0400 Subject: [PATCH 12/21] refactoring to synchronous pushing --- index.js | 170 ++-------------------------------------------- repos.js | 2 +- reposProcessor.js | 167 +++++++++++++++++++++++++++++++++++++++++++++ 3 files changed, 172 insertions(+), 167 deletions(-) create mode 100644 reposProcessor.js diff --git a/index.js b/index.js index f4254e2..dd44f62 100644 --- a/index.js +++ b/index.js @@ -10,176 +10,24 @@ const inquirer = require("inquirer"); const dotenv = require('dotenv') dotenv.config(); -const opt = { debug: true } //const assignments = JSON.parse(dotenv.parse(Buffer.from(process.env.ASSIGNMENTS), opt)["REPOS"]); -const token = process.env.TOKEN; -const githubUser = process.env.GITUSER; -const slackToken = process.env.SLACKTOKEN; - -// Import Axios for HTTP requests -const axios = require("axios"); - -// Import shelljs to run bash (git) commands -const shell = require("shelljs"); - -// Import Slack API to send messages to students -const { WebClient } = require("@slack/web-api"); - -const slack = new WebClient(slackToken); repoDetails = repoDetails.filter(repoDetail => !repoDetail.skip); -function findRepoDetailsByName(repos, repoNames) { - - let allReposFiltered = []; - repoNames.forEach(repoName => { - let reposFiltered = repos.filter(repo => repo.name === repoName); - if (reposFiltered.length === 1) { - allReposFiltered.push(reposFiltered[0]); - } else { - console.log(`repo details for ${repoName} not found`); - } - }) - return allReposFiltered; -} - -const checkRepo = (student, repoName, slackAlert, callback, failureCallBack) => { - return axios.get(`https://github.com/${student.github}/${repoName}`) - .then( - (response) => { - console.log(`\x1b[32m ${student.github} has made their '${repoName}' repo!`); - if (callback) { - callback(); - } - }, - (error) => { - if (slackAlert) { - sendMessage(student.slack, repoName); - } - console.log(`\x1b[31m ${student.github} has not made their '${repoName}' repo yet.` + (slackAlert ? ' Alert sent.' : '')); - if (failureCallBack) { - failureCallBack(); - } - } - ) -} - -const checkReposContinuously = (reposSelected, i, slackAlert) => { - // create for loop to check all student repos and see if they exist - - const repoName = reposSelected[i].name; - - console.log(`\n\x1b[33m ======= checking if '${repoName}' repo exists =======\n`); - - let promises = []; - studentList.forEach((student) => { - // Do an HTTP get on each students supposed repo - promises.push(checkRepo(student, repoName, slackAlert)); - }); - - // continue to next repo - Promise.allSettled(promises).then((results) => { - i++; - if (reposSelected[i]) { - checkReposContinuously(reposSelected, i, slackAlert); - } else { - console.log(`\n\x1b[33m =============== FINISHED ==============\n`); - } - - }); -}; - -const cloneAndPushRepos = (allSelectedRepos, i) => { - - let repoName = allSelectedRepos[i].name; - let repoUrl = allSelectedRepos[i].url; - - console.log(`\n ==================================================`); - console.log(`\n ===== Going to try cloning repo '${repoName}' ====`); - - let { stdoutClone, stderrClone, codeClone } = shell.exec(`git clone ${repoUrl}`, { silent: true }); - if (stderrClone) { - console.log(`Could not clone ${repoUrl}`, stderrClone); - } - - // Change branch to main as this is new Github default - shell.cd(`${repoName}`); - let { stdoutCheckout, stderrCheckout, codeCheckout } = shell.exec("git checkout -b main", { silent: true }); - if (stderrCheckout) { - console.log(`Could not crete and switch to main branch`, stderrCheckout); - } - - console.log(`\n ===== Going to try pushing repo '${repoName}' ====`); - pushRepoToStudents(repoName, allSelectedRepos[i + 1]); - - shell.exec("cd .."); - - // continue to next repo - i++ - if (allSelectedRepos[i]) { - cloneAndPushRepos(allSelectedRepos, i); - } -} - - -const pushRepoToStudents = (repoName, hasNext) => { - - // Create a forloop to go through each student - let repoCheckPromisesPerStudent = []; - studentList.forEach((student) => { - - repoCheckPromisesPerStudent.push(checkRepo(student, repoName, false, () => { - // First create a URL using the student's username and the repo name - const studentUrl = `https://github.com/${student.github}/${repoName}.git`; - - // Force a push of the assignment main repo - - let { stdout, stderr, code } = shell.exec(`git push ${studentUrl} --force`, { silent: true }); - if (stderr) { - console.log(`\x1b[31m Could not push code to ${student.github} at ${studentUrl}. Error: ${stderr}`); - //console.log(`\x1b[31m Could not push code to ${student.github} at ${studentUrl}, Maybe they have not yet made the repo yet or you are not collabator on it`); - } - })); - - }); - - Promise.allSettled(repoCheckPromisesPerStudent).then((result) => { - if (!hasNext) { - console.log(`\n \x1b[32m ============ FINISHED pushing ${repoName} ============`); - } - }); -}; - -// Function to clone assignment locally -const setupRepos = (allSelectedRepos) => { - - // Setup github authentication so you have access to stack education - shell.exec(`git config --global user.name "${githubUser}"`); - shell.exec(`git config --global user.password "${token}"`); - - // First remove the repo folder and remake it empty - shell.rm("-rf", "repo"); - shell.exec("mkdir repo"); - - // Now clone the repo into repo folder - shell.cd("repo"); - - cloneAndPushRepos(allSelectedRepos, 0); -}; - +const {findRepoDetailsByName, setupRepos, checkReposContinuously} = require("./reposProcessor"); const processByOption = (option, allReposFiltered) => { if ( option == "1: Privately check if student repos exist. (No Slack message reminder).") { - checkReposContinuously(allReposFiltered, 0, false); + checkReposContinuously(studentList, allReposFiltered, 0, false); // If Option 2 is selected do an alerting check. } else if (option == "2: Check if student repos exist. (With Slack message reminder).") { - checkReposContinuously(allReposFiltered, 0, true); + checkReposContinuously(studentList, allReposFiltered, 0, true); // If option 3 is selected then clone the assignment then push. } else if (option == "3: Push assignment repo to students.") { - setupRepos(allReposFiltered); + setupRepos(studentList, allReposFiltered); // If option 4 is selected then exit the app. } @@ -259,15 +107,5 @@ const promptUser = () => { .then(handlePromptAnswer); }; -const sendMessage = (slackId, repoName) => { - // Connect to slack and post the reminder message using the slackId provided. - (async () => { - const result = await slack.chat.postMessage({ - channel: slackId, - text: `Your repo was not found. Please create the following repo on Github. If you have created the repo please check the spelling or make the repo public. \n \n *Repo Name:* \n \`${repoName}\` \n \n Then please add \`${githubUser}\` as a collaborator`, - }); - })(); -}; - // When the app runs simply prompt the user. promptUser(); \ No newline at end of file diff --git a/repos.js b/repos.js index a939240..5caea06 100644 --- a/repos.js +++ b/repos.js @@ -1,7 +1,7 @@ const repoDetails = [{ url: "https://github.com/stackeducation/fantasy-scoring.git", name: "fantasy-scoring", - skip: true + skip: false }, { url: "https://github.com/stackeducation/order-book.git", diff --git a/reposProcessor.js b/reposProcessor.js new file mode 100644 index 0000000..03b6f56 --- /dev/null +++ b/reposProcessor.js @@ -0,0 +1,167 @@ + +// Import Axios for HTTP requests +const axios = require("axios"); + +// Import shelljs to run bash (git) commands +const shell = require("shelljs"); + +const token = process.env.TOKEN; +const githubUser = process.env.GITUSER; +const slackToken = process.env.SLACKTOKEN; + +// Import Slack API to send messages to students +const { WebClient } = require("@slack/web-api"); + +const slack = new WebClient(slackToken); + +function findRepoDetailsByName(repos, repoNames) { + + let allReposFiltered = []; + repoNames.forEach(repoName => { + let reposFiltered = repos.filter(repo => repo.name === repoName); + if (reposFiltered.length === 1) { + allReposFiltered.push(reposFiltered[0]); + } else { + console.log(`repo details for ${repoName} not found`); + } + }) + return allReposFiltered; +} + +const checkRepo = (student, repoName, slackAlert, callback, failureCallBack) => { + return axios.get(`https://github.com/${student.github}/${repoName}`) + .then( + (response) => { + console.log(`\x1b[32m ${student.github} has made their '${repoName}' repo!`); + if (callback) { + callback(); + } + }, + (error) => { + if (slackAlert) { + sendMessage(student.slack, repoName); + } + console.log(`\x1b[31m ${student.github} has not made their '${repoName}' repo yet.` + (slackAlert ? ' Alert sent.' : '')); + if (failureCallBack) { + failureCallBack(); + } + } + ) +} + +const checkReposContinuously = (studentList, reposSelected, i, slackAlert) => { + // create for loop to check all student repos and see if they exist + + const repoName = reposSelected[i].name; + + console.log(`\n\x1b[33m ======= checking if '${repoName}' repo exists =======\n`); + + let promises = []; + studentList.forEach((student) => { + // Do an HTTP get on each students supposed repo + promises.push(checkRepo(student, repoName, slackAlert)); + }); + + // continue to next repo + Promise.allSettled(promises).then((results) => { + i++; + if (reposSelected[i]) { + checkReposContinuously(studentList, reposSelected, i, slackAlert); + } else { + console.log(`\n\x1b[33m =============== FINISHED ==============\n`); + } + + }); +}; + +const cloneAndPushRepos = (studentList, allSelectedRepos, i) => { + + let repoName = allSelectedRepos[i].name; + let repoUrl = allSelectedRepos[i].url; + + console.log(`\n ==================================================`); + console.log(`\n ===== Going to try cloning repo '${repoName}' ====`); + + let { stdoutClone, stderrClone, codeClone } = shell.exec(`git clone ${repoUrl}`, { silent: true }); + if (stderrClone) { + console.log(`Could not clone ${repoUrl}`, stderrClone); + } + + // Change branch to main as this is new Github default + shell.cd(`${repoName}`); + let { stdoutCheckout, stderrCheckout, codeCheckout } = shell.exec("git checkout -b main", { silent: true }); + if (stderrCheckout) { + console.log(`Could not crete and switch to main branch`, stderrCheckout); + } + + console.log(`\n ===== Going to try pushing repo '${repoName}' ====`); + pushRepoToStudents(studentList, repoName, allSelectedRepos, i); + + shell.exec("cd .."); + + +} + + +const pushRepoToStudents = (studentList, repoName, allSelectedRepos, i) => { + + // Create a forloop to go through each student + let repoCheckPromisesPerStudent = []; + studentList.forEach((student) => { + + repoCheckPromisesPerStudent.push(checkRepo(student, repoName, false, () => { + // First create a URL using the student's username and the repo name + const studentUrl = `https://github.com/${student.github}/${repoName}.git`; + + // Force a push of the assignment main repo + + let { stdout, stderr, code } = shell.exec(`git push ${studentUrl}`, { silent: true }); // --force + if (stderr) { + console.log(`\x1b[31m Could not push code to ${student.github} at ${studentUrl}. Error: ${stderr}`); + //console.log(`\x1b[31m Could not push code to ${student.github} at ${studentUrl}, Maybe they have not yet made the repo yet or you are not collabator on it`); + } + })); + + }); + + Promise.allSettled(repoCheckPromisesPerStudent).then((result) => { + console.log(`\n \x1b[32m ============ FINISHED pushing ${repoName} ============`); + + // continue to next repo + i++ + if (allSelectedRepos[i]) { + cloneAndPushRepos(studentList, allSelectedRepos, i); + }else{ + console.log(`\n\x1b[33m =============== FINISHED ==============\n`); + } + }); +}; + +// Function to clone assignment locally +const setupRepos = (studentList, allSelectedRepos) => { + + // Setup github authentication so you have access to stack education + shell.exec(`git config --global user.name "${githubUser}"`); + shell.exec(`git config --global user.password "${token}"`); + + // First remove the repo folder and remake it empty + shell.rm("-rf", "repo"); + shell.exec("mkdir repo"); + + // Now clone the repo into repo folder + shell.cd("repo"); + + cloneAndPushRepos(studentList, allSelectedRepos, 0); +}; + + +const sendMessage = (slackId, repoName) => { + // Connect to slack and post the reminder message using the slackId provided. + (async () => { + const result = await slack.chat.postMessage({ + channel: slackId, + text: `Your repo was not found. Please create the following repo on Github. If you have created the repo please check the spelling or make the repo public. \n \n *Repo Name:* \n \`${repoName}\` \n \n Then please add \`${githubUser}\` as a collaborator`, + }); + })(); +}; +module.exports = { findRepoDetailsByName, setupRepos, checkReposContinuously } \ No newline at end of file From 9fd2e0db82da5f2472b6d190048c591a509f9fe5 Mon Sep 17 00:00:00 2001 From: kdsbatra Date: Thu, 8 Jul 2021 19:32:34 -0400 Subject: [PATCH 13/21] small refactor --- reposProcessor.js | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/reposProcessor.js b/reposProcessor.js index 03b6f56..62ffdf5 100644 --- a/reposProcessor.js +++ b/reposProcessor.js @@ -91,10 +91,10 @@ const cloneAndPushRepos = (studentList, allSelectedRepos, i) => { shell.cd(`${repoName}`); let { stdoutCheckout, stderrCheckout, codeCheckout } = shell.exec("git checkout -b main", { silent: true }); if (stderrCheckout) { - console.log(`Could not crete and switch to main branch`, stderrCheckout); + console.log(`Could not create and switch to main branch`, stderrCheckout); } - console.log(`\n ===== Going to try pushing repo '${repoName}' ====`); + pushRepoToStudents(studentList, repoName, allSelectedRepos, i); shell.exec("cd .."); @@ -105,6 +105,7 @@ const cloneAndPushRepos = (studentList, allSelectedRepos, i) => { const pushRepoToStudents = (studentList, repoName, allSelectedRepos, i) => { + console.log(`\n ===== Going to try pushing repo '${repoName}' ====`); // Create a forloop to go through each student let repoCheckPromisesPerStudent = []; studentList.forEach((student) => { From ddd8447802a4dad2e79f4d314892f8f9b72c45d6 Mon Sep 17 00:00:00 2001 From: kdsbatra Date: Thu, 8 Jul 2021 19:49:03 -0400 Subject: [PATCH 14/21] disable fantasy push and fixing formatting of messages --- repos.js | 10 ++++++++-- reposProcessor.js | 21 ++++++++++++++------- 2 files changed, 22 insertions(+), 9 deletions(-) diff --git a/repos.js b/repos.js index 5caea06..c91056a 100644 --- a/repos.js +++ b/repos.js @@ -1,7 +1,13 @@ -const repoDetails = [{ +const repoDetails = [ + { + url: "https://github.com/stackeducation/for-the-empire.git", + name: "for-the-empire", + skip: true + }, + { url: "https://github.com/stackeducation/fantasy-scoring.git", name: "fantasy-scoring", - skip: false + skip: true }, { url: "https://github.com/stackeducation/order-book.git", diff --git a/reposProcessor.js b/reposProcessor.js index 62ffdf5..f2ad37c 100644 --- a/reposProcessor.js +++ b/reposProcessor.js @@ -5,6 +5,8 @@ const axios = require("axios"); // Import shelljs to run bash (git) commands const shell = require("shelljs"); +//const { studentList } = require("./studentList"); + const token = process.env.TOKEN; const githubUser = process.env.GITUSER; const slackToken = process.env.SLACKTOKEN; @@ -68,7 +70,7 @@ const checkReposContinuously = (studentList, reposSelected, i, slackAlert) => { if (reposSelected[i]) { checkReposContinuously(studentList, reposSelected, i, slackAlert); } else { - console.log(`\n\x1b[33m =============== FINISHED ==============\n`); + console.log(`\n\x1b[33m ================= FINISHED ==================\n`); } }); @@ -80,18 +82,23 @@ const cloneAndPushRepos = (studentList, allSelectedRepos, i) => { let repoUrl = allSelectedRepos[i].url; console.log(`\n ==================================================`); - console.log(`\n ===== Going to try cloning repo '${repoName}' ====`); + console.log(` ===== Going to try cloning repo '${repoName}' =====`); let { stdoutClone, stderrClone, codeClone } = shell.exec(`git clone ${repoUrl}`, { silent: true }); if (stderrClone) { - console.log(`Could not clone ${repoUrl}`, stderrClone); + console.log(`\n\x1b[31m Could not clone ${repoUrl}`, stderrClone); + }else{ + console.log(`\n\x1b[32m Clone of ${repoUrl} done`); } // Change branch to main as this is new Github default shell.cd(`${repoName}`); + console.log(`\n ===== Going to checkout main branch for repo '${repoName}' =====`); let { stdoutCheckout, stderrCheckout, codeCheckout } = shell.exec("git checkout -b main", { silent: true }); if (stderrCheckout) { - console.log(`Could not create and switch to main branch`, stderrCheckout); + console.log(`\n\x1b[31m Could not create and switch to main branch`, stderrCheckout); + }else{ + console.log(`\n\x1b[32m Checked out main branch`); } @@ -105,7 +112,7 @@ const cloneAndPushRepos = (studentList, allSelectedRepos, i) => { const pushRepoToStudents = (studentList, repoName, allSelectedRepos, i) => { - console.log(`\n ===== Going to try pushing repo '${repoName}' ====`); + console.log(`\n ===== Going to try pushing repo '${repoName}' ====\n`); // Create a forloop to go through each student let repoCheckPromisesPerStudent = []; studentList.forEach((student) => { @@ -126,14 +133,14 @@ const pushRepoToStudents = (studentList, repoName, allSelectedRepos, i) => { }); Promise.allSettled(repoCheckPromisesPerStudent).then((result) => { - console.log(`\n \x1b[32m ============ FINISHED pushing ${repoName} ============`); + console.log(`\n\x1b[32m ============ FINISHED pushing ${repoName} ============`); // continue to next repo i++ if (allSelectedRepos[i]) { cloneAndPushRepos(studentList, allSelectedRepos, i); }else{ - console.log(`\n\x1b[33m =============== FINISHED ==============\n`); + console.log(`\n\x1b[33m =================== FINISHED ===================\n`); } }); }; From fd55760a5450205f4cd37f0ef6128adf464f9619 Mon Sep 17 00:00:00 2001 From: kdsbatra Date: Thu, 8 Jul 2021 20:52:28 -0400 Subject: [PATCH 15/21] some more formatting changes --- index.js | 4 ++-- repos.js | 2 +- reposProcessor.js | 15 +++++++-------- studentList.js | 18 +++++++++--------- 4 files changed, 19 insertions(+), 20 deletions(-) diff --git a/index.js b/index.js index dd44f62..22ef546 100644 --- a/index.js +++ b/index.js @@ -19,11 +19,11 @@ const {findRepoDetailsByName, setupRepos, checkReposContinuously} = require("./r const processByOption = (option, allReposFiltered) => { if ( option == "1: Privately check if student repos exist. (No Slack message reminder).") { - checkReposContinuously(studentList, allReposFiltered, 0, false); + checkReposContinuously(allReposFiltered, 0, false); // If Option 2 is selected do an alerting check. } else if (option == "2: Check if student repos exist. (With Slack message reminder).") { - checkReposContinuously(studentList, allReposFiltered, 0, true); + checkReposContinuously(allReposFiltered, 0, true); // If option 3 is selected then clone the assignment then push. } else if (option == "3: Push assignment repo to students.") { diff --git a/repos.js b/repos.js index c91056a..7ab84ab 100644 --- a/repos.js +++ b/repos.js @@ -7,7 +7,7 @@ const repoDetails = [ { url: "https://github.com/stackeducation/fantasy-scoring.git", name: "fantasy-scoring", - skip: true + skip: false }, { url: "https://github.com/stackeducation/order-book.git", diff --git a/reposProcessor.js b/reposProcessor.js index f2ad37c..27d0313 100644 --- a/reposProcessor.js +++ b/reposProcessor.js @@ -43,7 +43,7 @@ const checkRepo = (student, repoName, slackAlert, callback, failureCallBack) => if (slackAlert) { sendMessage(student.slack, repoName); } - console.log(`\x1b[31m ${student.github} has not made their '${repoName}' repo yet.` + (slackAlert ? ' Alert sent.' : '')); + console.log(`\n\x1b[31m ${student.github} has not made their '${repoName}' repo yet.` + (slackAlert ? ' Alert sent.' : '')); if (failureCallBack) { failureCallBack(); } @@ -81,8 +81,8 @@ const cloneAndPushRepos = (studentList, allSelectedRepos, i) => { let repoName = allSelectedRepos[i].name; let repoUrl = allSelectedRepos[i].url; - console.log(`\n ==================================================`); - console.log(` ===== Going to try cloning repo '${repoName}' =====`); + console.log(`\n\x1b[0m ==================================================`); + console.log(`\x1b[0m ===== Going to try cloning repo '${repoName}' =====`); let { stdoutClone, stderrClone, codeClone } = shell.exec(`git clone ${repoUrl}`, { silent: true }); if (stderrClone) { @@ -93,7 +93,7 @@ const cloneAndPushRepos = (studentList, allSelectedRepos, i) => { // Change branch to main as this is new Github default shell.cd(`${repoName}`); - console.log(`\n ===== Going to checkout main branch for repo '${repoName}' =====`); + console.log(`\n\x1b[0m ===== Going to checkout main branch for repo '${repoName}' =====`); let { stdoutCheckout, stderrCheckout, codeCheckout } = shell.exec("git checkout -b main", { silent: true }); if (stderrCheckout) { console.log(`\n\x1b[31m Could not create and switch to main branch`, stderrCheckout); @@ -104,15 +104,12 @@ const cloneAndPushRepos = (studentList, allSelectedRepos, i) => { pushRepoToStudents(studentList, repoName, allSelectedRepos, i); - shell.exec("cd .."); - - } const pushRepoToStudents = (studentList, repoName, allSelectedRepos, i) => { - console.log(`\n ===== Going to try pushing repo '${repoName}' ====\n`); + console.log(`\n\x1b[0m ===== Going to try pushing repo '${repoName}' ====\n`); // Create a forloop to go through each student let repoCheckPromisesPerStudent = []; studentList.forEach((student) => { @@ -135,6 +132,8 @@ const pushRepoToStudents = (studentList, repoName, allSelectedRepos, i) => { Promise.allSettled(repoCheckPromisesPerStudent).then((result) => { console.log(`\n\x1b[32m ============ FINISHED pushing ${repoName} ============`); + shell.cd("..");// go back to repo directory + // continue to next repo i++ if (allSelectedRepos[i]) { diff --git a/studentList.js b/studentList.js index 7e0e77c..e34ca67 100644 --- a/studentList.js +++ b/studentList.js @@ -1,15 +1,15 @@ const studentList = [ { github: "kdsbatra", slack: "U0246KNS2KB" }, - { github: "brnjackson", slack: "U023U8NK89Z" }, - { github: "Cpluchak", slack: "U0246LJV90R" }, + // { github: "brnjackson", slack: "U023U8NK89Z" }, + // { github: "Cpluchak", slack: "U0246LJV90R" }, { github: "Forensicrose", slack: "U0246LKG6E5" }, - { github: "jeraldina", slack: "U0246LK6D33" }, - { github: "kjmatt91", slack: "U0246LJTD97" }, - { github: "katskurka", slack: "U023Z44D690" }, - { github: "KevinSalina", slack: "U023V2RJA7P" }, - { github: "mhafez1978", slack: "U023R04GK1B" }, - { github: "RubyDF", slack: "U0246LKC43T" }, - { github: "sherryliztynan", slack: "U0246LJAMS5" }, + // { github: "jeraldina", slack: "U0246LK6D33" }, + // { github: "kjmatt91", slack: "U0246LJTD97" }, + // { github: "katskurka", slack: "U023Z44D690" }, + // { github: "KevinSalina", slack: "U023V2RJA7P" }, + // { github: "mhafez1978", slack: "U023R04GK1B" }, + // { github: "RubyDF", slack: "U0246LKC43T" }, + // { github: "sherryliztynan", slack: "U0246LJAMS5" }, // { github: "reinhal", slack: "U023U7T8RD1" }, // { github: "StandyMerizier", slack: "U023QUP3KEZ" }, From 964747300127db8851c1bad9cc08a13055b155d8 Mon Sep 17 00:00:00 2001 From: kdsbatra Date: Thu, 8 Jul 2021 21:00:03 -0400 Subject: [PATCH 16/21] some more formatting changes --- reposProcessor.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/reposProcessor.js b/reposProcessor.js index 27d0313..580d69e 100644 --- a/reposProcessor.js +++ b/reposProcessor.js @@ -120,7 +120,7 @@ const pushRepoToStudents = (studentList, repoName, allSelectedRepos, i) => { // Force a push of the assignment main repo - let { stdout, stderr, code } = shell.exec(`git push ${studentUrl}`, { silent: true }); // --force + let { stdout, stderr, code } = shell.exec(`git push ${studentUrl} --force`, { silent: true }); // --force if (stderr) { console.log(`\x1b[31m Could not push code to ${student.github} at ${studentUrl}. Error: ${stderr}`); //console.log(`\x1b[31m Could not push code to ${student.github} at ${studentUrl}, Maybe they have not yet made the repo yet or you are not collabator on it`); From b3e3ec3a11a48a453dceb919934af7621b324f3f Mon Sep 17 00:00:00 2001 From: kdsbatra Date: Fri, 9 Jul 2021 18:38:48 -0400 Subject: [PATCH 17/21] fix for repo check --- index.js | 4 ++-- studentList.js | 6 +++--- 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/index.js b/index.js index 22ef546..dd44f62 100644 --- a/index.js +++ b/index.js @@ -19,11 +19,11 @@ const {findRepoDetailsByName, setupRepos, checkReposContinuously} = require("./r const processByOption = (option, allReposFiltered) => { if ( option == "1: Privately check if student repos exist. (No Slack message reminder).") { - checkReposContinuously(allReposFiltered, 0, false); + checkReposContinuously(studentList, allReposFiltered, 0, false); // If Option 2 is selected do an alerting check. } else if (option == "2: Check if student repos exist. (With Slack message reminder).") { - checkReposContinuously(allReposFiltered, 0, true); + checkReposContinuously(studentList, allReposFiltered, 0, true); // If option 3 is selected then clone the assignment then push. } else if (option == "3: Push assignment repo to students.") { diff --git a/studentList.js b/studentList.js index e34ca67..2f344c4 100644 --- a/studentList.js +++ b/studentList.js @@ -1,14 +1,14 @@ const studentList = [ { github: "kdsbatra", slack: "U0246KNS2KB" }, - // { github: "brnjackson", slack: "U023U8NK89Z" }, + // { github: "brnjackson", slack: "U023U8NK89Z" }, // { github: "Cpluchak", slack: "U0246LJV90R" }, - { github: "Forensicrose", slack: "U0246LKG6E5" }, + // { github: "Forensicrose", slack: "U0246LKG6E5" }, // { github: "jeraldina", slack: "U0246LK6D33" }, // { github: "kjmatt91", slack: "U0246LJTD97" }, // { github: "katskurka", slack: "U023Z44D690" }, // { github: "KevinSalina", slack: "U023V2RJA7P" }, // { github: "mhafez1978", slack: "U023R04GK1B" }, - // { github: "RubyDF", slack: "U0246LKC43T" }, + // { github: "RubyDF", slack: "U0246LKC43T" }, // { github: "sherryliztynan", slack: "U0246LJAMS5" }, // { github: "reinhal", slack: "U023U7T8RD1" }, From 9a4b7a3b89abc6f9a0161399a0a6e5b23747df0f Mon Sep 17 00:00:00 2001 From: kdsbatra Date: Tue, 13 Jul 2021 21:20:35 -0400 Subject: [PATCH 18/21] added way to handle student selection --- index.js | 96 ++++++++++++++++++++++++++++++++--------------- repos.js | 10 ++++- reposProcessor.js | 9 +++-- studentList.js | 22 +++++------ 4 files changed, 90 insertions(+), 47 deletions(-) diff --git a/index.js b/index.js index dd44f62..cb72ab4 100644 --- a/index.js +++ b/index.js @@ -1,5 +1,5 @@ // Import Student List -const { studentList } = require("./studentList"); +let { studentList } = require("./studentList"); let { repoDetails } = require("./repos.js"); @@ -14,78 +14,114 @@ dotenv.config(); repoDetails = repoDetails.filter(repoDetail => !repoDetail.skip); -const {findRepoDetailsByName, setupRepos, checkReposContinuously} = require("./reposProcessor"); +studentList = studentList.filter(student => !student.skip); -const processByOption = (option, allReposFiltered) => { +studentList.forEach(student => { + student.name = student.name ? student.name : student.github +}); + +const { filterArrayBySelectedNames, setupRepos, checkReposContinuously } = require("./reposProcessor"); + +const processByOption = (option, allReposFiltered, allStudentsFiltered) => { if ( option == "1: Privately check if student repos exist. (No Slack message reminder).") { - checkReposContinuously(studentList, allReposFiltered, 0, false); + checkReposContinuously(allStudentsFiltered, allReposFiltered, 0, false); // If Option 2 is selected do an alerting check. } else if (option == "2: Check if student repos exist. (With Slack message reminder).") { - checkReposContinuously(studentList, allReposFiltered, 0, true); + checkReposContinuously(allStudentsFiltered, allReposFiltered, 0, true); // If option 3 is selected then clone the assignment then push. } else if (option == "3: Push assignment repo to students.") { - setupRepos(studentList, allReposFiltered); + setupRepos(allStudentsFiltered, allReposFiltered); // If option 4 is selected then exit the app. } return; } -const handlePromptAnswer = (answers) => { - - let reposSelectedByName = answers.repoOptions; - let allReposFiltered = repoDetails; - - console.log(` Repos selected: ${answers.repoOptions}\n`); +const findFilteredItemsBySelectedNames = (allItem, selectedNames, type) => { // If option 1 is selected so a silent check. - if (reposSelectedByName == "exit") { - return; + if (selectedNames == "exit") { + return false; - } else if (!reposSelectedByName.length) { - console.log(`\x1b[33m Nothing was selected, Exiting`); - return; + } else if (!selectedNames.length) { + console.log(`\x1b[33m Nothing was selected`); + return false; - } else if (reposSelectedByName.indexOf("all") > -1) { - if (reposSelectedByName.length > 1) { + } else if (selectedNames.indexOf("all") > -1) { + if (selectedNames.length > 1) { console.log(`\x1b[33m All Repos selected, will ignore other options`); } - } else { - let exitSelected = reposSelectedByName.indexOf("exit"); - if (exitSelected > -1 && reposSelectedByName.length > 1) {//dont really need to check size here again + return allItem; + } else {// filter out selected repos + let exitSelected = selectedNames.indexOf("exit"); + if (exitSelected > -1 && selectedNames.length > 1) {//dont really need to check size here again console.log(`\x1b[33m Exit was selected along specific repos, ignoring Exit`); - reposSelectedByName.splice(exitSelected, 1); + selectedNames.splice(exitSelected, 1); } - allReposFiltered = findRepoDetailsByName(repoDetails, reposSelectedByName); + allItem = filterArrayBySelectedNames(allItem, selectedNames); - if (allReposFiltered.length !== reposSelectedByName.length) { - console.log(`Some repo URL is not found, found items include: [${allReposFiltered}] and repoNames selected were [${reposSelectedByName}]`) - return; + if (allItem.length !== selectedNames.length) { + console.log(`Some ${type} are not found, found ${type} include: [${allItem}] and ${type} Names selected were [${selectedNames}]`) + return false; } + + return allItem; } +} + +const handlePromptAnswer = (answers) => { + + let reposSelectedByName = answers.repoOptions; + let studentsSelectedByName = answers.studentOptions; - processByOption(answers.option, allReposFiltered); + let allReposFiltered = repoDetails; + let allStudentsFiltered = studentList; + + console.log(` Repos selected: ${answers.repoOptions}\n`); + console.log(` Students selected: ${answers.studentOptions}\n`); + + allReposFiltered = findFilteredItemsBySelectedNames(allReposFiltered, reposSelectedByName, 'repos'); + + allStudentsFiltered = findFilteredItemsBySelectedNames(allStudentsFiltered, studentsSelectedByName, 'students'); + + if (!allReposFiltered || !allStudentsFiltered) { + console.log(`\x1b[33m Exiting`); + return; + } + + //console.log(`Final selected items: \n Repos: ${allReposFiltered}\n Students: ${allStudentsFiltered}`); + + processByOption(answers.option, allReposFiltered, allStudentsFiltered); } const promptsTypes = [ { name: "repoOptions", type: "checkbox", - message: "Please select repos you want to check", + message: "Please select repos you want to check or push", choices: ["exit", "all", new inquirer.Separator()].concat(repoDetails), default: ["all"] }, + { + name: "studentOptions", + type: "checkbox", + message: "Please select people you want to check or push to", + choices: ["exit", "all", new inquirer.Separator()].concat(studentList), + default: ["all"] + }, { name: "option", type: "list", message: "Please select your operation.", when: (answers) => { - if (answers.repoOptions == "none" || !answers.repoOptions.length) { + if (answers.studentOptions == "none" || !answers.studentOptions.length) { + return false; + } else if (answers.studentOptions == "none" || !answers.studentOptions.length) { return false; } return true; diff --git a/repos.js b/repos.js index 7ab84ab..9c67726 100644 --- a/repos.js +++ b/repos.js @@ -13,6 +13,12 @@ const repoDetails = [ url: "https://github.com/stackeducation/order-book.git", name: "order-book", skip: false - }]; + }, + { + url: "https://github.com/stackeducation/password-validator.git", + name: "password-validator", + skip: false + } +]; -module.exports = {repoDetails}; \ No newline at end of file +module.exports = { repoDetails }; \ No newline at end of file diff --git a/reposProcessor.js b/reposProcessor.js index 580d69e..9c6a118 100644 --- a/reposProcessor.js +++ b/reposProcessor.js @@ -16,11 +16,11 @@ const { WebClient } = require("@slack/web-api"); const slack = new WebClient(slackToken); -function findRepoDetailsByName(repos, repoNames) { +function filterArrayBySelectedNames(allItems, selectedNames) { let allReposFiltered = []; - repoNames.forEach(repoName => { - let reposFiltered = repos.filter(repo => repo.name === repoName); + selectedNames.forEach(repoName => { + let reposFiltered = allItems.filter(repo => repo.name === repoName); if (reposFiltered.length === 1) { allReposFiltered.push(reposFiltered[0]); } else { @@ -30,6 +30,7 @@ function findRepoDetailsByName(repos, repoNames) { return allReposFiltered; } + const checkRepo = (student, repoName, slackAlert, callback, failureCallBack) => { return axios.get(`https://github.com/${student.github}/${repoName}`) .then( @@ -171,4 +172,4 @@ const sendMessage = (slackId, repoName) => { }); })(); }; -module.exports = { findRepoDetailsByName, setupRepos, checkReposContinuously } \ No newline at end of file +module.exports = { filterArrayBySelectedNames, setupRepos, checkReposContinuously } \ No newline at end of file diff --git a/studentList.js b/studentList.js index 2f344c4..16155ea 100644 --- a/studentList.js +++ b/studentList.js @@ -1,15 +1,15 @@ const studentList = [ - { github: "kdsbatra", slack: "U0246KNS2KB" }, - // { github: "brnjackson", slack: "U023U8NK89Z" }, - // { github: "Cpluchak", slack: "U0246LJV90R" }, - // { github: "Forensicrose", slack: "U0246LKG6E5" }, - // { github: "jeraldina", slack: "U0246LK6D33" }, - // { github: "kjmatt91", slack: "U0246LJTD97" }, - // { github: "katskurka", slack: "U023Z44D690" }, - // { github: "KevinSalina", slack: "U023V2RJA7P" }, - // { github: "mhafez1978", slack: "U023R04GK1B" }, - // { github: "RubyDF", slack: "U0246LKC43T" }, - // { github: "sherryliztynan", slack: "U0246LJAMS5" }, + { skip: false, name: "karandeep", github: "kdsbatra", slack: "U0246KNS2KB" }, + { github: "brnjackson", slack: "U023U8NK89Z" }, + { github: "Cpluchak", slack: "U0246LJV90R" }, + { github: "Forensicrose", slack: "U0246LKG6E5" }, + { github: "jeraldina", slack: "U0246LK6D33" }, + { github: "kjmatt91", slack: "U0246LJTD97" }, + { github: "katskurka", slack: "U023Z44D690" }, + { github: "KevinSalina", slack: "U023V2RJA7P" }, + { github: "mhafez1978", slack: "U023R04GK1B" }, + { github: "RubyDF", slack: "U0246LKC43T" }, + { github: "sherryliztynan", slack: "U0246LJAMS5" }, // { github: "reinhal", slack: "U023U7T8RD1" }, // { github: "StandyMerizier", slack: "U023QUP3KEZ" }, From 98ef23a7edd28a597558d26f8b8e4fbe05f14598 Mon Sep 17 00:00:00 2001 From: kdsbatra Date: Tue, 20 Jul 2021 09:20:39 -0400 Subject: [PATCH 19/21] disable student choices loop --- index.js | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/index.js b/index.js index cb72ab4..5713201 100644 --- a/index.js +++ b/index.js @@ -112,7 +112,8 @@ const promptsTypes = [ type: "checkbox", message: "Please select people you want to check or push to", choices: ["exit", "all", new inquirer.Separator()].concat(studentList), - default: ["all"] + default: ["all"], + loop: false }, { name: "option", From 37557c225bed45b42a5b5e74dc376f8fb1807f8b Mon Sep 17 00:00:00 2001 From: kdsbatra Date: Tue, 20 Jul 2021 21:22:33 -0400 Subject: [PATCH 20/21] hazy calculator added --- repos.js | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/repos.js b/repos.js index 9c67726..4fa17e0 100644 --- a/repos.js +++ b/repos.js @@ -18,6 +18,11 @@ const repoDetails = [ url: "https://github.com/stackeducation/password-validator.git", name: "password-validator", skip: false + }, + { + url: "https://github.com/stackeducation/hazy-calculator.git", + name: "hazy-calculator", + skip: false } ]; From 51d7a602b8f3c829e91a59fccf4114e13f851098 Mon Sep 17 00:00:00 2001 From: undefined Date: Fri, 6 Aug 2021 12:23:28 -0500 Subject: [PATCH 21/21] Adds repos from week 9 --- DOTENV-example.env | 5 ----- repos.js | 23 +++++++++++++++++++++++ 2 files changed, 23 insertions(+), 5 deletions(-) delete mode 100644 DOTENV-example.env diff --git a/DOTENV-example.env b/DOTENV-example.env deleted file mode 100644 index 9b2c613..0000000 --- a/DOTENV-example.env +++ /dev/null @@ -1,5 +0,0 @@ -ASSIGNMENT=https://github.com/hollisjamison/repo-name.git -REPONAME=repo-name -USERNAME=hollisjamison@gmail.com -TOKEN=GITHUB-ACCESS-TOKEN -SLACKTOKEN=SLACK-OAUTH-TOKEN \ No newline at end of file diff --git a/repos.js b/repos.js index 4fa17e0..44d60b9 100644 --- a/repos.js +++ b/repos.js @@ -23,7 +23,30 @@ const repoDetails = [ url: "https://github.com/stackeducation/hazy-calculator.git", name: "hazy-calculator", skip: false + }, + { + url: "https://github.com/stackeducation/custom-error-page.git", + name: "custom-error-page", + skip: false + }, + { + url: "https://github.com/stackeducation/duck-hunt.git", + name: "duck-hunt", + skip: false + }, + { + url: "https://github.com/stackeducation/custom-error-page.git", + name: "custom-error-page", + skip: false + }, + { + url: "https://github.com/stackeducation/tv-synopsis.git", + name: "tv-synopsis", + skip: false } + + + ]; module.exports = { repoDetails }; \ No newline at end of file