32 |
33 |
34 | ## Preview
35 |
36 | ### Repos
37 |
38 | This page shows a list of all of the user's repos. With optional filter on name.
39 |
40 | [](https://michael-currin.netlify.app/repos/)
41 |
42 | ### Topics
43 |
44 | Show all repos grouped by topic (e.g. `#jekyll` or `#github-pages-site`).
45 |
46 | [](https://michael-currin.netlify.app/topics/)
47 |
48 |
49 | ## Setup your own portfolio
50 |
51 | How to reuse this repo and to make portfolio site for yourself.
52 |
53 | 1. Fork this repo to your own GitHub account.
54 | 2. Follow instructions in the docs for local or remote setup.
55 | 3. Make any custom updates like config values and making the doc badges point to your repo.
56 | 4. Comply with [License](#license) section below.
57 |
58 | In the setup instructions, you'll generate a GitHub secret token for your account. The GitHub GraphQL query will then get data for you as the authenticating user. You do not have to set your own GitHub username anywhere.
59 |
60 |
61 | ## Documentation
62 |
63 |
13 |
14 |
15 |
16 |
17 |
18 |
--------------------------------------------------------------------------------
/_plugins/github_gql.rb:
--------------------------------------------------------------------------------
1 | # Query the API and make the results available as Liquid variables.
2 | require_relative "process"
3 |
4 | module GitHubGQL
5 | class Generator < Jekyll::Generator
6 | @@QUERY_PATH = "repos_with_topics.gql"
7 |
8 | def read_env()
9 | @disable_gql = ENV["DISABLE_GQL"]
10 | @debug = ENV["DEBUG"]
11 |
12 | @token = ENV["GITHUB_TOKEN"]
13 | unless @token
14 | raise "GitHub API token must be set"
15 | end
16 | end
17 |
18 | def query
19 | if @disable_gql
20 | @repos = {}
21 | @topics = {}
22 | else
23 | gh_api = Process::GitHubAPI.new(@token, @@QUERY_PATH, @debug)
24 | @repos, @topics = gh_api.get_repos_and_topics
25 | end
26 | end
27 |
28 | def generate(site)
29 | self.read_env
30 | self.query
31 |
32 | site.data["all_repos"] = @repos
33 | site.data["all_topics"] = @topics
34 | end
35 | end
36 | end
37 |
--------------------------------------------------------------------------------
/_plugins/process.rb:
--------------------------------------------------------------------------------
1 | # Query the GraphQL API and process the data.
2 | require "json"
3 | require_relative "request"
4 |
5 | module Process
6 | def self.total_commits_of_repo(repo)
7 | # Get count of total commits, but allow branch to be not set for an empty repo edge-case.
8 | branch = repo["defaultBranchRef"]
9 |
10 | branch ? branch["commits"]["history"]["totalCount"] : 0
11 | end
12 |
13 | def self.topics_as_names(fetched_repo)
14 | topics = fetched_repo["repositoryTopics"]["nodes"]
15 | topics.map { |t| t["topic"]["name"] }
16 | end
17 |
18 | def self.repo_as_hash(repo, total_commits, topic_names)
19 | # We can't use symbols here as Jekyll can't handle symbols.
20 | # A class or struct was not practical so hash is used here.
21 | {
22 | "name" => repo["name"],
23 | "url" => repo["url"],
24 | "description" => repo["description"],
25 | "is_fork" => repo["isFork"],
26 |
27 | "created_at" => repo["createdAt"],
28 | "updated_at" => repo["updatedAt"],
29 |
30 | "stars" => repo["stargazers"]["totalCount"],
31 | "forks" => repo["forkCount"],
32 | "total_commits" => total_commits,
33 |
34 | "topics" => topic_names,
35 | }
36 | end
37 |
38 | class GitHubAPI
39 | @@API_URL = "https://api.github.com/graphql"
40 |
41 | def initialize(token, query_filename, debug)
42 | @headers = {
43 | 'Authorization': "token #{token}",
44 | 'Content-Type': "application/json",
45 | }
46 | @payload = format_payload(query_filename)
47 | @debug = debug
48 |
49 | @fetched_repos = []
50 |
51 | @repos = {}
52 | # Key must be topic name.
53 | # Value must be a hash, with key as repo name and value as hash of repo attributes.
54 | @topics = Hash.new { |hash, key| hash[key] = {} }
55 | end
56 |
57 | def request
58 | req = Request.new(@@API_URL, @headers, @payload)
59 | resp_data = req.query()
60 | user = resp_data["viewer"]
61 |
62 | @fetched_original_repos = user["originalRepos"]["nodes"]
63 | @fetched_forked_repos = user["forkedRepos"]["nodes"]
64 | end
65 |
66 | def format_payload(query_filename)
67 | query_path = File.join File.dirname(__FILE__), query_filename
68 | query_contents = File.open(query_path).read
69 |
70 | { 'query': query_contents }
71 | end
72 |
73 | def parse_repo(repo)
74 | if @debug == "2"
75 | puts "REPO RAW DATA"
76 | puts JSON.pretty_generate repo
77 | end
78 |
79 | total_commits = Process::total_commits_of_repo(repo)
80 | topic_names = Process::topics_as_names(repo)
81 |
82 | Process::repo_as_hash(repo, total_commits, topic_names)
83 | end
84 |
85 | def extract_repos_and_topics(fetched_repos)
86 | fetched_repos.each do |fetched_repo|
87 | if @debug
88 | puts "FETCHED #{fetched_repo["name"]}"
89 | end
90 |
91 | repo = self.parse_repo(fetched_repo)
92 |
93 | topic_names = Process::topics_as_names(fetched_repo)
94 | topic_names.each do |topic|
95 | if @debug
96 | puts " TOPIC #{topic}"
97 | end
98 |
99 | @topics[topic][repo["name"]] = repo
100 | end
101 |
102 | @repos[repo["name"]] = repo
103 | end
104 | end
105 |
106 | def get_repos_and_topics
107 | self.request
108 | self.extract_repos_and_topics(@fetched_original_repos)
109 | self.extract_repos_and_topics(@fetched_forked_repos)
110 |
111 | [@repos, @topics]
112 | end
113 | end
114 | end
115 |
--------------------------------------------------------------------------------
/_plugins/repos_with_topics.gql:
--------------------------------------------------------------------------------
1 | # Public repos owned by the current user.
2 | #
3 | # Querying original and forked repos separately helps overcome the page limit of 100 somewhat,
4 | # without implementing pages.
5 |
6 | fragment Repos on RepositoryConnection {
7 | nodes {
8 | # Metadata
9 | name
10 | url
11 | description
12 | isFork
13 |
14 | # Dates
15 | createdAt
16 | updatedAt
17 |
18 | # Counts
19 | stargazers {
20 | totalCount
21 | }
22 | forkCount
23 | defaultBranchRef {
24 | commits: target {
25 | ... on Commit {
26 | history(first: 1) {
27 | totalCount
28 | }
29 | }
30 | }
31 | }
32 |
33 | # TODO: use additional fields, at risk of request timeout.
34 | repositoryTopics(first: 100) {
35 | nodes {
36 | topic {
37 | name
38 | # stargazers {
39 | # totalCount
40 | # }
41 | # viewerHasStarred
42 | }
43 | #url
44 | }
45 | }
46 | }
47 | }
48 |
49 | query ownedRepos {
50 | viewer {
51 | originalRepos: repositories(
52 | first: 100
53 | ownerAffiliations: OWNER
54 | privacy: PUBLIC
55 | isFork: false
56 | orderBy: { field: UPDATED_AT, direction: DESC }
57 | ) {
58 | ...Repos
59 | }
60 |
61 | forkedRepos: repositories(
62 | first: 10 # Avoid timeout because I have so many forks.
63 | ownerAffiliations: OWNER
64 | privacy: PUBLIC
65 | isFork: true
66 | orderBy: { field: UPDATED_AT, direction: DESC }
67 | ) {
68 | ...Repos
69 | }
70 | }
71 | }
72 |
--------------------------------------------------------------------------------
/_plugins/request.rb:
--------------------------------------------------------------------------------
1 | # Request module.
2 | #
3 | # Do a request to the GitHub GraphQL API and return data.
4 | require "json"
5 | require "faraday"
6 |
7 | class Request
8 | def initialize(url, headers, payload)
9 | @url = url
10 | @headers = headers
11 | @payload = payload
12 | end
13 |
14 | def post
15 | puts "Do POST request"
16 | resp = Faraday.post(
17 | @url,
18 | @payload.to_json,
19 | @headers,
20 | )
21 |
22 | puts "Status: #{resp.status}"
23 | if resp.status > 299
24 | puts "Body:"
25 | puts resp.body
26 | raise "Request status: #{resp.status}"
27 | end
28 |
29 | JSON.parse resp.body
30 | end
31 |
32 | def query()
33 | results = self.post()
34 |
35 | errors = results["errors"]
36 | if errors
37 | puts "Errors on response:"
38 | puts JSON.pretty_generate errors
39 | raise "Request error!"
40 | end
41 |
42 | results["data"]
43 | end
44 |
45 | def test
46 | data = self.query()
47 |
48 | puts "Pretty printed response"
49 | puts JSON.pretty_generate data
50 | end
51 | end
52 |
--------------------------------------------------------------------------------
/_plugins/thousands-separated-filter.rb:
--------------------------------------------------------------------------------
1 | # From: https://github.com/MichaelCurrin/Liquid-Thousands-Separated-Filter
2 | module Jekyll
3 | module ThousandsSeparatedFilter
4 | def thousands_separated(input, separator = ",")
5 | input.to_s.gsub(/(\d)(?=(\d\d\d)+(?!\d))/, "\\1#{separator}")
6 | end
7 | end
8 | end
9 |
10 | Liquid::Template.register_filter(Jekyll::ThousandsSeparatedFilter)
11 |
--------------------------------------------------------------------------------
/_sass/_overrides.scss:
--------------------------------------------------------------------------------
1 | /** Basic **/
2 |
3 | html {
4 | background-color: #333;
5 | }
6 |
7 | body {
8 | height: 100%;
9 | color: white;
10 | }
11 |
12 | .content h1,
13 | .content h2,
14 | .content h3,
15 | .content h4 {
16 | color: white;
17 | }
18 |
19 | /* Using dark background means treating links differently in main.*/
20 | #main {
21 | a {
22 | color: cornflowerblue;
23 | }
24 |
25 | a:hover {
26 | color: lightskyblue;
27 | }
28 | }
29 |
30 | /* Use the theme's blue on the white bg cards. */
31 | .card {
32 | a {
33 | color: #3273dc;
34 | }
35 |
36 | a:hover {
37 | color: grey;
38 | }
39 | }
40 |
41 | /** List JS **/
42 |
43 | /* For columns of cards, remove shadow mainly - override Bulma styling of `list` class, as this is used for ListJS. */
44 | .columns.list {
45 | background-color: inherit;
46 | border-radius: inherit;
47 | box-shadow: inherit;
48 | }
49 |
50 | /* Allow search bar to have a reasonable size - override Bulma setting of 100%. */
51 | .search.input {
52 | width: inherit;
53 | }
54 |
--------------------------------------------------------------------------------
/about.md:
--------------------------------------------------------------------------------
1 | ---
2 | title: About
3 | layout: page
4 | ---
5 |
6 | ## Why
7 |
8 | This website is a showcase of my own repos and the topics they fit into. For my own ease of using in searching and comparing my projects and for sharing them with others beyond the limitations of the standard view of repos on a profile on GitHub.
9 |
10 |
11 | ## Where
12 |
13 | [](https://github.com/MichaelCurrin/my-github-projects)
14 |
15 |
16 | ## What
17 |
18 | This project a static website hosted on [Netlify](https://netlify.com) for free and uses the following tools:
19 |
20 | - [](https://jekyllrb.com)
21 | - [](https://github.com/jekyll-octopod/jekyll-bulma)
22 | - [](https://www.ruby-lang.org)
23 | - [](https://developer.github.com/v4/)
24 |
25 |
26 | ## How
27 |
28 | On build, a request is done to GitHub GraphQL API to get repos and their topic labels. For the All Topics page, the structure is inverted such that topics contain repos.
29 |
30 | You can fork and reuse this project to make a site showing your own GitHub repos. Follow the repo's [README](https://github.com/MichaelCurrin/my-github-projects/blob/master/README.md).
31 |
32 |
33 | ## Background
34 |
35 | The idea was inspired a quickstart dev portfolio that GitHub supplies:
36 |
37 | - The original repo: [github/personal-website](https://github.com/github/personal-website)
38 | - My site, using a fork of the above: [michaelcurrin.github.io/](https://michaelcurrin.github.io/)
39 |
--------------------------------------------------------------------------------
/docs/README.md:
--------------------------------------------------------------------------------
1 | ---
2 | permalink: /
3 | ---
4 | ## Documentation
5 |
6 | [](https://github.com/MichaelCurrin/my-github-projects)
7 |
8 | - [Overview](overview.md) - info about how this project works and its purpose.
9 | - [Requirements](requirements.md) - Read this before you start.
10 | - [Installation](installation.md) - Install locally.
11 | - [Usage](usage.md) - Run locally.
12 | - [Deploy](deploy.md) - Setup and run on Netlify.
13 | - [Token](token.md) - Generate a GitHub access token.
14 | - [Development](development.md) - For understanding and changing this project.
15 |
--------------------------------------------------------------------------------
/docs/deploy.md:
--------------------------------------------------------------------------------
1 | # Deploy
2 |
3 |
4 | ## Create a token
5 |
6 | Follow the [Token](token.md) doc then continue below.
7 |
8 |
9 | ## Setup Netlify
10 |
11 | 1. Ensure you have the repo or a fork in your GitHub account.
12 | 2. Add the repo to your Netlify account.
13 | 3. Edit the deploy **environment** variables - add `GITHUB_TOKEN` and use your value.
14 | 4. Open the deployed URL.
15 |
16 | Notes on the build command in [netlify.toml][] config:
17 |
18 | - The _Jekyll_ install is automatic, so just the JS install is needed.
19 | - An `.env` file is not needed here, since using Netlify secrets.
20 | - Netlify does not use _Bundler_.
21 |
22 | Note that _Node_ is already available on Netlify.
23 |
24 | [netlify.toml]: https://github.com/MichaelCurrin/my-github-projects/blob/master/netlify.toml
25 |
26 | ## Setup GitHub Pages
27 |
28 | Note that this does **not build** to GitHub Pages.
29 |
30 | You need to add a GitHub Actions workflow instead, which handles install and run steps and use of the token.
31 |
--------------------------------------------------------------------------------
/docs/development.md:
--------------------------------------------------------------------------------
1 | # Development
2 |
3 | Notes for developing this project.
4 |
5 |
6 | ## Background
7 |
8 | This project was inspired by the listing of repository cards shown through [github/personal-website](https://github.com/github/personal-website) repo. That shows data for a couple of repos, using the [Jekyll GitHub Metadata plugin](https://github.com/jekyll/github-metadata) and GitHub REST API internally. The public repos output from the plugin covers repos in detail, but there is not topic data and the language labels are limited (they are inferred and they do not reflect the purpose or tooling of a project).
9 |
10 | This _My GitHub Projects_ repo goes a step further by getting repos and their topics, then grouping them by their topics (labels set for a GitHub repo). This was made possible by create a plugin (in Ruby) and for efficiency this was done using the GitHub GraphQL API (such that one request returns 100 repos and their labels at once).
11 |
12 | I did a proof-of-concept for a Ruby plugin for GraphQL request using this repo - [MichaelCurrin/github-gql-ruby](https://github.com/MichaelCurrin/github-gql-ruby). However, the two projects have diverged as I made more changes in this project than that one, until I can make that one installable or as a submodule + symlink into plugins directory. Also this portfolio site will be easier for me to maintain using a Ruby library for GraphQL or a Python script (which would write out a JSON file to be read as a data file by Jekyll).
13 | I chose Ruby initially for interest so I could do something useful with Ruby but the solution is not so flexible for me.
14 |
15 |
16 | ## Future development ideas
17 |
18 | - [ ] Adding sorting of own repos by various fields.
19 | - [ ] Add section to focus on chosen repos as a showcase.
20 | - [ ] Add section to focus on chosen topics.
21 | - [ ] Add images for topics.
22 | - [ ] Show favorited repos, alone or by topic.
23 | - [ ] Add paging to get more than 100 repos.
24 | - [ ] Add GraphQL params on the payload for variables.
25 | - [ ] Add use of language tag. See the original repo.
26 |
27 |
28 | ## Query
29 |
30 | I can't exclude archived repos in the query. There is a `isLocked` filter but this gives no results even though I have to archived repos.
31 |
32 | I can still use `isArchived` as a field on a repo.
33 |
34 | Both `pushedAt` and `updatedAt` give the same value I think for a push. But the `pushedAt` one doesn't count updating the repo setup on GitHub, meaning `updatedAt` will be more recent so I use that.
35 |
36 |
37 | ## Access token
38 |
39 | It could be possible to mark the token as _optional_ and return empty data in the custom plugin, but this causes issues in other parts which except a structure.
40 |
41 | One way to reduce build time is to comment out the Jekyll GitHub Metadata Plugin from the gem file or to set the number of repos in the GQL query file to a low number.
42 |
43 | To avoid your token being exposed in a PR build triggered by a malicious fork (which might add to the build command or `Makefile`, please keep your log visibility as **private** in your Netlify app's Deploy settings.
44 |
45 |
46 | ## Styling
47 |
48 | The [jekyll-octopod/jekyll-bulma](https://github.com/jekyll-octopod/jekyll-bulma) gem is used. This makes it easy to start using existing templating approach based on [Bulma](https://bulma.io/) component styling. It also means Bulma is instead and locked at a version, which was the main reason for using the theme here.
49 |
50 | Bulma links:
51 |
52 | - [Form controls](https://bulma.io/documentation/form/general/)
53 | - [Panel](https://bulma.io/documentation/components/panel/) doc - for search bar.
54 |
55 |
56 | ### CSS file
57 |
58 | See the [SASS][] directory.
59 |
60 | [SASS]: https://github.com/MichaelCurrin/my-github-projects/tree/master/_sass
61 |
62 | This file shadows the name of an empty file in the theme, to ensure it gets processed. There may be
63 | better ways but this works okay. This content is added to the main.css file created mostly from
64 | Bulma content.
65 |
66 | This is not ideal as it does not replace the existing rule (such as background color), but it does
67 | appends at the bottom of the main.css, which still works. Maybe this could be split out further
68 | using multiple files, variables and imports, but this works okay.
69 |
70 | Maybe override in utilities/derived-variables. Or over variables before import is done, where color variables are used.
71 |
72 |
73 | ## Reloading
74 |
75 | At build time:
76 |
77 | - GitHub metadata - A request is done to GitHub API through the Jekyll GitHub Metadata plugin, which adds `site.github` to the templating namespace. This includes details about the owner, the current repo (based on the remote origin if local) and public repos.
78 | - GraphQL request - A request is done to GitHub GraphQL API using this project's custom plugin.
79 |
80 | When saving changes to the repo, the server will restart. The GitHub metadata will not be fetched again but any changes to changes to templating will be applied. The GraphQL request will also be done - investigation could be done to avoid this happening.
81 |
82 |
83 | ## Running scripts
84 |
85 | The Ruby plugin script cannot be run directly, only through Jekyll. This seems to be a bug in one of the gems.
86 |
87 | More specifically, it happens after `jekyll` is installed (it does install `eventmachine` in vendor but this can't pick it up).
88 |
89 | ```sh
90 | $ bundle exec ruby request.rb
91 | ```
92 | ```
93 | Could not find eventmachine-1.2.7 in any of the sources
94 | Run `bundle install` to install missing gems.
95 | ```
96 |
97 | This does not help:
98 |
99 | ```ruby
100 | gem 'eventmachine', '1.2.7'
101 | ```
102 |
103 | Update: Maybe adding `eventmachine` to Gemfile and bundle install would then help?
104 |
105 |
106 | ## Format Ruby scripts
107 |
108 | ```sh
109 | $ make fmt
110 | ```
111 |
112 |
113 | ## Packages
114 |
115 | ### list.js
116 |
117 | Add live filtering to repos based on user search input.
118 |
119 | - Docs - https://listjs.com
120 | - NPM - https://www.npmjs.com/package/list.js
121 |
122 |
123 | ### jemoji
124 |
125 | - https://github.com/jekyll/jemoji
126 |
127 | This adds support for emojis. This helps for processing emojis in descriptions. Unfortunately, while it processes something like `:shield:` it does not process others like `:badger:`. See the Badge Generator repo.
128 |
129 | ### jekyll-timeago
130 |
131 | - https://github.com/markets/jekyll-timeago
132 |
133 | Adds support for showing a date as how long ago (e.g. `today` or `2 months and 2 days ago`). A downside of this is that `today` is relative to the build date and not the date for the viewer visiting the site, so this should go back to plain dates, or the site should rebuild more often.
134 |
135 | ### jekyll-github-metadata
136 |
137 | Take this out of `Gemfile` locally to avoid API rate limit warnings. You just won't get user profile data of the user, such as the logo.
138 |
--------------------------------------------------------------------------------
/docs/installation.md:
--------------------------------------------------------------------------------
1 | ## Installation
2 | > How to setup the project locally
3 |
4 |
5 | ## Install system dependencies
6 |
7 | - Ruby and Bundler - follow this [gist](https://gist.github.com/3af38fca4e2903cdedfb8402c18b2936).
8 | - Install Node.js - follow this [gist](https://gist.github.com/MichaelCurrin/aa1fc56419a355972b96bce23f3bccba).
9 |
10 |
11 | ## Install project packages
12 |
13 | Setup a hook to build before pushing.
14 |
15 | ```sh
16 | $ make hooks
17 | ```
18 |
19 | Install local packages - NPM packages in `node_modules` and gems in `vendor`.
20 |
21 | ```sh
22 | $ make install
23 | ```
24 |
25 |
26 | ## Configure
27 |
28 | 1. Make sure you generated a token as per the [Token](token.md) doc.
29 | 2. Create an dotenv file from the template.
30 | ```sh
31 | $ cp .env.template .env
32 | ```
33 | 3. Open the `.env` file and add your secret token value and save the file.
34 |
35 | The result will be something like:
36 |
37 | - `.env`
38 | ```sh
39 | GITHUB_TOKEN=abcedf123
40 | ```
41 |
42 | This project has been set up to **ignore** this file, to prevent it being accidentally committed and shared publicly.
43 |
--------------------------------------------------------------------------------
/docs/overview.md:
--------------------------------------------------------------------------------
1 | # Overview
2 |
3 | ## How it works
4 |
5 | This project will show your GitHub account's public repos as a statically generated Jekyll site, both locally or on a remote location such as on Netlify. (This _could_ work also with GitHub Actions to run the custom plugins and Jekyll 4. See the [GitHub Actions](https://jekyllrb.com/docs/continuous-integration/github-actions/) section on Jekyll docs - then a schedule parameter could be used for nightly or weekly builds.)
6 |
7 | The main limitation that the site has rebuilt in order to get the latest repos and topic tags, but that is easy enough to trigger a new build by hand occasionally on Netlify - command-line `curl` POST requests can even trigger a build. And also this project works best when you have a lot of repos (over 10) and also use detailed but consistent tags based on the use (tool / linter / static site) or tech used (programming language / library / host location).
8 |
9 |
10 | ## Purpose
11 |
12 | This project is setup to show repo data for the **current authenticated GitHub user** (i.e. not other users). This is easy with the `jekyll-github-metadata` plugin, but that uses GitHub API version 3 and it does not handle labels. So through some Ruby plugin scripts, this project fetches 100 repos including topics on each and then build a object with topic labels on the outside and repos within.
13 |
14 | You can **fork** this project and setup as a Netlify static site which shows your **own** repos and their topic labels. You just have to configure your secret token and the query will get your repos.
15 |
16 | When setup as a website, this project can serve the following purposes for the owner:
17 |
18 | - Quick reference to **find your own repos** by name and check their stats. With future development, you can find most recent, most starred, etc.
19 | - Group your repos by **topic**.
20 | - This is is very useful as a portfolio for **job interviews**, since someone can for example see how many Machine Learning, Python and static site projects you have. They can see at a glance what **activity** there is (last updated, how many stars) and optionally click through to see the actual repo.
21 | - This project is useful for maintaining or searching projects **for yourself**. For example if you want to find all your projects which are hosted on GitHub Pages or Netlify (assuming they are well-labelled). Or all the templates projects.
22 | - If you want to teach someone about a language or tool and what to show them what you've made, you can guide them to certain topics.
23 | - This project gives you freedom to change the **styling** if you want to present the data in a different way.
24 | - After future development, you can highlight repos or topics to **guide visitors towards**, or help you get to your most important or frequently accesses areas first.
25 |
26 | If you want to explore your _private_ repos only, change the `privacy` value in the GraphQL query from `PUBLIC` to `PRIVATE`. Though you might want to just build that locally to avoid sharing that data.
27 |
--------------------------------------------------------------------------------
/docs/requirements.md:
--------------------------------------------------------------------------------
1 | # Requirements
2 |
3 | | Name | Purpose |
4 | | -------------------- | ---------------------------------------------------------------------------- |
5 | | GitHub account | Repos owned by your account will used for reporting. |
6 | | [GitHub dev token][] | For GraphQL API requests. Only _read_ access to your public repos is needed. |
7 | | [Netlify][] account | Optionally used to deploy the site remotely. |
8 | | [Ruby][] >= 2.6 | Run the custom Jekyll [plugins][] - includes a query to the GitHub API. |
9 | | [Bundler][] | Install project-scoped gems from the [Gemfile][]. |
10 | | [Node][] | Install and run project-scoped Node packages from the [package.json][]. |
11 |
12 | This project will **not** work on GitHub Pages, unless you use GitHub Actions. Netlify is used here because it requires much less configuration than GitHub Actions.
13 |
14 | [GitHub dev token]: https://github.com/settings/tokens
15 | [Netlify]: https://netlify.com
16 | [Ruby]: https://www.ruby-lang.org/en/
17 | [Node]: https://nodejs.org/
18 | [Bundler]: https://bundler.io/
19 |
20 | [plugins]: https://github.com/MichaelCurrin/my-github-projects/tree/master/_plugins
21 | [package.json]: https://github.com/MichaelCurrin/my-github-projects/blob/master/package.json
22 | [Gemfile]: https://github.com/MichaelCurrin/my-github-projects/blob/master/Gemfile
23 |
--------------------------------------------------------------------------------
/docs/token.md:
--------------------------------------------------------------------------------
1 | # Token
2 | > Create a GitHub API token
3 |
4 | This project relies on create a GitHub API access token with read-only access to your own repos.
5 | The token is then sent to GitHub API on a POST request.
6 |
7 |
8 | To set this up:
9 |
10 | 1. Open **Personal access tokens** page on your GitHub account.
11 | 1. Settings page.
12 | 2. Developer Settings.
13 | 3. [Tokens](https://github.com/settings/tokens) page.
14 | 2. Grant **read-only** permissions to your public repos.
15 | - Tick the `public_repo` option only.
16 | 3. **Create** the token.
17 | 4. **Copy** the token value.
18 | - The value will **not** be visible after you leave this screen, however, you can always regenerate the token value.
19 |
20 | You may continue to the [Remote](remote.md) or local [Installation](installation.md) steps, where you will add the token to your secret environment variables.
21 |
--------------------------------------------------------------------------------
/docs/usage.md:
--------------------------------------------------------------------------------
1 | # Usage
2 | > Run locally
3 |
4 |
5 | ## Serve
6 |
7 | Start the development server.
8 |
9 | ```sh
10 | $ make serve
11 | ```
12 |
13 | Open in the browser:
14 |
15 | - http://localhost:4000/
16 |
17 |
18 | ## Build
19 |
20 | Do a build with verbose logging.
21 |
22 | ```sh
23 | $ make build-dev
24 | ```
25 |
26 |
27 | ## Disable fetch
28 |
29 | Run the build or serve steps without fetching GraphQL API data.
30 |
31 | ```sh
32 | $ DISABLE_GQL=1 make build-dev
33 | ```
34 |
35 | This will be quicker to run and doesn't require auth set up (an empty `.env` file is needed at least). The rendered site will just be mostly empty.
36 |
37 |
38 | Note that the `github-metadata` plugin will still be used, to fetch user data like profile image. This doesn't require a token but will eventually get API rejects past the rate limiting threshold.
39 |
--------------------------------------------------------------------------------
/favicon.ico:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/MichaelCurrin/my-github-projects/15f8b2f4efe98dd38f9f332d6c6ddc6bf110f97a/favicon.ico
--------------------------------------------------------------------------------
/hooks/pre-push:
--------------------------------------------------------------------------------
1 | #!/bin/sh -e
2 |
3 | # On a feature branch that has no remote yet, this first part would fail.
4 | git pull --rebase || git pull --rebase origin master
5 |
6 | make all
7 |
--------------------------------------------------------------------------------
/index.md:
--------------------------------------------------------------------------------
1 | ---
2 | title: Home
3 | layout: home
4 | ---
5 |
6 | # [{{ site.github.owner_name }}]({{ site.github.owner_url }})
7 |
8 | 
9 |
10 | {{ site.github.owner.bio }}
11 |
--------------------------------------------------------------------------------
/netlify.toml:
--------------------------------------------------------------------------------
1 | [build]
2 | command = "make setup-js build-prod"
3 | publish = "_site"
4 |
5 |
6 | # The `activesupport` gem needs this from v7 on.
7 | [context.production]
8 | environment = { RUBY_VERSION = "2.7.0" }
9 |
10 | [context.deploy-preview]
11 | environment = { RUBY_VERSION = "2.7.0" }
12 |
--------------------------------------------------------------------------------
/package-lock.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "my-github-projects",
3 | "version": "0.10.2",
4 | "lockfileVersion": 2,
5 | "requires": true,
6 | "packages": {
7 | "": {
8 | "name": "my-github-projects",
9 | "version": "0.10.2",
10 | "license": "MIT",
11 | "dependencies": {
12 | "list.js": "^2.3.1"
13 | }
14 | },
15 | "node_modules/list.js": {
16 | "version": "2.3.1",
17 | "resolved": "https://registry.npmjs.org/list.js/-/list.js-2.3.1.tgz",
18 | "integrity": "sha512-jnmm7DYpKtH3DxtO1E2VNCC9Gp7Wrp/FWA2JxQrZUhVJ2RCQBd57pCN6W5w6jpsfWZV0PCAbTX2NOPgyFeeZZg==",
19 | "dependencies": {
20 | "string-natural-compare": "^2.0.2"
21 | },
22 | "engines": {
23 | "node": "^6.0 || ^8.0 || ^10.0 || ^12.0 || >=14"
24 | }
25 | },
26 | "node_modules/string-natural-compare": {
27 | "version": "2.0.3",
28 | "resolved": "https://registry.npmjs.org/string-natural-compare/-/string-natural-compare-2.0.3.tgz",
29 | "integrity": "sha512-4Kcl12rNjc+6EKhY8QyDVuQTAlMWwRiNbsxnVwBUKFr7dYPQuXVrtNU4sEkjF9LHY0AY6uVbB3ktbkIH4LC+BQ=="
30 | }
31 | },
32 | "dependencies": {
33 | "list.js": {
34 | "version": "2.3.1",
35 | "resolved": "https://registry.npmjs.org/list.js/-/list.js-2.3.1.tgz",
36 | "integrity": "sha512-jnmm7DYpKtH3DxtO1E2VNCC9Gp7Wrp/FWA2JxQrZUhVJ2RCQBd57pCN6W5w6jpsfWZV0PCAbTX2NOPgyFeeZZg==",
37 | "requires": {
38 | "string-natural-compare": "^2.0.2"
39 | }
40 | },
41 | "string-natural-compare": {
42 | "version": "2.0.3",
43 | "resolved": "https://registry.npmjs.org/string-natural-compare/-/string-natural-compare-2.0.3.tgz",
44 | "integrity": "sha512-4Kcl12rNjc+6EKhY8QyDVuQTAlMWwRiNbsxnVwBUKFr7dYPQuXVrtNU4sEkjF9LHY0AY6uVbB3ktbkIH4LC+BQ=="
45 | }
46 | }
47 | }
48 |
--------------------------------------------------------------------------------
/package.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "my-github-projects",
3 | "version": "0.10.2",
4 | "description": "Dev portfolio static site showing a user's GitHub repos grouped by topic",
5 | "private": "true",
6 | "author": "MichaelCurrin",
7 | "license": "MIT",
8 | "dependencies": {
9 | "list.js": "^2.3.1"
10 | }
11 | }
12 |
--------------------------------------------------------------------------------
/repos.md:
--------------------------------------------------------------------------------
1 | ---
2 | title: Repos
3 | layout: page
4 | ---
5 |
6 | This page shows all public GitHub repos which are owned by me.
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
19 |
20 |
21 |
22 |
23 |
24 |
25 |
26 | {% for repo_data in site.data.all_repos %}
27 | {% assign repo = repo_data[1] %}
28 |