From 81e9f485d7d1f8e39bfd82110d6c2cccc7da7810 Mon Sep 17 00:00:00 2001 From: Matt Solomon Date: Thu, 30 Sep 2021 10:16:12 -0700 Subject: [PATCH 1/4] feat: allow any RPC URL (remove dependence on Infura) --- .github/workflows/governance-checks.yaml | 2 +- utils/clients/ethers.ts | 4 ++-- utils/constants.ts | 2 +- 3 files changed, 4 insertions(+), 4 deletions(-) diff --git a/.github/workflows/governance-checks.yaml b/.github/workflows/governance-checks.yaml index 97eec883035..08cabc5aefd 100644 --- a/.github/workflows/governance-checks.yaml +++ b/.github/workflows/governance-checks.yaml @@ -52,6 +52,6 @@ jobs: env: GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} ETHERSCAN_API_KEY: ${{ secrets.ETHERSCAN_API_KEY }} - INFURA_API_KEY: ${{ secrets.INFURA_API_KEY }} + RPC_URL: ${{ secrets.RPC_URL }} DAO_NAME: ${{ matrix.DAO_NAME }} GOVERNOR_ADDRESS: ${{ matrix.GOVERNOR_ADDRESS }} diff --git a/utils/clients/ethers.ts b/utils/clients/ethers.ts index f3d6421b63b..1f96c53f285 100644 --- a/utils/clients/ethers.ts +++ b/utils/clients/ethers.ts @@ -1,4 +1,4 @@ import { providers } from "ethers"; -import { INFURA_API_KEY } from "../constants"; +import { RPC_URL } from "../constants"; -export const provider = new providers.InfuraProvider(1, INFURA_API_KEY); +export const provider = new providers.JsonRpcProvider(RPC_URL); diff --git a/utils/constants.ts b/utils/constants.ts index c649d165014..4902cfda205 100644 --- a/utils/constants.ts +++ b/utils/constants.ts @@ -2,7 +2,7 @@ export const REPOSITORY: string = process.env.GITHUB_REPOSITORY!; export const [GITHUB_REPO_OWNER, GITHUB_REPO_NAME] = typeof REPOSITORY === "string" ? REPOSITORY.split("/") : []; export const GOVERNOR_ADDRESS: string = process.env.GOVERNOR_ADDRESS!; -export const INFURA_API_KEY: string = process.env.INFURA_API_KEY!; +export const RPC_URL: string = process.env.RPC_URL!; export const ETHERSCAN_API_KEY: string = process.env.ETHERSCAN_API_KEY!; export const DAO_NAME: string = process.env.DAO_NAME!; export const REPORTS_BRANCH = "reports"; From 395be42a1031e0f445037b927cf39d48ce88d445 Mon Sep 17 00:00:00 2001 From: Matt Solomon Date: Thu, 30 Sep 2021 10:16:56 -0700 Subject: [PATCH 2/4] feat: save files locally when not in CI --- .github/workflows/governance-checks.yaml | 1 + .gitignore | 2 +- index.ts | 66 ++++++++++++++---------- package.json | 1 + utils/constants.ts | 1 + yarn.lock | 5 ++ 6 files changed, 48 insertions(+), 28 deletions(-) diff --git a/.github/workflows/governance-checks.yaml b/.github/workflows/governance-checks.yaml index 08cabc5aefd..81112901885 100644 --- a/.github/workflows/governance-checks.yaml +++ b/.github/workflows/governance-checks.yaml @@ -55,3 +55,4 @@ jobs: RPC_URL: ${{ secrets.RPC_URL }} DAO_NAME: ${{ matrix.DAO_NAME }} GOVERNOR_ADDRESS: ${{ matrix.GOVERNOR_ADDRESS }} + RUNNING_LOCALLY: 0 diff --git a/.gitignore b/.gitignore index 64326427b71..55ef8a17b40 100644 --- a/.gitignore +++ b/.gitignore @@ -1,3 +1,3 @@ node_modules .idea - +reports/ diff --git a/index.ts b/index.ts index 668b010c042..b2010f5f080 100644 --- a/index.ts +++ b/index.ts @@ -1,11 +1,13 @@ +require('dotenv').config() +import fs from 'fs'; import { DAO_NAME, GITHUB_REPO_NAME, GITHUB_REPO_OWNER, GOVERNOR_ADDRESS, REPORTS_BRANCH, + RUNNING_LOCALLY } from "./utils/constants"; -import { github } from "./utils/clients/github"; import { governorBravo } from "./utils/contracts/governor-bravo"; import { provider } from "./utils/clients/ethers"; import { AllCheckResults, Proposal } from "./types"; @@ -32,6 +34,7 @@ async function main() { .map((proposal) => proposal.args as unknown as Proposal); for (const proposal of activeProposals) { + console.log(`Checking proposal ${proposal.id}...`); const checkResults: AllCheckResults = Object.fromEntries( await Promise.all( Object.keys(ALL_CHECKS).map(async (checkId) => [ @@ -56,37 +59,46 @@ async function main() { : null, ]); - let sha: string | undefined; - try { - const { data } = await github.rest.repos.getContent({ + const report = toProposalReport( + { start: startBlock, end: endBlock, current: latestBlock }, + proposal, + checkResults + ); + + if (RUNNING_LOCALLY) { + // Running locally, dump to file + const dir = `./reports/${DAO_NAME}/${GOVERNOR_ADDRESS}/`; // TODO more robust way to keep this in sync with `path` + if (!fs.existsSync(dir)) fs.mkdirSync(dir, { recursive: true }); + fs.writeFileSync(`${dir}/${proposal.id}.md`, report); + + } else { + // Running in CI, save to file on REPORTS_BRANCH + const { github } = await import("./utils/clients/github"); // lazy load to avoid errors about missing env vars when not in CI + let sha: string | undefined; + try { + const { data } = await github.rest.repos.getContent({ + owner: GITHUB_REPO_OWNER, + repo: GITHUB_REPO_NAME, + ref: REPORTS_BRANCH, + path, + }); + if ("sha" in data) { + sha = data.sha; + } + } catch (error) { + console.warn("Failed to get sha for file at path", path, error); + } + + await github.rest.repos.createOrUpdateFileContents({ owner: GITHUB_REPO_OWNER, repo: GITHUB_REPO_NAME, - ref: REPORTS_BRANCH, + branch: REPORTS_BRANCH, + message: `Update ${path} as of ${formattedDateTime}`, + content: Buffer.from(report, "utf-8").toString("base64"), path, + sha, }); - if ("sha" in data) { - sha = data.sha; - } - } catch (error) { - console.warn("Failed to get sha for file at path", path, error); } - - await github.rest.repos.createOrUpdateFileContents({ - owner: GITHUB_REPO_OWNER, - repo: GITHUB_REPO_NAME, - branch: REPORTS_BRANCH, - message: `Update ${path} as of ${formattedDateTime}`, - content: Buffer.from( - toProposalReport( - { start: startBlock, end: endBlock, current: latestBlock }, - proposal, - checkResults - ), - "utf-8" - ).toString("base64"), - path, - sha, - }); } catch (error) { console.error("Failed to update file contents", error); } diff --git a/package.json b/package.json index 57f9cc96dcd..83f4db246f8 100644 --- a/package.json +++ b/package.json @@ -27,6 +27,7 @@ "@ethercast/etherscan-client": "^1.0.1", "@octokit/action": "^3.15.2", "@types/node": "^16.7.13", + "dotenv": "^10.0.0", "ethers": "^5.4.6", "ts-node": "^10.2.1", "typescript": "^4.4.2" diff --git a/utils/constants.ts b/utils/constants.ts index 4902cfda205..f27a9f86d28 100644 --- a/utils/constants.ts +++ b/utils/constants.ts @@ -6,3 +6,4 @@ export const RPC_URL: string = process.env.RPC_URL!; export const ETHERSCAN_API_KEY: string = process.env.ETHERSCAN_API_KEY!; export const DAO_NAME: string = process.env.DAO_NAME!; export const REPORTS_BRANCH = "reports"; +export const RUNNING_LOCALLY = Boolean(process.env.RUNNING_LOCALLY) // use 1 or 0 because Boolean('false') = true \ No newline at end of file diff --git a/yarn.lock b/yarn.lock index 99db0daebc8..2312e2b749d 100644 --- a/yarn.lock +++ b/yarn.lock @@ -578,6 +578,11 @@ diff@^4.0.1: resolved "https://registry.yarnpkg.com/diff/-/diff-4.0.2.tgz#60f3aecb89d5fae520c11aa19efc2bb982aade7d" integrity sha512-58lmxKSA4BNyLz+HHMUzlOEpg09FV+ev6ZMe3vJihgdxzgcwZ8VoEEPmALCZG9LmqfVoNMMKpttIYTVG6uDY7A== +dotenv@^10.0.0: + version "10.0.0" + resolved "https://registry.yarnpkg.com/dotenv/-/dotenv-10.0.0.tgz#3d4227b8fb95f81096cdd2b66653fb2c7085ba81" + integrity sha512-rlBi9d8jpv9Sf1klPjNfFAuWDjKLwTIJJ/VxtoTwIR6hnZxcEOQCZg2oIL3MWBYw5GpUDKOEnND7LXTbIpQ03Q== + elliptic@6.5.4: version "6.5.4" resolved "https://registry.yarnpkg.com/elliptic/-/elliptic-6.5.4.tgz#da37cebd31e79a1367e941b592ed1fbebd58abbb" From 0e2bae94e11e3af191937f8c57f5e71f750c259f Mon Sep 17 00:00:00 2001 From: Matt Solomon Date: Thu, 30 Sep 2021 10:20:43 -0700 Subject: [PATCH 3/4] docs: update README --- README.md | 27 +++++++++++++++++++++++++-- 1 file changed, 25 insertions(+), 2 deletions(-) diff --git a/README.md b/README.md index ef634397e81..25580f2ff39 100644 --- a/README.md +++ b/README.md @@ -5,6 +5,29 @@ including automated scripts that apply checks to live proposals to allow for better informed voting. -# Reports +## Reports -Find the reports [here](https://github.com/Uniswap/governance-seatbelt/tree/reports) \ No newline at end of file +Find the reports [here](https://github.com/Uniswap/governance-seatbelt/tree/reports) when run in CI, or in the `reports` folder if running locally + +## Development + +Create a file called `.env` with the following environment variables: + +```sh +# URL to your node, e.g. Infura or Alchemy endpoint +RPC_URL=yourNodeUrl + +# Etherscan API key: https://etherscan.io/myapikey +ETHERSCAN_API_KEY=yourEtherscanApiKey + +# Name of the DAO to check +DAO_NAME=Compound + +# Address of that DAO's governor contract +GOVERNOR_ADDRESS=0xc0Da02939E1441F497fd74F78cE7Decb17B66529 + +# Set to 1 if running locally, or 0 for CI +RUNNING_LOCALLY=1 +``` + +Other environment variables needed for CI can be found in `.github/workflows/governance-checks.yaml` From 6bd5777987bc558d3e894a767136b8e84ccf0852 Mon Sep 17 00:00:00 2001 From: Matt Solomon Date: Thu, 30 Sep 2021 11:39:23 -0700 Subject: [PATCH 4/4] chore: add .env files to .gitignore --- .gitignore | 2 ++ 1 file changed, 2 insertions(+) diff --git a/.gitignore b/.gitignore index 55ef8a17b40..551d0deb9ce 100644 --- a/.gitignore +++ b/.gitignore @@ -1,3 +1,5 @@ node_modules .idea reports/ +.env +.env.local