├── .babelrc.js ├── .dependabot └── config.yml ├── .eslintrc.js ├── .github ├── CODEOWNERS └── workflows │ ├── master-check-publish.yml │ ├── pull-request-audit-dependencies.yml │ └── pull-request-check.yml ├── .gitignore ├── .huskyrc.js ├── .lintignore ├── .lintstagedrc.js ├── .npmpackagejsonlintignore ├── .releaserc.js ├── CHANGELOG.md ├── CONTRIBUTING.md ├── LICENSE.md ├── README.md ├── action.yml ├── annotations.json ├── commitlint.config.js ├── dist └── index.js ├── index.js ├── lib ├── index.js └── patch.js ├── npmpackagejsonlint.config.js ├── package.json ├── patch.js ├── prettier.config.js ├── rollup.config.js ├── src ├── annotation.ts ├── annotations.ts ├── github.ts ├── index.ts └── inputs.ts ├── tsconfig.json └── yarn.lock /.babelrc.js: -------------------------------------------------------------------------------- 1 | module.exports = { 2 | presets: ['@attest/typescript', '@attest/env-node', '@attest/jest'], 3 | } 4 | -------------------------------------------------------------------------------- /.dependabot/config.yml: -------------------------------------------------------------------------------- 1 | version: 1 2 | update_configs: 3 | - package_manager: 'javascript' 4 | directory: '/' 5 | update_schedule: 'weekly' 6 | version_requirement_updates: increase_versions_if_necessary 7 | automerged_updates: 8 | - match: 9 | dependency_type: 'all' 10 | update_type: 'in_range' 11 | default_labels: 12 | - '🤖 Dependency update' 13 | commit_message: 14 | prefix: 'build' 15 | include_scope: true 16 | -------------------------------------------------------------------------------- /.eslintrc.js: -------------------------------------------------------------------------------- 1 | module.exports = { 2 | extends: ['@attest/typescript', '@attest/node'], 3 | parserOptions: { 4 | ecmaVersion: 2020, 5 | }, 6 | overrides: [ 7 | { 8 | files: ['package.json'], 9 | rules: { 10 | 'package-json/sort-collections': [ 11 | 2, 12 | [ 13 | 'devDependencies', 14 | 'dependencies', 15 | 'peerDependencies', 16 | 'optionalDepedencies', 17 | 'bundledDepednencies', 18 | 'config', 19 | ], 20 | ], 21 | }, 22 | }, 23 | ], 24 | } 25 | -------------------------------------------------------------------------------- /.github/CODEOWNERS: -------------------------------------------------------------------------------- 1 | # Attest Codeowners File for annotations-action 2 | # Automatically adds original contributors to pull requests for packages 3 | 4 | # Note: This file was automatically generated from the @attest/generate-codeowners tool, any edits will be overwritten 5 | 6 | 7 | -------------------------------------------------------------------------------- /.github/workflows/master-check-publish.yml: -------------------------------------------------------------------------------- 1 | name: Master Check & Publish 2 | 3 | on: 4 | push: 5 | branches: 6 | - master 7 | 8 | jobs: 9 | publish: 10 | runs-on: ubuntu-18.04 11 | steps: 12 | - uses: actions/checkout@v1 13 | - name: Configure Git 14 | run: | 15 | git --version 16 | git config --global user.email admin@askattest.com 17 | git config --global user.name attest-admin 18 | git remote rm origin 19 | git remote add origin "https://attest-admin:$GITHUB_TOKEN@github.com/$GITHUB_REPOSITORY.git" 20 | git checkout -b master 21 | git push -u origin master 22 | env: 23 | GITHUB_TOKEN: ${{ secrets.ADMIN_GH_TOKEN }} 24 | - name: 'Cache yarn' 25 | uses: actions/cache@v1 26 | with: 27 | path: ~/.cache/yarn 28 | key: ${{ runner.os }}-yarn-${{ hashFiles('yarn.lock') }} 29 | restore-keys: | 30 | ${{ runner.os }}-yarn- 31 | - name: 'Cache node_modules' 32 | uses: actions/cache@v1 33 | with: 34 | path: ${{ github.workspace }}/node_modules 35 | key: ${{ runner.os }}-node_modules-${{ hashFiles('yarn.lock') }} 36 | restore-keys: | 37 | ${{ runner.os }}-node_modules- 38 | - name: 'Setup registry' 39 | run: | 40 | echo "//npm.pkg.github.com/:_authToken=$GITHUB_TOKEN" >> ~/.npmrc 41 | echo "@attest:registry=https://npm.pkg.github.com/" >> ~/.npmrc 42 | env: 43 | GITHUB_TOKEN: ${{ secrets.ADMIN_GH_TOKEN }} 44 | - name: 'Install dependencies' 45 | run: yarn install --frozen-lockfile 46 | - name: 'Lint' 47 | run: yarn lint 48 | - name: 'Format' 49 | run: yarn format 50 | - name: Build 51 | run: yarn build 52 | - name: Version 53 | run: yarn semantic-release 54 | env: 55 | GH_TOKEN: ${{ secrets.ADMIN_GH_TOKEN }} 56 | -------------------------------------------------------------------------------- /.github/workflows/pull-request-audit-dependencies.yml: -------------------------------------------------------------------------------- 1 | name: Pull Request Audit Dependencies 2 | on: [pull_request] 3 | 4 | jobs: 5 | prCheck: 6 | name: audit 7 | runs-on: ubuntu-latest 8 | steps: 9 | - uses: actions/checkout@v1 10 | - run: | 11 | echo "//npm.pkg.github.com/:_authToken=$NODE_AUTH_TOKEN" >> ~/.npmrc 12 | echo "@attest:registry=https://npm.pkg.github.com/" >> ~/.npmrc 13 | env: 14 | NODE_AUTH_TOKEN: ${{secrets.ADMIN_GH_TOKEN}} 15 | - run: yarn audit 16 | -------------------------------------------------------------------------------- /.github/workflows/pull-request-check.yml: -------------------------------------------------------------------------------- 1 | name: Pull Request Check 2 | on: [pull_request] 3 | 4 | jobs: 5 | healthcheck: 6 | name: 'healthcheck' 7 | runs-on: ubuntu-18.04 8 | steps: 9 | - uses: actions/checkout@v1 10 | - name: 'Cache yarn' 11 | uses: actions/cache@v1 12 | with: 13 | path: ~/.cache/yarn 14 | key: ${{ runner.os }}-yarn-${{ hashFiles('yarn.lock') }} 15 | restore-keys: | 16 | ${{ runner.os }}-yarn- 17 | - name: 'Cache node_modules' 18 | uses: actions/cache@v1 19 | with: 20 | path: ${{ github.workspace }}/node_modules 21 | key: ${{ runner.os }}-node_modules-${{ hashFiles('yarn.lock') }} 22 | restore-keys: | 23 | ${{ runner.os }}-node_modules- 24 | - name: 'Setup registry' 25 | run: | 26 | echo "//npm.pkg.github.com/:_authToken=$GITHUB_TOKEN" >> ~/.npmrc 27 | echo "@attest:registry=https://npm.pkg.github.com/" >> ~/.npmrc 28 | env: 29 | GITHUB_TOKEN: ${{ secrets.ADMIN_GH_TOKEN }} 30 | - name: 'Install dependencies' 31 | run: yarn install --frozen-lockfile 32 | - name: 'Typecheck' 33 | run: yarn typecheck 34 | - name: 'Lint' 35 | run: yarn lint 36 | - name: 'Format' 37 | run: yarn format 38 | - name: 'Build' 39 | run: yarn build 40 | - name: 'Install dependencies (production)' 41 | run: yarn install --frozen-lockfile --production 42 | - name: 'Test' 43 | uses: ./ 44 | with: 45 | path: ./annotations.json 46 | title: Annotation Test 47 | token: ${{ secrets.GITHUB_TOKEN }} 48 | - uses: hmarr/auto-approve-action@v2.0.0 49 | if: github.actor == 'dependabot[bot]' || github.actor == 'dependabot-preview[bot]' 50 | with: 51 | github-token: '${{ secrets.GITHUB_TOKEN }}' 52 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | # csilk Gitignore default # 2 | ########################### 3 | 4 | .env 5 | 6 | # Editors # 7 | ########### 8 | .vscode 9 | .idea 10 | *.iml 11 | .project 12 | .gradle/ 13 | /nbproject/private/ 14 | 15 | # Compiled source # 16 | ################### 17 | 18 | dist 19 | *.com 20 | *.class 21 | *.dll 22 | *.exe 23 | *.o 24 | *.so 25 | 26 | # Packages # 27 | ############ 28 | 29 | *.7z 30 | *.dmg 31 | *.gz 32 | *.iso 33 | *.jar 34 | *.rar 35 | *.tar 36 | *.zip 37 | .vs 38 | *.msi 39 | *.nupkg 40 | 41 | # Logs and databases # 42 | ###################### 43 | 44 | *.log 45 | *.sql 46 | *.sqlite 47 | npm-debug.log* 48 | coverage 49 | junit.xml 50 | 51 | # Caches # 52 | ########## 53 | 54 | .eslintcache 55 | eslint-data 56 | /tmp/ 57 | /.cache-loader 58 | 59 | # Node # 60 | ######## 61 | 62 | lib-cov 63 | *.seed 64 | *.log 65 | *.dat 66 | *.out 67 | *.pid 68 | *.gz 69 | pids 70 | logs 71 | npm-debug.log 72 | node_modules/ 73 | .pnp.js 74 | .pnp 75 | .yarn-meta 76 | /packages/lockfile/index.js 77 | /.nyc_output 78 | .npmrc 79 | 80 | # OS generated files # 81 | ###################### 82 | 83 | .DS_Store 84 | .DS_Store? 85 | ._* 86 | .Spotlight-V100 87 | .Trashes 88 | ehthumbs.db 89 | Thumbs.db 90 | debug.log 91 | .settings 92 | .settings/* 93 | .buildpath 94 | *.iml 95 | sftp-config* 96 | *.sublime-* 97 | 98 | # Reports # 99 | ###################### 100 | coverage 101 | -------------------------------------------------------------------------------- /.huskyrc.js: -------------------------------------------------------------------------------- 1 | module.exports = { 2 | hooks: { 3 | 'pre-commit': 'lint-staged', 4 | 'commit-msg': 'commitlint -E HUSKY_GIT_PARAMS', 5 | }, 6 | } 7 | -------------------------------------------------------------------------------- /.lintignore: -------------------------------------------------------------------------------- 1 | .vscode/ 2 | dist/ 3 | node_modules/ 4 | .pnp.js 5 | CHANGELOG.md 6 | -------------------------------------------------------------------------------- /.lintstagedrc.js: -------------------------------------------------------------------------------- 1 | module.exports = { 2 | '*.@(css|html|js|json|less|md|scss|ts|vue|yaml|yml)': [ 3 | 'yarn prettier --ignore-path .lintignore --write', 4 | ], 5 | '*.@(md|js|jsx|ts|tsx|json)': [ 6 | 'yarn eslint --ext md,tsx,ts,js,ts,json --ignore-path .lintignore --fix', 7 | ], 8 | 'package.json': ['yarn codeowners'], 9 | } 10 | -------------------------------------------------------------------------------- /.npmpackagejsonlintignore: -------------------------------------------------------------------------------- 1 | **/__tests__/**/package.json 2 | node_modules 3 | -------------------------------------------------------------------------------- /.releaserc.js: -------------------------------------------------------------------------------- 1 | module.exports = { 2 | release: { 3 | branches: ['master'], 4 | }, 5 | plugins: [ 6 | '@semantic-release/commit-analyzer', 7 | [ 8 | '@semantic-release/release-notes-generator', 9 | { 10 | config: '@attest/conventional-changelog', 11 | }, 12 | ], 13 | [ 14 | '@semantic-release/changelog', 15 | { 16 | config: '@attest/conventional-changelog', 17 | changelogFile: 'CHANGELOG.md', 18 | }, 19 | ], 20 | '@semantic-release/github', 21 | [ 22 | '@semantic-release/git', 23 | { 24 | assets: ['CHANGELOG.md', 'dist/index.js'], 25 | }, 26 | ], 27 | ], 28 | } 29 | -------------------------------------------------------------------------------- /CHANGELOG.md: -------------------------------------------------------------------------------- 1 | ## [1.0.7](https://github.com/Attest/annotations-action/compare/v1.0.6...v1.0.7) (2020-02-20) 2 | 3 | ### Bug Fix - check input path exists 4 | 5 | check input path exists; if it does not warn and exitGH-10 6 | 7 | Reference: [5ca622d](https://github.com/Attest/annotations-action/commit/5ca622d) 8 | Ticket: [GH-10] 9 | 10 | 11 | ### Build System - ignore lib checking 12 | 13 | ignore lib type checking since there is an error in the dependency typesGH-8 14 | 15 | Reference: [fd637cd](https://github.com/Attest/annotations-action/commit/fd637cd) 16 | Ticket: [GH-8] 17 | 18 | 19 | ### Documentation - add docs for expected structure 20 | 21 | add documenation around the expected structure for the file input 22 | structure with link to exampleGH-8 23 | 24 | Reference: [a7c2f2e](https://github.com/Attest/annotations-action/commit/a7c2f2e) 25 | Ticket: [GH-8] 26 | 27 | ## [1.0.6](https://github.com/Attest/annotations-action/compare/v1.0.5...v1.0.6) (2020-02-19) 28 | 29 | ### Bug Fix - exclude lib check 30 | 31 | use real import and exlude lib checking as there is a problem with the type layer 32 | 33 | Reference: [10c1eef](https://github.com/Attest/annotations-action/commit/10c1eef) 34 | Ticket: [ch8743](https://app.clubhouse.io/attest/story/8743) 35 | 36 | ## [1.0.5](https://github.com/Attest/annotations-action/compare/v1.0.4...v1.0.5) (2020-02-19) 37 | 38 | ### Bug Fix - fix runtime errors 39 | 40 | patch runtime issue with navigator being included, this is not safe for use in node 41 | 42 | Reference: [63e5270](https://github.com/Attest/annotations-action/commit/63e5270) 43 | Ticket: [ch8743](https://app.clubhouse.io/attest/story/8743) 44 | 45 | ## [1.0.4](https://github.com/Attest/annotations-action/compare/v1.0.3...v1.0.4) (2020-02-18) 46 | 47 | ### Bug Fix - fix build issues 48 | 49 | fix build issues where dependencies where causing failures at runtime, 50 | add a navigator object to global scope so `@octokit/request` does not 51 | fail, as this is not available in node 52 | 53 | Reference: [2927f53](https://github.com/Attest/annotations-action/commit/2927f53) 54 | Ticket: [ch8743](https://app.clubhouse.io/attest/story/8743) 55 | 56 | ## [1.0.3](https://github.com/Attest/annotations-action/compare/v1.0.2...v1.0.3) (2020-02-14) 57 | 58 | ### Bug Fix - add missing dist file 59 | 60 | add dist/index.js that we can distribute the action 61 | 62 | Reference: [421fd9f](https://github.com/Attest/annotations-action/commit/421fd9f) 63 | Ticket: [ch8743](https://app.clubhouse.io/attest/story/8743) 64 | 65 | ## [1.0.2](https://github.com/Attest/annotations-action/compare/v1.0.1...v1.0.2) (2020-02-13) 66 | 67 | ### Bug Fix - github release assets 68 | Reference: [fcee803](https://github.com/Attest/annotations-action/commit/fcee803) 69 | Ticket: [ch8743](https://app.clubhouse.io/attest/story/8743) 70 | 71 | ## [1.0.1](https://github.com/Attest/annotations-action/compare/v1.0.0...v1.0.1) (2020-02-13) 72 | 73 | ### Bug Fix - bundle dependencies 74 | 75 | remove dependecies for external so that they are compiled into the dist 76 | 77 | Reference: [bd3ad1e](https://github.com/Attest/annotations-action/commit/bd3ad1e) 78 | Ticket: [ch8743](https://app.clubhouse.io/attest/story/8743) 79 | 80 | ### Bug Fix - update included assets 81 | 82 | - include node_modules in release archive (required for github actions) 83 | 84 | Reference: [542f756](https://github.com/Attest/annotations-action/commit/542f756) 85 | Ticket: [ch8743](https://app.clubhouse.io/attest/story/8743) 86 | 87 | 88 | ### Continuous Integration - correct branding 89 | 90 | correct branding in action.yml 91 | 92 | Reference: [f3f4ea0](https://github.com/Attest/annotations-action/commit/f3f4ea0) 93 | Ticket: [ch8743](https://app.clubhouse.io/attest/story/8743) 94 | 95 | # 1.0.0 (2020-02-13) 96 | 97 | ### Build System - update all dependencies 98 | 99 | - update all dependencies to the latest versions 100 | - fix issues with types with `@octokit/rest` 101 | - update dependabot to use `build` for the prefix as `chore` is no 102 | longer valid 103 | 104 | Reference: [83eaa9c](https://github.com/Attest/annotations-action/commit/83eaa9c) 105 | Ticket: [ch8743](https://app.clubhouse.io/attest/story/8743) 106 | 107 | 108 | ### Continuous Integration - update pipelines 109 | 110 | - simplify master pipeline; and ensure that we add the correct remote (use 111 | env var) 112 | - add dependency audit check 113 | 114 | Reference: [695c1e5](https://github.com/Attest/annotations-action/commit/695c1e5) 115 | Ticket: [ch8743](https://app.clubhouse.io/attest/story/8743) 116 | 117 | ### Continuous Integration - remove dry run mode 118 | 119 | run real release cycle 120 | 121 | Reference: [952e10e](https://github.com/Attest/annotations-action/commit/952e10e) 122 | Ticket: [ch8743](https://app.clubhouse.io/attest/story/8743) 123 | 124 | ### Continuous Integration - use config property 125 | 126 | use config property over preset; preset will not resolve the module but attempt to use one of the standard presets available 127 | 128 | Reference: [593f33e](https://github.com/Attest/annotations-action/commit/593f33e) 129 | Ticket: [ch8743](https://app.clubhouse.io/attest/story/8743) 130 | 131 | 132 | ### Feature - add action logic 133 | 134 | - create logic for writing annotations from a given json file 135 | - add action.yml 136 | - add example into workflow 137 | 138 | Reference: [0fc4fb8](https://github.com/Attest/annotations-action/commit/0fc4fb8) 139 | Ticket: [ch8753](https://app.clubhouse.io/attest/story/8753) 140 | 141 | 142 | ### - setup 143 | 144 | Create base repository adding the following tooling: 145 | 146 | - eslint 147 | - prettier 148 | - rollup 149 | - typescript 150 | - github workflows 151 | - semantic-release (in dry run mode) 152 | - commit lint 153 | - lintstaged + husky 154 | - gitignore 155 | - dependabot 156 | 157 | Reference: [12281b2](https://github.com/Attest/annotations-action/commit/12281b2) 158 | Ticket: [ch8753](https://app.clubhouse.io/attest/story/8753) 159 | 160 | ### - init 161 | Reference: [21b51d6](https://github.com/Attest/annotations-action/commit/21b51d6) 162 | -------------------------------------------------------------------------------- /CONTRIBUTING.md: -------------------------------------------------------------------------------- 1 | # Contributing 2 | 3 | When contributing to this repository, please first discuss the change you wish to make via issue, 4 | email, or any other method with the owners of this repository before making a change. 5 | 6 | All code style is controlled by eslint and prettier, please do not disable unless there is good reason to do so 7 | 8 | ## Submitting Changes 9 | 10 | ### Committing 11 | 12 | We are using the [conventional commits](https://www.conventionalcommits.org/en/v1.0.0-beta.4/) format to commit our code, please read it as it has all the information you need. 13 | 14 | All commits require a `type`, `scope`, `description`, long form descriptive `body` and a ticket reference eg. `ch1234` 15 | 16 | They should be structured as follows: 17 | 18 | ```bash 19 | 20 | feat(scope): I made a change 21 | 22 | BREAKING CHANGE: This is a description of the change i've made 23 | 24 | [ch1234] / #1234 25 | ``` 26 | 27 | ### Pull Request Process 28 | 29 | Please send a GitHub Pull Request to Attest with a clear list of what you've done. 30 | 31 | PRs need to be approved by a repo owner as well as pass all CI/CD pipeline checks 32 | -------------------------------------------------------------------------------- /LICENSE.md: -------------------------------------------------------------------------------- 1 | The MIT License (MIT) 2 | 3 | Copyright (c) 2019 Attest Technologies Limited 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # Annotations Action 2 | 3 | GitHub action for creating annotations from JSON file 4 | 5 | ## Note 6 | 7 | This repository uses npm packages from `@attest` scope on github; we are working hard to open source these packages. 8 | 9 | ## 🔥 Getting started 10 | 11 | Make sure you have a `~/.npmrc` file setup with a [github token](https://github.com/settings/tokens/new) (read packages scope) to authenticate with the Github package registry for [fe-tools](https://github.com/Attest/fe-tools/packages) 12 | 13 | ``` 14 | //npm.pkg.github.com/:_authToken={githubtoken} 15 | @attest:registry=https://npm.pkg.github.com/ 16 | ``` 17 | 18 | Then install with 19 | 20 | ``` 21 | yarn 22 | ``` 23 | 24 | ## Example workflow 25 | 26 | `workflow.yml` 27 | 28 | ``` 29 | name: workflow 30 | on: [push] 31 | jobs: 32 | job: 33 | runs-on: ubuntu-18.04 34 | steps: 35 | - uses: actions/checkout@v1 36 | - name: Annotate 37 | uses: Attest/annotations-action@v0.1.0 38 | with: 39 | token: ${{ secrets.GITHUB_TOKEN }} 40 | input: './annotations.json' 41 | title: 'Annotate Files' 42 | ``` 43 | 44 | ### Input file structure 45 | 46 | The expected structure for the input is defined [here in the source](https://github.com/Attest/annotations-action/blob/master/src/annotation.ts), for an example please look at [`annotations.json`](https://github.com/Attest/annotations-action/blob/master/annotations.json). 47 | -------------------------------------------------------------------------------- /action.yml: -------------------------------------------------------------------------------- 1 | name: 'Annotations Action' 2 | description: 'Dynamically label pull requests affecting packages in a monorepo / workspace' 3 | author: 'Attest Engineering (https://askattest.com)' 4 | branding: 5 | icon: 'edit-3' 6 | color: 'blue' 7 | inputs: 8 | secret: 9 | description: 'The GITHUB_TOKEN secret' 10 | path: 11 | description: 'The JSON file to consume' 12 | title: 13 | description: 'The actions title' 14 | runs: 15 | using: 'node12' 16 | main: 'lib/index.js' 17 | -------------------------------------------------------------------------------- /annotations.json: -------------------------------------------------------------------------------- 1 | [ 2 | { 3 | "message": "This is a annotation message", 4 | "path": "annotations.json", 5 | "column": { "start": 17, "end": 45 }, 6 | "line": { "start": 3, "end": 3 }, 7 | "level": "notice" 8 | }, 9 | { 10 | "message": "This is a annotation group", 11 | "path": "annotations.json", 12 | "column": { "start": 3, "end": 4 }, 13 | "line": { "start": 9, "end": 15 }, 14 | "level": "notice" 15 | }, 16 | { 17 | "message": "This is a annotation on file outside of changed", 18 | "path": "LICENSE.md", 19 | "line": { "start": 1, "end": 1 }, 20 | "level": "warning" 21 | } 22 | ] 23 | -------------------------------------------------------------------------------- /commitlint.config.js: -------------------------------------------------------------------------------- 1 | module.exports = { 2 | extends: ['@commitlint/config-conventional'], 3 | rules: { 4 | 'references-empty': [2, 'never'], 5 | }, 6 | parserPreset: { 7 | parserOpts: { 8 | issuePrefixes: ['^(?=.*[ch)(?=.*]).*', '^#|[0-9]'], 9 | }, 10 | }, 11 | } 12 | -------------------------------------------------------------------------------- /index.js: -------------------------------------------------------------------------------- 1 | require('./patch') 2 | require('./dist') 3 | -------------------------------------------------------------------------------- /lib/index.js: -------------------------------------------------------------------------------- 1 | require('./patch') 2 | 3 | /* eslint-disable-next-line import/no-unresolved */ 4 | require('../dist') 5 | -------------------------------------------------------------------------------- /lib/patch.js: -------------------------------------------------------------------------------- 1 | ;(function patch() { 2 | global.navigator = {} 3 | })() 4 | -------------------------------------------------------------------------------- /npmpackagejsonlint.config.js: -------------------------------------------------------------------------------- 1 | module.exports = require('@attest/config-npm-package-json-lint') 2 | -------------------------------------------------------------------------------- /package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "annotations-action", 3 | "version": "0.0.0", 4 | "private": true, 5 | "description": "GitHub action for creating annotations from JSON file", 6 | "main": "dist/index.js", 7 | "files": [ 8 | "dist" 9 | ], 10 | "scripts": { 11 | "-----------------UTILITY---------------": ".", 12 | "commit": "git-cz", 13 | "clean:nodemodules": "rimraf node_modules, yarn.lock", 14 | "clean:dist": "rimraf dist", 15 | "clean:jest": "rimraf **/node_modules/.cache && jest --clearCache &> /dev/null", 16 | "nuke": "run-p -c clean:jest clean:nodemodules clean:dist && yarn", 17 | "---------------CODEOWNERS--------------": ".", 18 | "codeowners": "yarn generate-codeowners", 19 | "--------------TYPECHECKING-------------": ".", 20 | "typecheck": "tsc --noEmit --skipLibCheck", 21 | "----------------BUILD TOOLS----------------": ".", 22 | "build": "rollup -c", 23 | "----------------LINTING----------------": ".", 24 | "lint": "run-s lint:packagejson 'lint:eslint {@}' --", 25 | "lint:eslint": "eslint --ext md,tsx,ts,js,ts,json --ignore-path .lintignore .", 26 | "lint:packagejson": "npmPkgJsonLint ./packages", 27 | "----------------Formatting----------------": ".", 28 | "format": "prettier '**/*.{css,html,js,json,less,md,scss,ts,vue,yaml,yml}' --ignore-path .lintignore --check" 29 | }, 30 | "repository": "https://github.com/Attest/annotations-action.git", 31 | "keywords": [ 32 | "github", 33 | "actions", 34 | "annotations", 35 | "tools", 36 | "config", 37 | "attest", 38 | "askattest" 39 | ], 40 | "author": "Attest Engineering (https://askattest.com)", 41 | "license": "MIT", 42 | "homepage": "https://askattest.com", 43 | "config": { 44 | "commitizen": { 45 | "path": "./node_modules/@attest/standard-commits" 46 | } 47 | }, 48 | "dependencies": { 49 | "@actions/core": "^1.2.3", 50 | "@actions/github": "2.1.1", 51 | "@octokit/core": "^2.4.3", 52 | "@octokit/rest": "^16.43.1" 53 | }, 54 | "devDependencies": { 55 | "@attest/babel-preset-env-node": "^1.0.3", 56 | "@attest/babel-preset-jest": "^1.0.3", 57 | "@attest/babel-preset-typescript": "^2.0.1", 58 | "@attest/config-jest": "^0.3.36", 59 | "@attest/config-npm-package-json-lint": "^0.2.7", 60 | "@attest/config-prettier": "^0.3.4", 61 | "@attest/config-rollup-typescript": "^1.0.11", 62 | "@attest/config-typescript": "^1.0.6", 63 | "@attest/conventional-changelog": "^1.0.19", 64 | "@attest/eslint-config": "^0.2.8", 65 | "@attest/eslint-config-node": "^0.1.0", 66 | "@attest/eslint-config-typescript": "^0.1.21", 67 | "@attest/generate-codeowners": "^0.1.22", 68 | "@attest/standard-commits": "^0.1.51", 69 | "@babel/core": "^7.9.0", 70 | "@semantic-release/changelog": "^5.0.1", 71 | "@semantic-release/commit-analyzer": "^8.0.1", 72 | "@semantic-release/git": "^9.0.0", 73 | "@semantic-release/github": "^7.0.5", 74 | "@semantic-release/release-notes-generator": "^9.0.1", 75 | "husky": "^4.2.5", 76 | "lint-staged": "^10.1.7", 77 | "npm-run-all": "^4.1.5", 78 | "rimraf": "^3.0.2", 79 | "semantic-release": "^17.0.7", 80 | "typescript": "^3.8.3" 81 | }, 82 | "optionalDependencies": { 83 | "eslint-plugin-react-hooks": "^2.5.1" 84 | }, 85 | "engines": { 86 | "node": ">=12.13 <13" 87 | }, 88 | "resolutions": { 89 | "minimist": "^1.2.5", 90 | "**/os-locale": "^3.1.0" 91 | }, 92 | "contributors": [ 93 | "Blake Newman (https://askattest.com)" 94 | ] 95 | } 96 | -------------------------------------------------------------------------------- /patch.js: -------------------------------------------------------------------------------- 1 | ;(function patchNavigatorIssue() { 2 | global.navigator = {} 3 | })() 4 | -------------------------------------------------------------------------------- /prettier.config.js: -------------------------------------------------------------------------------- 1 | module.exports = require('@attest/config-prettier') 2 | -------------------------------------------------------------------------------- /rollup.config.js: -------------------------------------------------------------------------------- 1 | const config = require('@attest/config-rollup-typescript') 2 | const { dependencies: packageDependencies } = require('./package.json') 3 | 4 | const dependencies = Object.keys(packageDependencies) 5 | 6 | module.exports = config().map(configuration => { 7 | const external = configuration.external.filter(dependency => !dependencies.includes(dependency)) 8 | 9 | return { ...configuration, external } 10 | }) 11 | -------------------------------------------------------------------------------- /src/annotation.ts: -------------------------------------------------------------------------------- 1 | export interface Annotation { 2 | message: string 3 | path: string 4 | line?: AnnotationSourcePositionReference 5 | column?: AnnotationSourcePositionReference 6 | level: AnnotationLevel 7 | } 8 | 9 | export type AnnotationLevel = 'notice' | 'warning' | 'failure' 10 | export interface AnnotationSourcePositionReference { 11 | start?: number 12 | end?: number 13 | } 14 | -------------------------------------------------------------------------------- /src/annotations.ts: -------------------------------------------------------------------------------- 1 | import { Annotation } from '@/annotation' 2 | 3 | export type AnnotationsConclusion = 'success' | 'failure' | 'neutral' 4 | 5 | export class Annotations extends Array { 6 | public static fromJSON(json: string): Annotations { 7 | return new Annotations(...JSON.parse(json)) 8 | } 9 | 10 | public hasFailure(): boolean { 11 | return this.some(annotation => annotation.level === 'failure') 12 | } 13 | 14 | public hasWarning(): boolean { 15 | return this.some(annotation => annotation.level === 'warning') 16 | } 17 | 18 | public get failures(): Annotation[] { 19 | return this.filter(annotation => annotation.level === 'failure') 20 | } 21 | 22 | public get warnings(): Annotation[] { 23 | return this.filter(annotation => annotation.level === 'warning') 24 | } 25 | 26 | public get notices(): Annotation[] { 27 | return this.filter(annotation => annotation.level === 'notice') 28 | } 29 | 30 | public get conclusion(): AnnotationsConclusion { 31 | if (this.length === 0) return 'success' 32 | if (this.hasFailure()) return 'failure' 33 | if (this.hasWarning()) return 'neutral' 34 | return 'success' 35 | } 36 | } 37 | -------------------------------------------------------------------------------- /src/github.ts: -------------------------------------------------------------------------------- 1 | import { Annotations } from '@/annotations' 2 | import { Context } from '@actions/github/lib/context' 3 | import { Octokit } from '@octokit/rest' 4 | import github from '@actions/github' 5 | 6 | export class Github { 7 | private readonly client: Octokit 8 | private readonly context: Context 9 | private readonly owner: string 10 | private readonly repo: string 11 | private readonly sha: string 12 | private check: Octokit.ChecksCreateResponse | null = null 13 | 14 | public constructor(token: string) { 15 | this.client = (new github.GitHub({ 16 | auth: token, 17 | }) as unknown) as Octokit 18 | this.context = github.context 19 | this.owner = this.context.repo.owner 20 | this.repo = this.context.repo.repo 21 | this.sha = this.context.payload.pull_request?.head.sha ?? this.context.sha 22 | } 23 | 24 | private static githubAnnotationFromAnnotation( 25 | annotations: Annotations, 26 | ): Octokit.ChecksUpdateParamsOutputAnnotations[] { 27 | return annotations.map(annotation => { 28 | const { level, message, path, column = {}, line = {} } = annotation 29 | 30 | const startLine = line?.start ?? 0 31 | const endLine = line?.end ?? 0 32 | 33 | const isSameLinePosition = startLine === endLine 34 | const startColumn = isSameLinePosition ? column?.start ?? line.end : undefined 35 | const endColumn = isSameLinePosition ? column?.end ?? line.start : undefined 36 | 37 | return { 38 | annotation_level: level, 39 | message, 40 | path, 41 | start_column: startColumn, 42 | end_column: endColumn, 43 | start_line: startLine, 44 | end_line: endLine, 45 | } 46 | }) 47 | } 48 | 49 | public async createCheck(name: string): Promise { 50 | const { owner, repo, sha } = this 51 | 52 | const response = await this.client.checks.create({ 53 | owner, 54 | repo, 55 | name, 56 | head_sha: sha, 57 | status: 'in_progress', 58 | }) 59 | 60 | this.check = response.data 61 | 62 | return this 63 | } 64 | 65 | public async updateCheckWithAnnotations(annotations: Annotations): Promise { 66 | if (this.check === null) return 67 | 68 | const { owner, repo } = this 69 | const { name, id } = this.check 70 | 71 | await this.client.checks.update({ 72 | owner, 73 | repo, 74 | check_run_id: id, 75 | name, 76 | status: 'completed', 77 | conclusion: annotations.conclusion, 78 | output: { 79 | title: `${name}: output`, 80 | summary: `${annotations.length} annotations written`, 81 | text: ` 82 | - Failures: ${annotations.failures.length} 83 | - Warnings: ${annotations.warnings.length} 84 | - Notices: ${annotations.notices.length} 85 | `, 86 | annotations: Github.githubAnnotationFromAnnotation(annotations), 87 | }, 88 | }) 89 | } 90 | } 91 | -------------------------------------------------------------------------------- /src/index.ts: -------------------------------------------------------------------------------- 1 | import { Annotations } from '@/annotations' 2 | import { Github } from '@/github' 3 | import { getInputs } from '@/inputs' 4 | import core from '@actions/core' 5 | import fs from 'fs' 6 | 7 | async function main(): Promise { 8 | const { token, title, path } = getInputs() 9 | 10 | if (!fs.existsSync(path)) { 11 | core.warning(`Input file ${path} does not exist`) 12 | return 13 | } 14 | 15 | const github = new Github(token) 16 | await github.createCheck(title) 17 | 18 | const file = fs.readFileSync(path) 19 | const annotations = Annotations.fromJSON(file.toString()) 20 | 21 | await github.updateCheckWithAnnotations(annotations) 22 | } 23 | 24 | main().catch(error => { 25 | /* eslint-disable-next-line no-console */ 26 | console.error(error.stack) 27 | core.setFailed(`annotations-action: ${error.message}`) 28 | }) 29 | -------------------------------------------------------------------------------- /src/inputs.ts: -------------------------------------------------------------------------------- 1 | import core from '@actions/core' 2 | 3 | export interface EnviromentOptions { 4 | token: string 5 | title: string 6 | path: string 7 | } 8 | 9 | export function getInputs(): EnviromentOptions { 10 | const token = core.getInput('token') 11 | const path = core.getInput('path') 12 | const title = core.getInput('title') 13 | 14 | return validateEnvironmentOptions({ token, path, title }) 15 | } 16 | 17 | function validateEnvironmentOptions( 18 | environment: Partial, 19 | ): E { 20 | if (!environment.token) { 21 | throw new Error('`token` input must be set.') 22 | } 23 | 24 | if (!environment.path) { 25 | throw new Error('`path` input must be set.') 26 | } 27 | 28 | if (!environment.title) { 29 | throw new Error('`title` input must be set') 30 | } 31 | 32 | return environment as E 33 | } 34 | -------------------------------------------------------------------------------- /tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "extends": "@attest/config-typescript", 3 | "compilerOptions": { 4 | "baseUrl": "." 5 | } 6 | } 7 | --------------------------------------------------------------------------------