-
Notifications
You must be signed in to change notification settings - Fork 24
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Feat/deploy #82
Merged
Merged
Feat/deploy #82
Changes from all commits
Commits
Show all changes
13 commits
Select commit
Hold shift + click to select a range
f76e124
Add testnet connection
ittechhunter 3d1d660
Fix building issue
ittechhunter 7882619
Merge branch 'main' into fix/ticket73
elliotBraem 3aa6edd
Add a unit test
ittechhunter a57975d
Add deploy code
ittechhunter 8ff1cdf
Merge branch 'main' into feat/deploy
elliotBraem 8da4211
Merge branch 'NEARBuilders:main' into main
ittechhunter 1cbb611
Merge branch 'NEARBuilders:main' into main
ittechhunter 1f7febc
Fix build & deploy test code
ittechhunter 5b1b749
Fix build code
ittechhunter 1705cfe
fix: Update ReadMe
ittechhunter 6f69cb7
Check deploy command validation
ittechhunter 9b99ff8
Refactor validation check
ittechhunter File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,9 +1,127 @@ | ||
import { BaseConfig } from "./config"; | ||
import path from "path"; | ||
import { exec, ExecException } from "child_process"; | ||
|
||
import { BaseConfig, readConfig } from "@/lib/config"; | ||
import { buildApp } from "@/lib/build"; | ||
import { readWorkspace } from "@/lib/workspace"; | ||
import { Log, Network } from "@/lib/types"; | ||
import { readdir, remove, move, pathExists } from "@/lib/utils/fs"; | ||
import { Logger } from "./logger"; | ||
|
||
const DEPLOY_DIST_FOLDER = "build"; | ||
|
||
export type DeployOptions = { | ||
deployAccountId?: string; | ||
signerAccountId?: string; | ||
signerPublicKey?: string; | ||
signerPrivateKey?: string; | ||
network?: Network; | ||
}; | ||
|
||
// translate files from src/widget to src | ||
export async function translateForBosCli(dist: string) { | ||
const srcDir = path.join(dist, "src", "widget"); | ||
const targetDir = path.join(dist, "src"); | ||
|
||
const new_files = await readdir(srcDir).catch(() => ([])); | ||
const original_files = await readdir(targetDir).catch(() => ([])); | ||
|
||
for (const file of new_files) { | ||
await move(path.join(srcDir, file), path.join(targetDir, file), { overwrite: true }); | ||
} | ||
|
||
for (const file of original_files) { | ||
if (new_files.includes(file)) | ||
continue; | ||
|
||
await remove(path.join(targetDir, file)); | ||
} | ||
} | ||
|
||
// deploy the app widgets and modules | ||
export async function deployAppCode(src: string, config: BaseConfig) { | ||
export async function deployAppCode(src: string, dist: string, opts: DeployOptions) { | ||
const fullSrc = path.resolve(src); | ||
const fullDist = path.resolve(dist); | ||
|
||
const deploying = log.loading(`[${fullSrc}] Deploying app`, LogLevels.BUILD); | ||
|
||
// Build | ||
await buildApp(src, dist, opts.network); | ||
|
||
// Translate for bos cli | ||
await log.wait( | ||
translateForBosCli(dist), | ||
`[${fullDist}] Translating files for bos cli`, | ||
`[${fullDist}] Translated successfully`, | ||
`[${fullDist}] Failed to translate`, | ||
LogLevels.BUILD | ||
); | ||
|
||
// Exec bos-cli; | ||
const config = await readConfig(path.join(src, "bos.config.json"), opts.network); | ||
|
||
const BOS_DEPLOY_ACCOUNT_ID = config.accounts.deploy || opts.deployAccountId; | ||
const BOS_SIGNER_ACCOUNT_ID = config.accounts.signer || opts.signerAccountId; | ||
const BOS_SIGNER_PUBLIC_KEY = opts.signerPublicKey; | ||
const BOS_SIGNER_PRIVATE_KEY = opts.signerPrivateKey; | ||
|
||
if (!BOS_DEPLOY_ACCOUNT_ID) { | ||
deploying.error(`Necessary values not provided, please provide Account ID for deploy`); | ||
return; | ||
} else if (!BOS_SIGNER_ACCOUNT_ID) { | ||
deploying.error(`Necessary values not provided, please provide Signer Account ID for deploy`); | ||
return; | ||
} else if (!BOS_SIGNER_PUBLIC_KEY || !BOS_SIGNER_PRIVATE_KEY) { | ||
deploying.error(`Necessary values not provided, please provide private & public key for deploy`); | ||
return; | ||
} | ||
|
||
exec( | ||
`cd ${dist} && npx bos components deploy "${BOS_DEPLOY_ACCOUNT_ID}" sign-as "${BOS_SIGNER_ACCOUNT_ID}" network-config "${opts.network}" sign-with-plaintext-private-key --signer-public-key "${BOS_SIGNER_PUBLIC_KEY}" --signer-private-key "${BOS_SIGNER_PRIVATE_KEY}" send`, | ||
(error: ExecException | null, stdout: string, stderr: string) => { | ||
if (!error) { | ||
deploying.finish(`[${fullSrc}] App deployed successfully`); | ||
return; | ||
} | ||
|
||
deploying.error(error.message); | ||
} | ||
); | ||
} | ||
|
||
// publish data.json to SocialDB | ||
export async function deployAppData(src: string, config: BaseConfig) { | ||
} | ||
|
||
export async function deploy(appName: string, opts: DeployOptions) { | ||
const src = '.'; | ||
|
||
// Deploy single project | ||
if (!appName) { | ||
if (await pathExists(path.join(src, "bos.config.json"))) { // Check if the directory has bos.config.json file | ||
await deployAppCode(src, path.join(src, DEPLOY_DIST_FOLDER), opts); | ||
return; | ||
} else { // Check if the directory has bos.workspace.json file | ||
if (await pathExists(path.join(src, "bos.workspace.json"))) { | ||
log.error(`Please provide app name`); | ||
return; | ||
} | ||
} | ||
|
||
log.error(`[${src}] bos.config.json file is not existing in the project`); | ||
return; | ||
} | ||
|
||
// Deploy workspace app | ||
const { apps } = await readWorkspace(src); | ||
|
||
const findingApp = log.loading(`Finding ${appName} in the workspace`, LogLevels.BUILD); | ||
const appSrc = apps.find((app) => app.includes(appName)); | ||
if (!appSrc) { | ||
findingApp.error(`Not found ${appName} in the workspace`); | ||
return; | ||
} | ||
findingApp.finish(`Found ${appName} in the workspace`); | ||
|
||
await deployAppCode(appSrc, path.join(DEPLOY_DIST_FOLDER, appSrc), opts); | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,118 @@ | ||
import * as process from "child_process"; | ||
import { deployAppCode } from '@/lib/deploy'; | ||
import { BaseConfig, DEFAULT_CONFIG } from '@/lib/config'; | ||
import * as fs from '@/lib/utils/fs'; | ||
import { LogLevel, Logger } from "@/lib/logger"; | ||
|
||
import { vol, } from 'memfs'; | ||
jest.mock('fs', () => require('memfs').fs); | ||
jest.mock('fs/promises', () => require('memfs').fs.promises); | ||
jest.mock('child_process', () => ({ | ||
exec: jest.fn((command: string) => { | ||
return command; | ||
}), | ||
})) | ||
|
||
const app_example = { | ||
"./bos.config.json": JSON.stringify({ | ||
...DEFAULT_CONFIG, | ||
account: "test.near", | ||
ipfs: { | ||
gateway: "https://testipfs/ipfs", | ||
}, | ||
format: true, | ||
}), | ||
"./aliases.json": JSON.stringify({ | ||
"name": "world", | ||
}), | ||
"./ipfs/logo.svg": "<svg viewBox='0 0 100 100'><circle cx='50' cy='50' r='50' fill='red' /></svg>", | ||
"./module/hello/utils.ts": "const hello = (name: string) => `Hello, ${name}!`; export default { hello };", | ||
"./widget/index.tsx": "type Hello = {}; const hello: Hello = 'hi'; export default hello;", | ||
"./widget/index.metadata.json": JSON.stringify({ | ||
name: "Hello", | ||
description: "Hello world widget", | ||
}), | ||
"./widget/nested/index.tsx": "type Hello = {}; const hello: Hello = 'hi'; export default hello;", | ||
"./widget/nested/index.metadata.json": JSON.stringify({ | ||
name: "Nested Hello", | ||
description: "Nested Hello world widget", | ||
}), | ||
"./widget/module.tsx": "VM.require('${module_hello_utils}'); export default hello('world');", | ||
"./widget/config.jsx": "return <h1>${config_account}${config_account_deploy}</h1>;", | ||
"./widget/alias.tsx": "export default <h1>Hello ${alias_name}!</h1>;", | ||
"./widget/ipfs.tsx": "export default <img height='100' src='${ipfs_logo.svg}' />;", | ||
"./data/thing/data.json": JSON.stringify({ | ||
"type": "efiz.near/type/thing", | ||
}), | ||
"./data/thing/datastring.jsonc": JSON.stringify({ | ||
name: "Thing", | ||
}), | ||
}; | ||
|
||
const app_example_output = { | ||
"/build/ipfs.json": JSON.stringify({ | ||
"logo.svg": "QmHash", | ||
}, null, 2) + "\n", | ||
"/build/src/hello.utils.module.js": "const hello = (name) => `Hello, ${name}!`;\nreturn { hello };\n", | ||
"/build/src/index.jsx": "const hello = \"hi\";\nreturn hello(props);\n", | ||
"/build/src/nested.index.jsx": "const hello = \"hi\";\nreturn hello(props);\n", | ||
"/build/src/module.jsx": "VM.require(\"test.near/widget/hello.utils.module\");\nreturn hello(\"world\");\n", | ||
"/build/src/config.jsx": "return <h1>test.neartest.near</h1>;\n", | ||
"/build/src/alias.jsx": "return <h1>Hello world!</h1>;\n", | ||
"/build/src/ipfs.jsx": "return <img height=\"100\" src=\"https://testipfs/ipfs/QmHash\" />;\n", | ||
"/build/data.json": JSON.stringify({ | ||
"test.near": { | ||
thing: { | ||
data: { | ||
"type": "efiz.near/type/thing", | ||
}, | ||
datastring: JSON.stringify({ | ||
name: "Thing", | ||
}) | ||
}, | ||
widget: { | ||
index: { | ||
metadata: { | ||
name: "Hello", | ||
description: "Hello world widget", | ||
} | ||
}, | ||
"nested.index": { | ||
metadata: { | ||
name: "Nested Hello", | ||
description: "Nested Hello world widget", | ||
} | ||
|
||
} | ||
} | ||
} | ||
}, null, 2) + "\n", | ||
}; | ||
|
||
const unmockedFetch = global.fetch; | ||
const unmockedLog = global.log; | ||
|
||
describe('deploy', () => { | ||
beforeEach(() => { | ||
vol.reset(); | ||
vol.fromJSON(app_example, '/app_example'); | ||
|
||
global.fetch = (() => { | ||
return Promise.resolve({ | ||
json: () => Promise.resolve({ | ||
cid: "QmHash", | ||
}) | ||
}) | ||
}) as any; | ||
global.log = new Logger(LogLevel.ERROR); | ||
}) | ||
afterAll(() => { | ||
global.fetch = unmockedFetch; | ||
global.log = unmockedLog; | ||
}) | ||
|
||
it('should match expected input for bos-cli-rs', async () => { | ||
await deployAppCode('/app_example', '/build', {}); | ||
expect(vol.toJSON('/build')).toEqual(app_example_output); | ||
elliotBraem marked this conversation as resolved.
Show resolved
Hide resolved
|
||
}) | ||
}) |
Oops, something went wrong.
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This all looks good, can you run
bw help
and update the README with this new command?