Commit 75734fe
Changed files (10)
src/constants.ts
@@ -1,1 +0,0 @@
-export const MY_BADGES_JSON_PATH = 'my-badges/my-badges.json'
src/get-badges.ts
@@ -1,100 +0,0 @@
-import { collect, Data } from './collect/collect.js'
-import fs from 'node:fs'
-import { Badge } from './badges.js'
-import { Octokit, RequestError } from 'octokit'
-import { decodeBase64 } from './utils.js'
-import { MY_BADGES_JSON_PATH } from './constants.js'
-
-export const getData = async (
- octokit: Octokit,
- dataPath: string,
- username: string,
-): Promise<Data> => {
- if (dataPath !== '') {
- if (!fs.existsSync(dataPath)) {
- throw new Error('Data file not found')
- }
- return JSON.parse(fs.readFileSync(dataPath, 'utf8')) as Data
- }
-
- if (!username) {
- throw new Error('Specify username')
- }
-
- const data = await collect(octokit, username)
- if (!fs.existsSync('data')) {
- fs.mkdirSync('data')
- }
- fs.writeFileSync(`data/${username}.json`, JSON.stringify(data, null, 2))
-
- return data
-}
-
-export const getOldData = async (
- octokit: Octokit,
- owner: string,
- repo: string,
- myBadges?: any, // test snapshot
-) => {
- console.log('Loading my-badges.json')
- try {
- const { data } =
- myBadges ||
- (await octokit.request<'content-file'>(
- 'GET /repos/{owner}/{repo}/contents/{path}',
- {
- owner,
- repo,
- path: MY_BADGES_JSON_PATH,
- },
- ))
- const oldJson = decodeBase64(data.content)
- const jsonSha = data.sha
- const userBadges = JSON.parse(oldJson)
-
- // Add missing tier property in old my-badges.json.
- for (const b of userBadges) {
- if (b.tier === undefined) b.tier = 0
- }
-
- return {
- userBadges,
- jsonSha,
- oldJson,
- }
- } catch (err) {
- console.log(err)
- if (err instanceof RequestError && err.response?.status != 404) {
- throw err
- }
- }
-
- return {}
-}
-
-export const getBadges = async (
- octokit: Octokit,
- dataPath: string,
- username: string,
- owner: string,
- repo: string,
-): Promise<{
- data: Data
- userBadges: Badge[]
- oldJson?: string
- jsonSha?: string
-}> => {
- const data = await getData(octokit, dataPath, username)
- const {
- oldJson = undefined,
- jsonSha = undefined,
- userBadges = [],
- } = owner && repo ? await getOldData(octokit, owner, repo) : {}
-
- return {
- data,
- oldJson,
- jsonSha,
- userBadges,
- }
-}
src/get-data.ts
@@ -0,0 +1,31 @@
+import { collect, Data } from './collect/collect.js'
+import fs from 'node:fs'
+import { Badge } from './badges.js'
+import { Octokit, RequestError } from 'octokit'
+import { decodeBase64 } from './utils.js'
+import { MY_BADGES_JSON_PATH } from './constants.js'
+
+export async function getData(
+ octokit: Octokit,
+ dataPath: string,
+ username: string,
+): Promise<Data> {
+ if (dataPath !== '') {
+ if (!fs.existsSync(dataPath)) {
+ throw new Error('Data file not found')
+ }
+ return JSON.parse(fs.readFileSync(dataPath, 'utf8')) as Data
+ }
+
+ if (!username) {
+ throw new Error('Specify username')
+ }
+
+ const data = await collect(octokit, username)
+ if (!fs.existsSync('data')) {
+ fs.mkdirSync('data')
+ }
+ fs.writeFileSync(`data/${username}.json`, JSON.stringify(data, null, 2))
+
+ return data
+}
src/main.ts
@@ -4,11 +4,12 @@ import minimist from 'minimist'
import { Octokit } from 'octokit'
import { retry } from '@octokit/plugin-retry'
import { throttling } from '@octokit/plugin-throttling'
-import { updateReadme } from './update-readme.js'
-import { updateBadges } from './update-badges.js'
import { presentBadges } from './present-badges.js'
-import { getBadges } from './get-badges.js'
+import { getData } from './get-data.js'
import { allBadges } from './all-badges/index.js'
+import { getUserBadges, gitClone, gitPush } from './repo.js'
+import { updateBadges } from './update-badges.js'
+import { updateReadme } from './update-readme.js'
void (async function main() {
try {
@@ -28,7 +29,8 @@ void (async function main() {
omit,
compact,
} = argv
- const [owner, repo] = repository?.split('/', 2) || [username, username]
+ const [owner, repo]: [string | undefined, string | undefined] =
+ repository?.split('/', 2) || [username, username]
const pickBadges = pick ? pick.split(',') : []
const omitBadges = omit ? omit.split(',') : []
@@ -55,14 +57,10 @@ void (async function main() {
retry: { doNotRetry: ['429'] },
})
- let { userBadges, data, oldJson, jsonSha } = await getBadges(
- octokit,
- dataPath,
- username,
- owner,
- repo,
- )
+ if (owner && repo) gitClone(owner, repo)
+ const data = await getData(octokit, dataPath, username)
+ let userBadges = getUserBadges()
userBadges = presentBadges(
allBadges.map((m) => m.default),
data,
@@ -75,16 +73,11 @@ void (async function main() {
console.log(JSON.stringify(userBadges, null, 2))
if (owner && repo) {
- await updateBadges(
- octokit,
- owner,
- repo,
- userBadges,
- oldJson,
- jsonSha,
- dryrun,
- )
- await updateReadme(octokit, owner, repo, userBadges, size, dryrun)
+ updateBadges(userBadges)
+ updateReadme(userBadges, size)
+ if (!dryrun) {
+ gitPush()
+ }
}
} catch (e) {
console.error(e)
src/repo.ts
@@ -0,0 +1,43 @@
+import fs from 'node:fs'
+import { spawnSync } from 'node:child_process'
+import { chdir } from 'node:process'
+import { Badge } from './badges.js'
+
+export function gitClone(owner: string, repo: string) {
+ spawnSync(
+ 'git',
+ ['clone', '--depth=1', `git@github.com:${owner}/${repo}.git`, 'repo'],
+ {
+ stdio: 'inherit',
+ },
+ )
+
+ chdir('repo')
+
+ spawnSync('git', ['config', 'user.name', 'My Badges'], { stdio: 'inherit' })
+ spawnSync(
+ 'git',
+ ['config', 'user.email', 'my-badges@users.noreply.github.com'],
+ { stdio: 'inherit' },
+ )
+
+ chdir('..')
+}
+
+export function gitPush() {
+ chdir('repo')
+
+ spawnSync('git', ['add', '.'], { stdio: 'inherit' })
+ spawnSync('git', ['commit', '-m', 'Update badges'], { stdio: 'inherit' })
+ spawnSync('git', ['push'], { stdio: 'inherit' })
+
+ chdir('..')
+}
+
+export function getUserBadges(): Badge[] {
+ if (!fs.existsSync('my-badges/my-badges.json')) {
+ return []
+ }
+ const data = fs.readFileSync('my-badges/my-badges.json', 'utf8')
+ return JSON.parse(data)
+}
src/update-badges.ts
@@ -1,60 +1,17 @@
-import { Octokit, RequestError } from 'octokit'
+import fs from 'node:fs'
+import { chdir } from 'node:process'
import { Badge } from './badges.js'
-import { quoteAttr, upload } from './utils.js'
-import { MY_BADGES_JSON_PATH } from './constants.js'
+import { quoteAttr } from './utils.js'
-export async function updateBadges(
- octokit: Octokit,
- owner: string,
- repo: string,
- badges: Badge[],
- oldJson: string | undefined,
- jsonSha: string | undefined,
- dryrun: boolean,
-) {
- const newJson = JSON.stringify(badges, null, 2)
- if (newJson == oldJson) {
- console.log('No change in my-badges.json')
- } else {
- await upload(
- octokit,
- 'PUT /repos/{owner}/{repo}/contents/{path}',
- {
- owner,
- repo,
- path: MY_BADGES_JSON_PATH,
- message: 'Update my-badges',
- committer: {
- name: 'My Badges',
- email: 'my-badges@github.com',
- },
- content: newJson,
- sha: jsonSha,
- },
- dryrun,
- )
- }
+export function updateBadges(badges: Badge[]) {
+ chdir('repo')
+
+ fs.mkdirSync('my-badges', { recursive: true })
+ fs.writeFileSync('my-badges/my-badges.json', JSON.stringify(badges, null, 2))
for (const badge of badges) {
const badgePath = `my-badges/${badge.id}.md`
- let sha: string | undefined
- let oldContent: string | undefined
-
- try {
- console.log(`Loading ${badgePath}`)
- const resp = await octokit.request<'readme'>(
- 'GET /repos/{owner}/{repo}/contents/{path}',
- { owner, repo, path: badgePath },
- )
- sha = resp.data.sha
- oldContent = Buffer.from(resp.data.content, 'base64').toString('utf8')
- } catch (err) {
- if (err instanceof RequestError && err.response?.status != 404) {
- throw err
- }
- }
-
const desc = quoteAttr(badge.desc)
const content =
`<img src="${badge.image}" alt="${desc}" title="${desc}" width="128">\n` +
@@ -64,27 +21,8 @@ export async function updateBadges(
`\n\n\n` +
`Created by <a href="https://github.com/my-badges/my-badges">My Badges</a>`
- if (content === oldContent) {
- console.log(`No change in ${badgePath}`)
- continue
- }
-
- await upload(
- octokit,
- 'PUT /repos/{owner}/{repo}/contents/{path}',
- {
- owner,
- repo,
- path: badgePath,
- message: sha ? `Update ${badge.id}.md` : `Add ${badge.id}.md`,
- committer: {
- name: 'My Badges',
- email: 'my-badges@github.com',
- },
- content,
- sha: sha,
- },
- dryrun,
- )
+ fs.writeFileSync(badgePath, content)
}
+
+ chdir('..')
}
src/update-readme.ts
@@ -1,17 +1,35 @@
-import { Octokit } from 'octokit'
+import fs from 'node:fs'
+import { chdir } from 'node:process'
import { Badge } from './badges.js'
-import { quoteAttr, upload } from './utils.js'
-import { allBadges } from './all-badges/index.js'
+import { quoteAttr } from './utils.js'
+
+export function updateReadme(badges: Badge[], size: number | string) {
+ chdir('repo')
+
+ const readmeFilename = detectReadmeFilename()
+ const readmeContent = fs.readFileSync(readmeFilename, 'utf8')
+
+ const content = generateReadme(readmeContent, badges, size)
+ fs.writeFileSync(readmeFilename, content)
+
+ chdir('..')
+}
+
+function detectReadmeFilename(): string {
+ if (fs.existsSync('README.md')) return 'README.md'
+ if (fs.existsSync('readme.md')) return 'readme.md'
+ throw new Error('Cannot find README.md')
+}
export function generateReadme(
- readme: string,
+ readmeContent: string,
badges: Badge[],
size: number | string = 64,
) {
const startString = '<!-- my-badges start -->'
const endString = '<!-- my-badges end -->'
- let content = readme
+ let content = readmeContent
const start = content.indexOf(startString)
const end = content.indexOf(endString)
@@ -40,44 +58,3 @@ export function generateReadme(
return content
}
-
-export async function updateReadme(
- octokit: Octokit,
- owner: string,
- repo: string,
- badges: Badge[],
- size: number | string,
- dryrun: boolean,
-) {
- const readme = await octokit.request<'readme'>(
- 'GET /repos/{owner}/{repo}/readme',
- {
- owner,
- repo,
- },
- )
-
- const content = generateReadme(
- Buffer.from(readme.data.content, 'base64').toString('utf8'),
- badges,
- size,
- )
-
- await upload(
- octokit,
- 'PUT /repos/{owner}/{repo}/contents/{path}',
- {
- owner,
- repo,
- path: readme.data.path,
- message: 'Update my-badges',
- committer: {
- name: 'My Badges',
- email: 'my-badges@github.com',
- },
- content,
- sha: readme.data.sha,
- },
- dryrun,
- )
-}
test/get-badges.test.ts
@@ -4,7 +4,7 @@ import fs from 'node:fs'
import path from 'node:path'
import os from 'node:os'
import { Octokit } from 'octokit'
-import { getBadges, getOldData } from '../src/get-badges.js'
+import { getBadges, getOldData } from '../src/get-data.js'
import { encodeBase64 } from '../src/utils.js'
const tempy = () => fs.mkdtempSync(path.join(os.tmpdir(), 'tempy-'))
.gitignore
@@ -2,5 +2,6 @@
/data/
/dist/
/my-badges/
+/repo/
yarn.lock
coverage
package-lock.json
@@ -1,12 +1,12 @@
{
"name": "update-my-badges",
- "version": "1.0.106",
+ "version": "1.0.105",
"lockfileVersion": 3,
"requires": true,
"packages": {
"": {
"name": "update-my-badges",
- "version": "1.0.106",
+ "version": "1.0.105",
"license": "MIT",
"dependencies": {
"@octokit/plugin-retry": "^6.0.1",