├── .codespellrc ├── .github ├── CONTRIBUTING.md ├── ISSUE_TEMPLATE │ ├── bug-report.yml │ ├── config.yml │ └── feature-request.yml ├── dependabot.yml └── workflows │ ├── check-license.yml │ ├── check-npm-dependencies-task.yml │ ├── check-npm-task.yml │ ├── check-packaging-ncc-typescript-npm.yml │ ├── check-prettier-formatting-task.yml │ ├── check-toc-task.yml │ ├── check-tsconfig-task.yml │ ├── integration.yml │ ├── spell-check-task.yml │ ├── sync-labels-npm.yml │ ├── test-javascript-jest-task.yml │ └── testdata │ ├── SpecificationSketch │ └── SpecificationSketch.ino │ └── some-projects │ ├── InvalidSketch │ └── Invalid Sketch.ino │ └── PermissiveLibrary │ ├── PermissiveLibrary.h │ └── library.properties ├── .gitignore ├── .licensed.yml ├── .licenses └── npm │ ├── @actions │ ├── core.dep.yml │ ├── exec.dep.yml │ ├── http-client.dep.yml │ ├── io.dep.yml │ └── tool-cache.dep.yml │ ├── @fastify │ └── busboy.dep.yml │ ├── semver-6.3.0.dep.yml │ ├── semver-7.7.2.dep.yml │ ├── tunnel.dep.yml │ └── undici.dep.yml ├── .npmrc ├── .prettierignore ├── LICENSE.txt ├── README.md ├── Taskfile.yml ├── __tests__ ├── main.test.ts └── testdata │ └── tags.json ├── action.yml ├── dist ├── index.js ├── unzip └── unzip-darwin ├── jest.config.js ├── package-lock.json ├── package.json ├── poetry.lock ├── pyproject.toml ├── src ├── installer.ts └── main.ts └── tsconfig.json /.codespellrc: -------------------------------------------------------------------------------- 1 | # Source: https://github.com/arduino/tooling-project-assets/blob/main/workflow-templates/assets/spell-check/.codespellrc 2 | # See: https://github.com/codespell-project/codespell#using-a-config-file 3 | [codespell] 4 | # In the event of a false positive, add the problematic word, in all lowercase, to a comma-separated list here: 5 | ignore-words-list = afterall 6 | skip = ./.git,./.licenses,./dist,__pycache__,node_modules,./go.mod,./go.sum,./package-lock.json,./poetry.lock,./yarn.lock 7 | builtin = clear,informal,en-GB_to_en-US 8 | check-filenames = 9 | check-hidden = 10 | -------------------------------------------------------------------------------- /.github/CONTRIBUTING.md: -------------------------------------------------------------------------------- 1 | ## Development workflow 2 | 3 | ### 1. Install tools 4 | 5 | #### Node.js 6 | 7 | [**npm**](https://www.npmjs.com/) is used for dependency management. 8 | 9 | Follow the installation instructions here:
10 | https://nodejs.dev/download 11 | 12 | The **Node.js** version in use is defined in the `engines.node` field of [`package.json`](../package.json). 13 | 14 | [nvm](https://github.com/nvm-sh/nvm) is recommended to easily switch between Node.js versions. 15 | 16 | #### Python 17 | 18 | **Python**-based tools are used for some project development operations. 19 | 20 | The **Python** version in use is defined in the `tool.poetry.dependencies` field of [`pyproject.toml`](../pyproject.toml). 21 | 22 | #### Task 23 | 24 | The [**Task**](https://taskfile.dev) task runner tool is used for all common development and validation operations. 25 | 26 | Follow the installation instructions here:
27 | https://taskfile.dev/installation/ 28 | 29 | ### 2. Install dependencies 30 | 31 | To work on the codebase you have to install all the dependencies: 32 | 33 | ``` 34 | task npm:install-deps 35 | ``` 36 | 37 | ### 3. Coding 38 | 39 | Now you're ready to work some [TypeScript](https://www.typescriptlang.org/) magic! 40 | 41 | Make sure to write or update tests for your work when appropriate. 42 | 43 | ### 4. Format code 44 | 45 | Format the code to follow the standard style for the project: 46 | 47 | ``` 48 | task general:format-prettier 49 | ``` 50 | 51 | ### 5. Run tests 52 | 53 | To run tests set the environment variable `GITHUB_TOKEN` with a valid Personal Access Token and then: 54 | 55 | ``` 56 | task js:test 57 | ``` 58 | 59 | See the [official Github documentation][pat-docs] to learn more about Personal Access Tokens. 60 | 61 | ### 6. Build 62 | 63 | It is necessary to compile the code before it can be used by GitHub Actions. Remember to run this commands before committing any code changes: 64 | 65 | ``` 66 | task build 67 | ``` 68 | 69 | ### 7. Commit 70 | 71 | Everything is now ready to make your contribution to the project, so commit it to the repository and submit a pull request. 72 | 73 | Thanks! 74 | 75 | ## Common Development Operations 76 | 77 | ### Dependency License Metadata 78 | 79 | Metadata about the license types of all dependencies is cached in the repository. To update this cache, run the following command from the repository root folder: 80 | 81 | ```text 82 | task general:cache-dep-licenses 83 | ``` 84 | 85 | The necessary **Licensed** tool can be installed by following [these instructions](https://github.com/github/licensed#as-an-executable). 86 | 87 | Unfortunately, **Licensed** does not have Windows support. 88 | 89 | An updated cache is also generated whenever the cache is found to be outdated by the "**Check Go Dependencies**" CI workflow and made available for download via the `dep-licenses-cache` [workflow artifact](https://docs.github.com/actions/managing-workflow-runs/downloading-workflow-artifacts). 90 | 91 | ### Running Checks 92 | 93 | Checks and tests are set up to ensure the project content is functional and compliant with the established standards. 94 | 95 | You can run the full suite of checks by running the following command from a terminal in a path under the repository: 96 | 97 | ```text 98 | task check 99 | ``` 100 | 101 | ### Automatic Corrections 102 | 103 | Tools are provided to automatically bring the project into compliance with some of the required checks. 104 | 105 | You can make these automatic fixes by running the following command from a terminal in a path under the repository: 106 | 107 | ```text 108 | task fix 109 | ``` 110 | 111 | ### Other Operations 112 | 113 | Individual tasks are provided for each specific common validation and automated correction operation. The convenience `check` and `fix` tasks run all of the relevant individual tasks, so it is not necessary for the contributor to use the individual tasks. However, in some cases it may be more efficient to run the single specific task of interest. 114 | 115 | You can learn the names of all the available tasks by running the following command from a terminal in a path under the repository: 116 | 117 | ```text 118 | task --list 119 | ``` 120 | 121 | ## Release workflow 122 | 123 | Instructions for releasing a new version of the action: 124 | 125 | 1. If the release will increment the major version, update the action refs in the examples in `README.md` (e.g., `uses: arduino/arduino-lint-action@v1` -> `uses: arduino/arduino-lint-action@v2`). 126 | 1. Create a [GitHub release](https://docs.github.com/en/github/administering-a-repository/managing-releases-in-a-repository#creating-a-release), following the `vX.Y.Z` tag name convention. Make sure to follow [the SemVer specification](https://semver.org/). 127 | 1. Rebase the release branch for that major version (e.g., `v1` branch for the `v1.x.x` tags) on the tag. If no branch exists for the release's major version, create one. 128 | 129 | [pat-docs]: https://docs.github.com/en/authentication/keeping-your-account-and-data-secure/creating-a-personal-access-token 130 | -------------------------------------------------------------------------------- /.github/ISSUE_TEMPLATE/bug-report.yml: -------------------------------------------------------------------------------- 1 | # Source: https://github.com/arduino/tooling-project-assets/blob/main/issue-templates/forms/general/bug-report.yml 2 | # See: https://docs.github.com/communities/using-templates-to-encourage-useful-issues-and-pull-requests/syntax-for-issue-forms 3 | 4 | name: Bug report 5 | description: Report a problem with the code or documentation in this repository. 6 | labels: 7 | - "type: imperfection" 8 | body: 9 | - type: textarea 10 | id: description 11 | attributes: 12 | label: Describe the problem 13 | validations: 14 | required: true 15 | - type: textarea 16 | id: reproduce 17 | attributes: 18 | label: To reproduce 19 | description: Provide the specific set of steps we can follow to reproduce the problem. 20 | validations: 21 | required: true 22 | - type: textarea 23 | id: expected 24 | attributes: 25 | label: Expected behavior 26 | description: What would you expect to happen after following those instructions? 27 | validations: 28 | required: true 29 | - type: input 30 | id: project-version 31 | attributes: 32 | label: "'arduino/arduino-lint-action' version" 33 | description: | 34 | Which version of `arduino/arduino-lint-action` are you using? 35 | _This should be the most recent version available._ 36 | validations: 37 | required: true 38 | - type: textarea 39 | id: additional 40 | attributes: 41 | label: Additional context 42 | description: Add any additional information here. 43 | validations: 44 | required: false 45 | - type: checkboxes 46 | id: checklist 47 | attributes: 48 | label: Issue checklist 49 | description: Please double-check that you have done each of the following things before submitting the issue. 50 | options: 51 | - label: I searched for previous reports in [the issue tracker](https://github.com/arduino/arduino-lint-action/issues?q=) 52 | required: true 53 | - label: I verified the problem still occurs when using the latest version 54 | required: true 55 | - label: My report contains all necessary details 56 | required: true 57 | -------------------------------------------------------------------------------- /.github/ISSUE_TEMPLATE/config.yml: -------------------------------------------------------------------------------- 1 | # Source: https://github.com/arduino/tooling-project-assets/blob/main/issue-templates/template-choosers/github-actions/config.yml 2 | # See: https://docs.github.com/communities/using-templates-to-encourage-useful-issues-and-pull-requests/configuring-issue-templates-for-your-repository#configuring-the-template-chooser 3 | 4 | blank_issues_enabled: false 5 | contact_links: 6 | - name: Learn about using this project 7 | url: https://github.com/arduino/arduino-lint-action#readme 8 | about: Detailed usage documentation is available here. 9 | - name: Learn about GitHub Actions 10 | url: https://docs.github.com/actions 11 | about: Everything you need to know to get started with GitHub Actions. 12 | - name: Support request 13 | url: https://forum.arduino.cc/ 14 | about: We can help you out on the Arduino Forum! 15 | - name: Discuss development work on the project 16 | url: https://groups.google.com/a/arduino.cc/g/developers 17 | about: Arduino Developers Mailing List 18 | -------------------------------------------------------------------------------- /.github/ISSUE_TEMPLATE/feature-request.yml: -------------------------------------------------------------------------------- 1 | # Source: https://github.com/arduino/tooling-project-assets/blob/main/issue-templates/forms/general/bug-report.yml 2 | # See: https://docs.github.com/communities/using-templates-to-encourage-useful-issues-and-pull-requests/syntax-for-issue-forms 3 | 4 | name: Feature request 5 | description: Suggest an enhancement to this project. 6 | labels: 7 | - "type: enhancement" 8 | body: 9 | - type: textarea 10 | id: description 11 | attributes: 12 | label: Describe the request 13 | validations: 14 | required: true 15 | - type: textarea 16 | id: current 17 | attributes: 18 | label: Describe the current behavior 19 | description: | 20 | What is the current behavior of `arduino/arduino-lint-action` in relation to your request? 21 | How can we reproduce that behavior? 22 | validations: 23 | required: true 24 | - type: input 25 | id: project-version 26 | attributes: 27 | label: "'arduino/arduino-lint-action' version" 28 | description: | 29 | Which version of `arduino/arduino-lint-action` are you using? 30 | _This should be the most recent version available._ 31 | validations: 32 | required: true 33 | - type: textarea 34 | id: additional 35 | attributes: 36 | label: Additional context 37 | description: Add any additional information here. 38 | validations: 39 | required: false 40 | - type: checkboxes 41 | id: checklist 42 | attributes: 43 | label: Issue checklist 44 | description: Please double-check that you have done each of the following things before submitting the issue. 45 | options: 46 | - label: I searched for previous requests in [the issue tracker](https://github.com/arduino/arduino-lint-action/issues?q=) 47 | required: true 48 | - label: I verified the feature was still missing when using the latest version 49 | required: true 50 | - label: My request contains all necessary details 51 | required: true 52 | -------------------------------------------------------------------------------- /.github/dependabot.yml: -------------------------------------------------------------------------------- 1 | # See: https://docs.github.com/en/code-security/supply-chain-security/configuration-options-for-dependency-updates#about-the-dependabotyml-file 2 | version: 2 3 | 4 | updates: 5 | # Configure check for outdated GitHub Actions actions in workflows. 6 | # Source: https://github.com/arduino/tooling-project-assets/blob/main/workflow-templates/assets/dependabot/README.md 7 | # See: https://docs.github.com/en/code-security/supply-chain-security/keeping-your-actions-up-to-date-with-dependabot 8 | - package-ecosystem: github-actions 9 | directory: / # Check the repository's workflows under /.github/workflows/ 10 | assignees: 11 | - per1234 12 | open-pull-requests-limit: 100 13 | schedule: 14 | interval: daily 15 | labels: 16 | - "topic: infrastructure" 17 | - package-ecosystem: npm 18 | directory: / 19 | assignees: 20 | - per1234 21 | open-pull-requests-limit: 100 22 | schedule: 23 | interval: daily 24 | labels: 25 | - "topic: infrastructure" 26 | ignore: 27 | - dependency-name: "@types/node" 28 | # @types/node should be kept in sync with the major version of Node.js that is in use. 29 | # So we only want automated updates for minor and patch releases of this dependency. 30 | update-types: 31 | - "version-update:semver-major" 32 | -------------------------------------------------------------------------------- /.github/workflows/check-license.yml: -------------------------------------------------------------------------------- 1 | # Source: https://github.com/arduino/tooling-project-assets/blob/main/workflow-templates/check-license.md 2 | name: Check License 3 | 4 | # See: https://docs.github.com/actions/using-workflows/events-that-trigger-workflows 5 | on: 6 | create: 7 | push: 8 | paths: 9 | - ".github/workflows/check-license.ya?ml" 10 | # See: https://github.com/licensee/licensee/blob/master/docs/what-we-look-at.md#detecting-the-license-file 11 | - "[cC][oO][pP][yY][iI][nN][gG]*" 12 | - "[cC][oO][pP][yY][rR][iI][gG][hH][tH]*" 13 | - "[lL][iI][cC][eE][nN][cCsS][eE]*" 14 | - "[oO][fF][lL]*" 15 | - "[pP][aA][tT][eE][nN][tT][sS]*" 16 | pull_request: 17 | paths: 18 | - ".github/workflows/check-license.ya?ml" 19 | - "[cC][oO][pP][yY][iI][nN][gG]*" 20 | - "[cC][oO][pP][yY][rR][iI][gG][hH][tH]*" 21 | - "[lL][iI][cC][eE][nN][cCsS][eE]*" 22 | - "[oO][fF][lL]*" 23 | - "[pP][aA][tT][eE][nN][tT][sS]*" 24 | schedule: 25 | # Run periodically to catch breakage caused by external changes. 26 | - cron: "0 6 * * WED" 27 | workflow_dispatch: 28 | repository_dispatch: 29 | 30 | jobs: 31 | run-determination: 32 | runs-on: ubuntu-latest 33 | permissions: {} 34 | outputs: 35 | result: ${{ steps.determination.outputs.result }} 36 | steps: 37 | - name: Determine if the rest of the workflow should run 38 | id: determination 39 | run: | 40 | RELEASE_BRANCH_REGEX="refs/heads/[0-9]+.[0-9]+.x" 41 | # The `create` event trigger doesn't support `branches` filters, so it's necessary to use Bash instead. 42 | if [[ 43 | "${{ github.event_name }}" != "create" || 44 | "${{ github.ref }}" =~ $RELEASE_BRANCH_REGEX 45 | ]]; then 46 | # Run the other jobs. 47 | RESULT="true" 48 | else 49 | # There is no need to run the other jobs. 50 | RESULT="false" 51 | fi 52 | 53 | echo "result=$RESULT" >> $GITHUB_OUTPUT 54 | 55 | check-license: 56 | name: ${{ matrix.check-license.path }} 57 | needs: run-determination 58 | if: needs.run-determination.outputs.result == 'true' 59 | runs-on: ubuntu-latest 60 | permissions: 61 | contents: read 62 | 63 | strategy: 64 | fail-fast: false 65 | 66 | matrix: 67 | check-license: 68 | - path: ./ 69 | # TODO: Define the project's license file name here: 70 | expected-filename: LICENSE.txt 71 | # SPDX identifier: https://spdx.org/licenses/ 72 | expected-type: Apache-2.0 73 | 74 | steps: 75 | - name: Checkout repository 76 | uses: actions/checkout@v4 77 | 78 | - name: Install Ruby 79 | uses: ruby/setup-ruby@v1 80 | with: 81 | ruby-version: ruby # Install latest version 82 | 83 | - name: Install licensee 84 | run: gem install licensee 85 | 86 | - name: Check license file for ${{ matrix.check-license.path }} 87 | run: | 88 | EXIT_STATUS=0 89 | 90 | # Go into folder path 91 | cd ./${{ matrix.check-license.path }} 92 | 93 | # See: https://github.com/licensee/licensee 94 | LICENSEE_OUTPUT="$(licensee detect --json --confidence=100)" 95 | 96 | DETECTED_LICENSE_FILE="$(echo "$LICENSEE_OUTPUT" | jq .matched_files[0].filename | tr --delete '\r')" 97 | echo "Detected license file: $DETECTED_LICENSE_FILE" 98 | if [ "$DETECTED_LICENSE_FILE" != "\"${{ matrix.check-license.expected-filename }}\"" ]; then 99 | echo "::error file=${DETECTED_LICENSE_FILE}::detected license file $DETECTED_LICENSE_FILE doesn't match expected: ${{ matrix.check-license.expected-filename }}" 100 | EXIT_STATUS=1 101 | fi 102 | 103 | DETECTED_LICENSE_TYPE="$(echo "$LICENSEE_OUTPUT" | jq .matched_files[0].matched_license | tr --delete '\r')" 104 | echo "Detected license type: $DETECTED_LICENSE_TYPE" 105 | if [ "$DETECTED_LICENSE_TYPE" != "\"${{ matrix.check-license.expected-type }}\"" ]; then 106 | echo "::error file=${DETECTED_LICENSE_FILE}::detected license type $DETECTED_LICENSE_TYPE doesn't match expected \"${{ matrix.check-license.expected-type }}\"" 107 | EXIT_STATUS=1 108 | fi 109 | 110 | exit $EXIT_STATUS 111 | -------------------------------------------------------------------------------- /.github/workflows/check-npm-dependencies-task.yml: -------------------------------------------------------------------------------- 1 | # Source: https://github.com/arduino/tooling-project-assets/blob/main/workflow-templates/check-npm-dependencies-task.md 2 | name: Check npm Dependencies 3 | 4 | # See: https://docs.github.com/actions/using-workflows/events-that-trigger-workflows 5 | on: 6 | create: 7 | push: 8 | paths: 9 | - ".github/workflows/check-npm-dependencies-task.ya?ml" 10 | - ".licenses/**" 11 | - ".licensed.json" 12 | - ".licensed.ya?ml" 13 | - "Taskfile.ya?ml" 14 | - "**/.gitmodules" 15 | - "**/.npmrc" 16 | - "**/package.json" 17 | - "**/package-lock.json" 18 | pull_request: 19 | paths: 20 | - ".github/workflows/check-npm-dependencies-task.ya?ml" 21 | - ".licenses/**" 22 | - ".licensed.json" 23 | - ".licensed.ya?ml" 24 | - "Taskfile.ya?ml" 25 | - "**/.gitmodules" 26 | - "**/.npmrc" 27 | - "**/package.json" 28 | - "**/package-lock.json" 29 | schedule: 30 | # Run periodically to catch breakage caused by external changes. 31 | - cron: "0 8 * * WED" 32 | workflow_dispatch: 33 | repository_dispatch: 34 | 35 | jobs: 36 | run-determination: 37 | runs-on: ubuntu-latest 38 | permissions: {} 39 | outputs: 40 | result: ${{ steps.determination.outputs.result }} 41 | steps: 42 | - name: Determine if the rest of the workflow should run 43 | id: determination 44 | run: | 45 | RELEASE_BRANCH_REGEX="refs/heads/[0-9]+.[0-9]+.x" 46 | # The `create` event trigger doesn't support `branches` filters, so it's necessary to use Bash instead. 47 | if [[ 48 | "${{ github.event_name }}" != "create" || 49 | "${{ github.ref }}" =~ $RELEASE_BRANCH_REGEX 50 | ]]; then 51 | # Run the other jobs. 52 | RESULT="true" 53 | else 54 | # There is no need to run the other jobs. 55 | RESULT="false" 56 | fi 57 | 58 | echo "result=$RESULT" >> $GITHUB_OUTPUT 59 | 60 | check-cache: 61 | needs: run-determination 62 | if: needs.run-determination.outputs.result == 'true' 63 | runs-on: ubuntu-latest 64 | permissions: 65 | contents: read 66 | 67 | steps: 68 | - name: Checkout repository 69 | uses: actions/checkout@v4 70 | with: 71 | submodules: recursive 72 | 73 | # This is required to allow licensee/setup-licensed to install licensed via Ruby gem. 74 | - name: Install Ruby 75 | uses: ruby/setup-ruby@v1 76 | with: 77 | ruby-version: ruby # Install latest version 78 | 79 | - name: Install licensed 80 | uses: licensee/setup-licensed@v1.3.2 81 | with: 82 | github_token: ${{ secrets.GITHUB_TOKEN }} 83 | version: 5.x 84 | 85 | - name: Setup Node.js 86 | uses: actions/setup-node@v4 87 | with: 88 | node-version-file: package.json 89 | 90 | - name: Install Task 91 | uses: arduino/setup-task@v2 92 | with: 93 | repo-token: ${{ secrets.GITHUB_TOKEN }} 94 | version: 3.x 95 | 96 | - name: Update dependencies license metadata cache 97 | run: task --silent general:cache-dep-licenses 98 | 99 | - name: Check for outdated cache 100 | id: diff 101 | run: | 102 | git add . 103 | if ! git diff --cached --color --exit-code; then 104 | echo 105 | echo "::error::Dependency license metadata out of sync. See: https://github.com/arduino/tooling-project-assets/blob/main/workflow-templates/check-go-dependencies-task.md#metadata-cache" 106 | exit 1 107 | fi 108 | 109 | # Some might find it convenient to have CI generate the cache rather than setting up for it locally 110 | - name: Upload cache to workflow artifact 111 | if: failure() && steps.diff.outcome == 'failure' 112 | uses: actions/upload-artifact@v4 113 | with: 114 | if-no-files-found: error 115 | include-hidden-files: true 116 | name: dep-licenses-cache 117 | path: .licenses/ 118 | 119 | check-deps: 120 | needs: run-determination 121 | if: needs.run-determination.outputs.result == 'true' 122 | runs-on: ubuntu-latest 123 | permissions: 124 | contents: read 125 | 126 | steps: 127 | - name: Checkout repository 128 | uses: actions/checkout@v4 129 | with: 130 | submodules: recursive 131 | 132 | # This is required to allow licensee/setup-licensed to install licensed via Ruby gem. 133 | - name: Install Ruby 134 | uses: ruby/setup-ruby@v1 135 | with: 136 | ruby-version: ruby # Install latest version 137 | 138 | - name: Install licensed 139 | uses: licensee/setup-licensed@v1.3.2 140 | with: 141 | github_token: ${{ secrets.GITHUB_TOKEN }} 142 | version: 5.x 143 | 144 | - name: Setup Node.js 145 | uses: actions/setup-node@v4 146 | with: 147 | node-version-file: package.json 148 | 149 | - name: Install Task 150 | uses: arduino/setup-task@v2 151 | with: 152 | repo-token: ${{ secrets.GITHUB_TOKEN }} 153 | version: 3.x 154 | 155 | - name: Check for dependencies with unapproved licenses 156 | run: task --silent general:check-dep-licenses 157 | -------------------------------------------------------------------------------- /.github/workflows/check-npm-task.yml: -------------------------------------------------------------------------------- 1 | # Source: https://github.com/arduino/tooling-project-assets/blob/main/workflow-templates/check-npm-task.md 2 | name: Check npm 3 | 4 | # See: https://docs.github.com/en/actions/reference/events-that-trigger-workflows 5 | on: 6 | create: 7 | push: 8 | paths: 9 | - ".github/workflows/check-npm-task.ya?ml" 10 | - "**/.npmrc" 11 | - "**/package.json" 12 | - "**/package-lock.json" 13 | - "Taskfile.ya?ml" 14 | pull_request: 15 | paths: 16 | - ".github/workflows/check-npm-task.ya?ml" 17 | - "**/.npmrc" 18 | - "**/package.json" 19 | - "**/package-lock.json" 20 | - "Taskfile.ya?ml" 21 | schedule: 22 | # Run every Tuesday at 8 AM UTC to catch breakage resulting from changes to the JSON schema. 23 | - cron: "0 8 * * TUE" 24 | workflow_dispatch: 25 | repository_dispatch: 26 | 27 | jobs: 28 | run-determination: 29 | runs-on: ubuntu-latest 30 | permissions: {} 31 | outputs: 32 | result: ${{ steps.determination.outputs.result }} 33 | steps: 34 | - name: Determine if the rest of the workflow should run 35 | id: determination 36 | run: | 37 | RELEASE_BRANCH_REGEX="refs/heads/[0-9]+.[0-9]+.x" 38 | # The `create` event trigger doesn't support `branches` filters, so it's necessary to use Bash instead. 39 | if [[ 40 | "${{ github.event_name }}" != "create" || 41 | "${{ github.ref }}" =~ $RELEASE_BRANCH_REGEX 42 | ]]; then 43 | # Run the other jobs. 44 | RESULT="true" 45 | else 46 | # There is no need to run the other jobs. 47 | RESULT="false" 48 | fi 49 | 50 | echo "result=$RESULT" >> $GITHUB_OUTPUT 51 | 52 | validate: 53 | name: validate (${{ matrix.project.path }}) 54 | needs: run-determination 55 | if: needs.run-determination.outputs.result == 'true' 56 | runs-on: ubuntu-latest 57 | permissions: 58 | contents: read 59 | 60 | strategy: 61 | fail-fast: false 62 | matrix: 63 | project: 64 | - path: . 65 | 66 | steps: 67 | - name: Checkout repository 68 | uses: actions/checkout@v4 69 | 70 | - name: Setup Node.js 71 | uses: actions/setup-node@v4 72 | with: 73 | node-version-file: package.json 74 | 75 | - name: Install Task 76 | uses: arduino/setup-task@v2 77 | with: 78 | repo-token: ${{ secrets.GITHUB_TOKEN }} 79 | version: 3.x 80 | 81 | - name: Validate package.json 82 | run: | 83 | task \ 84 | --silent \ 85 | npm:validate \ 86 | PROJECT_PATH="${{ matrix.project.path }}" 87 | 88 | check-sync: 89 | name: check-sync (${{ matrix.project.path }}) 90 | needs: run-determination 91 | if: needs.run-determination.outputs.result == 'true' 92 | runs-on: ubuntu-latest 93 | permissions: 94 | contents: read 95 | 96 | strategy: 97 | fail-fast: false 98 | matrix: 99 | project: 100 | - path: . 101 | 102 | steps: 103 | - name: Checkout repository 104 | uses: actions/checkout@v4 105 | 106 | - name: Setup Node.js 107 | uses: actions/setup-node@v4 108 | with: 109 | node-version-file: package.json 110 | 111 | - name: Install Task 112 | uses: arduino/setup-task@v2 113 | with: 114 | repo-token: ${{ secrets.GITHUB_TOKEN }} 115 | version: 3.x 116 | 117 | - name: Install npm dependencies 118 | run: | 119 | task \ 120 | npm:install-deps \ 121 | PROJECT_PATH="${{ matrix.project.path }}" 122 | 123 | - name: Check package-lock.json 124 | run: | 125 | git \ 126 | diff \ 127 | --color \ 128 | --exit-code \ 129 | "${{ matrix.project.path }}/package-lock.json" 130 | -------------------------------------------------------------------------------- /.github/workflows/check-packaging-ncc-typescript-npm.yml: -------------------------------------------------------------------------------- 1 | name: Check Packaging 2 | 3 | on: 4 | push: 5 | paths: 6 | - ".github/workflows/check-packaging-ncc-typescript-npm.yml" 7 | - ".npmrc" 8 | - "lerna.json" 9 | - "package.json" 10 | - "package-lock.json" 11 | - "tsconfig.json" 12 | - "**.[jt]sx?" 13 | pull_request: 14 | paths: 15 | - ".github/workflows/check-packaging-ncc-typescript-npm.yml" 16 | - ".npmrc" 17 | - "lerna.json" 18 | - "package.json" 19 | - "package-lock.json" 20 | - "tsconfig.json" 21 | - "**.[jt]sx?" 22 | workflow_dispatch: 23 | repository_dispatch: 24 | 25 | jobs: 26 | check-packaging: 27 | runs-on: ubuntu-latest 28 | 29 | steps: 30 | - name: Checkout 31 | uses: actions/checkout@v4 32 | 33 | - name: Setup Node.js 34 | uses: actions/setup-node@v4 35 | with: 36 | node-version-file: package.json 37 | 38 | - name: Install Task 39 | uses: arduino/setup-task@v2 40 | with: 41 | repo-token: ${{ secrets.GITHUB_TOKEN }} 42 | version: 3.x 43 | 44 | - name: Build action 45 | run: task ts:build 46 | 47 | - name: Check packaging 48 | # Ignoring CR because ncc's output has a mixture of line endings, while the repository should only contain 49 | # Unix-style EOL. 50 | run: git diff --ignore-cr-at-eol --color --exit-code dist 51 | -------------------------------------------------------------------------------- /.github/workflows/check-prettier-formatting-task.yml: -------------------------------------------------------------------------------- 1 | # Source: https://github.com/arduino/tooling-project-assets/blob/main/workflow-templates/check-prettier-formatting-task.md 2 | name: Check Prettier Formatting 3 | 4 | # See: https://docs.github.com/en/free-pro-team@latest/actions/reference/events-that-trigger-workflows 5 | on: 6 | create: 7 | push: 8 | paths: 9 | - ".github/workflows/check-prettier-formatting-task.ya?ml" 10 | - "Taskfile.ya?ml" 11 | - "**/.npmrc" 12 | - "**/.prettierignore" 13 | - "**/.prettierrc*" 14 | # Prettier-covered file patterns are defined by: 15 | # https://github.com/github-linguist/linguist/blob/master/lib/linguist/languages.yml 16 | # CSS 17 | - "**.css" 18 | - "**.wxss" 19 | # PostCSS 20 | - "**.pcss" 21 | - "**.postcss" 22 | # Less 23 | - "**.less" 24 | # SCSS 25 | - "**.scss" 26 | # GraphQL 27 | - "**.graphqls?" 28 | - "**.gql" 29 | # handlebars 30 | - "**.handlebars" 31 | - "**.hbs" 32 | # HTML 33 | - "**.mjml" 34 | - "**.html?" 35 | - "**.html.hl" 36 | - "**.st" 37 | - "**.xht" 38 | - "**.xhtml" 39 | # Vue 40 | - "**.vue" 41 | # JavaScript 42 | - "**.flow" 43 | - "**._?jsb?" 44 | - "**.bones" 45 | - "**.cjs" 46 | - "**.es6?" 47 | - "**.frag" 48 | - "**.gs" 49 | - "**.jake" 50 | - "**.jscad" 51 | - "**.jsfl" 52 | - "**.js[ms]" 53 | - "**.[mn]js" 54 | - "**.pac" 55 | - "**.wxs" 56 | - "**.[xs]s?js" 57 | - "**.xsjslib" 58 | # JSX 59 | - "**.jsx" 60 | # TypeScript 61 | - "**.ts" 62 | # TSX 63 | - "**.tsx" 64 | # JSON 65 | - "**/.eslintrc" 66 | - "**.json" 67 | - "**.avsc" 68 | - "**.geojson" 69 | - "**.gltf" 70 | - "**.har" 71 | - "**.ice" 72 | - "**.JSON-tmLanguage" 73 | - "**.mcmeta" 74 | - "**.tfstate" 75 | - "**.topojson" 76 | - "**.webapp" 77 | - "**.webmanifest" 78 | - "**.yyp?" 79 | # JSONC 80 | - "**/.babelrc" 81 | - "**/.jscsrc" 82 | - "**/.js[hl]intrc" 83 | - "**.jsonc" 84 | - "**.sublime-*" 85 | # JSON5 86 | - "**.json5" 87 | # Markdown 88 | - "**.mdx?" 89 | - "**.markdown" 90 | - "**.mk?down" 91 | - "**.mdwn" 92 | - "**.mkdn?" 93 | - "**.ronn" 94 | - "**.workbook" 95 | # YAML 96 | - "**/.clang-format" 97 | - "**/.clang-tidy" 98 | - "**/.gemrc" 99 | - "**/glide.lock" 100 | - "**.ya?ml*" 101 | - "**.mir" 102 | - "**.reek" 103 | - "**.rviz" 104 | - "**.sublime-syntax" 105 | - "**.syntax" 106 | pull_request: 107 | paths: 108 | - ".github/workflows/check-prettier-formatting-task.ya?ml" 109 | - "Taskfile.ya?ml" 110 | - "**/.npmrc" 111 | - "**/.prettierignore" 112 | - "**/.prettierrc*" 113 | # CSS 114 | - "**.css" 115 | - "**.wxss" 116 | # PostCSS 117 | - "**.pcss" 118 | - "**.postcss" 119 | # Less 120 | - "**.less" 121 | # SCSS 122 | - "**.scss" 123 | # GraphQL 124 | - "**.graphqls?" 125 | - "**.gql" 126 | # handlebars 127 | - "**.handlebars" 128 | - "**.hbs" 129 | # HTML 130 | - "**.mjml" 131 | - "**.html?" 132 | - "**.html.hl" 133 | - "**.st" 134 | - "**.xht" 135 | - "**.xhtml" 136 | # Vue 137 | - "**.vue" 138 | # JavaScript 139 | - "**.flow" 140 | - "**._?jsb?" 141 | - "**.bones" 142 | - "**.cjs" 143 | - "**.es6?" 144 | - "**.frag" 145 | - "**.gs" 146 | - "**.jake" 147 | - "**.jscad" 148 | - "**.jsfl" 149 | - "**.js[ms]" 150 | - "**.[mn]js" 151 | - "**.pac" 152 | - "**.wxs" 153 | - "**.[xs]s?js" 154 | - "**.xsjslib" 155 | # JSX 156 | - "**.jsx" 157 | # TypeScript 158 | - "**.ts" 159 | # TSX 160 | - "**.tsx" 161 | # JSON 162 | - "**/.eslintrc" 163 | - "**.json" 164 | - "**.avsc" 165 | - "**.geojson" 166 | - "**.gltf" 167 | - "**.har" 168 | - "**.ice" 169 | - "**.JSON-tmLanguage" 170 | - "**.mcmeta" 171 | - "**.tfstate" 172 | - "**.topojson" 173 | - "**.webapp" 174 | - "**.webmanifest" 175 | - "**.yyp?" 176 | # JSONC 177 | - "**/.babelrc" 178 | - "**/.jscsrc" 179 | - "**/.js[hl]intrc" 180 | - "**.jsonc" 181 | - "**.sublime-*" 182 | # JSON5 183 | - "**.json5" 184 | # Markdown 185 | - "**.mdx?" 186 | - "**.markdown" 187 | - "**.mk?down" 188 | - "**.mdwn" 189 | - "**.mkdn?" 190 | - "**.ronn" 191 | - "**.workbook" 192 | # YAML 193 | - "**/.clang-format" 194 | - "**/.clang-tidy" 195 | - "**/.gemrc" 196 | - "**/glide.lock" 197 | - "**.ya?ml*" 198 | - "**.mir" 199 | - "**.reek" 200 | - "**.rviz" 201 | - "**.sublime-syntax" 202 | - "**.syntax" 203 | schedule: 204 | # Run periodically to catch breakage caused by external changes. 205 | - cron: "0 4 * * WED" 206 | workflow_dispatch: 207 | repository_dispatch: 208 | 209 | jobs: 210 | run-determination: 211 | runs-on: ubuntu-latest 212 | permissions: {} 213 | outputs: 214 | result: ${{ steps.determination.outputs.result }} 215 | steps: 216 | - name: Determine if the rest of the workflow should run 217 | id: determination 218 | run: | 219 | RELEASE_BRANCH_REGEX="refs/heads/[0-9]+.[0-9]+.x" 220 | # The `create` event trigger doesn't support `branches` filters, so it's necessary to use Bash instead. 221 | if [[ 222 | "${{ github.event_name }}" != "create" || 223 | "${{ github.ref }}" =~ $RELEASE_BRANCH_REGEX 224 | ]]; then 225 | # Run the other jobs. 226 | RESULT="true" 227 | else 228 | # There is no need to run the other jobs. 229 | RESULT="false" 230 | fi 231 | 232 | echo "result=$RESULT" >> $GITHUB_OUTPUT 233 | 234 | check: 235 | needs: run-determination 236 | if: needs.run-determination.outputs.result == 'true' 237 | runs-on: ubuntu-latest 238 | permissions: 239 | contents: read 240 | 241 | steps: 242 | - name: Checkout repository 243 | uses: actions/checkout@v4 244 | 245 | - name: Setup Node.js 246 | uses: actions/setup-node@v4 247 | with: 248 | node-version-file: package.json 249 | 250 | - name: Install Task 251 | uses: arduino/setup-task@v2 252 | with: 253 | repo-token: ${{ secrets.GITHUB_TOKEN }} 254 | version: 3.x 255 | 256 | - name: Format with Prettier 257 | run: | 258 | task \ 259 | general:format-prettier 260 | 261 | - name: Check formatting 262 | run: | 263 | git \ 264 | diff \ 265 | --color \ 266 | --exit-code 267 | -------------------------------------------------------------------------------- /.github/workflows/check-toc-task.yml: -------------------------------------------------------------------------------- 1 | # Source: https://github.com/arduino/tooling-project-assets/blob/main/workflow-templates/check-toc-task.md 2 | name: Check ToC 3 | 4 | # See: https://docs.github.com/actions/using-workflows/events-that-trigger-workflows 5 | on: 6 | create: 7 | push: 8 | paths: 9 | - ".github/workflows/check-toc-task.ya?ml" 10 | - ".npmrc" 11 | - "package.json" 12 | - "package-lock.json" 13 | - "README.md" 14 | - "Taskfile.ya?ml" 15 | pull_request: 16 | paths: 17 | - ".github/workflows/check-toc-task.ya?ml" 18 | - ".npmrc" 19 | - "package.json" 20 | - "package-lock.json" 21 | - "README.md" 22 | - "Taskfile.ya?ml" 23 | schedule: 24 | # Run periodically to catch breakage caused by external changes. 25 | - cron: "0 3 * * WED" 26 | workflow_dispatch: 27 | repository_dispatch: 28 | 29 | jobs: 30 | run-determination: 31 | runs-on: ubuntu-latest 32 | permissions: {} 33 | outputs: 34 | result: ${{ steps.determination.outputs.result }} 35 | steps: 36 | - name: Determine if the rest of the workflow should run 37 | id: determination 38 | run: | 39 | RELEASE_BRANCH_REGEX="refs/heads/[0-9]+.[0-9]+.x" 40 | # The `create` event trigger doesn't support `branches` filters, so it's necessary to use Bash instead. 41 | if [[ 42 | "${{ github.event_name }}" != "create" || 43 | "${{ github.ref }}" =~ $RELEASE_BRANCH_REGEX 44 | ]]; then 45 | # Run the other jobs. 46 | RESULT="true" 47 | else 48 | # There is no need to run the other jobs. 49 | RESULT="false" 50 | fi 51 | 52 | echo "result=$RESULT" >> $GITHUB_OUTPUT 53 | 54 | check: 55 | name: ${{ matrix.file.name }} 56 | needs: run-determination 57 | if: needs.run-determination.outputs.result == 'true' 58 | runs-on: ubuntu-latest 59 | permissions: 60 | contents: read 61 | 62 | strategy: 63 | fail-fast: false 64 | 65 | matrix: 66 | file: 67 | - name: README.md 68 | # Max ToC depth, for use with the markdown-toc --maxdepth flag. 69 | maxdepth: 3 70 | 71 | steps: 72 | - name: Checkout repository 73 | uses: actions/checkout@v4 74 | 75 | - name: Setup Node.js 76 | uses: actions/setup-node@v4 77 | with: 78 | node-version-file: package.json 79 | 80 | - name: Install Task 81 | uses: arduino/setup-task@v2 82 | with: 83 | repo-token: ${{ secrets.GITHUB_TOKEN }} 84 | version: 3.x 85 | 86 | - name: Rebuild ToC 87 | run: | 88 | task \ 89 | markdown:toc \ 90 | FILE_PATH="${{ github.workspace }}/${{ matrix.file.name }}" \ 91 | MAX_DEPTH=${{ matrix.file.maxdepth }} 92 | 93 | - name: Check ToC 94 | run: | 95 | git \ 96 | diff \ 97 | --color \ 98 | --exit-code 99 | -------------------------------------------------------------------------------- /.github/workflows/check-tsconfig-task.yml: -------------------------------------------------------------------------------- 1 | name: Check TypeScript Configuration 2 | 3 | # See: https://docs.github.com/en/actions/reference/events-that-trigger-workflows 4 | on: 5 | push: 6 | paths: 7 | - ".github/workflows/check-tsconfig-task.ya?ml" 8 | - "**/tsconfig*.json" 9 | - ".npmrc" 10 | - "package.json" 11 | - "package-lock.json" 12 | - "Taskfile.ya?ml" 13 | pull_request: 14 | paths: 15 | - ".github/workflows/check-tsconfig-task.ya?ml" 16 | - "**/tsconfig*.json" 17 | - ".npmrc" 18 | - "package.json" 19 | - "package-lock.json" 20 | - "Taskfile.ya?ml" 21 | schedule: 22 | # Run every Tuesday at 8 AM UTC to catch breakage from changes to the JSON schema. 23 | - cron: "0 8 * * TUE" 24 | workflow_dispatch: 25 | repository_dispatch: 26 | 27 | jobs: 28 | validate: 29 | name: validate (${{ matrix.file }}) 30 | runs-on: ubuntu-latest 31 | 32 | strategy: 33 | fail-fast: false 34 | 35 | matrix: 36 | file: 37 | - ./tsconfig.json 38 | 39 | steps: 40 | - name: Checkout repository 41 | uses: actions/checkout@v4 42 | 43 | - name: Setup Node.js 44 | uses: actions/setup-node@v4 45 | with: 46 | node-version-file: package.json 47 | 48 | - name: Install Task 49 | uses: arduino/setup-task@v2 50 | with: 51 | repo-token: ${{ secrets.GITHUB_TOKEN }} 52 | version: 3.x 53 | 54 | - name: Validate 55 | env: 56 | TSCONFIG_PATH: ${{ matrix.file }} 57 | run: | 58 | task \ 59 | --silent \ 60 | ts:validate 61 | -------------------------------------------------------------------------------- /.github/workflows/integration.yml: -------------------------------------------------------------------------------- 1 | name: Integration Tests 2 | 3 | on: 4 | pull_request: 5 | push: 6 | schedule: # Scheduled trigger checks for breakage caused by changes to arduino-lint 7 | # run every Tuesday at 3 AM UTC 8 | - cron: "0 3 * * 2" 9 | # workflow_dispatch event allows the workflow to be triggered manually 10 | # See: https://docs.github.com/en/actions/reference/events-that-trigger-workflows#workflow_dispatch 11 | workflow_dispatch: 12 | # repository_dispatch event allows the workflow to be triggered via the GitHub API 13 | # See: https://docs.github.com/en/actions/reference/events-that-trigger-workflows#repository_dispatch 14 | repository_dispatch: 15 | 16 | jobs: 17 | defaults: 18 | runs-on: ubuntu-latest 19 | 20 | steps: 21 | - name: Checkout local repository 22 | uses: actions/checkout@v4 23 | 24 | # Run the action using default values as much as possible. 25 | - name: Run action 26 | uses: ./ # Use the action from the local path. 27 | with: 28 | path: .github/workflows/testdata/SpecificationSketch 29 | 30 | expected-pass: 31 | runs-on: ubuntu-latest 32 | 33 | env: 34 | REPORT_FILE_PATH: /tmp/report.json 35 | steps: 36 | - name: Checkout local repository 37 | uses: actions/checkout@v4 38 | 39 | # The contents of the test data path are structured so that the step will fail if arduino-lint is not run with the configuration according to these inputs. 40 | - name: Run action 41 | uses: ./ 42 | with: 43 | path: .github/workflows/testdata/some-projects 44 | compliance: permissive 45 | library-manager: false 46 | project-type: library 47 | recursive: true 48 | report-file: ${{ env.REPORT_FILE_PATH }} 49 | official: true 50 | 51 | - name: Verify report file exists 52 | run: | 53 | [ -e "${{ env.REPORT_FILE_PATH }}" ] 54 | 55 | expected-fail: 56 | runs-on: ubuntu-latest 57 | 58 | steps: 59 | - name: Checkout local repository 60 | uses: actions/checkout@v4 61 | 62 | # The contents of the test data path are structured so that the step will fail if arduino-lint is run with the default configuration. 63 | - name: Run action 64 | id: arduino-lint 65 | continue-on-error: true 66 | uses: ./ 67 | with: 68 | path: .github/workflows/testdata/projects 69 | 70 | - name: Fail the job if the action run succeeded 71 | if: steps.arduino-lint.outcome == 'success' 72 | run: | 73 | echo "::error::The action run was expected to fail, but passed!" 74 | exit 1 75 | -------------------------------------------------------------------------------- /.github/workflows/spell-check-task.yml: -------------------------------------------------------------------------------- 1 | # Source: https://github.com/arduino/tooling-project-assets/blob/main/workflow-templates/spell-check-task.md 2 | name: Spell Check 3 | 4 | # See: https://docs.github.com/actions/using-workflows/events-that-trigger-workflows 5 | on: 6 | create: 7 | push: 8 | pull_request: 9 | schedule: 10 | # Run every Tuesday at 8 AM UTC to catch new misspelling detections resulting from dictionary updates. 11 | - cron: "0 8 * * TUE" 12 | workflow_dispatch: 13 | repository_dispatch: 14 | 15 | jobs: 16 | run-determination: 17 | runs-on: ubuntu-latest 18 | permissions: {} 19 | outputs: 20 | result: ${{ steps.determination.outputs.result }} 21 | steps: 22 | - name: Determine if the rest of the workflow should run 23 | id: determination 24 | run: | 25 | RELEASE_BRANCH_REGEX="refs/heads/[0-9]+.[0-9]+.x" 26 | # The `create` event trigger doesn't support `branches` filters, so it's necessary to use Bash instead. 27 | if [[ 28 | "${{ github.event_name }}" != "create" || 29 | "${{ github.ref }}" =~ $RELEASE_BRANCH_REGEX 30 | ]]; then 31 | # Run the other jobs. 32 | RESULT="true" 33 | else 34 | # There is no need to run the other jobs. 35 | RESULT="false" 36 | fi 37 | 38 | echo "result=$RESULT" >> $GITHUB_OUTPUT 39 | 40 | spellcheck: 41 | needs: run-determination 42 | if: needs.run-determination.outputs.result == 'true' 43 | runs-on: ubuntu-latest 44 | permissions: 45 | contents: read 46 | 47 | steps: 48 | - name: Checkout repository 49 | uses: actions/checkout@v4 50 | 51 | - name: Install Python 52 | uses: actions/setup-python@v5 53 | with: 54 | python-version-file: pyproject.toml 55 | 56 | - name: Install Task 57 | uses: arduino/setup-task@v2 58 | with: 59 | repo-token: ${{ secrets.GITHUB_TOKEN }} 60 | version: 3.x 61 | 62 | - name: Spell check 63 | run: | 64 | task \ 65 | general:check-spelling 66 | -------------------------------------------------------------------------------- /.github/workflows/sync-labels-npm.yml: -------------------------------------------------------------------------------- 1 | # Source: https://github.com/arduino/tooling-project-assets/blob/main/workflow-templates/sync-labels-npm.md 2 | name: Sync Labels 3 | 4 | env: 5 | CONFIGURATIONS_FOLDER: .github/label-configuration-files 6 | CONFIGURATIONS_ARTIFACT_PREFIX: label-configuration-file- 7 | 8 | # See: https://docs.github.com/actions/using-workflows/events-that-trigger-workflows 9 | on: 10 | push: 11 | paths: 12 | - ".github/workflows/sync-labels-npm.ya?ml" 13 | - ".github/label-configuration-files/*.ya?ml" 14 | - ".npmrc" 15 | - "package.json" 16 | - "package-lock.json" 17 | pull_request: 18 | paths: 19 | - ".github/workflows/sync-labels-npm.ya?ml" 20 | - ".github/label-configuration-files/*.ya?ml" 21 | - ".npmrc" 22 | - "package.json" 23 | - "package-lock.json" 24 | schedule: 25 | # Run daily at 8 AM UTC to sync with changes to shared label configurations. 26 | - cron: "0 8 * * *" 27 | workflow_dispatch: 28 | repository_dispatch: 29 | 30 | jobs: 31 | check: 32 | runs-on: ubuntu-latest 33 | permissions: 34 | contents: read 35 | 36 | steps: 37 | - name: Checkout repository 38 | uses: actions/checkout@v4 39 | 40 | - name: Setup Node.js 41 | uses: actions/setup-node@v4 42 | with: 43 | node-version-file: package.json 44 | 45 | - name: Download JSON schema for labels configuration file 46 | id: download-schema 47 | uses: carlosperate/download-file-action@v2 48 | with: 49 | file-url: https://raw.githubusercontent.com/arduino/tooling-project-assets/main/workflow-templates/assets/sync-labels/arduino-tooling-gh-label-configuration-schema.json 50 | location: ${{ runner.temp }}/label-configuration-schema 51 | 52 | - name: Install JSON schema validator 53 | run: npm install 54 | 55 | - name: Validate local labels configuration 56 | run: | 57 | # See: https://github.com/ajv-validator/ajv-cli#readme 58 | npx \ 59 | --package=ajv-cli \ 60 | --package=ajv-formats \ 61 | ajv validate \ 62 | --all-errors \ 63 | -c ajv-formats \ 64 | -s "${{ steps.download-schema.outputs.file-path }}" \ 65 | -d "${{ env.CONFIGURATIONS_FOLDER }}/*.{yml,yaml}" 66 | 67 | download: 68 | needs: check 69 | runs-on: ubuntu-latest 70 | permissions: {} 71 | 72 | strategy: 73 | matrix: 74 | filename: 75 | # Filenames of the shared configurations to apply to the repository in addition to the local configuration. 76 | # https://github.com/arduino/tooling-project-assets/blob/main/workflow-templates/assets/sync-labels 77 | - tooling.yml 78 | - universal.yml 79 | 80 | steps: 81 | - name: Download 82 | uses: carlosperate/download-file-action@v2 83 | with: 84 | file-url: https://raw.githubusercontent.com/arduino/tooling-project-assets/main/workflow-templates/assets/sync-labels/${{ matrix.filename }} 85 | 86 | - name: Pass configuration files to next job via workflow artifact 87 | uses: actions/upload-artifact@v4 88 | with: 89 | path: | 90 | *.yaml 91 | *.yml 92 | if-no-files-found: error 93 | name: ${{ env.CONFIGURATIONS_ARTIFACT_PREFIX }}${{ matrix.filename }} 94 | 95 | sync: 96 | needs: download 97 | runs-on: ubuntu-latest 98 | permissions: 99 | contents: read 100 | issues: write 101 | 102 | steps: 103 | - name: Set environment variables 104 | run: | 105 | # See: https://docs.github.com/actions/using-workflows/workflow-commands-for-github-actions#setting-an-environment-variable 106 | echo "MERGED_CONFIGURATION_PATH=${{ runner.temp }}/labels.yml" >> "$GITHUB_ENV" 107 | 108 | - name: Determine whether to dry run 109 | id: dry-run 110 | if: > 111 | github.event_name == 'pull_request' || 112 | ( 113 | ( 114 | github.event_name == 'push' || 115 | github.event_name == 'workflow_dispatch' 116 | ) && 117 | github.ref != format('refs/heads/{0}', github.event.repository.default_branch) 118 | ) 119 | run: | 120 | # Use of this flag in the github-label-sync command will cause it to only check the validity of the 121 | # configuration. 122 | echo "flag=--dry-run" >> $GITHUB_OUTPUT 123 | 124 | - name: Checkout repository 125 | uses: actions/checkout@v4 126 | 127 | - name: Download configuration file artifacts 128 | uses: actions/download-artifact@v4 129 | with: 130 | merge-multiple: true 131 | pattern: ${{ env.CONFIGURATIONS_ARTIFACT_PREFIX }}* 132 | path: ${{ env.CONFIGURATIONS_FOLDER }} 133 | 134 | - name: Remove unneeded artifacts 135 | uses: geekyeggo/delete-artifact@v5 136 | with: 137 | name: ${{ env.CONFIGURATIONS_ARTIFACT_PREFIX }}* 138 | 139 | - name: Setup Node.js 140 | uses: actions/setup-node@v4 141 | with: 142 | node-version-file: package.json 143 | 144 | - name: Merge label configuration files 145 | run: | 146 | # Merge all configuration files 147 | shopt -s extglob 148 | cat "${{ env.CONFIGURATIONS_FOLDER }}"/*.@(yml|yaml) > "${{ env.MERGED_CONFIGURATION_PATH }}" 149 | 150 | - name: Install github-label-sync 151 | run: npm install 152 | 153 | - name: Sync labels 154 | env: 155 | GITHUB_ACCESS_TOKEN: ${{ secrets.GITHUB_TOKEN }} 156 | run: | 157 | # See: https://github.com/Financial-Times/github-label-sync 158 | npx \ 159 | github-label-sync \ 160 | --labels "${{ env.MERGED_CONFIGURATION_PATH }}" \ 161 | ${{ steps.dry-run.outputs.flag }} \ 162 | ${{ github.repository }} 163 | -------------------------------------------------------------------------------- /.github/workflows/test-javascript-jest-task.yml: -------------------------------------------------------------------------------- 1 | # Source: https://github.com/per1234/.github/blob/main/workflow-templates/test-javascript-jest-task.md 2 | name: Test JavaScript 3 | 4 | on: 5 | push: 6 | paths: 7 | - ".github/workflows/test-javascript-jest-task.ya?ml" 8 | - ".github/.?codecov.ya?ml" 9 | - "dev/.?codecov.ya?ml" 10 | - ".?codecov.ya?ml" 11 | - "**/.npmrc" 12 | - "**/jest.config.[cm]?js" 13 | - "**/jest.config.json" 14 | - "**/jest.config.ts" 15 | - "**/package.json" 16 | - "**/package-lock.json" 17 | - "Taskfile.ya?ml" 18 | - "__tests__/testdata/**" 19 | - "**/tsconfig.json" 20 | - "**.[jt]sx?" 21 | pull_request: 22 | paths: 23 | - ".github/workflows/test-javascript-jest-task.ya?ml" 24 | - ".github/.?codecov.ya?ml" 25 | - "dev/.?codecov.ya?ml" 26 | - ".?codecov.ya?ml" 27 | - "**/.npmrc" 28 | - "**/jest.config.[cm]?js" 29 | - "**/jest.config.json" 30 | - "**/jest.config.ts" 31 | - "**/package.json" 32 | - "**/package-lock.json" 33 | - "Taskfile.ya?ml" 34 | - "__tests__/testdata/**" 35 | - "**/tsconfig.json" 36 | - "**.[jt]sx?" 37 | workflow_dispatch: 38 | repository_dispatch: 39 | 40 | jobs: 41 | run-determination: 42 | runs-on: ubuntu-latest 43 | permissions: {} 44 | outputs: 45 | result: ${{ steps.determination.outputs.result }} 46 | steps: 47 | - name: Determine if the rest of the workflow should run 48 | id: determination 49 | run: | 50 | RELEASE_BRANCH_REGEX="refs/heads/[0-9]+.[0-9]+.x" 51 | # The `create` event trigger doesn't support `branches` filters, so it's necessary to use Bash instead. 52 | if [[ 53 | "${{ github.event_name }}" != "create" || 54 | "${{ github.ref }}" =~ $RELEASE_BRANCH_REGEX 55 | ]]; then 56 | # Run the other jobs. 57 | RESULT="true" 58 | else 59 | # There is no need to run the other jobs. 60 | RESULT="false" 61 | fi 62 | 63 | echo "result=$RESULT" >> $GITHUB_OUTPUT 64 | 65 | test: 66 | name: test (${{ matrix.project.path }}, ${{ matrix.operating-system }}) 67 | needs: run-determination 68 | if: needs.run-determination.outputs.result == 'true' 69 | runs-on: ${{ matrix.operating-system }} 70 | defaults: 71 | run: 72 | shell: bash 73 | permissions: 74 | contents: read 75 | 76 | strategy: 77 | fail-fast: false 78 | matrix: 79 | project: 80 | - path: . 81 | operating-system: 82 | - ubuntu-latest 83 | 84 | steps: 85 | - name: Checkout 86 | uses: actions/checkout@v4 87 | 88 | - name: Setup Node.js 89 | uses: actions/setup-node@v4 90 | with: 91 | node-version-file: package.json 92 | 93 | - name: Install Task 94 | uses: arduino/setup-task@v2 95 | with: 96 | repo-token: ${{ secrets.GITHUB_TOKEN }} 97 | version: 3.x 98 | 99 | - name: Run tests 100 | run: | 101 | task \ 102 | --silent \ 103 | js:test \ 104 | PROJECT_PATH="${{ matrix.project.path }}" 105 | 106 | - name: Send unit tests coverage to Codecov 107 | if: runner.os == 'Linux' 108 | uses: codecov/codecov-action@v4 109 | with: 110 | # Even though the file is specified via the `file` input. The action still pointlessly searches for the file 111 | # by default. 112 | disable_search: true 113 | fail_ci_if_error: ${{ github.repository == 'arduino/arduino-lint-action' }} 114 | file: ${{ matrix.project.path }}/coverage/lcov.info 115 | # If triggered by a push/PR by a human from a branch in the repo, the token from the action secret is used. 116 | # If triggered by a Dependabot PR, the token from the Dependabot secret is used. 117 | # If triggered by a PR from a fork, the action allows a "tokenless" upload. 118 | token: ${{ secrets.CODECOV_TOKEN }} 119 | -------------------------------------------------------------------------------- /.github/workflows/testdata/SpecificationSketch/SpecificationSketch.ino: -------------------------------------------------------------------------------- 1 | void setup() {} 2 | void loop() {} 3 | -------------------------------------------------------------------------------- /.github/workflows/testdata/some-projects/InvalidSketch/Invalid Sketch.ino: -------------------------------------------------------------------------------- 1 | void setup() {} 2 | void loop() {} 3 | -------------------------------------------------------------------------------- /.github/workflows/testdata/some-projects/PermissiveLibrary/PermissiveLibrary.h: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/arduino/arduino-lint-action/ccb6809d6c6e3221e5d2e05f8341a49bdc5b1c4a/.github/workflows/testdata/some-projects/PermissiveLibrary/PermissiveLibrary.h -------------------------------------------------------------------------------- /.github/workflows/testdata/some-projects/PermissiveLibrary/library.properties: -------------------------------------------------------------------------------- 1 | name=ArduinoGraphics 2 | version=1.0.0 3 | author=Cristian Maglie , Pippo Pluto 4 | maintainer=Cristian Maglie 5 | sentence=A library that requires the permissive compliance setting to pass the checks. 6 | paragraph= 7 | category=Other 8 | url=http://example.com/ 9 | architectures=avr 10 | # Invalid permissive value only allowed in permissive compliance mode 11 | permissive=foo 12 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | # Dependency directory 2 | node_modules/ 3 | 4 | # Ignore built ts files 5 | __tests__/runner/* 6 | lib/**/* 7 | -------------------------------------------------------------------------------- /.licensed.yml: -------------------------------------------------------------------------------- 1 | # See: https://github.com/github/licensed/blob/master/docs/configuration.md 2 | 3 | # Source: https://github.com/arduino/tooling-project-assets/blob/main/workflow-templates/assets/check-dependencies/Apache-2.0/.licensed.yml 4 | allowed: 5 | # The following are based on https://www.apache.org/legal/resolved.html#category-a 6 | - apache-2.0 7 | - apache-1.1 8 | - php-3.01 9 | # "MX4J License" - no SPDX ID 10 | - bsd-2-clause 11 | - bsd-2-clause-netbsd # Deprecated ID for `bsd-2-clause` 12 | - bsd-2-clause-views 13 | - bsd-2-clause-freebsd # Deprecated ID for `bsd-2-clause-views` 14 | - bsd-3-clause 15 | - bsd-3-clause-clear 16 | # "DOM4J License" - no SPDX ID 17 | - postgresql 18 | # "Eclipse Distribution License 1.0" - no SPDX ID 19 | - mit 20 | - x11 21 | - isc 22 | - smlnj 23 | - standardml-nj # Deprecated ID for `smlnj` 24 | # "Cup Parser Generator" - no SPDX ID 25 | - icu 26 | - ncsa 27 | - w3c 28 | # "W3C Community Contributor License Agreement" - no SPDX ID 29 | - xnet 30 | - zlib 31 | # "FSF autoconf license" - no SPDX ID 32 | - afl-3.0 33 | # "Service+Component+Architecture+Specifications" - no SPDX ID 34 | # "OOXML XSD ECMA License" 35 | - ms-pl 36 | - cc-pddc 37 | - psf-2.0 38 | # "Python Imaging Library Software License" 39 | - apafml 40 | - bsl-1.0 41 | - ogl-uk-3.0 42 | - wtfpl 43 | - unicode-tou 44 | - zpl-2.0 45 | # "ACE license" - no SPDX ID 46 | - upl-1.0 47 | # "Open Grid Forum License" - no SPDX ID 48 | # 'Google "Additional IP Rights Grant (Patents)" file' - no SPDX ID 49 | - unlicense 50 | - hpnd 51 | - mulanpsl-2.0 52 | - cc0-1.0 53 | # The following are based on individual license text 54 | - lgpl-2.0-or-later 55 | - lgpl-2.0+ # Deprecated ID for `lgpl-2.0-or-later` 56 | - lgpl-2.1-only 57 | - lgpl-2.1 # Deprecated ID for `lgpl-2.1-only` 58 | - lgpl-2.1-or-later 59 | - lgpl-2.1+ # Deprecated ID for `lgpl-2.1-or-later` 60 | - lgpl-3.0-only 61 | - lgpl-3.0 # Deprecated ID for `lgpl-3.0-only` 62 | - lgpl-3.0-or-later 63 | - lgpl-3.0+ # Deprecated ID for `lgpl-3.0-or-later` 64 | -------------------------------------------------------------------------------- /.licenses/npm/@actions/core.dep.yml: -------------------------------------------------------------------------------- 1 | --- 2 | name: "@actions/core" 3 | version: 1.11.1 4 | type: npm 5 | summary: Actions core lib 6 | homepage: https://github.com/actions/toolkit/tree/main/packages/core 7 | license: mit 8 | licenses: 9 | - sources: LICENSE.md 10 | text: |- 11 | The MIT License (MIT) 12 | 13 | Copyright 2019 GitHub 14 | 15 | Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: 16 | 17 | The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. 18 | 19 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 20 | notices: [] 21 | -------------------------------------------------------------------------------- /.licenses/npm/@actions/exec.dep.yml: -------------------------------------------------------------------------------- 1 | --- 2 | name: "@actions/exec" 3 | version: 1.1.1 4 | type: npm 5 | summary: Actions exec lib 6 | homepage: https://github.com/actions/toolkit/tree/main/packages/exec 7 | license: mit 8 | licenses: 9 | - sources: LICENSE.md 10 | text: |- 11 | The MIT License (MIT) 12 | 13 | Copyright 2019 GitHub 14 | 15 | Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: 16 | 17 | The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. 18 | 19 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 20 | notices: [] 21 | -------------------------------------------------------------------------------- /.licenses/npm/@actions/http-client.dep.yml: -------------------------------------------------------------------------------- 1 | --- 2 | name: "@actions/http-client" 3 | version: 2.2.3 4 | type: npm 5 | summary: Actions Http Client 6 | homepage: https://github.com/actions/toolkit/tree/main/packages/http-client 7 | license: mit 8 | licenses: 9 | - sources: LICENSE 10 | text: | 11 | Actions Http Client for Node.js 12 | 13 | Copyright (c) GitHub, Inc. 14 | 15 | All rights reserved. 16 | 17 | MIT License 18 | 19 | Permission is hereby granted, free of charge, to any person obtaining a copy of this software and 20 | associated documentation files (the "Software"), to deal in the Software without restriction, 21 | including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, 22 | and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, 23 | subject to the following conditions: 24 | 25 | The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. 26 | 27 | THE SOFTWARE IS PROVIDED *AS IS*, WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT 28 | LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN 29 | NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, 30 | WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE 31 | SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 32 | notices: [] 33 | -------------------------------------------------------------------------------- /.licenses/npm/@actions/io.dep.yml: -------------------------------------------------------------------------------- 1 | --- 2 | name: "@actions/io" 3 | version: 1.1.3 4 | type: npm 5 | summary: Actions io lib 6 | homepage: https://github.com/actions/toolkit/tree/main/packages/io 7 | license: mit 8 | licenses: 9 | - sources: LICENSE.md 10 | text: |- 11 | The MIT License (MIT) 12 | 13 | Copyright 2019 GitHub 14 | 15 | Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: 16 | 17 | The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. 18 | 19 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 20 | notices: [] 21 | -------------------------------------------------------------------------------- /.licenses/npm/@actions/tool-cache.dep.yml: -------------------------------------------------------------------------------- 1 | --- 2 | name: "@actions/tool-cache" 3 | version: 2.0.2 4 | type: npm 5 | summary: Actions tool-cache lib 6 | homepage: https://github.com/actions/toolkit/tree/main/packages/tool-cache 7 | license: mit 8 | licenses: 9 | - sources: LICENSE.md 10 | text: |- 11 | The MIT License (MIT) 12 | 13 | Copyright 2019 GitHub 14 | 15 | Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: 16 | 17 | The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. 18 | 19 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 20 | notices: [] 21 | -------------------------------------------------------------------------------- /.licenses/npm/@fastify/busboy.dep.yml: -------------------------------------------------------------------------------- 1 | --- 2 | name: "@fastify/busboy" 3 | version: 2.0.0 4 | type: npm 5 | summary: A streaming parser for HTML form data for node.js 6 | homepage: 7 | license: mit 8 | licenses: 9 | - sources: LICENSE 10 | text: |- 11 | Copyright Brian White. All rights reserved. 12 | 13 | Permission is hereby granted, free of charge, to any person obtaining a copy 14 | of this software and associated documentation files (the "Software"), to 15 | deal in the Software without restriction, including without limitation the 16 | rights to use, copy, modify, merge, publish, distribute, sublicense, and/or 17 | sell copies of the Software, and to permit persons to whom the Software is 18 | furnished to do so, subject to the following conditions: 19 | 20 | The above copyright notice and this permission notice shall be included in 21 | all copies or substantial portions of the Software. 22 | 23 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 24 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 25 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 26 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 27 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING 28 | FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS 29 | IN THE SOFTWARE. 30 | notices: [] 31 | -------------------------------------------------------------------------------- /.licenses/npm/semver-6.3.0.dep.yml: -------------------------------------------------------------------------------- 1 | --- 2 | name: semver 3 | version: 6.3.0 4 | type: npm 5 | summary: The semantic version parser used by npm. 6 | homepage: 7 | license: isc 8 | licenses: 9 | - sources: LICENSE 10 | text: | 11 | The ISC License 12 | 13 | Copyright (c) Isaac Z. Schlueter and Contributors 14 | 15 | Permission to use, copy, modify, and/or distribute this software for any 16 | purpose with or without fee is hereby granted, provided that the above 17 | copyright notice and this permission notice appear in all copies. 18 | 19 | THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES 20 | WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF 21 | MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR 22 | ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES 23 | WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN 24 | ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR 25 | IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. 26 | notices: [] 27 | -------------------------------------------------------------------------------- /.licenses/npm/semver-7.7.2.dep.yml: -------------------------------------------------------------------------------- 1 | --- 2 | name: semver 3 | version: 7.7.2 4 | type: npm 5 | summary: The semantic version parser used by npm. 6 | homepage: 7 | license: isc 8 | licenses: 9 | - sources: LICENSE 10 | text: | 11 | The ISC License 12 | 13 | Copyright (c) Isaac Z. Schlueter and Contributors 14 | 15 | Permission to use, copy, modify, and/or distribute this software for any 16 | purpose with or without fee is hereby granted, provided that the above 17 | copyright notice and this permission notice appear in all copies. 18 | 19 | THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES 20 | WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF 21 | MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR 22 | ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES 23 | WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN 24 | ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR 25 | IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. 26 | notices: [] 27 | -------------------------------------------------------------------------------- /.licenses/npm/tunnel.dep.yml: -------------------------------------------------------------------------------- 1 | --- 2 | name: tunnel 3 | version: 0.0.6 4 | type: npm 5 | summary: Node HTTP/HTTPS Agents for tunneling proxies 6 | homepage: https://github.com/koichik/node-tunnel/ 7 | license: mit 8 | licenses: 9 | - sources: LICENSE 10 | text: | 11 | The MIT License (MIT) 12 | 13 | Copyright (c) 2012 Koichi Kobayashi 14 | 15 | Permission is hereby granted, free of charge, to any person obtaining a copy 16 | of this software and associated documentation files (the "Software"), to deal 17 | in the Software without restriction, including without limitation the rights 18 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 19 | copies of the Software, and to permit persons to whom the Software is 20 | furnished to do so, subject to the following conditions: 21 | 22 | The above copyright notice and this permission notice shall be included in 23 | all copies or substantial portions of the Software. 24 | 25 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 26 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 27 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 28 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 29 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 30 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 31 | THE SOFTWARE. 32 | - sources: README.md 33 | text: Licensed under the [MIT](https://github.com/koichik/node-tunnel/blob/master/LICENSE) 34 | license. 35 | notices: [] 36 | -------------------------------------------------------------------------------- /.licenses/npm/undici.dep.yml: -------------------------------------------------------------------------------- 1 | --- 2 | name: undici 3 | version: 5.29.0 4 | type: npm 5 | summary: An HTTP/1.1 client, written from scratch for Node.js 6 | homepage: https://undici.nodejs.org 7 | license: mit 8 | licenses: 9 | - sources: LICENSE 10 | text: | 11 | MIT License 12 | 13 | Copyright (c) Matteo Collina and Undici contributors 14 | 15 | Permission is hereby granted, free of charge, to any person obtaining a copy 16 | of this software and associated documentation files (the "Software"), to deal 17 | in the Software without restriction, including without limitation the rights 18 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 19 | copies of the Software, and to permit persons to whom the Software is 20 | furnished to do so, subject to the following conditions: 21 | 22 | The above copyright notice and this permission notice shall be included in all 23 | copies or substantial portions of the Software. 24 | 25 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 26 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 27 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 28 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 29 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 30 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 31 | SOFTWARE. 32 | - sources: README.md 33 | text: MIT 34 | notices: [] 35 | -------------------------------------------------------------------------------- /.npmrc: -------------------------------------------------------------------------------- 1 | # See: https://docs.npmjs.com/cli/configuring-npm/npmrc 2 | 3 | engine-strict = true 4 | -------------------------------------------------------------------------------- /.prettierignore: -------------------------------------------------------------------------------- 1 | .licenses/ 2 | __pycache__/ 3 | /dist/ 4 | /lib/ 5 | node_modules/ 6 | -------------------------------------------------------------------------------- /LICENSE.txt: -------------------------------------------------------------------------------- 1 | Apache License 2 | Version 2.0, January 2004 3 | http://www.apache.org/licenses/ 4 | 5 | TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION 6 | 7 | 1. Definitions. 8 | 9 | "License" shall mean the terms and conditions for use, reproduction, 10 | and distribution as defined by Sections 1 through 9 of this document. 11 | 12 | "Licensor" shall mean the copyright owner or entity authorized by 13 | the copyright owner that is granting the License. 14 | 15 | "Legal Entity" shall mean the union of the acting entity and all 16 | other entities that control, are controlled by, or are under common 17 | control with that entity. For the purposes of this definition, 18 | "control" means (i) the power, direct or indirect, to cause the 19 | direction or management of such entity, whether by contract or 20 | otherwise, or (ii) ownership of fifty percent (50%) or more of the 21 | outstanding shares, or (iii) beneficial ownership of such entity. 22 | 23 | "You" (or "Your") shall mean an individual or Legal Entity 24 | exercising permissions granted by this License. 25 | 26 | "Source" form shall mean the preferred form for making modifications, 27 | including but not limited to software source code, documentation 28 | source, and configuration files. 29 | 30 | "Object" form shall mean any form resulting from mechanical 31 | transformation or translation of a Source form, including but 32 | not limited to compiled object code, generated documentation, 33 | and conversions to other media types. 34 | 35 | "Work" shall mean the work of authorship, whether in Source or 36 | Object form, made available under the License, as indicated by a 37 | copyright notice that is included in or attached to the work 38 | (an example is provided in the Appendix below). 39 | 40 | "Derivative Works" shall mean any work, whether in Source or Object 41 | form, that is based on (or derived from) the Work and for which the 42 | editorial revisions, annotations, elaborations, or other modifications 43 | represent, as a whole, an original work of authorship. For the purposes 44 | of this License, Derivative Works shall not include works that remain 45 | separable from, or merely link (or bind by name) to the interfaces of, 46 | the Work and Derivative Works thereof. 47 | 48 | "Contribution" shall mean any work of authorship, including 49 | the original version of the Work and any modifications or additions 50 | to that Work or Derivative Works thereof, that is intentionally 51 | submitted to Licensor for inclusion in the Work by the copyright owner 52 | or by an individual or Legal Entity authorized to submit on behalf of 53 | the copyright owner. For the purposes of this definition, "submitted" 54 | means any form of electronic, verbal, or written communication sent 55 | to the Licensor or its representatives, including but not limited to 56 | communication on electronic mailing lists, source code control systems, 57 | and issue tracking systems that are managed by, or on behalf of, the 58 | Licensor for the purpose of discussing and improving the Work, but 59 | excluding communication that is conspicuously marked or otherwise 60 | designated in writing by the copyright owner as "Not a Contribution." 61 | 62 | "Contributor" shall mean Licensor and any individual or Legal Entity 63 | on behalf of whom a Contribution has been received by Licensor and 64 | subsequently incorporated within the Work. 65 | 66 | 2. Grant of Copyright License. Subject to the terms and conditions of 67 | this License, each Contributor hereby grants to You a perpetual, 68 | worldwide, non-exclusive, no-charge, royalty-free, irrevocable 69 | copyright license to reproduce, prepare Derivative Works of, 70 | publicly display, publicly perform, sublicense, and distribute the 71 | Work and such Derivative Works in Source or Object form. 72 | 73 | 3. Grant of Patent License. Subject to the terms and conditions of 74 | this License, each Contributor hereby grants to You a perpetual, 75 | worldwide, non-exclusive, no-charge, royalty-free, irrevocable 76 | (except as stated in this section) patent license to make, have made, 77 | use, offer to sell, sell, import, and otherwise transfer the Work, 78 | where such license applies only to those patent claims licensable 79 | by such Contributor that are necessarily infringed by their 80 | Contribution(s) alone or by combination of their Contribution(s) 81 | with the Work to which such Contribution(s) was submitted. If You 82 | institute patent litigation against any entity (including a 83 | cross-claim or counterclaim in a lawsuit) alleging that the Work 84 | or a Contribution incorporated within the Work constitutes direct 85 | or contributory patent infringement, then any patent licenses 86 | granted to You under this License for that Work shall terminate 87 | as of the date such litigation is filed. 88 | 89 | 4. Redistribution. You may reproduce and distribute copies of the 90 | Work or Derivative Works thereof in any medium, with or without 91 | modifications, and in Source or Object form, provided that You 92 | meet the following conditions: 93 | 94 | (a) You must give any other recipients of the Work or 95 | Derivative Works a copy of this License; and 96 | 97 | (b) You must cause any modified files to carry prominent notices 98 | stating that You changed the files; and 99 | 100 | (c) You must retain, in the Source form of any Derivative Works 101 | that You distribute, all copyright, patent, trademark, and 102 | attribution notices from the Source form of the Work, 103 | excluding those notices that do not pertain to any part of 104 | the Derivative Works; and 105 | 106 | (d) If the Work includes a "NOTICE" text file as part of its 107 | distribution, then any Derivative Works that You distribute must 108 | include a readable copy of the attribution notices contained 109 | within such NOTICE file, excluding those notices that do not 110 | pertain to any part of the Derivative Works, in at least one 111 | of the following places: within a NOTICE text file distributed 112 | as part of the Derivative Works; within the Source form or 113 | documentation, if provided along with the Derivative Works; or, 114 | within a display generated by the Derivative Works, if and 115 | wherever such third-party notices normally appear. The contents 116 | of the NOTICE file are for informational purposes only and 117 | do not modify the License. You may add Your own attribution 118 | notices within Derivative Works that You distribute, alongside 119 | or as an addendum to the NOTICE text from the Work, provided 120 | that such additional attribution notices cannot be construed 121 | as modifying the License. 122 | 123 | You may add Your own copyright statement to Your modifications and 124 | may provide additional or different license terms and conditions 125 | for use, reproduction, or distribution of Your modifications, or 126 | for any such Derivative Works as a whole, provided Your use, 127 | reproduction, and distribution of the Work otherwise complies with 128 | the conditions stated in this License. 129 | 130 | 5. Submission of Contributions. Unless You explicitly state otherwise, 131 | any Contribution intentionally submitted for inclusion in the Work 132 | by You to the Licensor shall be under the terms and conditions of 133 | this License, without any additional terms or conditions. 134 | Notwithstanding the above, nothing herein shall supersede or modify 135 | the terms of any separate license agreement you may have executed 136 | with Licensor regarding such Contributions. 137 | 138 | 6. Trademarks. This License does not grant permission to use the trade 139 | names, trademarks, service marks, or product names of the Licensor, 140 | except as required for reasonable and customary use in describing the 141 | origin of the Work and reproducing the content of the NOTICE file. 142 | 143 | 7. Disclaimer of Warranty. Unless required by applicable law or 144 | agreed to in writing, Licensor provides the Work (and each 145 | Contributor provides its Contributions) on an "AS IS" BASIS, 146 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or 147 | implied, including, without limitation, any warranties or conditions 148 | of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A 149 | PARTICULAR PURPOSE. You are solely responsible for determining the 150 | appropriateness of using or redistributing the Work and assume any 151 | risks associated with Your exercise of permissions under this License. 152 | 153 | 8. Limitation of Liability. In no event and under no legal theory, 154 | whether in tort (including negligence), contract, or otherwise, 155 | unless required by applicable law (such as deliberate and grossly 156 | negligent acts) or agreed to in writing, shall any Contributor be 157 | liable to You for damages, including any direct, indirect, special, 158 | incidental, or consequential damages of any character arising as a 159 | result of this License or out of the use or inability to use the 160 | Work (including but not limited to damages for loss of goodwill, 161 | work stoppage, computer failure or malfunction, or any and all 162 | other commercial damages or losses), even if such Contributor 163 | has been advised of the possibility of such damages. 164 | 165 | 9. Accepting Warranty or Additional Liability. While redistributing 166 | the Work or Derivative Works thereof, You may choose to offer, 167 | and charge a fee for, acceptance of support, warranty, indemnity, 168 | or other liability obligations and/or rights consistent with this 169 | License. However, in accepting such obligations, You may act only 170 | on Your own behalf and on Your sole responsibility, not on behalf 171 | of any other Contributor, and only if You agree to indemnify, 172 | defend, and hold each Contributor harmless for any liability 173 | incurred by, or claims asserted against, such Contributor by reason 174 | of your accepting any such warranty or additional liability. 175 | 176 | END OF TERMS AND CONDITIONS 177 | 178 | APPENDIX: How to apply the Apache License to your work. 179 | 180 | To apply the Apache License to your work, attach the following 181 | boilerplate notice, with the fields enclosed by brackets "[]" 182 | replaced with your own identifying information. (Don't include 183 | the brackets!) The text should be enclosed in the appropriate 184 | comment syntax for the file format. We also recommend that a 185 | file or class name and description of purpose be included on the 186 | same "printed page" as the copyright notice for easier 187 | identification within third-party archives. 188 | 189 | Copyright [yyyy] [name of copyright owner] 190 | 191 | Licensed under the Apache License, Version 2.0 (the "License"); 192 | you may not use this file except in compliance with the License. 193 | You may obtain a copy of the License at 194 | 195 | http://www.apache.org/licenses/LICENSE-2.0 196 | 197 | Unless required by applicable law or agreed to in writing, software 198 | distributed under the License is distributed on an "AS IS" BASIS, 199 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 200 | See the License for the specific language governing permissions and 201 | limitations under the License. 202 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # `arduino/arduino-lint-action` 2 | 3 | [![Tests Status](https://github.com/arduino/arduino-lint-action/actions/workflows/test-javascript-jest-task.yml/badge.svg)](https://github.com/arduino/arduino-lint-action/actions/workflows/test-javascript-jest-task.yml) 4 | [![Integration Tests Status](https://github.com/arduino/arduino-lint-action/workflows/Integration%20Tests/badge.svg)](https://github.com/arduino/arduino-lint-action/actions?workflow=Integration+Tests) 5 | [![Check License status](https://github.com/arduino/arduino-lint-action/actions/workflows/check-license.yml/badge.svg)](https://github.com/arduino/arduino-lint-action/actions/workflows/check-license.yml) 6 | [![Check npm Dependencies status](https://github.com/arduino/arduino-lint-action/actions/workflows/check-npm-dependencies-task.yml/badge.svg)](https://github.com/arduino/arduino-lint-action/actions/workflows/check-npm-dependencies-task.yml) 7 | [![Check Packaging status](https://github.com/arduino/arduino-lint-action/actions/workflows/check-packaging-ncc-typescript-npm.yml/badge.svg)](https://github.com/arduino/arduino-lint-action/actions/workflows/check-packaging-ncc-typescript-npm.yml) 8 | [![Check Prettier Formatting status](https://github.com/arduino/arduino-lint-action/actions/workflows/check-prettier-formatting-task.yml/badge.svg)](https://github.com/arduino/arduino-lint-action/actions/workflows/check-prettier-formatting-task.yml) 9 | [![Check TypeScript Configuration status](https://github.com/arduino/arduino-lint-action/actions/workflows/check-tsconfig-task.yml/badge.svg)](https://github.com/arduino/arduino-lint-action/actions/workflows/check-tsconfig-task.yml) 10 | [![Check npm status](https://github.com/arduino/arduino-lint-action/actions/workflows/check-npm-task.yml/badge.svg)](https://github.com/arduino/arduino-lint-action/actions/workflows/check-npm-task.yml) 11 | [![Spell Check status](https://github.com/arduino/arduino-lint-action/actions/workflows/spell-check-task.yml/badge.svg)](https://github.com/arduino/arduino-lint-action/actions/workflows/spell-check-task.yml) 12 | 13 | [GitHub Actions](https://docs.github.com/en/free-pro-team@latest/actions) action that uses 14 | [Arduino Lint](https://github.com/arduino/arduino-lint) to check for problems with [Arduino](https://www.arduino.cc/) 15 | projects: 16 | 17 | - Libraries 18 | - Sketches 19 | - Boards platforms 20 | - Boards Manager package indexes 21 | 22 | ## Table of contents 23 | 24 | 25 | 26 | - [Inputs](#inputs) 27 | - [`path`](#path) 28 | - [`version`](#version) 29 | - [`compliance`](#compliance) 30 | - [`library-manager`](#library-manager) 31 | - [`project-type`](#project-type) 32 | - [`recursive`](#recursive) 33 | - [`report-file`](#report-file) 34 | - [`verbose`](#verbose) 35 | - [`token`](#token) 36 | - [Usage](#usage) 37 | - [Contributing](#contributing) 38 | 39 | 40 | 41 | ## Inputs 42 | 43 | ### `path` 44 | 45 | Path containing Arduino project(s). 46 | 47 | **Default**: `./` 48 | 49 | ### `version` 50 | 51 | The version of [Arduino Lint](https://github.com/arduino/arduino-lint) to use. 52 | Can be an exact version (e.g., `1.0.0`) or a version range (e.g., `1.x`). 53 | 54 | **Default**: `1.x` 55 | 56 | ### `compliance` 57 | 58 | Configure how strict the tool is about which checks are considered errors vs warnings if they don't pass. 59 | 60 | #### Supported values 61 | 62 | - `strict` - enforces best practices, above and beyond the minimum requirements for specification compliance. Use this setting to ensure the best experience for the users of the project. 63 | - `specification` - enforces compliance with the official Arduino project specifications. 64 | - `permissive` - will cause the checks to fail only when severe problems are found. Although a project that passes at the permissive setting will work with the current Arduino development software versions, it may not be fully specification-compliant, risking incompatibility or a poor experience for the users. 65 | 66 | **Default**: `specification` 67 | 68 | ### `library-manager` 69 | 70 | Configure the checks for libraries in the [Arduino Library Manager](https://github.com/arduino/library-registry/blob/main/FAQ.md#readme) index. 71 | 72 | #### Supported values 73 | 74 | - `submit` - Also run additional checks required to pass before a library is accepted for inclusion in the index. 75 | - `update`- Also run additional checks required to pass before new releases of a library already in the index are accepted. 76 | - `false` - Don't run any Library Manager-specific checks. 77 | 78 | **Default**: `submit` for libraries, `false` for other project types 79 | 80 | ### `project-type` 81 | 82 | Configures which types of projects to check, along with their subprojects. 83 | 84 | #### Supported values 85 | 86 | - `sketch` 87 | - `library` 88 | - `platform` - [boards platform](https://arduino.github.io/arduino-cli/latest/platform-specification/) 89 | - `package-index` - Boards Manager [package index](https://arduino.github.io/arduino-cli/latest/package_index_json-specification/) 90 | - `all` - Run checks on any type of project that is detected 91 | 92 | **Default**: `all` 93 | 94 | ### `recursive` 95 | 96 | Set to `true` to search path recursively for Arduino projects to check. 97 | 98 | **Default**: `false` 99 | 100 | ### `report-file` 101 | 102 | Save a JSON formatted report on the checks to this file. 103 | 104 | ### `verbose` 105 | 106 | Set to `true` to show more information in the log about the checks being run. 107 | 108 | **Default**: `false` 109 | 110 | ### `token` 111 | 112 | GitHub access token used to get information from the GitHub API. 113 | 114 | **Default**: [`GITHUB_TOKEN`](https://docs.github.com/en/actions/security-guides/automatic-token-authentication) 115 | 116 | ## Usage 117 | 118 | The minimal workflow to run the default checks on the projects in the repository: 119 | 120 | ```yaml 121 | on: [push, pull_request] 122 | jobs: 123 | lint: 124 | runs-on: ubuntu-latest 125 | steps: 126 | - uses: actions/checkout@v4 127 | - uses: arduino/arduino-lint-action@v2 128 | ``` 129 | 130 | A more complex workflow which uses [inputs](#inputs) to configure the action for Library Manager ["update" mode](#library-manager) and strict compliance: 131 | 132 | ```yaml 133 | on: [push, pull_request] 134 | jobs: 135 | lint: 136 | runs-on: ubuntu-latest 137 | steps: 138 | - uses: actions/checkout@v4 139 | - uses: arduino/arduino-lint-action@v2 140 | with: 141 | library-manager: update 142 | compliance: strict 143 | ``` 144 | 145 | ## Contributing 146 | 147 | To report bugs or make feature requests, please submit an issue: https://github.com/arduino/arduino-lint-action/issues 148 | 149 | Pull requests are welcome! Please see the [contribution guidelines](.github/CONTRIBUTING.md) for information. 150 | -------------------------------------------------------------------------------- /Taskfile.yml: -------------------------------------------------------------------------------- 1 | # See: https://taskfile.dev/#/usage 2 | version: "3" 3 | 4 | vars: 5 | # Path of the primary npm-managed project: 6 | DEFAULT_NPM_PROJECT_PATH: ./ 7 | # Last version of ajv-cli with support for the JSON schema "Draft 4" specification 8 | SCHEMA_DRAFT_4_AJV_CLI_VERSION: 3.3.0 9 | 10 | tasks: 11 | build: 12 | desc: Build the project 13 | deps: 14 | - task: ts:build 15 | 16 | check: 17 | desc: Check for problems with the project 18 | deps: 19 | - task: general:check-spelling 20 | - task: js:test 21 | - task: npm:validate 22 | - task: ts:validate 23 | vars: 24 | TSCONFIG_PATH: "./tsconfig.json" 25 | 26 | fix: 27 | desc: Make automated corrections to the project's files 28 | deps: 29 | - task: general:correct-spelling 30 | - task: general:format-prettier 31 | - task: markdown:toc 32 | vars: 33 | FILE_PATH: README.md 34 | MAX_DEPTH: 3 35 | - task: npm:install-deps 36 | - task: poetry:sync 37 | - task: ts:build 38 | 39 | # Source: https://github.com/arduino/tooling-project-assets/blob/main/workflow-templates/assets/check-dependencies-task/Taskfile.yml 40 | general:cache-dep-licenses: 41 | desc: Cache dependency license metadata 42 | deps: 43 | - task: general:prepare-deps 44 | cmds: 45 | - | 46 | if ! which licensed &>/dev/null; then 47 | if [[ {{OS}} == "windows" ]]; then 48 | echo "Licensed does not have Windows support." 49 | echo "Please use Linux/macOS or download the dependencies cache from the GitHub Actions workflow artifact." 50 | else 51 | echo "licensed not found or not in PATH." 52 | echo "Please install: https://github.com/github/licensed#as-an-executable" 53 | fi 54 | exit 1 55 | fi 56 | - licensed cache 57 | 58 | # Source: https://github.com/arduino/tooling-project-assets/blob/main/workflow-templates/assets/check-dependencies-task/Taskfile.yml 59 | general:check-dep-licenses: 60 | desc: Check for unapproved dependency licenses 61 | deps: 62 | - task: general:cache-dep-licenses 63 | cmds: 64 | - licensed status 65 | 66 | # Source: https://github.com/arduino/tooling-project-assets/blob/main/workflow-templates/assets/spell-check-task/Taskfile.yml 67 | general:check-spelling: 68 | desc: Check for commonly misspelled words 69 | deps: 70 | - task: poetry:install-deps 71 | vars: 72 | POETRY_GROUPS: dev 73 | cmds: 74 | - poetry run codespell 75 | 76 | # Source: https://github.com/arduino/tooling-project-assets/blob/main/workflow-templates/assets/spell-check-task/Taskfile.yml 77 | general:correct-spelling: 78 | desc: Correct commonly misspelled words where possible 79 | deps: 80 | - task: poetry:install-deps 81 | vars: 82 | POETRY_GROUPS: dev 83 | cmds: 84 | - poetry run codespell --write-changes 85 | 86 | # Source: https://github.com/arduino/tooling-project-assets/blob/main/workflow-templates/assets/check-prettier-formatting-task/Taskfile.yml 87 | general:format-prettier: 88 | desc: Format all supported files with Prettier 89 | deps: 90 | - task: npm:install-deps 91 | cmds: 92 | - npx prettier --write . 93 | 94 | # Source: https://github.com/arduino/tooling-project-assets/blob/main/workflow-templates/assets/check-npm-dependencies-task/Taskfile.yml 95 | general:prepare-deps: 96 | desc: Prepare project dependencies for license check 97 | deps: 98 | - task: npm:install-deps 99 | 100 | js:test: 101 | desc: | 102 | Test the project's JavaScript/TypeScript code. 103 | Environment variable parameters: 104 | PROJECT_PATH: Path of the npm-managed project (default: {{.DEFAULT_NPM_PROJECT_PATH}}). 105 | deps: 106 | - task: npm:install-deps 107 | dir: | 108 | "{{default .DEFAULT_NPM_PROJECT_PATH .PROJECT_PATH}}" 109 | cmds: 110 | # See: https://jestjs.io/docs/ecmascript-modules#:~:text=Execute%20node%20with%20%2D%2Dexperimental%2Dvm%2Dmodules 111 | - | 112 | NODE_OPTIONS="$NODE_OPTIONS --experimental-vm-modules" \ 113 | npx \ 114 | jest \ 115 | --coverage 116 | 117 | # Source: https://github.com/arduino/tooling-project-assets/blob/main/workflow-templates/assets/check-toc-task/Taskfile.yml 118 | markdown:toc: 119 | desc: | 120 | Update the table of contents 121 | Environment variable parameters: 122 | FILE_PATH: Path of the file in which to update the ToC. 123 | MAX_DEPTH: The maximum heading level for which to add ToC items. 124 | deps: 125 | - task: npm:install-deps 126 | cmds: 127 | - | 128 | npx \ 129 | markdown-toc \ 130 | --bullets=- \ 131 | --maxdepth={{.MAX_DEPTH}} \ 132 | -i \ 133 | "{{.FILE_PATH}}" 134 | 135 | # Parameter variables: 136 | npm:install-deps: 137 | desc: | 138 | Install dependencies managed by npm. 139 | Environment variable parameters: 140 | PROJECT_PATH: Path of the npm-managed project (default: {{.DEFAULT_NPM_PROJECT_PATH}}). 141 | dir: | 142 | "{{default "./" .PROJECT_PATH}}" 143 | cmds: 144 | - npm install 145 | 146 | # Source: https://github.com/arduino/tooling-project-assets/blob/main/workflow-templates/assets/check-npm-task/Taskfile.yml 147 | npm:validate: 148 | desc: | 149 | Validate npm configuration files against their JSON schema. 150 | Environment variable parameters: 151 | PROJECT_PATH: Path of the npm-managed project (default: {{.DEFAULT_NPM_PROJECT_PATH}}). 152 | deps: 153 | - task: npm:install-deps 154 | vars: 155 | # Source: https://github.com/SchemaStore/schemastore/blob/master/src/schemas/json/package.json 156 | SCHEMA_URL: https://json.schemastore.org/package.json 157 | SCHEMA_PATH: 158 | sh: task utility:mktemp-file TEMPLATE="package-json-schema-XXXXXXXXXX.json" 159 | # Source: https://github.com/SchemaStore/schemastore/blob/master/src/schemas/json/ava.json 160 | AVA_SCHEMA_URL: https://json.schemastore.org/ava.json 161 | AVA_SCHEMA_PATH: 162 | sh: task utility:mktemp-file TEMPLATE="ava-schema-XXXXXXXXXX.json" 163 | # Source: https://github.com/SchemaStore/schemastore/blob/master/src/schemas/json/base.json 164 | BASE_SCHEMA_URL: https://json.schemastore.org/base.json 165 | BASE_SCHEMA_PATH: 166 | sh: task utility:mktemp-file TEMPLATE="base-schema-XXXXXXXXXX.json" 167 | # Source: https://github.com/SchemaStore/schemastore/blob/master/src/schemas/json/eslintrc.json 168 | ESLINTRC_SCHEMA_URL: https://json.schemastore.org/eslintrc.json 169 | ESLINTRC_SCHEMA_PATH: 170 | sh: task utility:mktemp-file TEMPLATE="eslintrc-schema-XXXXXXXXXX.json" 171 | # Source: https://github.com/SchemaStore/schemastore/blob/master/src/schemas/json/jscpd.json 172 | JSCPD_SCHEMA_URL: https://json.schemastore.org/jscpd.json 173 | JSCPD_SCHEMA_PATH: 174 | sh: task utility:mktemp-file TEMPLATE="jscpd-schema-XXXXXXXXXX.json" 175 | # Source: https://github.com/SchemaStore/schemastore/blob/master/src/schemas/json/npm-badges.json 176 | NPM_BADGES_SCHEMA_URL: https://json.schemastore.org/npm-badges.json 177 | NPM_BADGES_SCHEMA_PATH: 178 | sh: task utility:mktemp-file TEMPLATE="npm-badges-schema-XXXXXXXXXX.json" 179 | # Source: https://github.com/SchemaStore/schemastore/blob/master/src/schemas/json/partial-eslint-plugins.json 180 | PARTIAL_ESLINT_PLUGINS_SCHEMA_URL: https://json.schemastore.org/partial-eslint-plugins.json 181 | PARTIAL_ESLINT_PLUGINS_PATH: 182 | sh: task utility:mktemp-file TEMPLATE="partial-eslint-plugins-schema-XXXXXXXXXX.json" 183 | # Source: https://github.com/SchemaStore/schemastore/blob/master/src/schemas/json/prettierrc.json 184 | PRETTIERRC_SCHEMA_URL: https://json.schemastore.org/prettierrc.json 185 | PRETTIERRC_SCHEMA_PATH: 186 | sh: task utility:mktemp-file TEMPLATE="prettierrc-schema-XXXXXXXXXX.json" 187 | # Source: https://github.com/SchemaStore/schemastore/blob/master/src/schemas/json/semantic-release.json 188 | SEMANTIC_RELEASE_SCHEMA_URL: https://json.schemastore.org/semantic-release.json 189 | SEMANTIC_RELEASE_SCHEMA_PATH: 190 | sh: task utility:mktemp-file TEMPLATE="semantic-release-schema-XXXXXXXXXX.json" 191 | # Source: https://github.com/SchemaStore/schemastore/blob/master/src/schemas/json/stylelintrc.json 192 | STYLELINTRC_SCHEMA_URL: https://json.schemastore.org/stylelintrc.json 193 | STYLELINTRC_SCHEMA_PATH: 194 | sh: task utility:mktemp-file TEMPLATE="stylelintrc-schema-XXXXXXXXXX.json" 195 | INSTANCE_PATH: >- 196 | {{default .DEFAULT_NPM_PROJECT_PATH .PROJECT_PATH}}/package.json 197 | cmds: 198 | - wget --quiet --output-document="{{.SCHEMA_PATH}}" {{.SCHEMA_URL}} 199 | - wget --quiet --output-document="{{.AVA_SCHEMA_PATH}}" {{.AVA_SCHEMA_URL}} 200 | - wget --quiet --output-document="{{.BASE_SCHEMA_PATH}}" {{.BASE_SCHEMA_URL}} 201 | - wget --quiet --output-document="{{.ESLINTRC_SCHEMA_PATH}}" {{.ESLINTRC_SCHEMA_URL}} 202 | - wget --quiet --output-document="{{.JSCPD_SCHEMA_PATH}}" {{.JSCPD_SCHEMA_URL}} 203 | - wget --quiet --output-document="{{.NPM_BADGES_SCHEMA_PATH}}" {{.NPM_BADGES_SCHEMA_URL}} 204 | - wget --quiet --output-document="{{.PARTIAL_ESLINT_PLUGINS_PATH}}" {{.PARTIAL_ESLINT_PLUGINS_SCHEMA_URL}} 205 | - wget --quiet --output-document="{{.PRETTIERRC_SCHEMA_PATH}}" {{.PRETTIERRC_SCHEMA_URL}} 206 | - wget --quiet --output-document="{{.SEMANTIC_RELEASE_SCHEMA_PATH}}" {{.SEMANTIC_RELEASE_SCHEMA_URL}} 207 | - wget --quiet --output-document="{{.STYLELINTRC_SCHEMA_PATH}}" {{.STYLELINTRC_SCHEMA_URL}} 208 | - | 209 | npx \ 210 | --package=ajv-cli \ 211 | --package=ajv-formats \ 212 | ajv validate \ 213 | --all-errors \ 214 | --strict=false \ 215 | -s "{{.SCHEMA_PATH}}" \ 216 | -r "{{.AVA_SCHEMA_PATH}}" \ 217 | -r "{{.BASE_SCHEMA_PATH}}" \ 218 | -r "{{.ESLINTRC_SCHEMA_PATH}}" \ 219 | -r "{{.JSCPD_SCHEMA_PATH}}" \ 220 | -r "{{.NPM_BADGES_SCHEMA_PATH}}" \ 221 | -r "{{.PARTIAL_ESLINT_PLUGINS_PATH}}" \ 222 | -r "{{.PRETTIERRC_SCHEMA_PATH}}" \ 223 | -r "{{.SEMANTIC_RELEASE_SCHEMA_PATH}}" \ 224 | -r "{{.STYLELINTRC_SCHEMA_PATH}}" \ 225 | -d "{{.INSTANCE_PATH}}" 226 | 227 | poetry:install: 228 | desc: Install Poetry 229 | run: once 230 | vars: 231 | PYTHON_PATH: 232 | sh: task utility:normalize-path RAW_PATH="$(which python)" 233 | cmds: 234 | - | 235 | if ! which pipx &>/dev/null; then 236 | echo "pipx not found or not in PATH." 237 | echo "Please install: https://pipx.pypa.io/stable/installation/#installing-pipx" 238 | exit 1 239 | fi 240 | - | 241 | if ! which yq &>/dev/null; then 242 | echo "yq not found or not in PATH." 243 | echo "Please install: https://github.com/mikefarah/yq/#install" 244 | exit 1 245 | fi 246 | - | 247 | pipx install \ 248 | --python "{{.PYTHON_PATH}}" \ 249 | "poetry==$( \ 250 | yq \ 251 | --input-format toml \ 252 | --output-format yaml \ 253 | '.tool.poetry.group.pipx.dependencies.poetry' \ 254 | < pyproject.toml 255 | )" 256 | 257 | # Source: https://github.com/arduino/tooling-project-assets/blob/main/workflow-templates/assets/poetry-task/Taskfile.yml 258 | poetry:install-deps: 259 | desc: | 260 | Install dependencies managed by Poetry. 261 | Environment variable parameters: 262 | POETRY_GROUPS: Poetry dependency groups to install (default: install all dependencies). 263 | run: when_changed 264 | deps: 265 | - task: poetry:install 266 | cmds: 267 | - | 268 | poetry install \ 269 | {{if .POETRY_GROUPS}} --only {{.POETRY_GROUPS}} {{end}} 270 | 271 | poetry:sync: 272 | desc: Sync poetry.lock 273 | deps: 274 | - task: poetry:install 275 | cmds: 276 | - | 277 | poetry lock \ 278 | --no-cache \ 279 | --no-update 280 | 281 | ts:build: 282 | desc: Build the action's TypeScript code. 283 | deps: 284 | - task: npm:install-deps 285 | cmds: 286 | - npx tsc 287 | - npx ncc build 288 | 289 | ts:validate: 290 | desc: | 291 | Validate TypeScript configuration file against its JSON schema 292 | Environment variable parameters: 293 | TSCONFIG_PATH: Path of the TypeScript configuration file (default: ./tsconfig.json). 294 | vars: 295 | # Source: https://github.com/SchemaStore/schemastore/blob/master/src/schemas/json/tsconfig.json 296 | SCHEMA_URL: https://json.schemastore.org/tsconfig.json 297 | SCHEMA_PATH: 298 | sh: task utility:mktemp-file TEMPLATE="tsconfig-schema-XXXXXXXXXX.json" 299 | INSTANCE_PATH: '{{default "./tsconfig.json" .TSCONFIG_PATH}}' 300 | WORKING_FOLDER: 301 | sh: task utility:mktemp-folder TEMPLATE="ts-validate-XXXXXXXXXX" 302 | WORKING_INSTANCE_PATH: 303 | sh: echo "{{.WORKING_FOLDER}}/$(basename "{{.INSTANCE_PATH}}")" 304 | deps: 305 | - task: npm:install-deps 306 | cmds: 307 | - | 308 | # TypeScript allows comments in tsconfig.json. 309 | # ajv-cli did not support comments in JSON at the 3.x version in use (support was added in a later version). 310 | npx strip-json-comments-cli \ 311 | --no-whitespace \ 312 | "{{.INSTANCE_PATH}}" \ 313 | > "{{.WORKING_INSTANCE_PATH}}" 314 | - | 315 | wget \ 316 | --quiet \ 317 | --output-document="{{.SCHEMA_PATH}}" \ 318 | {{.SCHEMA_URL}} 319 | - | 320 | cd "{{.WORKING_FOLDER}}" # Workaround for https://github.com/npm/cli/issues/3210 321 | npx ajv-cli@{{.SCHEMA_DRAFT_4_AJV_CLI_VERSION}} validate \ 322 | --all-errors \ 323 | -s "{{.SCHEMA_PATH}}" \ 324 | -d "{{.WORKING_INSTANCE_PATH}}" 325 | 326 | # Make a temporary file named according to the passed TEMPLATE variable and print the path passed to stdout 327 | # Source: https://github.com/arduino/tooling-project-assets/blob/main/workflow-templates/assets/windows-task/Taskfile.yml 328 | utility:mktemp-file: 329 | vars: 330 | RAW_PATH: 331 | sh: mktemp --tmpdir "{{.TEMPLATE}}" 332 | cmds: 333 | - task: utility:normalize-path 334 | vars: 335 | RAW_PATH: "{{.RAW_PATH}}" 336 | 337 | # Make a temporary folder named according to the passed TEMPLATE variable and print the path passed to stdout 338 | # Source: https://github.com/arduino/tooling-project-assets/blob/main/workflow-templates/assets/windows-task/Taskfile.yml 339 | utility:mktemp-folder: 340 | vars: 341 | RAW_PATH: 342 | sh: mktemp --directory --tmpdir "{{.TEMPLATE}}" 343 | cmds: 344 | - task: utility:normalize-path 345 | vars: 346 | RAW_PATH: "{{.RAW_PATH}}" 347 | 348 | # Print a normalized version of the path passed via the RAW_PATH variable to stdout 349 | # Source: https://github.com/arduino/tooling-project-assets/blob/main/workflow-templates/assets/windows-task/Taskfile.yml 350 | utility:normalize-path: 351 | cmds: 352 | - | 353 | if [[ "{{.OS}}" == "Windows_NT" ]] && which cygpath &>/dev/null; then 354 | # Even though the shell handles POSIX format absolute paths as expected, external applications do not. 355 | # So paths passed to such applications must first be converted to Windows format. 356 | cygpath -w "{{.RAW_PATH}}" 357 | else 358 | echo "{{.RAW_PATH}}" 359 | fi 360 | -------------------------------------------------------------------------------- /__tests__/main.test.ts: -------------------------------------------------------------------------------- 1 | /* 2 | Copyright 2019 Arduino SA 3 | 4 | Licensed under the Apache License, Version 2.0 (the "License"); 5 | you may not use this file except in compliance with the License. 6 | You may obtain a copy of the License at 7 | 8 | http://www.apache.org/licenses/LICENSE-2.0 9 | 10 | Unless required by applicable law or agreed to in writing, software 11 | distributed under the License is distributed on an "AS IS" BASIS, 12 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | See the License for the specific language governing permissions and 14 | limitations under the License. 15 | */ 16 | 17 | import core = require("@actions/core"); 18 | import io = require("@actions/io"); 19 | import path = require("path"); 20 | import os = require("os"); 21 | import fs = require("fs"); 22 | import nock = require("nock"); 23 | 24 | const toolDir = path.join(__dirname, "runner", "tools"); 25 | const tempDir = path.join(__dirname, "runner", "temp"); 26 | const dataDir = path.join(__dirname, "testdata"); 27 | const IS_WINDOWS = process.platform === "win32"; 28 | 29 | process.env["RUNNER_TEMP"] = tempDir; 30 | process.env["RUNNER_TOOL_CACHE"] = toolDir; 31 | import * as installer from "../src/installer"; 32 | 33 | // Inputs for mock @actions/core 34 | let inputs = { 35 | token: process.env.GITHUB_TOKEN || "", 36 | } as any; 37 | 38 | describe("installer tests", () => { 39 | beforeEach(async function () { 40 | // Mock getInput 41 | jest.spyOn(core, "getInput").mockImplementation((name: string) => { 42 | return inputs[name]; 43 | }); 44 | 45 | await io.rmRF(toolDir); 46 | await io.rmRF(tempDir); 47 | await io.mkdirP(toolDir); 48 | await io.mkdirP(tempDir); 49 | }); 50 | 51 | afterAll(async () => { 52 | try { 53 | await io.rmRF(toolDir); 54 | await io.rmRF(tempDir); 55 | } catch { 56 | console.log("Failed to remove test directories"); 57 | } 58 | jest.restoreAllMocks(); 59 | }); 60 | 61 | it("Downloads version of arduino-lint if no matching version is installed", async () => { 62 | const toolPath = await installer.getArduinoLint("1.0.0"); 63 | const bindir = path.join(toolDir, "arduino-lint", "1.0.0", os.arch()); 64 | 65 | expect(toolPath == path.join(bindir, "arduino-lint")).toBe(true); 66 | expect(fs.existsSync(`${bindir}.complete`)).toBe(true); 67 | 68 | if (IS_WINDOWS) { 69 | expect(fs.existsSync(path.join(bindir, "arduino-lint.exe"))).toBe(true); 70 | } else { 71 | expect(fs.existsSync(path.join(bindir, "arduino-lint"))).toBe(true); 72 | } 73 | }, 20000); 74 | 75 | describe("Gets the latest release of arduino-lint", () => { 76 | beforeEach(() => { 77 | jest.spyOn(core, "getInput").mockImplementation((name: string) => { 78 | return inputs[name]; 79 | }); 80 | 81 | nock("https://api.github.com") 82 | .get("/repos/arduino/arduino-lint/git/refs/tags") 83 | .replyWithFile(200, path.join(dataDir, "tags.json")); 84 | }); 85 | 86 | afterEach(() => { 87 | nock.cleanAll(); 88 | nock.enableNetConnect(); 89 | jest.clearAllMocks(); 90 | }); 91 | 92 | it("Gets the latest version of arduino-lint 1.0.0 using 1.0 and no matching version is installed", async () => { 93 | await installer.getArduinoLint("1.0"); 94 | const bindir = path.join(toolDir, "arduino-lint", "1.0.0", os.arch()); 95 | 96 | expect(fs.existsSync(`${bindir}.complete`)).toBe(true); 97 | if (IS_WINDOWS) { 98 | expect(fs.existsSync(path.join(bindir, "arduino-lint.exe"))).toBe(true); 99 | } else { 100 | expect(fs.existsSync(path.join(bindir, "arduino-lint"))).toBe(true); 101 | } 102 | }, 20000); 103 | 104 | it("Gets latest version of the 1 major series using 1.x and no matching version is installed", async () => { 105 | await installer.getArduinoLint("1.x"); 106 | const bindir = path.join(toolDir, "arduino-lint", "1.0.0", os.arch()); 107 | 108 | expect(fs.existsSync(`${bindir}.complete`)).toBe(true); 109 | if (IS_WINDOWS) { 110 | expect(fs.existsSync(path.join(bindir, "arduino-lint.exe"))).toBe(true); 111 | } else { 112 | expect(fs.existsSync(path.join(bindir, "arduino-lint"))).toBe(true); 113 | } 114 | }, 20000); 115 | }); 116 | }); 117 | -------------------------------------------------------------------------------- /__tests__/testdata/tags.json: -------------------------------------------------------------------------------- 1 | [ 2 | { 3 | "ref": "refs/tags/1.0.0", 4 | "node_id": "MDM6UmVmMjk1NTczODg1OnJlZnMvdGFncy8xLjAuMA==", 5 | "url": "https://api.github.com/repos/arduino/arduino-lint/git/refs/tags/1.0.0", 6 | "object": { 7 | "sha": "e6edeaedb6578a8a2db54725584ba07eb9ce28a4", 8 | "type": "tag", 9 | "url": "https://api.github.com/repos/arduino/arduino-lint/git/tags/e6edeaedb6578a8a2db54725584ba07eb9ce28a4" 10 | } 11 | } 12 | ] 13 | -------------------------------------------------------------------------------- /action.yml: -------------------------------------------------------------------------------- 1 | name: "arduino/arduino-lint-action" 2 | description: "Check Arduino projects for problems." 3 | author: "Arduino" 4 | inputs: 5 | path: 6 | description: "Path containing Arduino projects." 7 | required: false 8 | version: 9 | description: "Version of the Arduino Lint tool to use." 10 | required: false 11 | default: "1.x" 12 | compliance: 13 | description: "How strict the checks are." 14 | required: false 15 | default: "specification" 16 | library-manager: 17 | description: "Configuration of the checks for libraries in the Arduino Library Manager index." 18 | required: false 19 | project-type: 20 | description: "The type of project to check." 21 | required: false 22 | default: "all" 23 | recursive: 24 | description: "Search path recursively for projects to check." 25 | required: false 26 | default: "false" 27 | report-file: 28 | description: "Save a JSON formatted report on the checks to this file." 29 | required: false 30 | verbose: 31 | description: "Show more information on the checks being run." 32 | required: false 33 | default: "false" 34 | official: 35 | description: "Run the checks that only apply to official (non 3rd party) Arduino projects." 36 | required: false 37 | default: "false" 38 | token: 39 | description: "GitHub access token used to get information from the GitHub API." 40 | required: false 41 | default: ${{ github.token }} 42 | runs: 43 | using: "node20" 44 | main: "dist/index.js" 45 | branding: 46 | icon: "check-square" 47 | color: "green" 48 | -------------------------------------------------------------------------------- /dist/unzip: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/arduino/arduino-lint-action/ccb6809d6c6e3221e5d2e05f8341a49bdc5b1c4a/dist/unzip -------------------------------------------------------------------------------- /dist/unzip-darwin: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/arduino/arduino-lint-action/ccb6809d6c6e3221e5d2e05f8341a49bdc5b1c4a/dist/unzip-darwin -------------------------------------------------------------------------------- /jest.config.js: -------------------------------------------------------------------------------- 1 | module.exports = { 2 | clearMocks: true, 3 | moduleFileExtensions: ["js", "ts"], 4 | testEnvironment: "node", 5 | testMatch: ["**/*.test.ts"], 6 | testRunner: "jest-circus/runner", 7 | transform: { 8 | "^.+\\.ts$": "ts-jest", 9 | }, 10 | verbose: true, 11 | }; 12 | -------------------------------------------------------------------------------- /package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "arduino-lint-action", 3 | "private": true, 4 | "description": "Check Arduino projects for problems", 5 | "main": "lib/main.js", 6 | "repository": { 7 | "type": "git", 8 | "url": "git+https://github.com/arduino/arduino-lint-action.git" 9 | }, 10 | "keywords": [ 11 | "actions", 12 | "arduino", 13 | "lint" 14 | ], 15 | "author": "Arduino", 16 | "license": "MIT", 17 | "dependencies": { 18 | "@actions/core": "^1.11.1", 19 | "@actions/http-client": "^2.2.3", 20 | "@actions/tool-cache": "^2.0.2", 21 | "semver": "^7.7.2" 22 | }, 23 | "devDependencies": { 24 | "@actions/io": "^1.1.3", 25 | "@types/jest": "^29.5.14", 26 | "@types/node": "^20.17.58", 27 | "@types/semver": "^7.7.0", 28 | "@vercel/ncc": "^0.38.3", 29 | "ajv-cli": "^5.0.0", 30 | "ajv-formats": "^3.0.1", 31 | "github-label-sync": "3.0.0", 32 | "jest": "^29.7.0", 33 | "jest-circus": "^29.7.0", 34 | "markdown-toc": "^1.2.0", 35 | "nock": "^13.5.6", 36 | "prettier": "^3.5.3", 37 | "ts-jest": "^29.3.4", 38 | "typescript": "^5.8.3" 39 | }, 40 | "engines": { 41 | "node": "20.x" 42 | } 43 | } 44 | -------------------------------------------------------------------------------- /pyproject.toml: -------------------------------------------------------------------------------- 1 | # See: https://python-poetry.org/docs/pyproject/ 2 | [tool.poetry] 3 | package-mode = false 4 | 5 | [tool.poetry.dependencies] 6 | python = "^3.12" 7 | 8 | [tool.poetry.group.dev.dependencies] 9 | codespell = "2.3.0" 10 | 11 | # The dependencies in this group are installed using pipx; NOT Poetry. The use of a `poetry` section is a hack required 12 | # in order to be able to manage updates of these dependencies via Dependabot, as used for all other dependencies. 13 | [tool.poetry.group.pipx] 14 | optional = true 15 | 16 | [tool.poetry.group.pipx.dependencies] 17 | poetry = "1.8.3" 18 | 19 | [build-system] 20 | requires = ["poetry-core"] 21 | build-backend = "poetry.core.masonry.api" 22 | -------------------------------------------------------------------------------- /src/installer.ts: -------------------------------------------------------------------------------- 1 | /* 2 | Copyright 2019 Arduino SA 3 | 4 | Licensed under the Apache License, Version 2.0 (the "License"); 5 | you may not use this file except in compliance with the License. 6 | You may obtain a copy of the License at 7 | 8 | http://www.apache.org/licenses/LICENSE-2.0 9 | 10 | Unless required by applicable law or agreed to in writing, software 11 | distributed under the License is distributed on an "AS IS" BASIS, 12 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | See the License for the specific language governing permissions and 14 | limitations under the License. 15 | */ 16 | 17 | // Load tempDirectory before it gets wiped by tool-cache 18 | let tempDirectory = process.env["RUNNER_TEMP"] || ""; 19 | 20 | import * as os from "os"; 21 | import * as path from "path"; 22 | import * as util from "util"; 23 | import * as httpm from "@actions/http-client"; 24 | import * as auth from "@actions/http-client/lib/auth"; 25 | import * as semver from "semver"; 26 | 27 | if (!tempDirectory) { 28 | let baseLocation; 29 | if (process.platform === "win32") { 30 | // On windows use the USERPROFILE env variable 31 | baseLocation = process.env["USERPROFILE"] || "C:\\"; 32 | } else { 33 | if (process.platform === "darwin") { 34 | baseLocation = "/Users"; 35 | } else { 36 | baseLocation = "/home"; 37 | } 38 | } 39 | tempDirectory = path.join(baseLocation, "actions", "temp"); 40 | } 41 | 42 | import * as core from "@actions/core"; 43 | import * as tc from "@actions/tool-cache"; 44 | 45 | let osPlat: string = os.platform(); 46 | let osArch: string = os.arch(); 47 | 48 | interface ITaskRef { 49 | ref: string; 50 | } 51 | 52 | export async function getArduinoLint(version: string): Promise { 53 | // resolve the version number 54 | const targetVersion = await computeVersion(version); 55 | if (targetVersion) { 56 | version = targetVersion; 57 | } 58 | 59 | // look if the binary is cached 60 | let toolPath: string; 61 | toolPath = tc.find("arduino-lint", version); 62 | 63 | // if not: download, extract and cache 64 | if (!toolPath) { 65 | toolPath = await downloadRelease(version); 66 | core.debug("arduino-lint cached under " + toolPath); 67 | } 68 | 69 | return path.join(toolPath, "arduino-lint"); 70 | } 71 | 72 | async function downloadRelease(version: string): Promise { 73 | // Download 74 | let fileName: string = getFileName(version); 75 | let downloadUrl: string = util.format( 76 | "https://github.com/arduino/arduino-lint/releases/download/%s/%s", 77 | version, 78 | fileName, 79 | ); 80 | core.debug("Downloading " + downloadUrl); 81 | let downloadPath: string | null = null; 82 | try { 83 | const token: string = core.getInput("token", { required: true }); 84 | downloadPath = await tc.downloadTool(downloadUrl, undefined, token); 85 | } catch (error) { 86 | if (typeof error === "string" || error instanceof Error) { 87 | core.debug(error.toString()); 88 | } 89 | throw `Failed to download version ${version}: ${error}`; 90 | } 91 | 92 | // Extract 93 | let extPath: string | null = null; 94 | if (osPlat == "win32") { 95 | extPath = await tc.extractZip(downloadPath); 96 | } else { 97 | extPath = await tc.extractTar(downloadPath); 98 | } 99 | 100 | // Install into the local tool cache - node extracts with a root folder that matches the fileName downloaded 101 | return await tc.cacheDir(extPath, "arduino-lint", version); 102 | } 103 | 104 | function getFileName(version: string): string { 105 | let arch = ""; 106 | let platform = ""; 107 | let ext = ""; 108 | switch (osPlat) { 109 | case "win32": 110 | platform = "Windows"; 111 | ext = "zip"; 112 | break; 113 | case "linux": 114 | platform = "Linux"; 115 | ext = "tar.gz"; 116 | break; 117 | case "darwin": 118 | platform = "macOS"; 119 | ext = "tar.gz"; 120 | break; 121 | } 122 | 123 | switch (osArch) { 124 | case "x32": 125 | arch = "32bit"; 126 | break; 127 | case "x64": 128 | arch = "64bit"; 129 | break; 130 | case "arm": 131 | arch = "ARMv7"; 132 | break; 133 | case "arm64": 134 | arch = "ARM64"; 135 | break; 136 | } 137 | 138 | return util.format("arduino-lint_%s_%s_%s.%s", version, platform, arch, ext); 139 | } 140 | 141 | // Retrieve a list of versions scraping tags from the Github API 142 | async function fetchVersions(): Promise { 143 | const token: string = core.getInput("token", { required: true }); 144 | const authHandler = new auth.PersonalAccessTokenCredentialHandler(token); 145 | let rest: httpm.HttpClient = new httpm.HttpClient("arduino-lint-action", [ 146 | authHandler, 147 | ]); 148 | let tags: ITaskRef[] = 149 | ( 150 | await rest.getJson( 151 | "https://api.github.com/repos/arduino/arduino-lint/git/refs/tags", 152 | ) 153 | ).result || []; 154 | 155 | return tags 156 | .filter((tag) => tag.ref.match(/\d+\.[\w\.]+/g)) 157 | .map((tag) => tag.ref.replace("refs/tags/", "")); 158 | } 159 | 160 | // Compute an actual version starting from the `version` configuration param. 161 | async function computeVersion(version: string): Promise { 162 | // strip trailing .x chars 163 | if (version.endsWith(".x")) { 164 | version = version.slice(0, version.length - 2); 165 | } 166 | 167 | const allVersions = await fetchVersions(); 168 | const possibleVersions = allVersions.filter((v) => v.startsWith(version)); 169 | 170 | const versionMap = new Map(); 171 | possibleVersions.forEach((v) => versionMap.set(normalizeVersion(v), v)); 172 | 173 | const versions = Array.from(versionMap.keys()) 174 | .sort(semver.rcompare) 175 | .map((v) => versionMap.get(v)); 176 | 177 | core.debug(`evaluating ${versions.length} versions`); 178 | 179 | if (versions.length === 0) { 180 | throw new Error("unable to get latest version"); 181 | } 182 | 183 | core.debug(`matched: ${versions[0]}`); 184 | 185 | return versions[0]; 186 | } 187 | 188 | // Make partial versions semver compliant. 189 | function normalizeVersion(version: string): string { 190 | const preStrings = ["beta", "rc", "preview"]; 191 | 192 | const versionPart = version.split("."); 193 | if (versionPart[1] == null) { 194 | //append minor and patch version if not available 195 | // e.g. 2 -> 2.0.0 196 | return version.concat(".0.0"); 197 | } else { 198 | // handle beta and rc 199 | // e.g. 1.10beta1 -? 1.10.0-beta1, 1.10rc1 -> 1.10.0-rc1 200 | if (preStrings.some((el) => versionPart[1].includes(el))) { 201 | versionPart[1] = versionPart[1] 202 | .replace("beta", ".0-beta") 203 | .replace("rc", ".0-rc") 204 | .replace("preview", ".0-preview"); 205 | return versionPart.join("."); 206 | } 207 | } 208 | 209 | if (versionPart[2] == null) { 210 | //append patch version if not available 211 | // e.g. 2.1 -> 2.1.0 212 | return version.concat(".0"); 213 | } else { 214 | // handle beta and rc 215 | // e.g. 1.8.5beta1 -> 1.8.5-beta1, 1.8.5rc1 -> 1.8.5-rc1 216 | if (preStrings.some((el) => versionPart[2].includes(el))) { 217 | versionPart[2] = versionPart[2] 218 | .replace("beta", "-beta") 219 | .replace("rc", "-rc") 220 | .replace("preview", "-preview"); 221 | return versionPart.join("."); 222 | } 223 | } 224 | 225 | return version; 226 | } 227 | -------------------------------------------------------------------------------- /src/main.ts: -------------------------------------------------------------------------------- 1 | /* 2 | Copyright 2019 Arduino SA 3 | 4 | Licensed under the Apache License, Version 2.0 (the "License"); 5 | you may not use this file except in compliance with the License. 6 | You may obtain a copy of the License at 7 | 8 | http://www.apache.org/licenses/LICENSE-2.0 9 | 10 | Unless required by applicable law or agreed to in writing, software 11 | distributed under the License is distributed on an "AS IS" BASIS, 12 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | See the License for the specific language governing permissions and 14 | limitations under the License. 15 | */ 16 | 17 | import * as core from "@actions/core"; 18 | import * as exec from "@actions/exec"; 19 | import * as installer from "./installer"; 20 | 21 | async function run() { 22 | try { 23 | const path = core.getInput("path"); 24 | const version = core.getInput("version"); 25 | const compliance = core.getInput("compliance"); 26 | const libraryManager = core.getInput("library-manager"); 27 | const projectType = core.getInput("project-type"); 28 | const recursive = core.getInput("recursive"); 29 | const reportFile = core.getInput("report-file"); 30 | const verbose = core.getInput("verbose"); 31 | const official = core.getInput("official"); 32 | 33 | let toolPath = "arduino-lint"; 34 | if (version) { 35 | toolPath = await installer.getArduinoLint(version); 36 | } 37 | 38 | await exec.exec(toolPath, ["--version"]); // Display the version of arduino-lint in use. 39 | 40 | const execArgs = [ 41 | "--compliance", 42 | compliance, 43 | "--project-type", 44 | projectType, 45 | ]; 46 | 47 | // Add arguments that don't have default input values only if they are defined. 48 | if (libraryManager) { 49 | execArgs.push("--library-manager", libraryManager); 50 | } 51 | 52 | if (reportFile) { 53 | execArgs.push("--report-file", reportFile); 54 | } 55 | 56 | // Add Boolean flags only if true. 57 | if (recursive == "true") { 58 | execArgs.push("--recursive"); 59 | } 60 | 61 | if (verbose == "true") { 62 | execArgs.push("--verbose"); 63 | } 64 | 65 | if (path) { 66 | execArgs.push(path); 67 | } 68 | 69 | const options = { 70 | env: { 71 | ARDUINO_LINT_OFFICIAL: official, // The official mode is set via an environment variable. 72 | }, 73 | }; 74 | 75 | await exec.exec(toolPath, execArgs, options); 76 | } catch (error) { 77 | if (error instanceof Error) { 78 | core.setFailed(error.message); 79 | } else { 80 | throw error; 81 | } 82 | } 83 | } 84 | 85 | run(); 86 | -------------------------------------------------------------------------------- /tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "compilerOptions": { 3 | /* Basic Options */ 4 | // "incremental": true, /* Enable incremental compilation */ 5 | "target": "es6" /* Specify ECMAScript target version: 'ES3' (default), 'ES5', 'ES2015', 'ES2016', 'ES2017', 'ES2018', 'ES2019' or 'ESNEXT'. */, 6 | "module": "commonjs" /* Specify module code generation: 'none', 'commonjs', 'amd', 'system', 'umd', 'es2015', or 'ESNext'. */, 7 | // "allowJs": true, /* Allow javascript files to be compiled. */ 8 | // "checkJs": true, /* Report errors in .js files. */ 9 | // "jsx": "preserve", /* Specify JSX code generation: 'preserve', 'react-native', or 'react'. */ 10 | // "declaration": true, /* Generates corresponding '.d.ts' file. */ 11 | // "declarationMap": true, /* Generates a sourcemap for each corresponding '.d.ts' file. */ 12 | // "sourceMap": true, /* Generates corresponding '.map' file. */ 13 | // "outFile": "./", /* Concatenate and emit output to single file. */ 14 | "outDir": "./lib" /* Redirect output structure to the directory. */, 15 | "rootDir": "./src" /* Specify the root directory of input files. Use to control the output directory structure with --outDir. */, 16 | // "composite": true, /* Enable project compilation */ 17 | // "tsBuildInfoFile": "./", /* Specify file to store incremental compilation information */ 18 | // "removeComments": true, /* Do not emit comments to output. */ 19 | // "noEmit": true, /* Do not emit outputs. */ 20 | // "importHelpers": true, /* Import emit helpers from 'tslib'. */ 21 | // "downlevelIteration": true, /* Provide full support for iterables in 'for-of', spread, and destructuring when targeting 'ES5' or 'ES3'. */ 22 | // "isolatedModules": true, /* Transpile each file as a separate module (similar to 'ts.transpileModule'). */ 23 | /* Strict Type-Checking Options */ 24 | "strict": true /* Enable all strict type-checking options. */, 25 | "noImplicitAny": false /* Raise error on expressions and declarations with an implied 'any' type. */, 26 | // "strictNullChecks": true, /* Enable strict null checks. */ 27 | // "strictFunctionTypes": true, /* Enable strict checking of function types. */ 28 | // "strictBindCallApply": true, /* Enable strict 'bind', 'call', and 'apply' methods on functions. */ 29 | // "strictPropertyInitialization": true, /* Enable strict checking of property initialization in classes. */ 30 | // "noImplicitThis": true, /* Raise error on 'this' expressions with an implied 'any' type. */ 31 | // "alwaysStrict": true, /* Parse in strict mode and emit "use strict" for each source file. */ 32 | /* Additional Checks */ 33 | // "noUnusedLocals": true, /* Report errors on unused locals. */ 34 | // "noUnusedParameters": true, /* Report errors on unused parameters. */ 35 | // "noImplicitReturns": true, /* Report error when not all code paths in function return a value. */ 36 | // "noFallthroughCasesInSwitch": true, /* Report errors for fallthrough cases in switch statement. */ 37 | /* Module Resolution Options */ 38 | // "moduleResolution": "node", /* Specify module resolution strategy: 'node' (Node.js) or 'classic' (TypeScript pre-1.6). */ 39 | // "baseUrl": "./", /* Base directory to resolve non-absolute module names. */ 40 | // "paths": {}, /* A series of entries which re-map imports to lookup locations relative to the 'baseUrl'. */ 41 | // "rootDirs": [], /* List of root folders whose combined content represents the structure of the project at runtime. */ 42 | // "typeRoots": [], /* List of folders to include type definitions from. */ 43 | // "types": [], /* Type declaration files to be included in compilation. */ 44 | // "allowSyntheticDefaultImports": true, /* Allow default imports from modules with no default export. This does not affect code emit, just typechecking. */ 45 | "esModuleInterop": true /* Enables emit interoperability between CommonJS and ES Modules via creation of namespace objects for all imports. Implies 'allowSyntheticDefaultImports'. */ 46 | // "preserveSymlinks": true, /* Do not resolve the real path of symlinks. */ 47 | // "allowUmdGlobalAccess": true, /* Allow accessing UMD globals from modules. */ 48 | /* Source Map Options */ 49 | // "sourceRoot": "", /* Specify the location where debugger should locate TypeScript files instead of source locations. */ 50 | // "mapRoot": "", /* Specify the location where debugger should locate map files instead of generated locations. */ 51 | // "inlineSourceMap": true, /* Emit a single file with source maps instead of having a separate file. */ 52 | // "inlineSources": true, /* Emit the source alongside the sourcemaps within a single file; requires '--inlineSourceMap' or '--sourceMap' to be set. */ 53 | /* Experimental Options */ 54 | // "experimentalDecorators": true, /* Enables experimental support for ES7 decorators. */ 55 | // "emitDecoratorMetadata": true, /* Enables experimental support for emitting type metadata for decorators. */ 56 | }, 57 | "exclude": ["node_modules", "**/*.test.ts"] 58 | } 59 | --------------------------------------------------------------------------------