mirror of
https://fast.feibisi.com/https://github.com/parcelvoy/platform.git
synced 2025-08-28 11:46:02 +08:00
Update release process (#192)
This commit is contained in:
parent
9d17439447
commit
5f8e061061
22 changed files with 147 additions and 70 deletions
27
.github/workflows/publish.yml
vendored
Normal file
27
.github/workflows/publish.yml
vendored
Normal file
|
@ -0,0 +1,27 @@
|
|||
name: Publish Packages
|
||||
|
||||
on:
|
||||
push:
|
||||
tags:
|
||||
- "v*.*.*"
|
||||
|
||||
jobs:
|
||||
build-package:
|
||||
name: "Publish to GitHub Packages"
|
||||
runs-on: ubuntu-latest
|
||||
permissions:
|
||||
contents: read
|
||||
packages: write
|
||||
if: github.repository_owner == 'parcelvoy'
|
||||
steps:
|
||||
- uses: actions/checkout@v3
|
||||
- name: Use Node.js 18.x
|
||||
uses: actions/setup-node@v3
|
||||
with:
|
||||
node-version: 18.x
|
||||
registry-url: https://npm.pkg.github.com/
|
||||
- run: npm ci
|
||||
- run: echo "registry=https://npm.pkg.github.com/@parcelvoy" >> .npmrc
|
||||
- run: npm run package:publish --tag=$(echo ${GITHUB_REF_NAME:1})
|
||||
env:
|
||||
NODE_AUTH_TOKEN: ${{secrets.GITHUB_TOKEN}}
|
2
.github/workflows/test.yml
vendored
2
.github/workflows/test.yml
vendored
|
@ -64,7 +64,7 @@ jobs:
|
|||
run: npm install && npm install --save-dev
|
||||
|
||||
- name: 'Run Jest Tests'
|
||||
run: npm run test -- --scope=platform
|
||||
run: npm run test -- --scope=@parcelvoy/platform
|
||||
env:
|
||||
NODE_ENV: test
|
||||
APP_SECRET: testing
|
||||
|
|
|
@ -24,4 +24,4 @@ USER node
|
|||
WORKDIR /usr/src/app
|
||||
COPY --chown=node:node --from=build /usr/src/app ./
|
||||
EXPOSE 3001
|
||||
CMD ["dumb-init", "node", "index.js"]
|
||||
CMD ["dumb-init", "node", "boot.js"]
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
{
|
||||
"ignore": ["**/*.test.ts", "**/*.spec.ts", "node_modules"],
|
||||
"watch": ["src", ".env"],
|
||||
"exec": "TZ=utc ts-node --transpile-only ./src/index.ts",
|
||||
"exec": "TZ=utc ts-node --transpile-only ./src/boot.ts",
|
||||
"ext": "ts,js,json"
|
||||
}
|
4
apps/platform/package-lock.json
generated
4
apps/platform/package-lock.json
generated
|
@ -1,11 +1,11 @@
|
|||
{
|
||||
"name": "platform",
|
||||
"name": "@parcelvoy/platform",
|
||||
"version": "0.1.0",
|
||||
"lockfileVersion": 3,
|
||||
"requires": true,
|
||||
"packages": {
|
||||
"": {
|
||||
"name": "platform",
|
||||
"name": "@parcelvoy/platform",
|
||||
"version": "0.1.0",
|
||||
"dependencies": {
|
||||
"@aws-sdk/client-s3": "^3.171.0",
|
||||
|
|
|
@ -1,6 +1,9 @@
|
|||
{
|
||||
"name": "platform",
|
||||
"name": "@parcelvoy/platform",
|
||||
"version": "0.1.0",
|
||||
"repository":"https://github.com/parcelvoy/platform",
|
||||
"main": "build/index.js",
|
||||
"types": "build/index.d.ts",
|
||||
"dependencies": {
|
||||
"@aws-sdk/client-s3": "^3.171.0",
|
||||
"@aws-sdk/client-ses": "^3.121.0",
|
||||
|
@ -56,7 +59,8 @@
|
|||
"test": "jest --forceExit --runInBand --testTimeout 10000",
|
||||
"docker:build": "docker buildx build -f ./Dockerfile -t ghcr.io/parcelvoy/api:latest -t ghcr.io/parcelvoy/api:$npm_config_tag ../../",
|
||||
"docker:build:push": "npm run docker:build -- --push",
|
||||
"migration:create": "node ./scripts/create-migration.mjs"
|
||||
"migration:create": "node ./scripts/create-migration.mjs",
|
||||
"package:publish": "npm run build && npm version $npm_config_tag --no-git-tag-version && npm pack && npm publish --tag=latest"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@types/busboy": "^1.5.0",
|
||||
|
@ -83,5 +87,6 @@
|
|||
"ts-jest": "^28.0.7",
|
||||
"ts-node": "^10.8.2",
|
||||
"typescript": "^4.9.3"
|
||||
}
|
||||
},
|
||||
"files": [ "/build", "/db" ]
|
||||
}
|
||||
|
|
|
@ -2,11 +2,15 @@ import Koa from 'koa'
|
|||
import koaBody from 'koa-body'
|
||||
import cors from '@koa/cors'
|
||||
import serve from 'koa-static'
|
||||
import controllers from './config/controllers'
|
||||
import controllers, { register } from './config/controllers'
|
||||
import { RequestError } from './core/errors'
|
||||
import { logger } from './config/logger'
|
||||
import Router from '@koa/router'
|
||||
|
||||
export default class Api extends Koa {
|
||||
router = new Router({ prefix: '/api' })
|
||||
controllers?: Record<string, Router>
|
||||
|
||||
constructor(
|
||||
public app: import('./app').default,
|
||||
) {
|
||||
|
@ -52,6 +56,21 @@ export default class Api extends Koa {
|
|||
defer: !app.env.mono,
|
||||
}))
|
||||
|
||||
controllers(this)
|
||||
this.registerControllers()
|
||||
}
|
||||
|
||||
getControllers() {
|
||||
return controllers(this.app)
|
||||
}
|
||||
|
||||
registerControllers() {
|
||||
this.controllers = this.getControllers()
|
||||
this.register(...Object.values(this.controllers))
|
||||
}
|
||||
|
||||
register(...routers: Router[]) {
|
||||
const root = register(this.router, ...routers)
|
||||
this.use(root.routes())
|
||||
.use(root.allowedMethods())
|
||||
}
|
||||
}
|
||||
|
|
|
@ -22,7 +22,7 @@ export default class App {
|
|||
return App.$main
|
||||
}
|
||||
|
||||
static async init(env: Env): Promise<App> {
|
||||
static async init<T extends typeof App>(this: T, env: Env): Promise<InstanceType<T>> {
|
||||
|
||||
logger.info('parcelvoy initializing')
|
||||
|
||||
|
@ -42,15 +42,20 @@ export default class App {
|
|||
const auth = loadAuth(env.auth)
|
||||
|
||||
// Setup app
|
||||
App.$main = new App(env,
|
||||
const app = new this(env,
|
||||
database,
|
||||
queue,
|
||||
auth,
|
||||
storage,
|
||||
error,
|
||||
)
|
||||
) as any
|
||||
|
||||
return App.$main
|
||||
return this.setMain(app)
|
||||
}
|
||||
|
||||
static setMain<T extends typeof App>(this: T, app: InstanceType<T>) {
|
||||
this.$main = app
|
||||
return app
|
||||
}
|
||||
|
||||
uuid = uuid()
|
||||
|
@ -59,8 +64,7 @@ export default class App {
|
|||
rateLimiter: RateLimiter
|
||||
#registered: { [key: string | number]: unknown }
|
||||
|
||||
// eslint-disable-next-line no-useless-constructor
|
||||
private constructor(
|
||||
constructor(
|
||||
public env: Env,
|
||||
public db: Database,
|
||||
public queue: Queue,
|
||||
|
@ -73,22 +77,30 @@ export default class App {
|
|||
this.unhandledErrorListener()
|
||||
}
|
||||
|
||||
async start() {
|
||||
start() {
|
||||
const runners = this.env.runners
|
||||
if (runners.includes('api')) {
|
||||
this.api = new Api(this)
|
||||
this.startApi()
|
||||
}
|
||||
if (runners.includes('worker')) {
|
||||
this.startWorker()
|
||||
}
|
||||
return this
|
||||
}
|
||||
|
||||
startApi(api?: Api) {
|
||||
this.api = api ?? new Api(this)
|
||||
const server = this.api?.listen(this.env.port)
|
||||
server.keepAliveTimeout = 65000
|
||||
server.requestTimeout = 0
|
||||
logger.info('parcelvoy:api ready')
|
||||
}
|
||||
if (runners.includes('worker')) {
|
||||
this.worker = new Worker(this)
|
||||
|
||||
startWorker(worker?: Worker) {
|
||||
this.worker = worker ?? new Worker(this)
|
||||
this.worker?.run()
|
||||
logger.info('parcelvoy:worker ready')
|
||||
}
|
||||
return this
|
||||
}
|
||||
|
||||
async close() {
|
||||
await this.worker?.close()
|
||||
|
|
5
apps/platform/src/boot.ts
Normal file
5
apps/platform/src/boot.ts
Normal file
|
@ -0,0 +1,5 @@
|
|||
import App from './app'
|
||||
import env from './config/env'
|
||||
|
||||
export default App.init(env())
|
||||
.then(app => app.start())
|
|
@ -20,28 +20,25 @@ import ProjectAdminController from '../projects/ProjectAdminController'
|
|||
import ProjectApiKeyController from '../projects/ProjectApiKeyController'
|
||||
import AdminController from '../auth/AdminController'
|
||||
import OrganizationController from '../organizations/OrganizationController'
|
||||
import App from '../app'
|
||||
|
||||
const register = (parent: Router, ...routers: Router[]) => {
|
||||
export const register = (parent: Router, ...routers: Router[]) => {
|
||||
for (const router of routers) {
|
||||
parent.use(router.routes(), router.allowedMethods())
|
||||
}
|
||||
return parent
|
||||
}
|
||||
|
||||
export default (api: import('../api').default) => {
|
||||
export default (app: App) => {
|
||||
|
||||
// Register the three main levels of routers
|
||||
const root = register(new Router({ prefix: '/api' }),
|
||||
adminRouter(),
|
||||
clientRouter(),
|
||||
publicRouter(),
|
||||
)
|
||||
|
||||
api.use(root.routes())
|
||||
.use(root.allowedMethods())
|
||||
const routers: Record<string, Router> = {
|
||||
admin: adminRouter(),
|
||||
client: clientRouter(),
|
||||
public: publicRouter(),
|
||||
}
|
||||
|
||||
// If we are running in mono mode, we need to also serve the UI
|
||||
if (api.app.env.mono) {
|
||||
if (app.env.mono) {
|
||||
const ui = new Router()
|
||||
ui.get('/(.*)', async (ctx, next) => {
|
||||
try {
|
||||
|
@ -50,9 +47,10 @@ export default (api: import('../api').default) => {
|
|||
return next()
|
||||
}
|
||||
})
|
||||
api.use(ui.routes())
|
||||
.use(ui.allowedMethods())
|
||||
routers.ui = ui
|
||||
}
|
||||
|
||||
return routers
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
|
@ -1,4 +1,5 @@
|
|||
import knex, { Knex as Database } from 'knex'
|
||||
import path from 'path'
|
||||
import { removeKey } from '../utilities'
|
||||
import { logger } from './logger'
|
||||
|
||||
|
@ -10,6 +11,7 @@ export interface DatabaseConfig {
|
|||
user: string
|
||||
password: string
|
||||
database?: string
|
||||
migrationPaths: string[]
|
||||
}
|
||||
|
||||
export type Query = (builder: Database.QueryBuilder<any>) => Database.QueryBuilder<any>
|
||||
|
@ -23,7 +25,7 @@ knex.QueryBuilder.extend('when', function(
|
|||
})
|
||||
|
||||
const connect = (config: DatabaseConfig, withDB = true) => {
|
||||
let connection = config
|
||||
let connection = removeKey('migrationPaths', config)
|
||||
if (!withDB) {
|
||||
connection = removeKey('database', connection)
|
||||
}
|
||||
|
@ -45,7 +47,7 @@ const connect = (config: DatabaseConfig, withDB = true) => {
|
|||
const migrate = async (config: DatabaseConfig, db: Database, fresh = false) => {
|
||||
if (fresh) await db.raw(`CREATE DATABASE ${config.database}`)
|
||||
return db.migrate.latest({
|
||||
directory: './db/migrations',
|
||||
directory: [path.resolve(__dirname, '../../db/migrations'), ...config.migrationPaths],
|
||||
tableName: 'migrations',
|
||||
loadExtensions: ['.js', '.ts'],
|
||||
})
|
||||
|
|
|
@ -55,6 +55,7 @@ export default (type?: EnvType): Env => {
|
|||
password: process.env.DB_PASSWORD!,
|
||||
port: parseInt(process.env.DB_PORT!),
|
||||
database: process.env.DB_DATABASE!,
|
||||
migrationPaths: process.env.DB_MIGRATION_PATHS?.split(',') ?? [],
|
||||
},
|
||||
redis: {
|
||||
host: process.env.REDIS_HOST!,
|
||||
|
|
|
@ -21,8 +21,6 @@ import UserAliasJob from '../users/UserAliasJob'
|
|||
import UserSchemaSyncJob from '../schema/UserSchemaSyncJob'
|
||||
import UserDeviceJob from '../users/UserDeviceJob'
|
||||
|
||||
export type Queues = Record<number, Queue>
|
||||
|
||||
export const loadJobs = (queue: Queue) => {
|
||||
queue.register(CampaignGenerateListJob)
|
||||
queue.register(CampaignInteractJob)
|
||||
|
@ -49,9 +47,3 @@ export const loadJobs = (queue: Queue) => {
|
|||
export default (config: QueueConfig) => {
|
||||
return new Queue(config)
|
||||
}
|
||||
|
||||
export const loadWorker = (config: QueueConfig) => {
|
||||
const queue = new Queue(config)
|
||||
loadJobs(queue)
|
||||
return queue
|
||||
}
|
||||
|
|
|
@ -12,7 +12,7 @@ addErrors(validator)
|
|||
|
||||
export { JSONSchemaType, IsValidSchema, validator }
|
||||
|
||||
export const validate = <T>(schema: JSONSchemaType<T>, data: any): T => {
|
||||
export function validate<T>(schema: JSONSchemaType<T>, data: any): T {
|
||||
const validate = validator.getSchema<T>(schema.$id!)
|
||||
|| validator.compile(schema)
|
||||
if (validate(data)) {
|
||||
|
|
|
@ -1,5 +1,8 @@
|
|||
import Api from './api'
|
||||
import App from './app'
|
||||
import env from './config/env'
|
||||
import Model from './core/Model'
|
||||
import Worker from './worker'
|
||||
import Job from './queue/Job'
|
||||
|
||||
export default App.init(env())
|
||||
.then(app => app.start())
|
||||
export { App, env, Model, Api, Worker, Job }
|
||||
|
|
|
@ -18,7 +18,7 @@ export interface ProviderSetupMeta {
|
|||
value: string | number
|
||||
}
|
||||
|
||||
export const ProviderSchema = <T extends ExternalProviderParams, D>(id: string, data: JSONSchemaType<D>): JSONSchemaType<T> => {
|
||||
export function ProviderSchema<_ extends ExternalProviderParams, D>(id: string, data: JSONSchemaType<D>): any {
|
||||
return {
|
||||
$id: id,
|
||||
type: 'object',
|
||||
|
|
|
@ -1,15 +1,17 @@
|
|||
import { loadWorker } from './config/queue'
|
||||
import { loadJobs } from './config/queue'
|
||||
import scheduler, { Scheduler } from './config/scheduler'
|
||||
import Queue from './queue'
|
||||
|
||||
export default class Worker {
|
||||
worker: Queue
|
||||
scheduler: Scheduler
|
||||
|
||||
constructor(
|
||||
public app: import('./app').default,
|
||||
) {
|
||||
this.worker = loadWorker(app.env.queue)
|
||||
this.worker = new Queue(app.env.queue)
|
||||
this.scheduler = scheduler(app)
|
||||
this.loadJobs()
|
||||
}
|
||||
|
||||
run() {
|
||||
|
@ -20,4 +22,8 @@ export default class Worker {
|
|||
await this.worker.close()
|
||||
await this.scheduler.close()
|
||||
}
|
||||
|
||||
loadJobs() {
|
||||
loadJobs(this.worker)
|
||||
}
|
||||
}
|
||||
|
|
4
apps/ui/package-lock.json
generated
4
apps/ui/package-lock.json
generated
|
@ -1,11 +1,11 @@
|
|||
{
|
||||
"name": "ui",
|
||||
"name": "@parcelvoy/ui",
|
||||
"version": "0.1.0",
|
||||
"lockfileVersion": 3,
|
||||
"requires": true,
|
||||
"packages": {
|
||||
"": {
|
||||
"name": "ui",
|
||||
"name": "@parcelvoy/ui",
|
||||
"version": "0.1.0",
|
||||
"dependencies": {
|
||||
"@fontsource/inter": "^4.5.14",
|
||||
|
|
|
@ -1,6 +1,7 @@
|
|||
{
|
||||
"name": "ui",
|
||||
"name": "@parcelvoy/ui",
|
||||
"version": "0.1.0",
|
||||
"repository":"https://github.com/parcelvoy/platform",
|
||||
"dependencies": {
|
||||
"@fontsource/inter": "^4.5.14",
|
||||
"@headlessui/react": "1.7.13",
|
||||
|
@ -45,7 +46,8 @@
|
|||
"eject": "react-scripts eject",
|
||||
"lint": "eslint \"src/**/*.{js,jsx,ts,tsx}\"",
|
||||
"docker:build": "docker buildx build -f ./Dockerfile -t ghcr.io/parcelvoy/ui:latest -t ghcr.io/parcelvoy/ui:$npm_config_tag ../../",
|
||||
"docker:build:push": "npm run docker:build -- --push"
|
||||
"docker:build:push": "npm run docker:build -- --push",
|
||||
"package:publish": "npm run build && npm version $npm_config_tag --no-git-tag-version && npm pack && npm publish --tag=latest"
|
||||
},
|
||||
"browserslist": {
|
||||
"production": [
|
||||
|
@ -68,5 +70,6 @@
|
|||
"eslint-plugin-promise": "^6.1.1",
|
||||
"eslint-plugin-react": "^7.31.11",
|
||||
"typescript": "^4.9.3"
|
||||
}
|
||||
},
|
||||
"files": [ "/build" ]
|
||||
}
|
||||
|
|
18
package-lock.json
generated
18
package-lock.json
generated
|
@ -13,6 +13,7 @@
|
|||
}
|
||||
},
|
||||
"apps/platform": {
|
||||
"name": "@parcelvoy/platform",
|
||||
"version": "0.1.0",
|
||||
"dependencies": {
|
||||
"@aws-sdk/client-s3": "^3.171.0",
|
||||
|
@ -137,6 +138,7 @@
|
|||
}
|
||||
},
|
||||
"apps/ui": {
|
||||
"name": "@parcelvoy/ui",
|
||||
"version": "0.1.0",
|
||||
"dependencies": {
|
||||
"@fontsource/inter": "^4.5.14",
|
||||
|
@ -6829,6 +6831,14 @@
|
|||
"url": "https://opencollective.com/parcel"
|
||||
}
|
||||
},
|
||||
"node_modules/@parcelvoy/platform": {
|
||||
"resolved": "apps/platform",
|
||||
"link": true
|
||||
},
|
||||
"node_modules/@parcelvoy/ui": {
|
||||
"resolved": "apps/ui",
|
||||
"link": true
|
||||
},
|
||||
"node_modules/@parse/node-apn": {
|
||||
"version": "5.1.3",
|
||||
"resolved": "https://registry.npmjs.org/@parse/node-apn/-/node-apn-5.1.3.tgz",
|
||||
|
@ -23044,10 +23054,6 @@
|
|||
"node": ">=4"
|
||||
}
|
||||
},
|
||||
"node_modules/platform": {
|
||||
"resolved": "apps/platform",
|
||||
"link": true
|
||||
},
|
||||
"node_modules/postcss": {
|
||||
"version": "8.4.22",
|
||||
"resolved": "https://registry.npmjs.org/postcss/-/postcss-8.4.22.tgz",
|
||||
|
@ -29409,10 +29415,6 @@
|
|||
"node": ">=0.8.0"
|
||||
}
|
||||
},
|
||||
"node_modules/ui": {
|
||||
"resolved": "apps/ui",
|
||||
"link": true
|
||||
},
|
||||
"node_modules/unbox-primitive": {
|
||||
"version": "1.0.2",
|
||||
"resolved": "https://registry.npmjs.org/unbox-primitive/-/unbox-primitive-1.0.2.tgz",
|
||||
|
|
|
@ -14,6 +14,7 @@
|
|||
"test": "lerna run test",
|
||||
"docker:build": "lerna run docker:build",
|
||||
"docker:build:push": "lerna run docker:build:push",
|
||||
"analyze:ui:bundle": "lerna run build && npx source-map-explorer './apps/ui/build/static/js/*.js'"
|
||||
"analyze:ui:bundle": "lerna run build && npx source-map-explorer './apps/ui/build/static/js/*.js'",
|
||||
"package:publish": "lerna run package:publish"
|
||||
}
|
||||
}
|
||||
|
|
|
@ -12,7 +12,8 @@
|
|||
"pretty": true,
|
||||
"sourceMap": true,
|
||||
"allowJs": true,
|
||||
"noEmit": false
|
||||
"noEmit": false,
|
||||
"declaration": true
|
||||
}
|
||||
}
|
||||
|
Loading…
Add table
Add a link
Reference in a new issue