{"id":15158120,"url":"https://github.com/ethereum/eip-bot","last_synced_at":"2025-09-30T08:31:16.471Z","repository":{"id":39866348,"uuid":"347575693","full_name":"ethereum/EIP-Bot","owner":"ethereum","description":"A collection of bots that make life easier on editors","archived":true,"fork":false,"pushed_at":"2023-01-07T20:57:17.000Z","size":33701,"stargazers_count":41,"open_issues_count":11,"forks_count":37,"subscribers_count":8,"default_branch":"master","last_synced_at":"2025-01-06T10:04:45.295Z","etag":null,"topics":["bot","eip","github-actions"],"latest_commit_sha":null,"homepage":"","language":"TypeScript","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"cc0-1.0","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/ethereum.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":".github/CODEOWNERS","security":null,"support":null}},"created_at":"2021-03-14T07:50:26.000Z","updated_at":"2024-11-02T13:52:38.000Z","dependencies_parsed_at":"2023-02-08T01:47:40.679Z","dependency_job_id":null,"html_url":"https://github.com/ethereum/EIP-Bot","commit_stats":null,"previous_names":[],"tags_count":13,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/ethereum%2FEIP-Bot","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/ethereum%2FEIP-Bot/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/ethereum%2FEIP-Bot/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/ethereum%2FEIP-Bot/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/ethereum","download_url":"https://codeload.github.com/ethereum/EIP-Bot/tar.gz/refs/heads/master","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":234719341,"owners_count":18876523,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["bot","eip","github-actions"],"created_at":"2024-09-26T20:40:22.996Z","updated_at":"2025-09-30T08:31:11.075Z","avatar_url":"https://github.com/ethereum.png","language":"TypeScript","funding_links":[],"categories":[],"sub_categories":[],"readme":"# EIP Linting Bot\n\nThis Github Actions integrated bot lints EIPs and provides feedback for authors; its goal is to catch simple problems, notify the relevant individuals to review, and merge simple changes automatically.\n\n# Usage\n\n```yml\non:\n  workflow_run:\n    workflows:\n      - Auto Review Bot Trigger\n    types:\n      - completed\n\nname: Auto Review Bot\njobs:\n  auto-review-bot:\n    runs-on: ubuntu-latest\n    name: Run\n    steps:\n      - name: Fetch PR Number\n        uses: dawidd6/action-download-artifact@6765a42d86407a3d532749069ac03705ad82ebc6\n        with:\n          name: pr-number\n          workflow: auto-review-trigger.yml\n          run_id: ${{ github.event.workflow_run.id }}\n\n      - name: Save PR Number\n        id: save-pr-number\n        run: echo \"::set-output name=pr::$(cat pr-number.txt)\"\n\n      - name: Checkout\n        uses: actions/checkout@2541b1294d2704b0964813337f33b291d3f8596b\n        with:\n          repository: ethereum/EIPs # Default, but best to be explicit here\n          ref: master\n\n      - name: Setup Node.js Environment\n        uses: actions/setup-node@2fddd8803e2f5c9604345a0b591c3020ee971a93\n        with:\n          node-version: 16\n\n      - name: Auto Review Bot\n        id: auto-review-bot\n        uses: ethereum/EIP-Bot@1e1bb6a58e02d28e9afa9462b00a518d9b47860e # dist\n        with:\n          GITHUB-TOKEN: ${{ secrets.TOKEN }}\n          PR_NUMBER: ${{ steps.save-pr-number.outputs.pr }}\n          CORE_EDITORS: '@MicahZoltu,@lightclient,@axic,@gcolvin,@SamWilsn,@Pandapip1'\n          ERC_EDITORS: '@lightclient,@axic,@SamWilsn,@Pandapip1'\n          NETWORKING_EDITORS: '@MicahZoltu,@lightclient,@axic,@SamWilsn'\n          INTERFACE_EDITORS: '@lightclient,@axic,@SamWilsn,@Pandapip1'\n          META_EDITORS: '@lightclient,@axic,@gcolvin,@SamWilsn,@Pandapip1'\n          INFORMATIONAL_EDITORS: '@lightclient,@axic,@gcolvin,@SamWilsn,@Pandapip1'\n          MAINTAINERS: '@alita-moore,@mryalamanchi'\n\n      - name: Enable Auto-Merge\n        uses: reitermarkus/automerge@a25ea0de41019ad13380d22e01db8f5638f1bcdc\n        with:\n          token: ${{ secrets.TOKEN }}\n          pull-request: ${{ steps.save-pr-number.outputs.pr }}\n\n      - name: Submit Approval\n        uses: hmarr/auto-approve-action@24ec4c8cc344fe1cdde70ff37e55ace9e848a1d8\n        with:\n          github-token: ${{ secrets.TOKEN }}\n          pull-request-number: ${{ steps.save-pr-number.outputs.pr }}\n```\n\n# Contributing\n\n## Standard Practices\n\n### Function Naming\n\nThis library uses concepts that may appear strange,\n\n- **require...** : functions that start with `require` are used to guarantee it responds with the resource you're looking for or else it will error\n- **assert...** : functions that start with `assert` are used to test something and if that test fails it'll respond with some kind of error message string. This is where the errors that the bot tells the author comes from.\n- **...Purifier** : functions that end in `purifier` are used to _purify_ test results, they help to keep the logic of assertions clean and handle cross error dependencies like the fact that if you change the status you need an editor approval, but then once you actually get that approval we don't want to show the error for changing the status (i.e. `if (changedStatus \u0026\u0026 !approvedByEditor) { return error } else if (changedStatus \u0026\u0026 approvedByEditor) { return }`).\n\nThese practices are applied to make things easier to understand. If you're not careful, then the logic can get tangled very quick, and then it's really hard to read and change things.\n\n### Testing\n\nThis bot employs two types of tests\n\n- functional\n- integration\n\nA functional test is your standard unit test. Take a small function and test its behavior thoroughly. You don't need anything more than jest to do this, and your code should be organized such that the sub functions are abstracted and tested. It also uses dependency injection for this reason (it's typically easier to mock that way). Everything should have unit tests.\n\nAn integration test is a test that considers the behavior as a whole. In this bot, we mock a network response from the github api using `nock`. When you do this for every network request you're able to get a snapshot and test the whole's behavior. All integration tests were once bugs that were fixed, so if you implement a feature you don't need to add an integration test. It's easier to manage this way, and it serves the purpose of reducing code regression. Integration tests tend to be brittle because of the number of different facets. So the code uses several homebrewed tools to maximize reliability.\n\nFeel free to share ideas on how to improve testing procedures.\n\n## Getting Started\n\n### Requirements\n\n1. node package manager (npm)\n2. Github Token\n3. Forked Repo\n4. nodejs\n\n### Quick Start (npm run it)\n\n`npm run it` runs the bot end to end; which means you can integrate and test with github directly. It uses the typescript built script so don't forget to build that by using `npm run build` or `npm run watch`.\n\n1. Download your forked `EIPS` repo\n2. Create a [Github Token](/creating-a-personal-access-token)\n3. Create a PR in your forked repo doing anything, I recommend just editing a couple lines in an already existing EIPs\n4. Create a .env variable in the root dir with the following information defined:\n\n```\nGITHUB_TOKEN = \u003cYOUR GITHUB TOKEN\u003e\nNODE_ENV = development\n\nPULL_NUMBER = \u003cpull_number\u003e\nBASE_SHA = \u003cbase sha of the PR\u003e\nHEAD_SHA = \u003chead sha of the PR\u003e\nREPO_OWNER_NAME = \u003cyour login\u003e\nREPO_NAME = EIPs\nGITHUB_REPOSITORY = \u003cyour login\u003e/EIPs\n```\n\n5. `npm run build \u0026\u0026 npm run it`\n\n### Quick Start (npm run mock)\n\n`npm run mock` is a tool built for writing integration tests, but it can also be used to develop. `npm run mock` uses the saved network data of previous pull requests and states of those pull requests. Try this by mocking [pull 3670](https://github.com/ethereum/EIPs/pull/3670)..\n\n1. Clone this repo\n2. Setup your local environment (requires node \u003e 14.x): `npm install`\n3. Create a .env variable in the root dir with the following information:\n\n```\nGITHUB_TOKEN = anything\n\nPULL_NUMBER = 3670\nREPO_OWNER_NAME = ethereum\nREPO_NAME = EIPs\nGITHUB_REPOSITORY = ethereum/EIPs\nEVENT_TYPE = pull_request_target\n```\n\n4. Then run the mock `npm run mock`\n5. You should get a response like the following\n\n```bash\nalitamoore@Alitas-MBP EIP-Bot % npm run mock\n\n\u003e auto-merge-eip@1.0.0 mock /Users/alitamoore/ethereum/EIP-Bot\n\u003e NODE_ENV=MOCK node -r dotenv/config build/src/index.js\n\nfailed to pass tests with the following errors:\n        - File with name EIPS/eip-3670.md is new and new files must be reviewed\n        - This PR requires review from one of [@micahzoltu, @lightclient, @arachnid, @cdetrio, @souptacular, @vbuterin, @nicksavers, @wanderer, @gcolvin]\n::error::failed to pass tests with the following errors:%0A     - File with name EIPS/eip-3670.md is new and new files must be reviewed%0A      - This PR requires review from one of [@micahzoltu, @lightclient, @arachnid, @cdetrio, @souptacular, @vbuterin, @nicksavers, @wanderer, @gcolvin]\nnpm ERR! code ELIFECYCLE\nnpm ERR! errno 1\nnpm ERR! auto-merge-eip@1.0.0 mock: `NODE_ENV=MOCK node -r dotenv/config build/src/index.js`\nnpm ERR! Exit status 1\nnpm ERR!\nnpm ERR! Failed at the auto-merge-eip@1.0.0 mock script.\nnpm ERR! This is probably not a problem with npm. There is likely additional logging output above.\n\nnpm ERR! A complete log of this run can be found in:\nnpm ERR!     /Users/alitamoore/.npm/_logs/2021-07-25T06_43_54_229Z-debug.log\n```\n\nIn this case, an error was expected because the bug in question was if the editors were mentioned if a status error occurred (if the status wasn't one of the allowed types)\n\n### Troubleshooting\n\n- \u003ci\u003eWhen I run it, I'm getting unexplainable errors with my github requests.\u003c/i\u003e\n  - Github limits the number of requests from a given IP, this may be avoidable if you only use the `octokit` but a VPN also works just fine\n\n## Code Style Guidelines (in no particular order)\n\nThis repo is a living repo, and it will grow with the EIP drafting and editing process. It's important to maintain code quality.\n\n1. Define every type (including octokit)\n2. Make clean and clear error messages\n3. Avoid abstraction\n4. Use [enums](https://www.sohamkamani.com/javascript/enums/) as much as possible\n\n## Explanations of Style Guidelines\n\nA couple things to keep in mind if you end up making changes to this\n\n#### 1. \u003cins\u003eDefine every type\u003c/ins\u003e\n\nDefine every type, no `any` types. The time it takes to define a type now will save you or someone else later a lot of time. If you make assumptions about types, protect those assumptions (throw exception if they are false).\n\nSometimes [Octokit types](https://www.npmjs.com/package/@octokit/types) can be difficult to index, but it's important that whenever possible the types are defined and assumptions protected.\n\n#### 2. \u003cins\u003eMake clean and clear error messages\u003c/ins\u003e\n\nThis bot has a single goal: catch simple mistakes automatically and save the editors time. So clear error messages that allow the PR author to change it themselves are very important.\n\n#### 3. \u003cins\u003eAvoid Abstraction\u003c/ins\u003e\n\nOnly abstract if necessary, keep things in one file where applicable; other examples of okay abstraction are types, regex, and methods used more than 3 times. Otherwise, it's often cleaner to just re-write things.\n\n```javascript\n// DON'T DO THIS\n** src/lib.ts **\nexport const baz = () =\u003e \"baz\"\n\n** src/foo.ts **\nimport { baz } from \"./lib\"\nexport const foo = () =\u003e baz();\n\n** src/bar.ts **\nimport { baz } from \"./lib\"\nexport const bar = () =\u003e baz();\n\n// DO THIS\n** src/foo.ts **\nconst baz = () =\u003e \"baz\"\nexport const foo = () =\u003e baz();\n\n** src/bar.ts **\nconst baz = () =\u003e \"baz\"\nexport const bar = () =\u003e baz();\n```\n\n#### 4. \u003cins\u003eAlways use enum when defining restricted string types\u003c/ins\u003e\n\nIn short, enums make code easier to read, trace, and maintain.\n\nBut here's a brief info if you haven't worked with them before\n\n```typescript\nenum EnumFoo {\n  bar = \"BAR\",\n  baz = \"BAZ\"\n}\ntype Foo = \"BAR\" | \"BAZ\";\n```\n\nInline declaration is maintained\n\n```typescript\nconst foo: EnumFoo;\nconst bar: Foo;\n// foo and bar both must be either \"BAR\" or \"BAZ\"\n```\n\nUse case is slightly different\n\n```typescript\nconst foo: EnumFoo = EnumFoo.baz; // you can't directly assign \"BAZ\"\nconst bar: Foo = \"BAZ\";\n```\n\nBut comparisons are maintained\n\n```typescript\n// taking variables from above\n(\"BAZ\" === foo) === (\"BAZ\" === bar) \u0026\u0026\n  (\"BAZ\" === EnumFoo.baz) === (\"BAZ\" === \"BAZ\");\n```\n\nIn addition to the above use case and string eradication it centralizes the strings to be matched so they can be easily changed. So, making life much easier if you wanted to change the names of statuses on an EIP.\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fethereum%2Feip-bot","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fethereum%2Feip-bot","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fethereum%2Feip-bot/lists"}