├── .babelrc ├── .gitignore ├── README.md ├── fixtures ├── installation_repositories.added.json ├── lambda-test-event.json ├── pull_request.opened.json ├── pull_request.synchronize.json └── push.json ├── index.js ├── lambda-test.js ├── logs └── .gitignore ├── nodemon.json ├── package.json ├── scripts ├── compare-commits.js ├── deploy.sh ├── get-logs.js ├── phpcs.js ├── test-commit.js └── test-pr.js ├── src ├── config.js ├── diff.js ├── format.js ├── hooks.js ├── index.js ├── linters │ ├── eslint │ │ └── index.js │ ├── index.js │ ├── phpcs │ │ └── index.js │ └── stylelint │ │ └── index.js ├── metadata.js ├── review.js ├── run.js └── util.js └── start-development.js /.babelrc: -------------------------------------------------------------------------------- 1 | { 2 | "plugins": ["transform-async-to-generator"], 3 | "presets": ["es2015", "stage-0"] 4 | } 5 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | *.pem 2 | .env 3 | build/ 4 | node_modules 5 | probot/ 6 | src/linters/phpcs/vendor 7 | bin/ 8 | lib/ 9 | event.json 10 | lambda-function.zip 11 | package-lock.json 12 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | 2 | 3 | 7 | 10 | 11 | 12 | 15 | 18 | 19 |
4 | hm-linter bot
5 | Automatically run the HM Coding Standards on any repository. 6 |
8 | 🤖 9 |
13 | A Human Made project. Maintained by @rmccue. 14 | 16 | 17 |
20 | 21 | Automatically run the [HM Coding standards](https://github.com/humanmade/coding-standards) on any repository. 22 | 23 | 24 | 25 | 26 | ## Installation 27 | 28 | To enable on any repository on GitHub, simply [head to the app page](https://github.com/apps/hm-linter) and Install/Configure. You'll get an initial report as a new issue if you have any existing linting errors in your codebase. 29 | 30 | Every repository is different, and you might want to customise the rules that the linter runs. Good news: you can do just that. hm-linter detects custom configuration files automatically, just create a `phpcs.ruleset.xml` file for phpcs, [`eslintrc.*`](https://eslint.org/docs/user-guide/configuring#configuration-file-formats) file for ESLint, or [`.stylelintrc`](https://stylelint.io/user-guide/configure) for stylelint. 31 | 32 | See the [HM Coding standards](https://github.com/humanmade/coding-standards) documentation for how to configure specific rules. 33 | 34 | **Note:** Custom configuration can only use rules/standards which hm-linter has available. This includes the HM Coding Standards as well as any dependencies of it (such as the WP Coding Standards). 35 | 36 | 37 | ## Configuration 38 | 39 | By default, hmlinter will use the latest version of the Human Made coding standards. You can configure it to use an older or fixed version by creating a `.github/hmlinter.yml` file. This file should look like: 40 | 41 | ```yaml 42 | # GLOBAL SETTINGS 43 | 44 | # By default, the version is set to "latest". This can be set to any version 45 | # from 0.4.2 and above, but you MUST include the full version number. 46 | # If you wish to increase the security releases automatically set the 47 | # version to be 'X.Y', otherwise it will be 'X.Y.Z'. 48 | version: latest 49 | 50 | # PER-STANDARD SETTINGS 51 | phpcs: 52 | # Set to false to disable phpcs 53 | enabled: true 54 | 55 | # Set to "inherit" to use the global version, "latest" for the latest 56 | # version, or a specific full version number. 57 | version: inherit 58 | 59 | eslint: 60 | enabled: true 61 | version: inherit 62 | 63 | stylelint: 64 | enabled: true 65 | version: inherit 66 | ``` 67 | 68 | Versions **MUST** be specified in full format (i.e. `0.5.0`). `latest` is available as a convenient shorthand for the latest published version, but note that this will be updated and may cause your code to fail future checks. 69 | 70 | 71 | ## Development 72 | 73 | hm-linter is a GitHub bot built on top of the [Probot framework](https://probot.github.io/). It runs on Lambda, which runs Node 12.x. 74 | 75 | To get started on development of hm-linter: 76 | 77 | 1. Clone this repository 78 | 2. `npm install` or `yarn install` the dependencies 79 | 80 | 81 | ## Testing 82 | 83 | ### Live Testing 84 | 85 | The easiest and best way to test hm-linter is to run the bot in development mode. This will run the bot locally, and uses a proxy to forward all webhook events from GitHub. 86 | 87 | `yarn start` will run a development copy of the linter bot inside a Lambda-like Docker container. 88 | 89 | To set this up: 90 | 91 | 1. Download "hm-linter-development Private Key" from the team 1Password Documents. 92 | 2. Save this file into the linter-bot directory as `development.private-key.pem` 93 | 3. Download "hm-linter-development .env" from the team 1Password Documents. 94 | 4. Save this file into the linter-bot directory as `.env` 95 | 5. Run `yarn start` 96 | 97 | The development mode is set up only on the [linter-bot-test](https://github.com/humanmade/linter-bot-test) repository. You can add it to other repositories on the `humanmade` organisation, but **please only do this temporarily**. You should remove any repositories you add as soon as you're finished testing. 98 | 99 | Webhook events for the development bot are sent to Smee.io, which [logs all events](https://smee.io/rpFoxbfDjkw5Srji). If you visit this page, you can also replay events; you should use this while developing/testing rather than repeatedly opening new PRs. 100 | 101 | A typical development process looks like this: 102 | 103 | 1. Generate the test event you want or find one that already exists 104 | 2. Write the first version of your code to handle it 105 | 3. `yarn start` 106 | 4. [Replay the event on Smee](https://smee.io/rpFoxbfDjkw5Srji) 107 | 5. Check that your code did what you expect 108 | 6. If your code worked, you're done 🙌 109 | 7. If your code didn't work, kill the bot 110 | 8. Repeat steps 2-7 until your code works. 111 | 112 | 113 | ### Replicating production issues 114 | 115 | The first step to replicating production issues is to understand the request being sent to hm-linter. Note that when running against these events, you are **testing against the live GitHub API**, so be careful. 116 | 117 | Access the CloudWatch Logs for hm-linter (ask the Cloud team for access) and find the request you received. If you have the AWS CLI installed, you can do this by running the `scripts/get-logs.js` command. 118 | 119 | Each check status page lists the various request IDs. The **Lambda ID** is the ID you need for pulling down the relevant logs and data. 120 | 121 | This will write the logs to `{id}.log`, and save the raw data to `{id}.json`. 122 | 123 | ```sh 124 | # For request deadbeef-badd-ecaf-dead-beefbaddecaf: 125 | node scripts/get-logs.js deadbeef-badd-ecaf-dead-beefbaddecaf 126 | 127 | # By default, this will only check the last 48 hours; to override, set HOUR_LIMIT: 128 | HOUR_LIMIT=192 node scripts/get-logs.js deadbeef-badd-ecaf-dead-beefbaddecaf 129 | ``` 130 | 131 | ``` 132 | Querying for deadbeef-badd-ecaf-dead-beefbaddecaf 133 | Waiting for results… 134 | Log saved to: deadbeef-badd-ecaf-dead-beefbaddecaf.log 135 | Raw data saved to: deadbeef-badd-ecaf-dead-beefbaddecaf.json 136 | ``` 137 | 138 | You can then run the handler against a simulated Lambda environment locally (using Docker): 139 | 140 | ``` 141 | # Run build at least once: 142 | npm run build 143 | 144 | # Run the handler. 145 | npm run test < deadbeef-badd-ecaf-dead-beefbaddecaf.json 146 | ``` 147 | 148 | **Note:** The format of the JSON data passed to `test` **must** be in API Gateway format (i.e. from the get-logs script). If you get an `Cannot read property 'x-github-event' of undefined` error, you're passing a GitHub event instead (i.e. from Smee). 149 | 150 | 151 | ### Deployment 152 | 153 | hm-linter is deployed on a Lambda instance. Deployment is handled via npm scripts, which you run via `npm run