Publish record in laconic registry on creating project and deployment

This commit is contained in:
Nabarun 2024-02-07 21:54:41 +05:30
parent bd6a6b330c
commit 845a09bd7c
8 changed files with 1339 additions and 22 deletions

1
.npmrc Normal file
View File

@ -0,0 +1 @@
@cerc-io:registry=https://git.vdb.to/api/packages/cerc-io/npm/

View File

@ -9,3 +9,14 @@
[githubOauth]
clientId = ""
clientSecret = ""
[registryConfig]
restEndpoint = "http://localhost:32776"
gqlEndpoint = "http://localhost:32770/api"
chainId = "laconic_9000-1"
privateKey = ""
bondId = ""
[registryConfig.fee]
amount = "200000"
denom = "aphoton"
gas = "550000"

View File

@ -3,6 +3,7 @@
"version": "1.0.0",
"main": "index.js",
"dependencies": {
"@cerc-io/laconic-sdk": "^0.1.14",
"@graphql-tools/schema": "^10.0.2",
"@graphql-tools/utils": "^10.0.12",
"@octokit/oauth-app": "^6.1.0",
@ -18,6 +19,7 @@
"nanoid": "3",
"nanoid-dictionary": "^5.0.0-beta.1",
"reflect-metadata": "^0.2.1",
"semver": "^7.6.0",
"toml": "^3.0.0",
"ts-node": "^10.9.2",
"typeorm": "^0.3.19",

View File

@ -13,8 +13,22 @@ export interface GithubOauthConfig {
clientSecret: string;
}
export interface RegistryConfig {
restEndpoint: string;
gqlEndpoint: string;
chainId: string;
privateKey: string;
bondId: string;
fee: {
amount: string;
denom: string;
gas: string;
}
}
export interface Config {
server: ServerConfig;
database: DatabaseConfig;
githubOauth: GithubOauthConfig;
registryConfig: RegistryConfig;
}

View File

@ -17,7 +17,7 @@ const log = debug('snowball:server');
export const main = async (): Promise<void> => {
// TODO: get config path using cli
const { server, database, githubOauth } = await getConfig<Config>(DEFAULT_CONFIG_FILE_PATH);
const { server, database, githubOauth, registryConfig } = await getConfig<Config>(DEFAULT_CONFIG_FILE_PATH);
// TODO: Move to Service class
const app = new OAuthApp({
@ -28,7 +28,7 @@ export const main = async (): Promise<void> => {
const db = new Database(database);
await db.init();
const service = new Service(db, app);
const service = new Service(db, app, { registryConfig });
const typeDefs = fs.readFileSync(path.join(__dirname, 'schema.gql')).toString();
const resolvers = await createResolvers(service);

View File

@ -7,7 +7,7 @@ import { Domain } from './entity/Domain';
import { Project } from './entity/Project';
import { EnvironmentVariable } from './entity/EnvironmentVariable';
const log = debug('snowball:database');
const log = debug('snowball:resolver');
// TODO: Remove Database argument and refactor code to Service
export const createResolvers = async (service: Service): Promise<any> => {
@ -132,6 +132,7 @@ export const createResolvers = async (service: Service): Promise<any> => {
return service.addProject(context.userId, organizationSlug, data);
} catch (err) {
log(err);
throw err;
}
},

View File

@ -1,5 +1,9 @@
import assert from 'assert';
import debug from 'debug';
import { DeepPartial, FindOptionsWhere } from 'typeorm';
import { inc as semverInc } from 'semver';
import { Registry } from '@cerc-io/laconic-sdk';
import { OAuthApp } from '@octokit/oauth-app';
@ -11,13 +15,23 @@ import { Organization } from './entity/Organization';
import { Project } from './entity/Project';
import { Permission, ProjectMember } from './entity/ProjectMember';
import { User } from './entity/User';
import { RegistryConfig } from './config';
const log = debug('snowball:service');
const APP_RECORD_TYPE = 'ApplicationRecord';
export class Service {
private db: Database;
private app: OAuthApp;
private registry: Registry;
private registryConfig: RegistryConfig;
constructor (db: Database, app: OAuthApp) {
constructor (db: Database, app: OAuthApp, { registryConfig }: { registryConfig: RegistryConfig }) {
this.db = db;
this.app = app;
this.registryConfig = registryConfig;
this.registry = new Registry(registryConfig.gqlEndpoint, registryConfig.restEndpoint, registryConfig.chainId);
}
async getUser (userId: string): Promise<User | null> {
@ -195,7 +209,61 @@ export class Service {
throw new Error('Organization does not exist');
}
return this.db.addProject(userId, organization.id, data);
const project = await this.db.addProject(userId, organization.id, data);
// TODO: Create deployment with building status
// TODO: Get record name from repo package.json name
const recordName = project.repository;
// Use laconic-sdk to publish record
// Reference: https://git.vdb.to/cerc-io/test-progressive-web-app/src/branch/main/scripts/publish-app-record.sh
// Fetch previous records
const records = await this.registry.queryRecords({
type: APP_RECORD_TYPE,
name: recordName
}, true);
// Get next version of record
const bondRecords = records.filter((record: any) => record.bondId === this.registryConfig.bondId);
const [latestBondRecord] = bondRecords.sort((a: any, b: any) => new Date(a.createTime).getTime() - new Date(b.createdTime).getTime());
const nextVersion = semverInc(latestBondRecord?.attributes.version ?? '0.0.0', 'minor');
// Create record of type ApplicationRecord and publish
const applicationRecord = {
type: APP_RECORD_TYPE,
version: nextVersion,
name: recordName,
// TODO: Get data from repo package.json
description: '',
homepage: '',
license: '',
author: '',
repository: '',
app_version: '',
// TODO: Get latest commit hash from repo production branch / deployment
repository_ref: '',
// TODO: Get from project framework/template type
app_type: 'webapp'
};
const result = await this.registry.setRecord(
{
privateKey: this.registryConfig.privateKey,
record: applicationRecord,
bondId: this.registryConfig.bondId
},
'',
this.registryConfig.fee
);
// TODO: Log deployment id
log(`Record ${result.data.id} published for deployment`);
return project;
}
async updateProject (projectId: string, data: DeepPartial<Project>): Promise<boolean> {

1254
yarn.lock

File diff suppressed because it is too large Load Diff