Skip to content

Commit

Permalink
add CI
Browse files Browse the repository at this point in the history
  • Loading branch information
eagleoflqj committed Aug 3, 2023
1 parent a39c0c6 commit 2f4bab2
Show file tree
Hide file tree
Showing 7 changed files with 185 additions and 8 deletions.
14 changes: 14 additions & 0 deletions .eslintrc-json.cjs
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
module.exports = {
env: {
es2021: true
},
extends: [
'eslint:recommended',
'standard'
],
rules: {
'no-unused-expressions': 0,
'quotes': [2, 'double'],
'quote-props': [2, 'always']
}
}
23 changes: 23 additions & 0 deletions .eslintrc.cjs
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
module.exports = {
env: {
node: true,
es2021: true
},
extends: [
'eslint:recommended',
'plugin:@typescript-eslint/recommended',
'standard'
],
parserOptions: {
ecmaVersion: 'latest',
parser: '@typescript-eslint/parser',
sourceType: 'module'
},
plugins: [
'@typescript-eslint'
],
rules: {
'@typescript-eslint/no-non-null-assertion': 0,
'no-undef': 0
}
}
30 changes: 30 additions & 0 deletions .github/workflows/validate.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
name: validate

on:
push:
branches:
- master
pull_request:

jobs:
validate:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v3
- name: Use Node.js latest
uses: actions/setup-node@v2
with:
node-version: 20.x
- name: Install node dependencies
run: |
npm i -g pnpm
pnpm i
- name: Run lint
run: |
pnpm run lint
- name: Type check
run: |
pnpm run check
- name: Validate JSON files
run: |
pnpm run validate
18 changes: 10 additions & 8 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -14,13 +14,15 @@ type PARENT_INDEX = {
}

type CHILD_INDEX = {
repo: string // e.g. rime/rime-double-pinyin
branch?: string // Omit if use default branch
name: string // Prefer Simplified Chinese if applicable
labels?: ('chord' | 'lua')[]
schemas: string[] // e.g. luna_pinyin
dependencies?: string[] // Hard dependencies, e.g. rime/rime-luna-pinyin
reverseDependencies?: string[] // Reverse-lookup dependencies, e.g. rime/rime-stroke
license?: string // Omit if no OSI-approved license
recipes: {
repo: string // e.g. rime/rime-double-pinyin
branch?: string // Omit if use default branch
name: string // Prefer Simplified Chinese if applicable
labels?: ('chord' | 'lua')[]
schemas: string[] // e.g. luna_pinyin
dependencies?: string[] // Hard dependencies, e.g. rime/rime-luna-pinyin
reverseDependencies?: string[] // Reverse-lookup dependencies, e.g. rime/rime-stroke
license?: string // Omit if no OSI-approved license
}[]
}
```
23 changes: 23 additions & 0 deletions package.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
{
"name": "rppi",
"license": "Apache-2.0",
"type": "module",
"scripts": {
"lint": "eslint --ext .ts,.cjs . && eslint -c .eslintrc-json.cjs --ext .json .",
"lint:fix": "eslint --ext .ts,.cjs --fix . && eslint -c .eslintrc-json.cjs --ext .json --fix .",
"check": "tsc --noEmit",
"validate": "ts-node-esm scripts/validate.ts",
"serve": "serve --cors"
},
"devDependencies": {
"@types/node": "^20.4.6",
"@typescript-eslint/eslint-plugin": "^6.2.1",
"eslint": "^8.46.0",
"eslint-config-standard": "^17.1.0",
"eslint-plugin-json": "^3.1.0",
"joi": "^17.9.2",
"serve": "^14.2.0",
"ts-node": "^10.9.1",
"typescript": "^5.1.6"
}
}
70 changes: 70 additions & 0 deletions scripts/validate.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,70 @@
import { readFileSync } from 'fs'
import joi from 'joi'

const INDEX = 'index.json'
const repoPattern = /^[-_a-zA-Z0-9]+\/[-_a-zA-Z0-9]+$/
const branchPattern = /^[-_a-zA-Z0-9]+$/
const schemaPattern = /^[-_a-zA-Z0-9]+$/
const labels = ['chord', 'lua']

const parent = joi.object({
date: joi.string().pattern(/\d+-\d+-\d+/),
categories: joi.array().items(
joi.object({
key: joi.string().required(),
name: joi.string().required()
})
).required()
})

const child = joi.object({
recipes: joi.array().items(
joi.object({
repo: joi.string().pattern(repoPattern).required(),
branch: joi.string().pattern(branchPattern),
name: joi.string().required(),
labels: joi.array().items(joi.string().valid(...labels)).unique(),
schemas: joi.array().items(joi.string().pattern(schemaPattern)).required().unique(),
dependencies: joi.array().items(joi.string().pattern(repoPattern)).unique(),
reverseDependencies: joi.array().items(joi.string().pattern(repoPattern)).unique(),
license: joi.string()
})
)
})

const repos: string[] = []
const deps: string[] = []

function validate (path: string) {
const file = `${path}/${INDEX}`
console.log(`Validating ${file}`)
const content = JSON.parse(readFileSync(file) as unknown as string)
const isParent = 'categories' in content
const { error } = (isParent ? parent : child).validate(content)
if (error) {
throw error
}
if (isParent) {
for (const category of content.categories) {
validate(`${path}/${category.key}`)
}
} else {
for (const recipe of content.recipes) {
const { repo, dependencies, reverseDependencies } = recipe
if (repos.includes(repo)) {
throw new Error(`Duplicated repo: ${repo}`)
}
repos.push(repo)
dependencies && deps.push(...dependencies)
reverseDependencies && deps.push(...reverseDependencies)
}
}
}

validate('.')

for (const dependency of deps) {
if (!repos.includes(dependency)) {
throw new Error(`Unknown dependency ${dependency}`)
}
}
15 changes: 15 additions & 0 deletions tsconfig.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
{
"compilerOptions": {
"target": "ESNext",
"useDefineForClassFields": true,
"module": "ESNext",
"moduleResolution": "Node",
"strict": true,
"isolatedModules": true,
"esModuleInterop": true,
"lib": ["ESNext"],
"skipLibCheck": true,
"noEmit": true
},
"include": ["scripts/**.ts"]
}

0 comments on commit 2f4bab2

Please sign in to comment.