diff --git a/README.md b/README.md index ef67fbc..c602da4 100644 --- a/README.md +++ b/README.md @@ -1,16 +1,43 @@ -# Spark Spells GitHub Action +# Spell Caster -Execute a spell on a persisted, forked network with a shareable link. +Execute a [Spark spell](https://github.com/marsfoundation/spark-spells) on a forked network with a shareable links. -## Running +Spell Caster can be run as CLI (for local testing) or configured as GitHub Action. + +## Running as CLI ```bash bun install # only first time -bun src/index.ts SparkEthereum_20240627 +# fill out .env based on .env.example + +#bun src/index.ts --root +bun src/index.ts --root ../spark-spell SparkEthereum_20240627 +``` + +## Running as Github Action + +Presents results as GitHub PR comment. + +```yml + - name: Spell Caster + uses: marsfoundation/spell-caster@action + with: + github-token: ${{ secrets.GITHUB_TOKEN }} + TENDERLY_API_KEY: ${{ secrets.TENDERLY_ACCESS_KEY }} + TENDERLY_PROJECT: ${{ secrets.TENDERLY_PROJECT }} + TENDERLY_ACCOUNT: ${{ secrets.TENDERLY_USER }} ``` ## Developing ```sh bun fix # to run linter, tests and typecheck -``` \ No newline at end of file +``` + +### Bun support + +GitHub Runners don't support bun as runner environment so we use bun for testing and bundling but not as runtime dependency. + +### GH Action + +New release of github action (pushed to `action`) branch is done after each commit to `main` branch. \ No newline at end of file diff --git a/src/bin/action.ts b/src/bin/action.ts index 030529d..a735e02 100644 --- a/src/bin/action.ts +++ b/src/bin/action.ts @@ -10,7 +10,7 @@ import { getRequiredGithubInput } from '../config/environments/action' import { findPendingSpells } from '../spells/findPendingSpells' async function main(): Promise { - const config = getConfig(getRequiredGithubInput) + const config = getConfig(getRequiredGithubInput, process.cwd()) const allPendingSpellNames = findPendingSpells(process.cwd()) core.info(`Pending spells: ${allPendingSpellNames.join(', ')}`) diff --git a/src/bin/cli.ts b/src/bin/cli.ts index b6f6439..1bb2f6d 100644 --- a/src/bin/cli.ts +++ b/src/bin/cli.ts @@ -1,12 +1,27 @@ import assert from 'node:assert' +import { parseArgs } from 'node:util' import { forkAndExecuteSpell } from '..' import { getConfig } from '../config' import { getRequiredShellEnv } from '../config/environments/cli' +import { ensureAbsolutePath } from '../utils/fs' + +async function main() { + const args = parseArgs({ + options: { + root: { + type: 'string', + }, + }, + allowPositionals: true, + strict: true, + }) + const rootPath = args.values.root + const spellName = args.positionals[0] -async function main(spellName?: string) { assert(spellName, 'Pass spell name as an argument ex. SparkEthereum_20240627') + assert(rootPath, 'Pass root path as an argument ex. --root /path/to/spark-spells') - const config = getConfig(getRequiredShellEnv) + const config = getConfig(getRequiredShellEnv, ensureAbsolutePath(rootPath)) console.log(`Executing spell ${spellName}`) const { forkRpc, appUrl } = await forkAndExecuteSpell(spellName, config) @@ -15,5 +30,4 @@ async function main(spellName?: string) { console.log(`Spark App URL: ${appUrl}`) } -const arg1 = process.argv[2] -await main(arg1) +await main() diff --git a/src/config/index.ts b/src/config/index.ts index fe3a225..33ffd0d 100644 --- a/src/config/index.ts +++ b/src/config/index.ts @@ -5,6 +5,7 @@ export interface Config { tenderly: TenderlyConfig networks: Record deployer: Address + spellsRepoPath: string } export interface NetworkConfig { @@ -19,7 +20,7 @@ export interface TenderlyConfig { apiKey: string } -export function getConfig(getEnvVariable: (key: string) => string): Config { +export function getConfig(getEnvVariable: (key: string) => string, spellsRepoPath: string): Config { return { tenderly: { account: getEnvVariable('TENDERLY_ACCOUNT'), @@ -39,5 +40,6 @@ export function getConfig(getEnvVariable: (key: string) => string): Config { }, }, deployer: zeroAddress, + spellsRepoPath, } } diff --git a/src/index.ts b/src/index.ts index d984ca1..a851d71 100644 --- a/src/index.ts +++ b/src/index.ts @@ -30,7 +30,12 @@ export async function forkAndExecuteSpell(spellName: string, config: Config): Pr }) const ethereumClient = new EthereumClient(rpc.adminRpcUrl, forkChainId, config.deployer) - const spellAddress = await deployContract(spellName, rpc.adminRpcUrl, config.deployer) + const spellAddress = await deployContract({ + contractName: spellName, + rpc: rpc.adminRpcUrl, + from: config.deployer, + cwd: config.spellsRepoPath, + }) await executeSpell({ spellAddress, network: chain, ethereumClient }) diff --git a/src/periphery/forge/index.ts b/src/periphery/forge/index.ts index 64a9702..2d1c01f 100644 --- a/src/periphery/forge/index.ts +++ b/src/periphery/forge/index.ts @@ -1,7 +1,12 @@ import { $ } from 'dax-sh' import { Address } from 'viem' -export async function deployContract(contractName: string, rpc: string, from: Address): Promise
{ - const result = await $`forge create --rpc-url ${rpc} --from ${from} ${contractName} --unlocked --json`.json() +export async function deployContract({ + contractName, + rpc, + from, + cwd, +}: { contractName: string; rpc: string; from: Address; cwd: string }): Promise
{ + const result = await $`forge create --rpc-url ${rpc} --from ${from} ${contractName} --unlocked --json`.cwd(cwd).json() return result.deployedTo } diff --git a/src/utils/fs.ts b/src/utils/fs.ts new file mode 100644 index 0000000..0d66567 --- /dev/null +++ b/src/utils/fs.ts @@ -0,0 +1,5 @@ +import * as path from 'node:path' + +export function ensureAbsolutePath(p: string): string { + return path.resolve(p) +}