38 Commits

Author SHA1 Message Date
Conventional Changelog Action
5e0ef822fd chore(release): v1.0.43 2021-10-15 07:18:53 +00:00
GitHub Actions
94635fe447 feat: reduce json output size 2021-10-15 09:17:49 +02:00
Conventional Changelog Action
5b36813618 chore(release): v1.0.42 2021-10-14 07:47:28 +00:00
GitHub Actions
dcf9898d67 fix(paginator): last page now correctly matches rex 2021-10-14 09:46:33 +02:00
Conventional Changelog Action
884fc90171 chore(release): v1.0.41 2021-10-14 07:13:40 +00:00
GitHub Actions
b97833f7c5 test: fixs suite 2021-10-14 09:12:48 +02:00
Simone Corsi
1d6848cd17 fix: should avoid index lock 2021-10-14 08:57:35 +02:00
Conventional Changelog Action
0e016f41d3 chore(release): v1.0.40 2021-10-13 22:22:11 +00:00
GitHub Actions
8f9b4ccf8d fix: fixes while exit condition 2021-10-14 00:20:38 +02:00
GitHub Actions
51da6c20db feat: paginates using async generator 2021-10-13 23:44:05 +02:00
Conventional Changelog Action
f7a8341bb1 chore(release): v1.0.39 2021-08-31 09:17:17 +00:00
Simone Corsi
c361d6e2b6 Merge pull request #12 from simonecorsi/dependabot/npm_and_yarn/path-parse-1.0.7
build(deps): bump path-parse from 1.0.6 to 1.0.7
2021-08-31 11:16:32 +02:00
dependabot[bot]
ef137b518e build(deps): bump path-parse from 1.0.6 to 1.0.7
Bumps [path-parse](https://github.com/jbgutierrez/path-parse) from 1.0.6 to 1.0.7.
- [Release notes](https://github.com/jbgutierrez/path-parse/releases)
- [Commits](https://github.com/jbgutierrez/path-parse/commits/v1.0.7)

---
updated-dependencies:
- dependency-name: path-parse
  dependency-type: indirect
...

Signed-off-by: dependabot[bot] <support@github.com>
2021-08-12 23:57:13 +00:00
Conventional Changelog Action
3e66d85077 chore(release): v1.0.38 2021-06-23 22:10:04 +00:00
Conventional Changelog Action
16430922c4 chore(release): v1.0.37 2021-06-23 22:09:38 +00:00
Simone Corsi
20b7de127d Merge pull request #7 from simonecorsi/dependabot/npm_and_yarn/hosted-git-info-2.8.9
build(deps): bump hosted-git-info from 2.8.8 to 2.8.9
2021-06-24 00:09:33 +02:00
Simone Corsi
9def6961a9 Merge pull request #9 from simonecorsi/dependabot/npm_and_yarn/normalize-url-4.5.1
build(deps): bump normalize-url from 4.5.0 to 4.5.1
2021-06-24 00:09:23 +02:00
Simone Corsi
f846c5ee47 Merge pull request #10 from simonecorsi/dependabot/npm_and_yarn/glob-parent-5.1.2
build(deps): bump glob-parent from 5.1.1 to 5.1.2
2021-06-24 00:09:00 +02:00
Simone Corsi
8133f1f32e Merge branch 'main' into dependabot/npm_and_yarn/normalize-url-4.5.1 2021-06-24 00:08:00 +02:00
Simone Corsi
19e564c928 Merge branch 'main' into dependabot/npm_and_yarn/glob-parent-5.1.2 2021-06-24 00:07:19 +02:00
Conventional Changelog Action
9c0b62271d chore(release): v1.0.36 2021-06-23 22:05:32 +00:00
GitHub Actions
7ceb9cb783 feat: saving json data for future use 2021-06-24 00:04:22 +02:00
Conventional Changelog Action
cee1906a39 chore(release): v1.0.35 2021-06-22 13:35:23 +00:00
Simone Corsi
0211f01bfb Merge pull request #11 from simonecorsi/dependabot/npm_and_yarn/set-getter-0.1.1
build(deps): bump set-getter from 0.1.0 to 0.1.1
2021-06-22 15:34:31 +02:00
dependabot[bot]
970d603c2e build(deps): bump set-getter from 0.1.0 to 0.1.1
Bumps [set-getter](https://github.com/doowb/set-getter) from 0.1.0 to 0.1.1.
- [Release notes](https://github.com/doowb/set-getter/releases)
- [Commits](https://github.com/doowb/set-getter/commits/0.1.1)

---
updated-dependencies:
- dependency-name: set-getter
  dependency-type: indirect
...

Signed-off-by: dependabot[bot] <support@github.com>
2021-06-21 21:38:21 +00:00
dependabot[bot]
e558e07817 build(deps): bump glob-parent from 5.1.1 to 5.1.2
Bumps [glob-parent](https://github.com/gulpjs/glob-parent) from 5.1.1 to 5.1.2.
- [Release notes](https://github.com/gulpjs/glob-parent/releases)
- [Changelog](https://github.com/gulpjs/glob-parent/blob/main/CHANGELOG.md)
- [Commits](https://github.com/gulpjs/glob-parent/compare/v5.1.1...v5.1.2)

---
updated-dependencies:
- dependency-name: glob-parent
  dependency-type: indirect
...

Signed-off-by: dependabot[bot] <support@github.com>
2021-06-12 15:27:03 +00:00
dependabot[bot]
202d6fe6c3 build(deps): bump normalize-url from 4.5.0 to 4.5.1
Bumps [normalize-url](https://github.com/sindresorhus/normalize-url) from 4.5.0 to 4.5.1.
- [Release notes](https://github.com/sindresorhus/normalize-url/releases)
- [Commits](https://github.com/sindresorhus/normalize-url/commits)

---
updated-dependencies:
- dependency-name: normalize-url
  dependency-type: indirect
...

Signed-off-by: dependabot[bot] <support@github.com>
2021-06-12 03:41:41 +00:00
Conventional Changelog Action
ab02c0d880 chore(release): v1.0.34 2021-05-19 09:24:47 +00:00
dependabot[bot]
110a667b31 build(deps): bump hosted-git-info from 2.8.8 to 2.8.9
Bumps [hosted-git-info](https://github.com/npm/hosted-git-info) from 2.8.8 to 2.8.9.
- [Release notes](https://github.com/npm/hosted-git-info/releases)
- [Changelog](https://github.com/npm/hosted-git-info/blob/v2.8.9/CHANGELOG.md)
- [Commits](https://github.com/npm/hosted-git-info/compare/v2.8.8...v2.8.9)

Signed-off-by: dependabot[bot] <support@github.com>
2021-05-19 09:24:36 +00:00
Conventional Changelog Action
fc187df45e chore(release): v1.0.33 2021-05-19 09:24:33 +00:00
Simone Corsi
389dc4441f Merge pull request #6 from simonecorsi/dependabot/npm_and_yarn/handlebars-4.7.7
build(deps): bump handlebars from 4.7.6 to 4.7.7
2021-05-19 11:24:02 +02:00
Simone Corsi
bbc8ec9ca5 Merge pull request #8 from simonecorsi/dependabot/npm_and_yarn/lodash-4.17.21
build(deps): bump lodash from 4.17.20 to 4.17.21
2021-05-19 11:23:53 +02:00
dependabot[bot]
10151792e7 build(deps): bump lodash from 4.17.20 to 4.17.21
Bumps [lodash](https://github.com/lodash/lodash) from 4.17.20 to 4.17.21.
- [Release notes](https://github.com/lodash/lodash/releases)
- [Commits](https://github.com/lodash/lodash/compare/4.17.20...4.17.21)

Signed-off-by: dependabot[bot] <support@github.com>
2021-05-11 23:57:18 +00:00
dependabot[bot]
012928bcda build(deps): bump handlebars from 4.7.6 to 4.7.7
Bumps [handlebars](https://github.com/wycats/handlebars.js) from 4.7.6 to 4.7.7.
- [Release notes](https://github.com/wycats/handlebars.js/releases)
- [Changelog](https://github.com/handlebars-lang/handlebars.js/blob/master/release-notes.md)
- [Commits](https://github.com/wycats/handlebars.js/compare/v4.7.6...v4.7.7)

Signed-off-by: dependabot[bot] <support@github.com>
2021-05-09 12:33:24 +00:00
Conventional Changelog Action
fe15d9358c chore(release): v1.0.32 2021-01-22 14:34:57 +00:00
Simone Corsi
5753aefaa3 docs: added documentation 2021-01-22 15:33:27 +01:00
GitHub Actions
fb228f6b20 Merge branch 'main' of github.com:simonecorsi/mawesome into main 2021-01-22 15:23:53 +01:00
GitHub Actions
3ad155575d chore: removed unused npm packages 2021-01-19 11:17:49 +01:00
10 changed files with 350 additions and 1073 deletions

View File

@@ -1,36 +1,36 @@
## <small>1.0.31 (2021-01-21)</small> ## <small>1.0.43 (2021-10-15)</small>
* feat: added user/email input for commiting ([58a7dc1](https://github.com/simonecorsi/mawesome/commit/58a7dc1)) * feat: reduce json output size ([94635fe](https://github.com/simonecorsi/mawesome/commit/94635fe))
## <small>1.0.30 (2021-01-16)</small> ## <small>1.0.42 (2021-10-14)</small>
* chore(release): v1.0.30 ([a5f15da](https://github.com/simonecorsi/mawesome/commit/a5f15da)) * chore(release): v1.0.42 ([5b36813](https://github.com/simonecorsi/mawesome/commit/5b36813))
* fix: removed push ([7f42ca0](https://github.com/simonecorsi/mawesome/commit/7f42ca0)) * fix(paginator): last page now correctly matches rex ([dcf9898](https://github.com/simonecorsi/mawesome/commit/dcf9898))
## <small>1.0.29 (2021-01-16)</small> ## <small>1.0.41 (2021-10-14)</small>
* chore(release): v1.0.29 ([874894b](https://github.com/simonecorsi/mawesome/commit/874894b)) * chore(release): v1.0.41 ([884fc90](https://github.com/simonecorsi/mawesome/commit/884fc90))
* ci: on pull_request hook ([748c821](https://github.com/simonecorsi/mawesome/commit/748c821)) * test: fixs suite ([b97833f](https://github.com/simonecorsi/mawesome/commit/b97833f))
* ci: test on push ([226c942](https://github.com/simonecorsi/mawesome/commit/226c942)) * fix: should avoid index lock ([1d6848c](https://github.com/simonecorsi/mawesome/commit/1d6848c))
* feat: added test workflow for pr ([1bd01f6](https://github.com/simonecorsi/mawesome/commit/1bd01f6))
## <small>1.0.28 (2021-01-16)</small> ## <small>1.0.40 (2021-10-13)</small>
* chore(release): v1.0.28 ([c805822](https://github.com/simonecorsi/mawesome/commit/c805822)) * chore(release): v1.0.40 ([0e016f4](https://github.com/simonecorsi/mawesome/commit/0e016f4))
* tests: added tests ([b8890fc](https://github.com/simonecorsi/mawesome/commit/b8890fc)) * fix: fixes while exit condition ([8f9b4cc](https://github.com/simonecorsi/mawesome/commit/8f9b4cc))
* feat: paginates using async generator ([51da6c2](https://github.com/simonecorsi/mawesome/commit/51da6c2))
## <small>1.0.27 (2021-01-16)</small> ## <small>1.0.39 (2021-08-31)</small>
* chore(release): v1.0.27 ([bf07858](https://github.com/simonecorsi/mawesome/commit/bf07858)) * chore(release): v1.0.39 ([f7a8341](https://github.com/simonecorsi/mawesome/commit/f7a8341))
* docs: typo ([46172a5](https://github.com/simonecorsi/mawesome/commit/46172a5)) * build(deps): bump path-parse from 1.0.6 to 1.0.7 ([ef137b5](https://github.com/simonecorsi/mawesome/commit/ef137b5))

View File

@@ -1,20 +1,41 @@
# My Awesome list # My Awesome List
This action query the github api to get starred list of the user and then generates a list ordered by languages. This action query the github api to get starred list of the user and then generates a list ordered by languages.
You can see an example of the output at my own [simonecorsi/awesome](https://github.com/simonecorsi/awesome) You can see an example of the output at my own [simonecorsi/awesome](https://github.com/simonecorsi/awesome)
## Setup ## Table of Contents
To use this action you have to create your own repository (eg: `yourname/awesome`), then create a new empty action in it and then use the [example workflow](#example-workflow) below as a starting point. <!-- toc -->
## Inputs - [Table of Contents](#table-of-contents)
- [Documentation](#documentation)
- [Requirements](#requirements)
- [Configuration](#configuration)
- [`api-token`](#api-token)
- [Example workflow](#example-workflow)
### `github-token` <!-- tocstop -->
The github workflow token is mandatory ## Documentation
### `api-token` ### Requirements
- An empty repository
- A personal github api key
### Configuration
The service can be configured setting the appropriate environment variables or writing an `.env` file.
| Variable | Description | Default |
| -------------- | ------------------------------------------- | -------------------------------- |
| `api-token` | Personal github api token. | `${{ secrets.API_TOKEN }}` |
| `github-token` | Action Token | `${{ secrets.GITHUB_TOKEN }}` |
| `github-name` | Name used for the commit, default to action | Github Action |
| `github-email` | email used for commit, default to action | actions@users.noreply.github.com |
#### `api-token`
The Personal API Access Token is mandatory to fetch stars from the API without incurring in Rate Limits. The Personal API Access Token is mandatory to fetch stars from the API without incurring in Rate Limits.
@@ -36,8 +57,11 @@ jobs:
steps: steps:
- uses: actions/checkout@v2 - uses: actions/checkout@v2
- name: Awesome generator - name: Awesome generator
uses: simonecorsi/mawesome@lastest uses: simonecorsi/mawesome@latest
with: with:
api-token: ${{ secrets.API_TOKEN }} api-token: ${{ secrets.API_TOKEN }}
github-token: ${{ secrets.GITHUB_TOKEN }} github-token: ${{ secrets.GITHUB_TOKEN }}
github-email: ${{ secrets.USER_EMAIL }}
github-name: ${{ github.repository_owner }}
``` ```

View File

@@ -10,6 +10,10 @@ inputs:
api-token: api-token:
description: 'Personal API Token' description: 'Personal API Token'
required: true required: true
github-name:
description: 'Name shown in the commit'
github-email:
description: 'Email shown in the commit'
runs: runs:
using: 'node12' using: 'node12'
main: 'index.js' main: 'index.js'

170
index.js
View File

@@ -18482,7 +18482,7 @@ const testParameter = (name, filters) => {
}; };
const normalizeDataURL = (urlString, {stripHash}) => { const normalizeDataURL = (urlString, {stripHash}) => {
const parts = urlString.match(/^data:(.*?),(.*?)(?:#(.*))?$/); const parts = urlString.match(/^data:([^,]*?),([^#]*?)(?:#(.*))?$/);
if (!parts) { if (!parts) {
throw new Error(`Invalid URL: ${urlString}`); throw new Error(`Invalid URL: ${urlString}`);
@@ -21356,12 +21356,32 @@ var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, ge
step((generator = generator.apply(thisArg, _arguments || [])).next()); step((generator = generator.apply(thisArg, _arguments || [])).next());
}); });
}; };
var __await = (this && this.__await) || function (v) { return this instanceof __await ? (this.v = v, this) : new __await(v); }
var __asyncGenerator = (this && this.__asyncGenerator) || function (thisArg, _arguments, generator) {
if (!Symbol.asyncIterator) throw new TypeError("Symbol.asyncIterator is not defined.");
var g = generator.apply(thisArg, _arguments || []), i, q = [];
return i = {}, verb("next"), verb("throw"), verb("return"), i[Symbol.asyncIterator] = function () { return this; }, i;
function verb(n) { if (g[n]) i[n] = function (v) { return new Promise(function (a, b) { q.push([n, v, a, b]) > 1 || resume(n, v); }); }; }
function resume(n, v) { try { step(g[n](v)); } catch (e) { settle(q[0][3], e); } }
function step(r) { r.value instanceof __await ? Promise.resolve(r.value.v).then(fulfill, reject) : settle(q[0][2], r); }
function fulfill(value) { resume("next", value); }
function reject(value) { resume("throw", value); }
function settle(f, v) { if (f(v), q.shift(), q.length) resume(q[0][0], q[0][1]); }
};
var __asyncValues = (this && this.__asyncValues) || function (o) {
if (!Symbol.asyncIterator) throw new TypeError("Symbol.asyncIterator is not defined.");
var m = o[Symbol.asyncIterator], i;
return m ? m.call(o) : (o = typeof __values === "function" ? __values(o) : o[Symbol.iterator](), i = {}, verb("next"), verb("throw"), verb("return"), i[Symbol.asyncIterator] = function () { return this; }, i);
function verb(n) { i[n] = o[n] && function (v) { return new Promise(function (resolve, reject) { v = o[n](v), settle(resolve, reject, v.done, v.value); }); }; }
function settle(resolve, reject, d, v) { Promise.resolve(v).then(function(v) { resolve({ value: v, done: d }); }, reject); }
};
var __importDefault = (this && this.__importDefault) || function (mod) { var __importDefault = (this && this.__importDefault) || function (mod) {
return (mod && mod.__esModule) ? mod : { "default": mod }; return (mod && mod.__esModule) ? mod : { "default": mod };
}; };
var _a; var _a;
Object.defineProperty(exports, "__esModule", ({ value: true })); Object.defineProperty(exports, "__esModule", ({ value: true }));
exports.pushNewFile = exports.OUTPUT_FILENAME = exports.generateMd = exports.paginate = exports.API_STARRED_URL = exports.REPO_USERNAME = exports.apiGetStar = exports.renderer = exports.isLastPage = exports.wait = void 0; exports.pushNewFiles = exports.MARKDOWN_FILENAME = exports.generateMd = exports.apiGetStar = exports.getNextPage = exports.renderer = exports.wait = exports.API_STARRED_URL = exports.REPO_USERNAME = void 0;
const fs_1 = __importDefault(__nccwpck_require__(5747));
const ejs_1 = __importDefault(__nccwpck_require__(8431)); const ejs_1 = __importDefault(__nccwpck_require__(8431));
const core = __importStar(__nccwpck_require__(2186)); const core = __importStar(__nccwpck_require__(2186));
const remark_1 = __importDefault(__nccwpck_require__(2081)); const remark_1 = __importDefault(__nccwpck_require__(2081));
@@ -21370,16 +21390,13 @@ const template_1 = __importDefault(__nccwpck_require__(3932));
const api_1 = __importDefault(__nccwpck_require__(8229)); const api_1 = __importDefault(__nccwpck_require__(8229));
const link_1 = __importDefault(__nccwpck_require__(9338)); const link_1 = __importDefault(__nccwpck_require__(9338));
const git_1 = __importDefault(__nccwpck_require__(6350)); const git_1 = __importDefault(__nccwpck_require__(6350));
const fs_1 = __importDefault(__nccwpck_require__(5747)); exports.REPO_USERNAME = (_a = process.env.GITHUB_REPOSITORY) === null || _a === void 0 ? void 0 : _a.split('/')[0];
exports.API_STARRED_URL = `${process.env.GITHUB_API_URL}/users/${exports.REPO_USERNAME}/starred`;
const fsp = fs_1.default.promises; const fsp = fs_1.default.promises;
function wait(time = 200) { function wait(time = 200) {
return new Promise((resolve) => setTimeout(resolve, time)); return new Promise((resolve) => setTimeout(resolve, time));
} }
exports.wait = wait; exports.wait = wait;
function isLastPage(links) {
return links.next === links.last;
}
exports.isLastPage = isLastPage;
function renderer(data, templateString = template_1.default) { function renderer(data, templateString = template_1.default) {
return __awaiter(this, void 0, void 0, function* () { return __awaiter(this, void 0, void 0, function* () {
try { try {
@@ -21392,32 +21409,91 @@ function renderer(data, templateString = template_1.default) {
}); });
} }
exports.renderer = renderer; exports.renderer = renderer;
function apiGetStar(url) { function getNextPage(links) {
const next = links.find((l) => l.rel === 'next');
const last = links.find((l) => l.rel === 'last');
if (!next || !last)
return null;
const matchNext = next.uri.match(/page=([0-9]*)/);
const matchLast = last.uri.match(/page=([0-9]*)/);
if (!matchNext || !matchLast)
return null;
if (matchNext[1] === matchLast[1])
return null;
return matchNext[1];
}
exports.getNextPage = getNextPage;
function paginateStars(url) {
return __asyncGenerator(this, arguments, function* paginateStars_1() {
let nextPage = '1';
while (nextPage) {
try {
const { headers, body } = yield __await(api_1.default.get(url, {
searchParams: {
page: nextPage,
},
}));
yield yield __await(body);
nextPage = getNextPage(link_1.default.parse(headers.link).refs);
yield __await(wait(1000)); // avoid limits
}
catch (e) {
console.error(e);
break;
}
}
});
}
function apiGetStar(url = exports.API_STARRED_URL) {
var e_1, _a;
var _b, _c, _d, _e, _f;
return __awaiter(this, void 0, void 0, function* () { return __awaiter(this, void 0, void 0, function* () {
const { headers, body } = yield api_1.default.get(url); const data = [];
return { try {
data: body, for (var _g = __asyncValues(paginateStars(url)), _h; _h = yield _g.next(), !_h.done;) {
links: link_1.default.parse(headers.link).refs.reduce((acc, val) => (Object.assign(Object.assign({}, acc), { [val.rel]: val.uri })), {}), const stars = _h.value;
}; for (const star of stars) {
data.push({
id: star.id,
node_id: star.node_id,
name: star.name,
full_name: star.full_name,
owner: {
login: (_b = star === null || star === void 0 ? void 0 : star.owner) === null || _b === void 0 ? void 0 : _b.login,
id: (_c = star === null || star === void 0 ? void 0 : star.owner) === null || _c === void 0 ? void 0 : _c.id,
avatar_url: (_d = star === null || star === void 0 ? void 0 : star.owner) === null || _d === void 0 ? void 0 : _d.avatar_url,
url: (_e = star === null || star === void 0 ? void 0 : star.owner) === null || _e === void 0 ? void 0 : _e.url,
html_url: (_f = star === null || star === void 0 ? void 0 : star.owner) === null || _f === void 0 ? void 0 : _f.html_url,
},
html_url: star.html_url,
description: star.description,
url: star.url,
languages_url: star.languages_url,
created_at: star.created_at,
updated_at: star.updated_at,
git_url: star.git_url,
ssh_url: star.ssh_url,
clone_url: star.clone_url,
homepage: star.homepage,
stargazers_count: star.stargazers_count,
watchers_count: star.watchers_count,
language: star.language,
topics: star.topics,
});
}
}
}
catch (e_1_1) { e_1 = { error: e_1_1 }; }
finally {
try {
if (_h && !_h.done && (_a = _g.return)) yield _a.call(_g);
}
finally { if (e_1) throw e_1.error; }
}
return data;
}); });
} }
exports.apiGetStar = apiGetStar; exports.apiGetStar = apiGetStar;
exports.REPO_USERNAME = (_a = process.env.GITHUB_REPOSITORY) === null || _a === void 0 ? void 0 : _a.split('/')[0];
exports.API_STARRED_URL = `${process.env.GITHUB_API_URL}/users/${exports.REPO_USERNAME}/starred`;
let links = {
next: exports.API_STARRED_URL,
last: undefined,
};
function paginate() {
return __awaiter(this, void 0, void 0, function* () {
if (isLastPage(links))
return null;
const r = yield apiGetStar(links.next);
links = r.links;
return r;
});
}
exports.paginate = paginate;
function generateMd(data) { function generateMd(data) {
return new Promise((resolve) => { return new Promise((resolve) => {
remark_1.default() remark_1.default()
@@ -21433,17 +21509,21 @@ function generateMd(data) {
}); });
} }
exports.generateMd = generateMd; exports.generateMd = generateMd;
exports.OUTPUT_FILENAME = core.getInput('output-filename') || 'README.md'; exports.MARKDOWN_FILENAME = core.getInput('output-filename') || 'README.md';
function pushNewFile(markdown) { function pushNewFiles(files = []) {
return __awaiter(this, void 0, void 0, function* () { return __awaiter(this, void 0, void 0, function* () {
yield fsp.writeFile(exports.OUTPUT_FILENAME, markdown); if (!files.length)
return;
yield git_1.default.pull(); yield git_1.default.pull();
yield git_1.default.add(exports.OUTPUT_FILENAME); yield Promise.all(files.map(({ filename, data }) => __awaiter(this, void 0, void 0, function* () {
yield git_1.default.commit(`chore(${exports.OUTPUT_FILENAME}): updated ${exports.OUTPUT_FILENAME}`); yield fsp.writeFile(filename, data);
yield git_1.default.add(filename);
})));
yield git_1.default.commit(`chore(updates): updated entries in files`);
yield git_1.default.push(); yield git_1.default.push();
}); });
} }
exports.pushNewFile = pushNewFile; exports.pushNewFiles = pushNewFiles;
/***/ }), /***/ }),
@@ -21487,14 +21567,7 @@ const core = __importStar(__nccwpck_require__(2186));
const helpers_1 = __nccwpck_require__(3015); const helpers_1 = __nccwpck_require__(3015);
function main() { function main() {
return __awaiter(this, void 0, void 0, function* () { return __awaiter(this, void 0, void 0, function* () {
let results = []; const results = yield helpers_1.apiGetStar();
while (true) {
// sorry.
const r = yield helpers_1.paginate();
if (!r || r === null)
break;
results = results.concat(r.data);
}
const sortedByLanguages = results.reduce((acc, val) => { const sortedByLanguages = results.reduce((acc, val) => {
const language = val.language || 'generic'; const language = val.language || 'generic';
if (!acc[language]) { if (!acc[language]) {
@@ -21511,7 +21584,16 @@ function main() {
updatedAt: Date.now(), updatedAt: Date.now(),
}); });
const markdown = yield helpers_1.generateMd(rendered); const markdown = yield helpers_1.generateMd(rendered);
yield helpers_1.pushNewFile(markdown); yield helpers_1.pushNewFiles([
{
filename: helpers_1.MARKDOWN_FILENAME,
data: markdown,
},
{
filename: 'data.json',
data: JSON.stringify(sortedByLanguages, null, 2),
},
]);
}); });
} }
exports.main = main; exports.main = main;

973
package-lock.json generated

File diff suppressed because it is too large Load Diff

View File

@@ -1,6 +1,6 @@
{ {
"name": "mawesome", "name": "mawesome",
"version": "1.0.31", "version": "1.0.43",
"description": "Generate awesome list from user starred repositories", "description": "Generate awesome list from user starred repositories",
"main": "index.js", "main": "index.js",
"author": "Simone Corsi<simonecorsi.dev@gmail.com>", "author": "Simone Corsi<simonecorsi.dev@gmail.com>",
@@ -12,7 +12,7 @@
"style:prettier": "prettier \"src/**/*.ts\" --list-different --write", "style:prettier": "prettier \"src/**/*.ts\" --list-different --write",
"build": "./node_modules/.bin/ncc build src/index.ts -o ./", "build": "./node_modules/.bin/ncc build src/index.ts -o ./",
"dev": "ts-node-dev src/index.ts", "dev": "ts-node-dev src/index.ts",
"prerelease": "npm run build && " "prerelease": "npm run build"
}, },
"keywords": [ "keywords": [
"github", "github",
@@ -37,7 +37,6 @@
"@vercel/ncc": "^0.26.2", "@vercel/ncc": "^0.26.2",
"ava": "^3.8.2", "ava": "^3.8.2",
"benchmark": "^2.1.4", "benchmark": "^2.1.4",
"conventional-gitlab-releaser": "^4.0.1",
"cz-conventional-changelog": "^3.2.0", "cz-conventional-changelog": "^3.2.0",
"eslint": "^7.17.0", "eslint": "^7.17.0",
"eslint-config-prettier": "^7.1.0", "eslint-config-prettier": "^7.1.0",

View File

@@ -1,3 +1,4 @@
import fs from 'fs';
import ejs from 'ejs'; import ejs from 'ejs';
import * as core from '@actions/core'; import * as core from '@actions/core';
import remark from 'remark'; import remark from 'remark';
@@ -8,9 +9,10 @@ import GithubApi from './api';
import link from './link'; import link from './link';
import git from './git'; import git from './git';
import type { PaginationLink, ApiGetStarResponse } from './types'; import type { PaginationLink, ApiGetStarResponse, Stars, Star } from './types';
import fs from 'fs'; export const REPO_USERNAME = process.env.GITHUB_REPOSITORY?.split('/')[0];
export const API_STARRED_URL = `${process.env.GITHUB_API_URL}/users/${REPO_USERNAME}/starred`;
const fsp = fs.promises; const fsp = fs.promises;
@@ -18,10 +20,6 @@ export function wait(time = 200): Promise<void> {
return new Promise((resolve) => setTimeout(resolve, time)); return new Promise((resolve) => setTimeout(resolve, time));
} }
export function isLastPage(links: PaginationLink): boolean {
return links.next === links.last;
}
export async function renderer( export async function renderer(
data: { [key: string]: any }, data: { [key: string]: any },
templateString = MD_TEMPLATE templateString = MD_TEMPLATE
@@ -34,32 +32,72 @@ export async function renderer(
} }
} }
export async function apiGetStar(url: string): Promise<ApiGetStarResponse> { export function getNextPage(links: PaginationLink[]): string | null {
const { headers, body }: any = await GithubApi.get(url); const next = links.find((l) => l.rel === 'next');
return { const last = links.find((l) => l.rel === 'last');
data: body, if (!next || !last) return null;
links: link.parse(headers.link).refs.reduce( const matchNext = next.uri.match(/page=([0-9]*)/);
(acc, val) => ({ const matchLast = last.uri.match(/page=([0-9]*)/);
...acc, if (!matchNext || !matchLast) return null;
[val.rel]: val.uri, if (matchNext[1] === matchLast[1]) return null;
}), return matchNext[1];
{}
),
};
} }
export const REPO_USERNAME = process.env.GITHUB_REPOSITORY?.split('/')[0]; async function* paginateStars(url: string): AsyncGenerator<Stars> {
export const API_STARRED_URL = `${process.env.GITHUB_API_URL}/users/${REPO_USERNAME}/starred`; let nextPage: string | null = '1';
while (nextPage) {
try {
const { headers, body } = await GithubApi.get(url, {
searchParams: {
page: nextPage,
},
});
yield (body as unknown) as Stars;
nextPage = getNextPage(link.parse(headers.link).refs);
await wait(1000); // avoid limits
} catch (e) {
console.error(e);
break;
}
}
}
let links: PaginationLink = { export async function apiGetStar(
next: API_STARRED_URL, url: string = API_STARRED_URL
last: undefined, ): Promise<ApiGetStarResponse> {
}; const data: Partial<Star>[] = [];
export async function paginate(): Promise<ApiGetStarResponse | null> { for await (const stars of paginateStars(url)) {
if (isLastPage(links)) return null; for (const star of stars) {
const r = await apiGetStar(links.next); data.push({
links = r.links; id: star.id,
return r; node_id: star.node_id,
name: star.name,
full_name: star.full_name,
owner: {
login: star?.owner?.login,
id: star?.owner?.id,
avatar_url: star?.owner?.avatar_url,
url: star?.owner?.url,
html_url: star?.owner?.html_url,
},
html_url: star.html_url,
description: star.description,
url: star.url,
languages_url: star.languages_url,
created_at: star.created_at,
updated_at: star.updated_at,
git_url: star.git_url,
ssh_url: star.ssh_url,
clone_url: star.clone_url,
homepage: star.homepage,
stargazers_count: star.stargazers_count,
watchers_count: star.watchers_count,
language: star.language,
topics: star.topics,
} as Partial<Star>);
}
}
return (data as unknown) as Stars;
} }
export function generateMd(data: string): Promise<string> { export function generateMd(data: string): Promise<string> {
@@ -77,12 +115,26 @@ export function generateMd(data: string): Promise<string> {
}); });
} }
export const OUTPUT_FILENAME: string = export const MARKDOWN_FILENAME: string =
core.getInput('output-filename') || 'README.md'; core.getInput('output-filename') || 'README.md';
export async function pushNewFile(markdown: string): Promise<any> {
await fsp.writeFile(OUTPUT_FILENAME, markdown); type File = {
filename: string;
data: string;
};
export async function pushNewFiles(files: File[] = []): Promise<any> {
if (!files.length) return;
await git.pull(); await git.pull();
await git.add(OUTPUT_FILENAME);
await git.commit(`chore(${OUTPUT_FILENAME}): updated ${OUTPUT_FILENAME}`); await Promise.all(
files.map(async ({ filename, data }) => {
await fsp.writeFile(filename, data);
await git.add(filename);
})
);
await git.commit(`chore(updates): updated entries in files`);
await git.push(); await git.push();
} }

View File

@@ -2,23 +2,17 @@ import * as core from '@actions/core';
import { import {
renderer, renderer,
paginate,
REPO_USERNAME, REPO_USERNAME,
generateMd, generateMd,
pushNewFile, pushNewFiles,
MARKDOWN_FILENAME,
apiGetStar,
} from './helpers'; } from './helpers';
import type { SortedLanguageList, Stars, Star } from './types'; import type { SortedLanguageList, Stars, Star } from './types';
export async function main(): Promise<any> { export async function main(): Promise<any> {
let results: Stars = []; const results: Stars = await apiGetStar();
while (true) {
// sorry.
const r = await paginate();
if (!r || r === null) break;
results = results.concat(r.data);
}
const sortedByLanguages = results.reduce( const sortedByLanguages = results.reduce(
(acc: SortedLanguageList, val: Star) => { (acc: SortedLanguageList, val: Star) => {
@@ -41,7 +35,16 @@ export async function main(): Promise<any> {
const markdown: string = await generateMd(rendered); const markdown: string = await generateMd(rendered);
await pushNewFile(markdown); await pushNewFiles([
{
filename: MARKDOWN_FILENAME,
data: markdown,
},
{
filename: 'data.json',
data: JSON.stringify(sortedByLanguages, null, 2),
},
]);
} }
export async function run(): Promise<any> { export async function run(): Promise<any> {

View File

@@ -5,14 +5,11 @@ export type SortedLanguageList = {
}; };
export type PaginationLink = { export type PaginationLink = {
next: string; uri: string;
last: string | undefined | null; rel: 'next' | 'last' | 'prev' | 'first';
}; };
export type Stars = Endpoints['GET /user/starred']['response']['data']; export type Stars = Endpoints['GET /user/starred']['response']['data'];
export type Star = Stars[number] | { language: string }; export type Star = Stars[number] | { language: string };
export type ApiGetStarResponse = { export type ApiGetStarResponse = Stars;
links: PaginationLink;
data: Stars;
};

View File

@@ -7,7 +7,7 @@ sinon.replace(core, 'getInput', sinon.fake());
import GithubApi from '../src/api'; import GithubApi from '../src/api';
const GithubApiFake = sinon.fake((rul) => ({ const GithubApiFake = sinon.fake((rul) => ({
body: 'data', body: [],
headers: { headers: {
link: link:
'<https://api.github.com/user/5617452/starred?page=2>; rel="next", <https://api.github.com/user/5617452/starred?page=2>; rel="last"', '<https://api.github.com/user/5617452/starred?page=2>; rel="next", <https://api.github.com/user/5617452/starred?page=2>; rel="last"',
@@ -32,13 +32,11 @@ const writeFile = sinon.fake();
sinon.replace(fsp, 'writeFile', writeFile); sinon.replace(fsp, 'writeFile', writeFile);
import { import {
isLastPage,
wait, wait,
renderer, renderer,
apiGetStar, apiGetStar,
paginate,
generateMd, generateMd,
pushNewFile, pushNewFiles,
} from '../src/helpers'; } from '../src/helpers';
test('wait should wait', async (t) => { test('wait should wait', async (t) => {
@@ -46,40 +44,15 @@ test('wait should wait', async (t) => {
t.pass(); t.pass();
}); });
test('isLastPage', (t) => {
t.true(
isLastPage({
next: 'last',
last: 'last',
})
);
t.false(
isLastPage({
next: 'last',
last: undefined,
})
);
});
test('renderer should render', async (t) => { test('renderer should render', async (t) => {
const output = await renderer({ variable: 123 }, 'Test: <%= variable %>'); const output = await renderer({ variable: 123 }, 'Test: <%= variable %>');
t.is(output, 'Test: 123'); t.is(output, 'Test: 123');
}); });
test('apiGetStar', async (t) => { test('apiGetStar', async (t) => {
let { data, links } = await apiGetStar('url'); let stars = await apiGetStar('url');
t.true(GithubApiFake.called); t.true(GithubApiFake.called);
t.is(data, 'data'); t.true(Array.isArray(stars));
t.deepEqual(links, {
last: 'https://api.github.com/user/5617452/starred?page=2',
next: 'https://api.github.com/user/5617452/starred?page=2',
});
});
test('paginate', async (t) => {
await paginate();
const res = await paginate();
t.is(res, null);
}); });
test('generateMd should create TOC', async (t) => { test('generateMd should create TOC', async (t) => {
@@ -97,10 +70,10 @@ test('generateMd should create TOC', async (t) => {
}); });
test('should push', async (t) => { test('should push', async (t) => {
await pushNewFile('# title'); await pushNewFiles([{ filename: 'README.md', data: '# title' }]);
t.true(writeFile.calledWith('README.md', '# title')); t.true(writeFile.called);
t.true(pull.called); t.true(pull.called);
t.true(add.calledWith('README.md')); t.true(add.called);
t.true(commit.calledWith('chore(README.md): updated README.md')); t.true(commit.called);
t.true(push.called); t.true(push.called);
}); });