149 |
150 | Closing this page will stop the inspection
151 |
152 |
153 | ├── server ├── __init__.py ├── temp │ └── __init__.py ├── runtime.txt ├── Procfile ├── static │ ├── img │ │ ├── check-icon.png │ │ ├── cross-icon.png │ │ ├── extra-logo.png │ │ ├── main-logo.png │ │ └── email-header.gif │ └── css │ │ └── report.css ├── templates │ ├── redirect.html │ └── login.html ├── settings.toml ├── main.py ├── requirements.txt ├── Dockerfile ├── alembic │ ├── README │ ├── script.py.mako │ ├── versions │ │ ├── ba474f47d3f2_initial_migration.py │ │ └── 9aa6d5120b0b_columns_for_additional_statistic_added.py │ └── env.py ├── fly.toml ├── config.py ├── db.py ├── app.py ├── utils │ └── sender.py ├── alembic.ini ├── routes.py └── models.py ├── chrome-extension ├── .eslintignore ├── public │ ├── favicon.ico │ ├── images │ │ ├── icon128.png │ │ ├── icon16.png │ │ ├── icon48.png │ │ ├── popup-header.gif │ │ └── repo-banner.gif │ └── manifest.json ├── src │ ├── features │ │ ├── env.ts │ │ ├── constants.ts │ │ ├── utils │ │ │ ├── timeout.ts │ │ │ ├── getYearMonth.ts │ │ │ ├── octokitRepoUrl.ts │ │ │ ├── createName.ts │ │ │ ├── asyncForEach.ts │ │ │ ├── getOctokitRepoData.ts │ │ │ ├── getLocation.ts │ │ │ ├── initUrl.ts │ │ │ ├── getOwnTabs.ts │ │ │ ├── initToken.ts │ │ │ ├── getPullRequestStatistic.ts │ │ │ ├── index.ts │ │ │ ├── getKeysForStatisticPeriod.ts │ │ │ ├── loadFromHistory.ts │ │ │ ├── popupCenter.ts │ │ │ ├── groupStarsHistoryByMonth.ts │ │ │ ├── calculateTotalRating.ts │ │ │ ├── getIssuesStatistic.ts │ │ │ └── serializeUser.ts │ │ ├── octokit.ts │ │ ├── queries │ │ │ ├── index.ts │ │ │ ├── starHistoryQuery.ts │ │ │ ├── repositoryQuery.ts │ │ │ ├── issuesQuery.ts │ │ │ ├── pullRequestsQuery.ts │ │ │ ├── getStargazersQuery.ts │ │ │ └── getForkersQuery.ts │ │ ├── gql │ │ │ └── queries │ │ │ │ ├── index.ts │ │ │ │ ├── repositoryQuery.ts │ │ │ │ ├── starHistoryQuery.ts │ │ │ │ ├── issuesQuery.ts │ │ │ │ ├── pullRequestsQuery.ts │ │ │ │ ├── getStargazersQuery.ts │ │ │ │ └── getForkersQuery.ts │ │ ├── api.ts │ │ ├── store │ │ │ ├── history.ts │ │ │ ├── models.ts │ │ │ ├── inspectData.ts │ │ │ ├── downloader.ts │ │ │ └── notification.ts │ │ ├── authentication.ts │ │ └── repoInspector.ts │ ├── assets │ │ └── scss │ │ │ ├── transition.scss │ │ │ ├── alerts.scss │ │ │ └── custom.scss │ ├── entry │ │ ├── background.ts │ │ ├── popup.ts │ │ └── options.ts │ ├── view │ │ ├── components │ │ │ ├── StatisticChart.vue │ │ │ ├── DownloadCard.vue │ │ │ ├── TotalRatingWeightsSettings.vue │ │ │ └── HistoryCard.vue │ │ ├── options.vue │ │ └── popup.vue │ └── global.d.ts ├── .prettierrc.cjs ├── graphql.config.yml ├── README.md ├── popup.html ├── options.html ├── background.html ├── .vscode │ └── settings.json ├── tsconfig.json ├── package.json ├── vite.config.js └── .eslintrc ├── .vscode └── launch.json ├── README.md └── .gitignore /server/__init__.py: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /server/temp/__init__.py: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /server/runtime.txt: -------------------------------------------------------------------------------- 1 | python-3.10.7 -------------------------------------------------------------------------------- /server/Procfile: -------------------------------------------------------------------------------- 1 | web: gunicorn -k uvicorn.workers.UvicornWorker main:app -------------------------------------------------------------------------------- /chrome-extension/.eslintignore: -------------------------------------------------------------------------------- 1 | node_modules/ 2 | public/ 3 | dist/ 4 | src/assets/ 5 | vite.config.js 6 | graphql.schema.ts 7 | -------------------------------------------------------------------------------- /server/static/img/check-icon.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/HetzVentures/repoInspector/HEAD/server/static/img/check-icon.png -------------------------------------------------------------------------------- /server/static/img/cross-icon.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/HetzVentures/repoInspector/HEAD/server/static/img/cross-icon.png -------------------------------------------------------------------------------- /server/static/img/extra-logo.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/HetzVentures/repoInspector/HEAD/server/static/img/extra-logo.png -------------------------------------------------------------------------------- /server/static/img/main-logo.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/HetzVentures/repoInspector/HEAD/server/static/img/main-logo.png -------------------------------------------------------------------------------- /chrome-extension/public/favicon.ico: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/HetzVentures/repoInspector/HEAD/chrome-extension/public/favicon.ico -------------------------------------------------------------------------------- /chrome-extension/src/features/env.ts: -------------------------------------------------------------------------------- 1 | const settings = { 2 | rollbarAccessToken: '', 3 | }; 4 | 5 | export default settings; 6 | -------------------------------------------------------------------------------- /server/static/img/email-header.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/HetzVentures/repoInspector/HEAD/server/static/img/email-header.gif -------------------------------------------------------------------------------- /chrome-extension/src/features/constants.ts: -------------------------------------------------------------------------------- 1 | export const USERS_QUERY_LIMIT = 20; 2 | 3 | export const MINIMUM_REQUEST_LIMIT_AMOUNT = 10; 4 | -------------------------------------------------------------------------------- /chrome-extension/public/images/icon128.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/HetzVentures/repoInspector/HEAD/chrome-extension/public/images/icon128.png -------------------------------------------------------------------------------- /chrome-extension/public/images/icon16.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/HetzVentures/repoInspector/HEAD/chrome-extension/public/images/icon16.png -------------------------------------------------------------------------------- /chrome-extension/public/images/icon48.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/HetzVentures/repoInspector/HEAD/chrome-extension/public/images/icon48.png -------------------------------------------------------------------------------- /chrome-extension/.prettierrc.cjs: -------------------------------------------------------------------------------- 1 | module.exports = { 2 | trailingComma: 'all', 3 | tabWidth: 2, 4 | semi: true, 5 | singleQuote: true, 6 | }; 7 | -------------------------------------------------------------------------------- /server/templates/redirect.html: -------------------------------------------------------------------------------- 1 | 2 |
3 | 6 | 7 | -------------------------------------------------------------------------------- /chrome-extension/public/images/popup-header.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/HetzVentures/repoInspector/HEAD/chrome-extension/public/images/popup-header.gif -------------------------------------------------------------------------------- /chrome-extension/public/images/repo-banner.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/HetzVentures/repoInspector/HEAD/chrome-extension/public/images/repo-banner.gif -------------------------------------------------------------------------------- /chrome-extension/src/features/utils/timeout.ts: -------------------------------------------------------------------------------- 1 | export const timeout = (ms: number) => 2 | new Promise((resolve) => { 3 | setTimeout(resolve, ms); 4 | }); 5 | -------------------------------------------------------------------------------- /server/settings.toml: -------------------------------------------------------------------------------- 1 | [development] 2 | dynaconf_merge = true 3 | 4 | [development.db] 5 | echo = true 6 | 7 | [production] 8 | dynaconf_merge = true 9 | 10 | 11 | -------------------------------------------------------------------------------- /chrome-extension/src/features/utils/getYearMonth.ts: -------------------------------------------------------------------------------- 1 | export const getYearMonth = (date: Date): string => 2 | `${date.getFullYear()}.${(date.getMonth() + 1).toString().padStart(2, '0')}`; 3 | -------------------------------------------------------------------------------- /chrome-extension/src/features/utils/octokitRepoUrl.ts: -------------------------------------------------------------------------------- 1 | import { createName } from './createName'; 2 | 3 | export const octokitRepoUrl = (repo: string) => 4 | // get repo name for octokit 5 | `/repos/${createName(repo)}`; 6 | -------------------------------------------------------------------------------- /server/main.py: -------------------------------------------------------------------------------- 1 | from routes import repository_router, login_router 2 | from app import app 3 | 4 | app.include_router(repository_router, tags=["repositories"], prefix="/repository") 5 | app.include_router(login_router, prefix="/login") 6 | -------------------------------------------------------------------------------- /chrome-extension/src/features/utils/createName.ts: -------------------------------------------------------------------------------- 1 | export const createName = (repo: string) => { 2 | // remove any parts of url beyond repo name 3 | const urlParts = repo.split('/'); 4 | 5 | return `${urlParts[3]}/${urlParts[4]}`; 6 | }; 7 | -------------------------------------------------------------------------------- /chrome-extension/src/features/octokit.ts: -------------------------------------------------------------------------------- 1 | import { Octokit } from '@octokit/core'; 2 | 3 | // Initialize octokit instance 4 | const initOctokit = (accessToken: null | void | string) => 5 | new Octokit({ auth: accessToken }); 6 | 7 | export { initOctokit }; 8 | -------------------------------------------------------------------------------- /server/requirements.txt: -------------------------------------------------------------------------------- 1 | Jinja2==3.1.2 2 | google-auth==2.13.0 3 | dynaconf==3.1.11 4 | PyMySQL==1.0.2 5 | sqlmodel==0.0.8 6 | fastapi[all]==0.85.0 7 | gunicorn==20.1.0 8 | pydantic>=1.8.0,<2.0.0 9 | uvicorn>=0.15.0,<0.16.0 10 | psycopg2-binary==2.9.5 11 | rollbar==0.16.3 12 | pdfkit==1.0.0 -------------------------------------------------------------------------------- /chrome-extension/src/features/utils/asyncForEach.ts: -------------------------------------------------------------------------------- 1 | export const asyncForEach = async ( 2 | array: any[], 3 | callback: (item: any, index: number, array: any[]) => Promise
149 |
150 | Closing this page will stop the inspection
151 |
152 |
153 |
47 |
48 | You’re ready to start inspecting repositories! Here’s how that works:
49 |
50 | 1. In your browser, go to the Github page for a repository you’re curious about, open the Chrome extension and click Inspect.
51 | Before you inspect, you have a few options for the data. Toggle between receiving Only Stars (default), Only Forks, Stars and Forks, or Sampling.
52 | 2. Once you click Inspect, you’ll see a progress window.
53 |
54 | Note - it may take a few seconds to start showing progress, and the larger the amount of Stars or Forks, the longer it will take to start and progress.
55 |
56 | Note - up to 40k Stars and 40k Forks can be pulled for any one inspection.
57 |
58 | 3. Your result will arrive in your inbox once the progress bar hits 100%.
59 | If you don't see the email right away, check your spam folder. The report will send from repoinspector@hetzventures.org.
60 |
61 | ## About us
62 |
63 | [repoInspector](https://chrome.google.com/webstore/detail/repo-inspector/hogkmljfjdgibeoepenpfggaiipngknb) was originally designed and started by the team at [Hetz Ventures](https://www.hetz.vc/). We were looking for a simple way to access useful data on repository user activity around Github projects for industry insights, due diligence, comparative analysis, etc.
64 |
65 | This Chrome extension is useful for other investors, startup founders and really anyone looking to better understand user behavior and their markets.
66 |
67 | We welcome contributors to this project! Here’s how you can get set up:
68 |
69 | ## Project setup
70 |
71 | There is both a client and a server in this repository. You can decide to only work on the client side (i.e. the chrome extension) or on both.
72 | To set up the client side, clone the repo and:
73 |
74 | ```
75 | cd chrome-extension
76 | yarn install
77 | ```
78 |
79 | ### Graphql schema generation
80 |
81 | ```
82 | yarn generate-ts-gql (This command must be executed each time after creating a new query to generate new types)
83 | ```
84 |
85 | ### Compiles and hot-reloads for development
86 |
87 | ```
88 | yarn build-watch
89 | ```
90 |
91 | This will create a `dist` folder. Go to [chrome://extensions](chrome://extensions) and click 'Load unpacked', after which navigate to the `dist` folder and click open, the extension should load and will reload with every save to the codebase.
92 |
93 | ### Compiles and minifies for production
94 |
95 | ```
96 | yarn run build
97 | ```
98 |
99 | ### Lints and fixes files
100 |
101 | ```
102 | yarn run lint
103 | ```
104 |
105 | ### Customize configuration
106 |
107 | See [Configuration Reference](https://cli.vuejs.org/config/).
108 |
109 | ### Server setup
110 |
111 | ```
112 | cd server
113 | pip install -r requirements.txt
114 | ```
115 |
116 | Create a file called `.secrets.toml` in the `server` directory and fill it in with the following (fill in the missing variables):
117 |
118 | ```
119 | [development]
120 | dynaconf_merge = true
121 |
122 | [development.db]
123 | sql_url = ''
124 |
125 | [development.google]
126 | data_client_id = ""
127 |
128 | [development.email]
129 | username = ''
130 | password = ''
131 | smtp_server = ''
132 | port = ''
133 |
134 | [development.security]
135 | # openssl rand -hex 32
136 | SECRET_KEY = ""
137 | ```
138 |
139 | ### Run server
140 |
141 | ```
142 | uvicorn main:app
143 | ```
144 |
145 | ### Production Setup
146 |
147 | The server is set up to run on Heroku, to push to heroku, add a new heroku remote and run from the base folder:
148 |
149 | ```
150 | git subtree push --prefix server heroku main
151 | ```
152 |
153 | The environment variables convention on the server `API_DB__` so for sql_url it would be `API_DB__sql_url`.
154 |
155 | ## Classifications
156 |
157 | Some data is classified by our business logic and is not fetched directly from Github. The following are data points we have defined:
158 |
159 | - Real user - user who has had more than three "events" (commit, PR, etc.) or user who has more than three followers.
160 | - Active user - user who has an event in the past year.
161 | - Country - while users can input their location in their profile, this is free-text which make it difficult to aggregate. To solve this problem, we use nominatim.openstreetmap.org location api to fetch the country of every location free-text and extract its country.
162 |
--------------------------------------------------------------------------------
/chrome-extension/src/view/components/TotalRatingWeightsSettings.vue:
--------------------------------------------------------------------------------
1 |
2 | Total: {{ totalWeight }}%
110 | 111 | 112 |
294 |
295 |
296 |