Skip to content

Commit

Permalink
feat: CLI for contributors archiving
Browse files Browse the repository at this point in the history
  • Loading branch information
gitcommitshow committed Sep 2, 2022
1 parent ba4f1b1 commit 4ae95c9
Show file tree
Hide file tree
Showing 5 changed files with 108 additions and 23 deletions.
45 changes: 42 additions & 3 deletions README.md
Original file line number Diff line number Diff line change
@@ -1,15 +1,54 @@
# open-community-kit
Tools and stats for open-source communities

# Installation

```
npm install -g open-community-kit
```

You can use npx as well if you just want to test a CLI command

# Usage

## Create a leaderboard of github contributors for all the repos of a user/org
(Contributor with highest # of contributions at the top)

Run `node contributors.js` from your terminal
### Using CLI

Run `open-community-kit yourGithubOrgName` from your terminal

Note: You can also use the shorthand `ock` in place of `open-commmunity-kit` i.e.

```
ock yourGitHubOrgName
```

This will
* Fetch data from Github APIs and prepare a leaderboard of all the contributors to (default "Git-Commit-Show" org) the user or org you mention in REPO_OWNER variable inside `contributors.js`
* Fetch data from Github APIs and prepare a leaderboard of all the contributors to public repositories of your GitHub organization/user accout
* Save the leaderboard in a csv file in the same folder

You will hit the API limits soon. To increase API limits, add GITHUB_PERSONAL_TOKEN in `contributors.js`
You will hit the API limits soon. **To increase API limits**, add [`GITHUB_PERSONAL_TOKEN`](https://github.com/settings/tokens) as well in the arguments i.e.

```
ock yourGitHubOrgName yourGitHubPersonalToken
```

### Using code

```javascript
const OCK = require('open-community-kit').OCK;
OCK.contributors.github.archive('your_github_org_or_username',
{ GITHUB_PERSONAL_TOKEN: 'your_gh_personal_token_optional'
});
```

## Settings for repeated usage

If you are going to use this command frequently, you might not want to set organization name and personal token again and again. Instead, you can set following environment variables and then you don't need to pass those variables as CLI arguments or function parameters

```
# Set these variables in the environment to avoid repeatedly specifying these variables
1. REPO_OWNER
2. GITHUB_PERSONAL_TOKEN
```
14 changes: 14 additions & 0 deletions cli.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
#!/usr/bin/env node

const OCK = require('./index').OCK;

let mainCommand = process.argv[1];
console.log("Running "+mainCommand+"...");
let REPO_OWNER = process.argv[2];
let GITHUB_PERSONAL_TOKEN = process.argv[3];

let options = {};
if(GITHUB_PERSONAL_TOKEN){
options.GITHUB_PERSONAL_TOKEN = GITHUB_PERSONAL_TOKEN;
}
OCK.contributors.github.archive(REPO_OWNER, options);
48 changes: 29 additions & 19 deletions contributors.js
Original file line number Diff line number Diff line change
Expand Up @@ -3,12 +3,14 @@
* @example To archive contributors leaderboard data in csv file, run `node contributors.js`
*/

exports.archiveContributorsLeaderboard = archiveContributorsLeaderboard

const https = require('https');

// INPUTS
// Mandatory: Repo owner that you want to analyze
// Configurations (Optional)
// Repo owner that you want to analyze
const REPO_OWNER = process.env.REPO_OWNER;
// Optional: Authentication using github token. When used, it will increase the API limits from 60 to 5000/hr
// Authentication using github token. When used, it will increase the API limits from 60 to 5000/hr
const GITHUB_PERSONAL_TOKEN = process.env.GITHUB_PERSONAL_TOKEN;
// END OF INPUTS

Expand All @@ -25,12 +27,16 @@ if(GITHUB_PERSONAL_TOKEN){

/**
* Get all github repos of an owner(user/org)
* @param {String} owner
* @param {Number} pageNo
* @param {string} owner The organization or user name on GitHub
* @param {Object} options Additional options e.g. { pageNo: 1 }
* @returns Promise<Array<Object> | String> JSON array of data on success, error on failure
* @example getAllRepos('myorghandle').then((repos) => console.log(repos)).catch((err) => console.log(err))
*/
async function getAllRepos(owner, pageNo = 1) {
async function getAllRepos(owner=REPO_OWNER, options) {
let pageNo = (options && options.pageNo) ? options.pageNo : 1;
if(options && options.GITHUB_PERSONAL_TOKEN){
GITHUB_REQUEST_OPTIONS.headers["Authorization"] = "token "+options.GITHUB_PERSONAL_TOKEN;
}
return new Promise((resolve, reject) => {
let url = `https://api.github.com/orgs/${owner}/repos?per_page=100&page=${pageNo}`;
console.log(url);
Expand All @@ -49,7 +55,7 @@ async function getAllRepos(owner, pageNo = 1) {
//It might have more data on the next page
pageNo++;
try {
let dataFromNextPage = await getAllRepos(owner, pageNo);
let dataFromNextPage = await getAllRepos(owner, { pageNo: pageNo } );
dataJsonArray.push(...dataFromNextPage);
} catch (err) {
console.log("No more pagination needed")
Expand All @@ -66,8 +72,8 @@ async function getAllRepos(owner, pageNo = 1) {

/**
* Get contributors for a Github repo
* @param {*} fullRepoName e.g. myorghandle/myreponame
* @param {*} pageNo
* @param {string} fullRepoName e.g. myorghandle/myreponame
* @param {number} pageNo
* @returns Promise<Array<Object> | String>
* @example getRepoContributors('myorghandle/myreponame').then((contributors) => console.log(contributors)).catch((err) => console.log(err))
*/
Expand Down Expand Up @@ -107,10 +113,11 @@ async function getRepoContributors(fullRepoName, pageNo = 1) {

/**
* Get all contributors across all the repos of an owner
* @param {*} owner github user or org handle
* @param {string} owner github user or org handle
* @param {Object} options Additional options
*/
async function getAllContributors(owner) {
let repos = await getAllRepos(owner);
async function getAllContributors(owner=REPO_OWNER, options) {
let repos = await getAllRepos(owner, options);
if (!repos || repos.length < 1) {
console.log("Error in getting repos for " + owner)
throw ("Error in getting repos for " + owner)
Expand Down Expand Up @@ -149,7 +156,7 @@ async function getAllContributors(owner) {

/**
* Adds up all the contributions by a contributor to different repos
* @param {*} contributors
* @param {Array} contributors
*/
function aggregateAllContributors(contributors) {
return contributors.reduce(function (grouped, currentItem) {
Expand Down Expand Up @@ -185,6 +192,10 @@ function sortReposByContributionsCount(repoContributionMappingArray){
})
}

/**
* Writes all contributors data to a file
* @param {Array} contributors
*/
function writeContributorLeaderboardToFile(contributors) {
const fs = require('fs');
let ghContributorLeaderboard = contributors.map((contributor) => {
Expand All @@ -201,10 +212,11 @@ function writeContributorLeaderboardToFile(contributors) {

/**
* Archives contributors leaderboard data sorted by contrbutions in a file
* @param {*} owner
* @param {string} owner The organization or user name on GitHub
* @param {Object} options Additional options
*/
async function archiveContributorsLeaderboard(owner) {
let contributors = await getAllContributors();
async function archiveContributorsLeaderboard(owner=REPO_OWNER, options) {
let contributors = await getAllContributors(owner, options);
if (!contributors || contributors.length < 1) {
console.log("Failed to get contributors for "+owner);
return;
Expand All @@ -218,6 +230,4 @@ async function archiveContributorsLeaderboard(owner) {
writeContributorLeaderboardToFile(contributors);

return ghHandles;
}

archiveContributorsLeaderboard(REPO_OWNER)
}
18 changes: 18 additions & 0 deletions index.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
const contributorsLib = require('./contributors');

/**
* Bundling all APIs together
* @param {*} options
*/

const OCK = {
contributors: {
github: {
archive: async function(owner, options){
contributorsLib.archiveContributorsLeaderboard(owner, options)
}
}
}
}

exports.OCK = OCK;
6 changes: 5 additions & 1 deletion package.json
Original file line number Diff line number Diff line change
@@ -1,8 +1,12 @@
{
"name": "open-community-kit",
"version": "1.0.0",
"version": "1.1.0",
"description": "Tools and stats for open-source communities",
"main": "contributors.js",
"bin": {
"ock": "cli.js",
"open-community-kit": "cli.js"
},
"scripts": {
"test": "echo \"Error: no test specified\" && exit 1"
},
Expand Down

0 comments on commit 4ae95c9

Please sign in to comment.