Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 0 additions & 5 deletions DOTENV-example.env

This file was deleted.

249 changes: 128 additions & 121 deletions index.js
Original file line number Diff line number Diff line change
@@ -1,140 +1,147 @@
// Import Student List
const {
studentList
} = require("./studentList");
let { studentList } = require("./studentList");

let { repoDetails } = require("./repos.js");

@kdsbatra kdsbatra Jul 8, 2021

Copy link
Copy Markdown
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

added repos as part of a new file instead of env file.

// 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 token = process.env.TOKEN;
const githubUser = process.env.USERNAME;
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);

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(
(response) => {
console.log(`\x1b[32m ${student.github} has made their repo!`)
},
(error) => {
console.log(`\x1b[31m ${student.github} has not made the repo yet.`);
}
);
});
};

const checkReposAlert = () => {
// 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(
(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.`);
}
);
});
};

// Function to clone assignment locally
const cloneAssignment = () => {
// 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}"`);
const dotenv = require('dotenv')
dotenv.config();

// First remove the repo folder and remake it empty
shell.exec("rm -rf repo");
shell.exec("mkdir repo");
//const assignments = JSON.parse(dotenv.parse(Buffer.from(process.env.ASSIGNMENTS), opt)["REPOS"]);

// Now clone the repo into that folder
shell.cd("repo");
shell.exec(`git clone ${assignmentUrl}`);
repoDetails = repoDetails.filter(repoDetail => !repoDetail.skip);

// 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`;
studentList = studentList.filter(student => !student.skip);

// Force a push of the assignment main repo
shell.exec(`git push ${studentUrl} --force`);
});
};
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(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(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(allStudentsFiltered, allReposFiltered);

// If option 4 is selected then exit the app.
}
return;
}

const findFilteredItemsBySelectedNames = (allItem, selectedNames, type) => {
// If option 1 is selected so a silent check.
if (selectedNames == "exit") {
return false;

} else if (!selectedNames.length) {
console.log(`\x1b[33m Nothing was selected`);
return false;

} else if (selectedNames.indexOf("all") > -1) {
if (selectedNames.length > 1) {
console.log(`\x1b[33m All Repos selected, will ignore other options`);
}

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`);

selectedNames.splice(exitSelected, 1);
}

allItem = filterArrayBySelectedNames(allItem, selectedNames);

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;

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 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"],
loop: false
},
{
name: "option",
type: "list",
message: "Please select your operation.",
when: (answers) => {
if (answers.studentOptions == "none" || !answers.studentOptions.length) {
return false;
} else if (answers.studentOptions == "none" || !answers.studentOptions.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: "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(promptsTypes)
// Then either check the repos or clone/push the assignment
.then((answer) => {
// If option 1 is selected so a silent check.
if (
answer.option ==
"1: Privately check if student repos exist. (No Slack message reminder)."
) {
checkReposSilent();
// If Option 2 is selected do an alerting check.
} else if (
answer.option ==
"2: Check if student repos exist. (With Slack message reminder)."
) {
checkReposAlert();
// If option 3 is selected then clone the assignment then push.
} else if (answer.option == "3: Push assignment repo to students.") {
cloneAssignment();
pushToStudents();
// If option 4 is selected then exit the app.
} else {
return;
}
});
};

const sendMessage = (slackId) => {
// 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}\``,
});
})();
.then(handlePromptAnswer);
};

// When the app runs simply prompt the user.
Expand Down
52 changes: 52 additions & 0 deletions repos.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,52 @@
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
},
{
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
},
{
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 };
Loading