From 258121befd57401557060fccd128f04fc3e51a61 Mon Sep 17 00:00:00 2001 From: per1234 Date: Sun, 29 Aug 2021 21:57:04 -0700 Subject: [PATCH 01/48] Fix typos in Godoc comments Some insignificant improvements to the comments resulting from a comprehensive review. --- debug.go | 2 +- properties.go | 26 +++++++++++++------------- 2 files changed, 14 insertions(+), 14 deletions(-) diff --git a/debug.go b/debug.go index 10ae626..af2e61d 100644 --- a/debug.go +++ b/debug.go @@ -34,7 +34,7 @@ import ( "strings" ) -// DebugExpandPropsInString output the substitutions made by +// DebugExpandPropsInString outputs the substitutions made by // ExpandPropsInString for debugging purposes. func (m *Map) DebugExpandPropsInString(str string) string { return m.expandProps(str, true) diff --git a/properties.go b/properties.go index 4527c88..933fc1e 100644 --- a/properties.go +++ b/properties.go @@ -54,12 +54,12 @@ syntax, for example: diecimila.build.variant=standard ... -This library has methods to parse this kind of files into a Map object. +This library has methods to parse this kind of file into a Map object. The Map internally keeps the insertion order so it can be retrieved later when cycling through the key sets. -The Map object has many helper methods to accomplish some common operation +The Map object has many helper methods to accomplish some common operations on this kind of data like cloning, merging, comparing and also extracting a submap or generating a map-of-submaps from the first "level" of the hierarchy. @@ -106,7 +106,7 @@ func GetOSSuffix() string { return osSuffix } -// SetOSSuffix force the OS suffix to the given value +// SetOSSuffix forces the OS suffix to the given value func SetOSSuffix(suffix string) { osSuffix = suffix } @@ -201,13 +201,13 @@ func (m *Map) parseLine(line string) error { } // SafeLoadFromPath is like LoadFromPath, except that it returns an empty Map if -// the specified file doesn't exists +// the specified file doesn't exist func SafeLoadFromPath(path *paths.Path) (*Map, error) { return SafeLoad(path.String()) } // SafeLoad is like Load, except that it returns an empty Map if the specified -// file doesn't exists +// file doesn't exist func SafeLoad(filepath string) (*Map, error) { _, err := os.Stat(filepath) if os.IsNotExist(err) { @@ -221,12 +221,12 @@ func SafeLoad(filepath string) (*Map, error) { return properties, nil } -// Get retrieve the value corresponding to key +// Get retrieves the value corresponding to key func (m *Map) Get(key string) string { return m.kv[key] } -// GetOk retrieve the value corresponding to key and return a true/false indicator +// GetOk retrieves the value corresponding to key and returns a true/false indicator // to check if the key is present in the map (true if the key is present) func (m *Map) GetOk(key string) (string, bool) { v, ok := m.kv[key] @@ -258,7 +258,7 @@ func (m *Map) Set(key, value string) { m.o = append(m.o, key) } -// Size return the number of elements in the map +// Size returns the number of elements in the map func (m *Map) Size() int { return len(m.kv) } @@ -299,7 +299,7 @@ func (m *Map) Remove(key string) { // "upload.maximum_size": "32256", // }, // "diecimila" : properties.Map{ -// "name=Arduino Duemilanove or Diecimila +// "name": "Arduino Duemilanove or Diecimila", // "upload.tool": "avrdude", // "upload.protocol": "arduino", // "bootloader.tool": "avrdude", @@ -375,7 +375,7 @@ func (m *Map) FirstLevelKeys() []string { // "diecimila.bootloader.low_fuses": "0xFF", // } // -// after calling SubTree("uno") will be transformed in: +// after calling SubTree("uno") will be transformed into: // // properties.Map{ // "name": "Arduino/Genuino Uno", @@ -396,13 +396,13 @@ func (m *Map) SubTree(rootKey string) *Map { return newMap } -// ExpandPropsInString use the Map to replace values into a format string. +// ExpandPropsInString uses the Map to replace values into a format string. // The format string should contains markers between braces, for example: // // "The selected upload protocol is {upload.protocol}." // // Each marker is replaced by the corresponding value of the Map. -// The values in the Map may contains other markers, they are evaluated +// The values in the Map may contain other markers, they are evaluated // recursively up to 10 times. func (m *Map) ExpandPropsInString(str string) string { return m.expandProps(str, false) @@ -495,7 +495,7 @@ func (m *Map) EqualsWithOrder(other *Map) bool { return reflect.DeepEqual(m.o, other.o) && reflect.DeepEqual(m.kv, other.kv) } -// MergeMapsOfProperties merge the map-of-Maps (obtained from the method FirstLevelOf()) into the +// MergeMapsOfProperties merges the map-of-Maps (obtained from the method FirstLevelOf()) into the // target map-of-Maps. func MergeMapsOfProperties(target map[string]*Map, sources ...map[string]*Map) map[string]*Map { for _, source := range sources { From 81f92cadf9da81372f5bcbf660eb692a258309c3 Mon Sep 17 00:00:00 2001 From: Cristian Maglie Date: Mon, 4 Oct 2021 10:12:16 +0200 Subject: [PATCH 02/48] Update to readme --- README.md | 3 +++ 1 file changed, 3 insertions(+) diff --git a/README.md b/README.md index a51bc83..fccc3ad 100644 --- a/README.md +++ b/README.md @@ -1,4 +1,7 @@ +**DEPRECATED: This library has been phased out in favor of: https://github.com/arduino/go-properties-orderedmap** +Please use the library above for new projects. + [![GoDoc](https://godoc.org/github.com/arduino/go-properties-orderedmap?status.svg)](https://godoc.org/github.com/arduino/go-properties-orderedmap) Package `properties` is a library for handling maps of hierarchical properties. From 19943ff22bb6375afc63045ccb93e9669e20e3ef Mon Sep 17 00:00:00 2001 From: Cristian Maglie Date: Mon, 4 Oct 2021 10:13:04 +0200 Subject: [PATCH 03/48] updated readme --- README.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/README.md b/README.md index fccc3ad..ac8b0bf 100644 --- a/README.md +++ b/README.md @@ -1,10 +1,10 @@ +# **DEPRECATED: This library has been phased out in favor of: https://github.com/arduino/go-properties-orderedmap** -**DEPRECATED: This library has been phased out in favor of: https://github.com/arduino/go-properties-orderedmap** Please use the library above for new projects. [![GoDoc](https://godoc.org/github.com/arduino/go-properties-orderedmap?status.svg)](https://godoc.org/github.com/arduino/go-properties-orderedmap) -Package `properties` is a library for handling maps of hierarchical properties. +Package `properties` is a library for handling maps of hierarchical properties. This library is mainly used in the Arduino platform software to handle configurations made of key/value pairs stored in files with an INI like From c6b97058605839fd2101182f000a9f9412a1ab85 Mon Sep 17 00:00:00 2001 From: Cristian Maglie Date: Mon, 4 Oct 2021 10:16:04 +0200 Subject: [PATCH 04/48] Revert "updated readme" This reverts commit 19943ff22bb6375afc63045ccb93e9669e20e3ef. --- README.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/README.md b/README.md index ac8b0bf..fccc3ad 100644 --- a/README.md +++ b/README.md @@ -1,10 +1,10 @@ -# **DEPRECATED: This library has been phased out in favor of: https://github.com/arduino/go-properties-orderedmap** +**DEPRECATED: This library has been phased out in favor of: https://github.com/arduino/go-properties-orderedmap** Please use the library above for new projects. [![GoDoc](https://godoc.org/github.com/arduino/go-properties-orderedmap?status.svg)](https://godoc.org/github.com/arduino/go-properties-orderedmap) -Package `properties` is a library for handling maps of hierarchical properties. +Package `properties` is a library for handling maps of hierarchical properties. This library is mainly used in the Arduino platform software to handle configurations made of key/value pairs stored in files with an INI like From 1b3dc14f0e827fcbaec2cc666703761781b5614d Mon Sep 17 00:00:00 2001 From: Cristian Maglie Date: Mon, 4 Oct 2021 10:16:10 +0200 Subject: [PATCH 05/48] Revert "Update to readme" This reverts commit 81f92cadf9da81372f5bcbf660eb692a258309c3. --- README.md | 3 --- 1 file changed, 3 deletions(-) diff --git a/README.md b/README.md index fccc3ad..a51bc83 100644 --- a/README.md +++ b/README.md @@ -1,7 +1,4 @@ -**DEPRECATED: This library has been phased out in favor of: https://github.com/arduino/go-properties-orderedmap** -Please use the library above for new projects. - [![GoDoc](https://godoc.org/github.com/arduino/go-properties-orderedmap?status.svg)](https://godoc.org/github.com/arduino/go-properties-orderedmap) Package `properties` is a library for handling maps of hierarchical properties. From bd8a6698f33e6b27fe9ab8c83a976bfa2560fba1 Mon Sep 17 00:00:00 2001 From: per1234 Date: Mon, 27 Sep 2021 03:28:04 -0700 Subject: [PATCH 06/48] Add CI workflow to synchronize with shared repository labels On every push that changes relevant files, and periodically, configure the repository's issue and pull request labels according to the universal, shared, and local label configuration files. --- .github/workflows/sync-labels.yml | 139 ++++++++++++++++++++++++++++++ 1 file changed, 139 insertions(+) create mode 100644 .github/workflows/sync-labels.yml diff --git a/.github/workflows/sync-labels.yml b/.github/workflows/sync-labels.yml new file mode 100644 index 0000000..f4c245e --- /dev/null +++ b/.github/workflows/sync-labels.yml @@ -0,0 +1,139 @@ +# Source: https://github.com/arduino/tooling-project-assets/blob/main/workflow-templates/sync-labels.md +name: Sync Labels + +# See: https://docs.github.com/en/actions/reference/events-that-trigger-workflows +on: + push: + paths: + - ".github/workflows/sync-labels.ya?ml" + - ".github/label-configuration-files/*.ya?ml" + pull_request: + paths: + - ".github/workflows/sync-labels.ya?ml" + - ".github/label-configuration-files/*.ya?ml" + schedule: + # Run daily at 8 AM UTC to sync with changes to shared label configurations. + - cron: "0 8 * * *" + workflow_dispatch: + repository_dispatch: + +env: + CONFIGURATIONS_FOLDER: .github/label-configuration-files + CONFIGURATIONS_ARTIFACT: label-configuration-files + +jobs: + check: + runs-on: ubuntu-latest + + steps: + - name: Checkout repository + uses: actions/checkout@v2 + + - name: Download JSON schema for labels configuration file + id: download-schema + uses: carlosperate/download-file-action@v1.0.3 + with: + file-url: https://raw.githubusercontent.com/arduino/tooling-project-assets/main/workflow-templates/assets/sync-labels/arduino-tooling-gh-label-configuration-schema.json + location: ${{ runner.temp }}/label-configuration-schema + + - name: Install JSON schema validator + run: | + sudo npm install \ + --global \ + ajv-cli \ + ajv-formats + + - name: Validate local labels configuration + run: | + # See: https://github.com/ajv-validator/ajv-cli#readme + ajv validate \ + --all-errors \ + -c ajv-formats \ + -s "${{ steps.download-schema.outputs.file-path }}" \ + -d "${{ env.CONFIGURATIONS_FOLDER }}/*.{yml,yaml}" + + download: + needs: check + runs-on: ubuntu-latest + + strategy: + matrix: + filename: + # Filenames of the shared configurations to apply to the repository in addition to the local configuration. + # https://github.com/arduino/tooling-project-assets/blob/main/workflow-templates/assets/sync-labels + - universal.yml + - tooling.yml + + steps: + - name: Download + uses: carlosperate/download-file-action@v1.0.3 + with: + file-url: https://raw.githubusercontent.com/arduino/tooling-project-assets/main/workflow-templates/assets/sync-labels/${{ matrix.filename }} + + - name: Pass configuration files to next job via workflow artifact + uses: actions/upload-artifact@v2 + with: + path: | + *.yaml + *.yml + if-no-files-found: error + name: ${{ env.CONFIGURATIONS_ARTIFACT }} + + sync: + needs: download + runs-on: ubuntu-latest + + steps: + - name: Set environment variables + run: | + # See: https://docs.github.com/en/actions/reference/workflow-commands-for-github-actions#setting-an-environment-variable + echo "MERGED_CONFIGURATION_PATH=${{ runner.temp }}/labels.yml" >> "$GITHUB_ENV" + + - name: Determine whether to dry run + id: dry-run + if: > + github.event_name == 'pull_request' || + ( + ( + github.event_name == 'push' || + github.event_name == 'workflow_dispatch' + ) && + github.ref != format('refs/heads/{0}', github.event.repository.default_branch) + ) + run: | + # Use of this flag in the github-label-sync command will cause it to only check the validity of the + # configuration. + echo "::set-output name=flag::--dry-run" + + - name: Checkout repository + uses: actions/checkout@v2 + + - name: Download configuration files artifact + uses: actions/download-artifact@v2 + with: + name: ${{ env.CONFIGURATIONS_ARTIFACT }} + path: ${{ env.CONFIGURATIONS_FOLDER }} + + - name: Remove unneeded artifact + uses: geekyeggo/delete-artifact@v1 + with: + name: ${{ env.CONFIGURATIONS_ARTIFACT }} + + - name: Merge label configuration files + run: | + # Merge all configuration files + shopt -s extglob + cat "${{ env.CONFIGURATIONS_FOLDER }}"/*.@(yml|yaml) > "${{ env.MERGED_CONFIGURATION_PATH }}" + + - name: Install github-label-sync + run: sudo npm install --global github-label-sync + + - name: Sync labels + env: + GITHUB_ACCESS_TOKEN: ${{ secrets.GITHUB_TOKEN }} + run: | + # See: https://github.com/Financial-Times/github-label-sync + github-label-sync \ + --labels "${{ env.MERGED_CONFIGURATION_PATH }}" \ + ${{ steps.dry-run.outputs.flag }} \ + ${{ github.repository }} From 05a1e3f42c76b805ddced7759b12566554833f23 Mon Sep 17 00:00:00 2001 From: per1234 Date: Thu, 16 Sep 2021 23:26:24 -0700 Subject: [PATCH 07/48] Add CI workflow to check for unapproved Go dependency licenses A task and GitHub Actions workflow are provided here for checking the license types of Go project dependencies. On every push and pull request that affects relevant files, the CI workflow will check: - If the dependency licenses cache is up to date - If any of the project's dependencies have an unapproved license type. Approval can be based on: - Universally allowed license type - Individual dependency --- .../workflows/check-go-dependencies-task.yml | 109 ++++++++++++++++++ .licensed.yml | 76 ++++++++++++ Taskfile.yml | 27 +++++ 3 files changed, 212 insertions(+) create mode 100644 .github/workflows/check-go-dependencies-task.yml create mode 100644 .licensed.yml create mode 100644 Taskfile.yml diff --git a/.github/workflows/check-go-dependencies-task.yml b/.github/workflows/check-go-dependencies-task.yml new file mode 100644 index 0000000..683d942 --- /dev/null +++ b/.github/workflows/check-go-dependencies-task.yml @@ -0,0 +1,109 @@ +# Source: https://github.com/arduino/tooling-project-assets/blob/main/workflow-templates/check-go-dependencies-task.md +name: Check Go Dependencies + +env: + # See: https://github.com/actions/setup-go/tree/v2#readme + GO_VERSION: "1.13" + +# See: https://docs.github.com/en/actions/reference/events-that-trigger-workflows +on: + push: + paths: + - ".github/workflows/check-go-dependencies-task.ya?ml" + - ".licenses/**" + - ".licensed.json" + - ".licensed.ya?ml" + - "Taskfile.ya?ml" + - "**/.gitmodules" + - "**/go.mod" + - "**/go.sum" + pull_request: + paths: + - ".github/workflows/check-go-dependencies-task.ya?ml" + - ".licenses/**" + - ".licensed.json" + - ".licensed.ya?ml" + - "Taskfile.ya?ml" + - "**/.gitmodules" + - "**/go.mod" + - "**/go.sum" + workflow_dispatch: + repository_dispatch: + +jobs: + check-cache: + runs-on: ubuntu-latest + + steps: + - name: Checkout repository + uses: actions/checkout@v2 + with: + submodules: recursive + + - name: Install licensed + uses: jonabc/setup-licensed@v1 + with: + github_token: ${{ secrets.GITHUB_TOKEN }} + version: 3.x + + - name: Install Go + uses: actions/setup-go@v2 + with: + go-version: ${{ env.GO_VERSION }} + + - name: Install Task + uses: arduino/setup-task@v1 + with: + repo-token: ${{ secrets.GITHUB_TOKEN }} + version: 3.x + + - name: Update dependencies license metadata cache + run: task --silent general:cache-dep-licenses + + - name: Check for outdated cache + id: diff + run: | + git add --intent-to-add . + if ! git diff --color --exit-code; then + echo + 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" + exit 1 + fi + + # Some might find it convenient to have CI generate the cache rather than setting up for it locally + - name: Upload cache to workflow artifact + if: failure() && steps.diff.outcome == 'failure' + uses: actions/upload-artifact@v2 + with: + if-no-files-found: error + name: dep-licenses-cache + path: .licenses/ + + check-deps: + runs-on: ubuntu-latest + + steps: + - name: Checkout repository + uses: actions/checkout@v2 + with: + submodules: recursive + + - name: Install licensed + uses: jonabc/setup-licensed@v1 + with: + github_token: ${{ secrets.GITHUB_TOKEN }} + version: 3.x + + - name: Install Go + uses: actions/setup-go@v2 + with: + go-version: ${{ env.GO_VERSION }} + + - name: Install Task + uses: arduino/setup-task@v1 + with: + repo-token: ${{ secrets.GITHUB_TOKEN }} + version: 3.x + + - name: Check for dependencies with unapproved licenses + run: task --silent general:check-dep-licenses diff --git a/.licensed.yml b/.licensed.yml new file mode 100644 index 0000000..9289441 --- /dev/null +++ b/.licensed.yml @@ -0,0 +1,76 @@ +# See: https://github.com/github/licensed/blob/master/docs/configuration.md +sources: + go: true + +apps: + - source_path: ./ + +# Source: https://github.com/arduino/tooling-project-assets/blob/main/workflow-templates/assets/check-dependencies/GPL-2.0/.licensed.yml +allowed: + # The following are based on: https://www.gnu.org/licenses/license-list.html#GPLCompatibleLicenses + - gpl-1.0-or-later + - gpl-1.0+ # Deprecated ID for `gpl-1.0-or-later` + - gpl-2.0-only + - gpl-2.0 # Deprecated ID for `gpl-2.0-only` + - gpl-2.0-or-later + - gpl-2.0+ # Deprecated ID for `gpl-2.0-or-later` + - lgpl-2.0-or-later + - lgpl-2.0+ # Deprecated ID for `lgpl-2.0-or-later` + - lgpl-2.1-only + - lgpl-2.1 # Deprecated ID for `lgpl-2.1-only` + - lgpl-2.1-or-later + - lgpl-2.1+ # Deprecated ID for `lgpl-2.1-or-later` + - fsfap + - artistic-2.0 + - clartistic + - sleepycat + - bsl-1.0 + - bsd-3-clause + - cecill-2.0 + - bsd-3-clause-clear + # "Cryptix General License" - no SPDX ID (https://github.com/spdx/license-list-XML/issues/456) + - ecos-2.0 + - efl-2.0 + - eudatagrid + - mit + - bsd-2-clause # Subsumed by `bsd-2-clause-views` + - bsd-2-clause-netbsd # Deprecated ID for `bsd-2-clause` + - bsd-2-clause-views # This is the version linked from https://www.gnu.org/licenses/license-list.html#FreeBSD + - bsd-2-clause-freebsd # Deprecated ID for `bsd-2-clause-views` + - hpnd + - imatix + - imlib2 + - ijg + # "Informal license" - this is a general class of license + - intel + - isc + - mpl-2.0 + - ncsa + # "License of Netscape JavaScript" - no SPDX ID + - oldap-2.7 + # "License of Perl 5 and below" - possibly `Artistic-1.0-Perl` ? + - cc0-1.0 + - cc-pddc + - psf-2.0 + - ruby + - sgi-b-2.0 + - smlnj + - standardml-nj # Deprecated ID for `smlnj` + - unicode-dfs-2015 + - upl-1.0 + - unlicense + - vim + - w3c + - wtfpl + - lgpl-2.0-or-later with wxwindows-exception-3.1 + - wxwindows # Deprecated ID for `lgpl-2.0-or-later with wxwindows-exception-3.1` + - x11 + - zlib + - zpl-2.0 + - zpl-2.1 + # The following are based on individual license text + - eupl-1.0 + - eupl-1.1 + - eupl-1.2 + - liliq-r-1.1 + - liliq-rplus-1.1 diff --git a/Taskfile.yml b/Taskfile.yml new file mode 100644 index 0000000..1876b50 --- /dev/null +++ b/Taskfile.yml @@ -0,0 +1,27 @@ +# See: https://taskfile.dev/#/usage +version: "3" + +tasks: + # Source: https://github.com/arduino/tooling-project-assets/blob/main/workflow-templates/assets/check-dependencies-task/Taskfile.yml + general:cache-dep-licenses: + desc: Cache dependency license metadata + cmds: + - | + if ! which licensed &>/dev/null; then + if [[ {{OS}} == "windows" ]]; then + echo "Licensed does not have Windows support." + echo "Please use Linux/macOS or download the dependencies cache from the GitHub Actions workflow artifact." + else + echo "licensed not found or not in PATH. Please install: https://github.com/github/licensed#as-an-executable" + fi + exit 1 + fi + - licensed cache + + # Source: https://github.com/arduino/tooling-project-assets/blob/main/workflow-templates/assets/check-dependencies-task/Taskfile.yml + general:check-dep-licenses: + desc: Check for unapproved dependency licenses + deps: + - task: general:cache-dep-licenses + cmds: + - licensed status From f61c49897cecc7421b4adc2b4e290b7b878228e5 Mon Sep 17 00:00:00 2001 From: per1234 Date: Thu, 16 Sep 2021 23:34:44 -0700 Subject: [PATCH 08/48] Make initial commit of dependency license metadata The `.licenses` folder contains a cache of license metadata for all the project's Go dependencies. This serves two purposes: - Allow the Licensed dependency license checker tool to only check licenses when a dependency is added or updated - Allow the maintainer to manually define license metadata when the licensee tool is unable to automatically detect it --- .../arduino/go-paths-helper.dep.yml | 350 ++++++++++++++++++ 1 file changed, 350 insertions(+) create mode 100644 .licenses/go-properties-orderedmap/go/github.com/arduino/go-paths-helper.dep.yml diff --git a/.licenses/go-properties-orderedmap/go/github.com/arduino/go-paths-helper.dep.yml b/.licenses/go-properties-orderedmap/go/github.com/arduino/go-paths-helper.dep.yml new file mode 100644 index 0000000..60f67dc --- /dev/null +++ b/.licenses/go-properties-orderedmap/go/github.com/arduino/go-paths-helper.dep.yml @@ -0,0 +1,350 @@ +--- +name: github.com/arduino/go-paths-helper +version: v1.0.1 +type: go +summary: +homepage: https://pkg.go.dev/github.com/arduino/go-paths-helper +license: gpl-2.0 +licenses: +- sources: LICENSE + text: |2 + GNU GENERAL PUBLIC LICENSE + Version 2, June 1991 + + Copyright (C) 1989, 1991 Free Software Foundation, Inc., + 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + Everyone is permitted to copy and distribute verbatim copies + of this license document, but changing it is not allowed. + + Preamble + + The licenses for most software are designed to take away your + freedom to share and change it. By contrast, the GNU General Public + License is intended to guarantee your freedom to share and change free + software--to make sure the software is free for all its users. This + General Public License applies to most of the Free Software + Foundation's software and to any other program whose authors commit to + using it. (Some other Free Software Foundation software is covered by + the GNU Lesser General Public License instead.) You can apply it to + your programs, too. + + When we speak of free software, we are referring to freedom, not + price. Our General Public Licenses are designed to make sure that you + have the freedom to distribute copies of free software (and charge for + this service if you wish), that you receive source code or can get it + if you want it, that you can change the software or use pieces of it + in new free programs; and that you know you can do these things. + + To protect your rights, we need to make restrictions that forbid + anyone to deny you these rights or to ask you to surrender the rights. + These restrictions translate to certain responsibilities for you if you + distribute copies of the software, or if you modify it. + + For example, if you distribute copies of such a program, whether + gratis or for a fee, you must give the recipients all the rights that + you have. You must make sure that they, too, receive or can get the + source code. And you must show them these terms so they know their + rights. + + We protect your rights with two steps: (1) copyright the software, and + (2) offer you this license which gives you legal permission to copy, + distribute and/or modify the software. + + Also, for each author's protection and ours, we want to make certain + that everyone understands that there is no warranty for this free + software. If the software is modified by someone else and passed on, we + want its recipients to know that what they have is not the original, so + that any problems introduced by others will not reflect on the original + authors' reputations. + + Finally, any free program is threatened constantly by software + patents. We wish to avoid the danger that redistributors of a free + program will individually obtain patent licenses, in effect making the + program proprietary. To prevent this, we have made it clear that any + patent must be licensed for everyone's free use or not licensed at all. + + The precise terms and conditions for copying, distribution and + modification follow. + + GNU GENERAL PUBLIC LICENSE + TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION + + 0. This License applies to any program or other work which contains + a notice placed by the copyright holder saying it may be distributed + under the terms of this General Public License. The "Program", below, + refers to any such program or work, and a "work based on the Program" + means either the Program or any derivative work under copyright law: + that is to say, a work containing the Program or a portion of it, + either verbatim or with modifications and/or translated into another + language. (Hereinafter, translation is included without limitation in + the term "modification".) Each licensee is addressed as "you". + + Activities other than copying, distribution and modification are not + covered by this License; they are outside its scope. The act of + running the Program is not restricted, and the output from the Program + is covered only if its contents constitute a work based on the + Program (independent of having been made by running the Program). + Whether that is true depends on what the Program does. + + 1. You may copy and distribute verbatim copies of the Program's + source code as you receive it, in any medium, provided that you + conspicuously and appropriately publish on each copy an appropriate + copyright notice and disclaimer of warranty; keep intact all the + notices that refer to this License and to the absence of any warranty; + and give any other recipients of the Program a copy of this License + along with the Program. + + You may charge a fee for the physical act of transferring a copy, and + you may at your option offer warranty protection in exchange for a fee. + + 2. You may modify your copy or copies of the Program or any portion + of it, thus forming a work based on the Program, and copy and + distribute such modifications or work under the terms of Section 1 + above, provided that you also meet all of these conditions: + + a) You must cause the modified files to carry prominent notices + stating that you changed the files and the date of any change. + + b) You must cause any work that you distribute or publish, that in + whole or in part contains or is derived from the Program or any + part thereof, to be licensed as a whole at no charge to all third + parties under the terms of this License. + + c) If the modified program normally reads commands interactively + when run, you must cause it, when started running for such + interactive use in the most ordinary way, to print or display an + announcement including an appropriate copyright notice and a + notice that there is no warranty (or else, saying that you provide + a warranty) and that users may redistribute the program under + these conditions, and telling the user how to view a copy of this + License. (Exception: if the Program itself is interactive but + does not normally print such an announcement, your work based on + the Program is not required to print an announcement.) + + These requirements apply to the modified work as a whole. If + identifiable sections of that work are not derived from the Program, + and can be reasonably considered independent and separate works in + themselves, then this License, and its terms, do not apply to those + sections when you distribute them as separate works. But when you + distribute the same sections as part of a whole which is a work based + on the Program, the distribution of the whole must be on the terms of + this License, whose permissions for other licensees extend to the + entire whole, and thus to each and every part regardless of who wrote it. + + Thus, it is not the intent of this section to claim rights or contest + your rights to work written entirely by you; rather, the intent is to + exercise the right to control the distribution of derivative or + collective works based on the Program. + + In addition, mere aggregation of another work not based on the Program + with the Program (or with a work based on the Program) on a volume of + a storage or distribution medium does not bring the other work under + the scope of this License. + + 3. You may copy and distribute the Program (or a work based on it, + under Section 2) in object code or executable form under the terms of + Sections 1 and 2 above provided that you also do one of the following: + + a) Accompany it with the complete corresponding machine-readable + source code, which must be distributed under the terms of Sections + 1 and 2 above on a medium customarily used for software interchange; or, + + b) Accompany it with a written offer, valid for at least three + years, to give any third party, for a charge no more than your + cost of physically performing source distribution, a complete + machine-readable copy of the corresponding source code, to be + distributed under the terms of Sections 1 and 2 above on a medium + customarily used for software interchange; or, + + c) Accompany it with the information you received as to the offer + to distribute corresponding source code. (This alternative is + allowed only for noncommercial distribution and only if you + received the program in object code or executable form with such + an offer, in accord with Subsection b above.) + + The source code for a work means the preferred form of the work for + making modifications to it. For an executable work, complete source + code means all the source code for all modules it contains, plus any + associated interface definition files, plus the scripts used to + control compilation and installation of the executable. However, as a + special exception, the source code distributed need not include + anything that is normally distributed (in either source or binary + form) with the major components (compiler, kernel, and so on) of the + operating system on which the executable runs, unless that component + itself accompanies the executable. + + If distribution of executable or object code is made by offering + access to copy from a designated place, then offering equivalent + access to copy the source code from the same place counts as + distribution of the source code, even though third parties are not + compelled to copy the source along with the object code. + + 4. You may not copy, modify, sublicense, or distribute the Program + except as expressly provided under this License. Any attempt + otherwise to copy, modify, sublicense or distribute the Program is + void, and will automatically terminate your rights under this License. + However, parties who have received copies, or rights, from you under + this License will not have their licenses terminated so long as such + parties remain in full compliance. + + 5. You are not required to accept this License, since you have not + signed it. However, nothing else grants you permission to modify or + distribute the Program or its derivative works. These actions are + prohibited by law if you do not accept this License. Therefore, by + modifying or distributing the Program (or any work based on the + Program), you indicate your acceptance of this License to do so, and + all its terms and conditions for copying, distributing or modifying + the Program or works based on it. + + 6. Each time you redistribute the Program (or any work based on the + Program), the recipient automatically receives a license from the + original licensor to copy, distribute or modify the Program subject to + these terms and conditions. You may not impose any further + restrictions on the recipients' exercise of the rights granted herein. + You are not responsible for enforcing compliance by third parties to + this License. + + 7. If, as a consequence of a court judgment or allegation of patent + infringement or for any other reason (not limited to patent issues), + conditions are imposed on you (whether by court order, agreement or + otherwise) that contradict the conditions of this License, they do not + excuse you from the conditions of this License. If you cannot + distribute so as to satisfy simultaneously your obligations under this + License and any other pertinent obligations, then as a consequence you + may not distribute the Program at all. For example, if a patent + license would not permit royalty-free redistribution of the Program by + all those who receive copies directly or indirectly through you, then + the only way you could satisfy both it and this License would be to + refrain entirely from distribution of the Program. + + If any portion of this section is held invalid or unenforceable under + any particular circumstance, the balance of the section is intended to + apply and the section as a whole is intended to apply in other + circumstances. + + It is not the purpose of this section to induce you to infringe any + patents or other property right claims or to contest validity of any + such claims; this section has the sole purpose of protecting the + integrity of the free software distribution system, which is + implemented by public license practices. Many people have made + generous contributions to the wide range of software distributed + through that system in reliance on consistent application of that + system; it is up to the author/donor to decide if he or she is willing + to distribute software through any other system and a licensee cannot + impose that choice. + + This section is intended to make thoroughly clear what is believed to + be a consequence of the rest of this License. + + 8. If the distribution and/or use of the Program is restricted in + certain countries either by patents or by copyrighted interfaces, the + original copyright holder who places the Program under this License + may add an explicit geographical distribution limitation excluding + those countries, so that distribution is permitted only in or among + countries not thus excluded. In such case, this License incorporates + the limitation as if written in the body of this License. + + 9. The Free Software Foundation may publish revised and/or new versions + of the General Public License from time to time. Such new versions will + be similar in spirit to the present version, but may differ in detail to + address new problems or concerns. + + Each version is given a distinguishing version number. If the Program + specifies a version number of this License which applies to it and "any + later version", you have the option of following the terms and conditions + either of that version or of any later version published by the Free + Software Foundation. If the Program does not specify a version number of + this License, you may choose any version ever published by the Free Software + Foundation. + + 10. If you wish to incorporate parts of the Program into other free + programs whose distribution conditions are different, write to the author + to ask for permission. For software which is copyrighted by the Free + Software Foundation, write to the Free Software Foundation; we sometimes + make exceptions for this. Our decision will be guided by the two goals + of preserving the free status of all derivatives of our free software and + of promoting the sharing and reuse of software generally. + + NO WARRANTY + + 11. BECAUSE THE PROGRAM IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY + FOR THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW. EXCEPT WHEN + OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES + PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED + OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF + MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE ENTIRE RISK AS + TO THE QUALITY AND PERFORMANCE OF THE PROGRAM IS WITH YOU. SHOULD THE + PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING, + REPAIR OR CORRECTION. + + 12. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING + WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR + REDISTRIBUTE THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, + INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING + OUT OF THE USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED + TO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY + YOU OR THIRD PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER + PROGRAMS), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE + POSSIBILITY OF SUCH DAMAGES. + + END OF TERMS AND CONDITIONS + + How to Apply These Terms to Your New Programs + + If you develop a new program, and you want it to be of the greatest + possible use to the public, the best way to achieve this is to make it + free software which everyone can redistribute and change under these terms. + + To do so, attach the following notices to the program. It is safest + to attach them to the start of each source file to most effectively + convey the exclusion of warranty; and each file should have at least + the "copyright" line and a pointer to where the full notice is found. + + + Copyright (C) + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License along + with this program; if not, write to the Free Software Foundation, Inc., + 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + + Also add information on how to contact you by electronic and paper mail. + + If the program is interactive, make it output a short notice like this + when it starts in an interactive mode: + + Gnomovision version 69, Copyright (C) year name of author + Gnomovision comes with ABSOLUTELY NO WARRANTY; for details type `show w'. + This is free software, and you are welcome to redistribute it + under certain conditions; type `show c' for details. + + The hypothetical commands `show w' and `show c' should show the appropriate + parts of the General Public License. Of course, the commands you use may + be called something other than `show w' and `show c'; they could even be + mouse-clicks or menu items--whatever suits your program. + + You should also get your employer (if you work as a programmer) or your + school, if any, to sign a "copyright disclaimer" for the program, if + necessary. Here is a sample; alter the names: + + Yoyodyne, Inc., hereby disclaims all copyright interest in the program + `Gnomovision' (which makes passes at compilers) written by James Hacker. + + , 1 April 1989 + Ty Coon, President of Vice + + This General Public License does not permit incorporating your program into + proprietary programs. If your program is a subroutine library, you may + consider it more useful to permit linking proprietary applications with the + library. If this is what you want to do, use the GNU Lesser General + Public License instead of this License. +notices: [] From a5d3172901e11edeb650718816f72bc894175ce8 Mon Sep 17 00:00:00 2001 From: per1234 Date: Thu, 16 Sep 2021 23:35:47 -0700 Subject: [PATCH 09/48] Manually define dependency license metadata that was not detected The "Licensed" dependency license checker tool uses the licensee tool to automatically determine the license type based on metadata provided by the dependency author. This must be in a standardized format without any modifications. In cases where that wasn't done, it is necessary to determine the license type and update the dependency license metadata cache in the `.licenses` folder manually. The Licensed tool will check this data whenever the dependency version is updated to make sure the license hasn't changed. --- .../go/github.com/arduino/go-paths-helper.dep.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.licenses/go-properties-orderedmap/go/github.com/arduino/go-paths-helper.dep.yml b/.licenses/go-properties-orderedmap/go/github.com/arduino/go-paths-helper.dep.yml index 60f67dc..651a930 100644 --- a/.licenses/go-properties-orderedmap/go/github.com/arduino/go-paths-helper.dep.yml +++ b/.licenses/go-properties-orderedmap/go/github.com/arduino/go-paths-helper.dep.yml @@ -4,7 +4,7 @@ version: v1.0.1 type: go summary: homepage: https://pkg.go.dev/github.com/arduino/go-paths-helper -license: gpl-2.0 +license: gpl-2.0-or-later licenses: - sources: LICENSE text: |2 From a0db727bf78f4d352d546a256781dfbff75773c4 Mon Sep 17 00:00:00 2001 From: per1234 Date: Mon, 20 Dec 2021 13:53:22 -0800 Subject: [PATCH 10/48] Use major version ref of `carlosperate/download-file-action` The `carlosperate/download-file-action` action is used in the GitHub Actions workflows as a convenient way to download external resources. A major version ref has been added to that repository. It will always point to the latest release of the "1" major version series. This means it is no longer necessary to do a full pin of the action version in use as before. Use of the major version ref will cause the workflow to use a stable version of the action, while also benefiting from ongoing development to the action up until such time as a new major release of an action is made. At that time we would need to evaluate whether any changes to the workflow are required by the breaking change that triggered the major release before manually updating the major ref (e.g., uses: `carlosperate/download-file-action@v2`). I think this approach strikes the right balance between stability and maintainability for these workflows. --- .github/workflows/sync-labels.yml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/.github/workflows/sync-labels.yml b/.github/workflows/sync-labels.yml index f4c245e..0273232 100644 --- a/.github/workflows/sync-labels.yml +++ b/.github/workflows/sync-labels.yml @@ -31,7 +31,7 @@ jobs: - name: Download JSON schema for labels configuration file id: download-schema - uses: carlosperate/download-file-action@v1.0.3 + uses: carlosperate/download-file-action@v1 with: file-url: https://raw.githubusercontent.com/arduino/tooling-project-assets/main/workflow-templates/assets/sync-labels/arduino-tooling-gh-label-configuration-schema.json location: ${{ runner.temp }}/label-configuration-schema @@ -66,7 +66,7 @@ jobs: steps: - name: Download - uses: carlosperate/download-file-action@v1.0.3 + uses: carlosperate/download-file-action@v1 with: file-url: https://raw.githubusercontent.com/arduino/tooling-project-assets/main/workflow-templates/assets/sync-labels/${{ matrix.filename }} From 3c74a573c739f5c59aab40e224a5e458d5367e63 Mon Sep 17 00:00:00 2001 From: per1234 Date: Mon, 2 May 2022 22:45:24 -0700 Subject: [PATCH 11/48] Bump action dependencies of "Check Go Dependencies" workflow --- .github/workflows/check-go-dependencies-task.yml | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/.github/workflows/check-go-dependencies-task.yml b/.github/workflows/check-go-dependencies-task.yml index 683d942..62b8b43 100644 --- a/.github/workflows/check-go-dependencies-task.yml +++ b/.github/workflows/check-go-dependencies-task.yml @@ -2,7 +2,7 @@ name: Check Go Dependencies env: - # See: https://github.com/actions/setup-go/tree/v2#readme + # See: https://github.com/actions/setup-go/tree/v3#readme GO_VERSION: "1.13" # See: https://docs.github.com/en/actions/reference/events-that-trigger-workflows @@ -36,7 +36,7 @@ jobs: steps: - name: Checkout repository - uses: actions/checkout@v2 + uses: actions/checkout@v3 with: submodules: recursive @@ -47,7 +47,7 @@ jobs: version: 3.x - name: Install Go - uses: actions/setup-go@v2 + uses: actions/setup-go@v3 with: go-version: ${{ env.GO_VERSION }} @@ -73,7 +73,7 @@ jobs: # Some might find it convenient to have CI generate the cache rather than setting up for it locally - name: Upload cache to workflow artifact if: failure() && steps.diff.outcome == 'failure' - uses: actions/upload-artifact@v2 + uses: actions/upload-artifact@v3 with: if-no-files-found: error name: dep-licenses-cache @@ -84,7 +84,7 @@ jobs: steps: - name: Checkout repository - uses: actions/checkout@v2 + uses: actions/checkout@v3 with: submodules: recursive @@ -95,7 +95,7 @@ jobs: version: 3.x - name: Install Go - uses: actions/setup-go@v2 + uses: actions/setup-go@v3 with: go-version: ${{ env.GO_VERSION }} From bc7e28216a064894cc92a7e300bb4dcb9aabfb9b Mon Sep 17 00:00:00 2001 From: per1234 Date: Mon, 2 May 2022 22:45:39 -0700 Subject: [PATCH 12/48] Update reference URL in "Check Go Dependencies" workflow - Update redirecting GitHub docs URL to new location - Configure GitHub docs URL to allow localization where available --- .github/workflows/check-go-dependencies-task.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/check-go-dependencies-task.yml b/.github/workflows/check-go-dependencies-task.yml index 62b8b43..91d376b 100644 --- a/.github/workflows/check-go-dependencies-task.yml +++ b/.github/workflows/check-go-dependencies-task.yml @@ -5,7 +5,7 @@ env: # See: https://github.com/actions/setup-go/tree/v3#readme GO_VERSION: "1.13" -# See: https://docs.github.com/en/actions/reference/events-that-trigger-workflows +# See: https://docs.github.com/actions/using-workflows/events-that-trigger-workflows on: push: paths: From fe66ce8350e71b647bc9294d3c22e6352ada4d6d Mon Sep 17 00:00:00 2001 From: per1234 Date: Mon, 2 May 2022 22:45:57 -0700 Subject: [PATCH 13/48] Detect unused dependency license metadata files The "Check Go Dependencies" GitHub Actions workflow checks for dependencies with incompatible or unapproved license types. The dependency license metadata consumed by the "Licensed" tool is cached in the project repository, in a dedicated file for each dependency. The `check-cache` job of the workflow checks whether that cache is in sync with the project's current dependencies. It does this by using the "Licensed" tool to update the cache and then a `git diff` command to check whether that resulted in any changes (which would indicate it is out of sync). Out of sync states could result from any of three distinct conditions: - Missing metadata file - Incorrect metadata file contents - Superfluous metadata file An incorrectly configured `git diff` command previously caused the last of these to be missed. My first take at this system was simply using `git diff --exit-code` alone. That detects the last two, but misses the first. I added the `git add --intent-to-add .` command to detect added files, but didn't realize that it caused the last to be missed. Superfluous files in the dependency license metadata cache won't actually interfere with its intended functionality, but it is still important to avoid an accumulation of unused files. The new commands will catch all three of the possible out of sync conditions by staging all changes that result from the metadata cache update to the repository and then comparing those against the `HEAD` commit. I considered an alternative approach which works just as well as the chosen one: ``` git add . git diff --exit-code HEAD ``` However, I feel that the `--cached` flag makes the `git diff` command more self-explanatory. --- .github/workflows/check-go-dependencies-task.yml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/.github/workflows/check-go-dependencies-task.yml b/.github/workflows/check-go-dependencies-task.yml index 91d376b..1af17cb 100644 --- a/.github/workflows/check-go-dependencies-task.yml +++ b/.github/workflows/check-go-dependencies-task.yml @@ -63,8 +63,8 @@ jobs: - name: Check for outdated cache id: diff run: | - git add --intent-to-add . - if ! git diff --color --exit-code; then + git add . + if ! git diff --cached --color --exit-code; then echo 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" exit 1 From 599fa85fc610543e62e3675c28308772a1695673 Mon Sep 17 00:00:00 2001 From: per1234 Date: Mon, 2 May 2022 22:46:11 -0700 Subject: [PATCH 14/48] Add schedule trigger to "Check Go Dependencies" workflow The workflow is configured to run whenever any relevant file in the repository is changed. However, the results of the workflow run are also dependent on the external environment it runs in, which include: - The software running on the GitHub hosted GitHub Actions runner machines - The GitHub Actions actions used by the workflow - The dependencies that are installed by the workflow directly or via the GitHub Actions actions it uses The workflow does not fully pin to a specific version of external tools. This was done in the interest of reducing the maintenance burden of keeping the systems up to date. However, it also means that a new release of one of those tools can cause the workflow runs to start failing (which might happen through an enhancement to that resource resolving a false negative, or a defect causing a false negative). When the repository file path trigger is used by itself, this sort of external breakage is only revealed when an unrelated change triggers the workflow. That can be distracting even to a dedicated member of the project development team, as well as confusing and discouraging to any contributor. This type of change can be caught by adding a `schedule` event trigger that causes the workflow to run periodically in addition to the other on-demand triggers. This allows the problem to be identified and resolved at the maintainer's convenience, separate from the unrelated development work. --- .github/workflows/check-go-dependencies-task.yml | 3 +++ 1 file changed, 3 insertions(+) diff --git a/.github/workflows/check-go-dependencies-task.yml b/.github/workflows/check-go-dependencies-task.yml index 1af17cb..bc2ab4a 100644 --- a/.github/workflows/check-go-dependencies-task.yml +++ b/.github/workflows/check-go-dependencies-task.yml @@ -27,6 +27,9 @@ on: - "**/.gitmodules" - "**/go.mod" - "**/go.sum" + schedule: + # Run periodically to catch breakage caused by external changes. + - cron: "0 8 * * WED" workflow_dispatch: repository_dispatch: From 021a791b4eb0eb367adfccf516afed70c737620f Mon Sep 17 00:00:00 2001 From: per1234 Date: Mon, 2 May 2022 22:46:23 -0700 Subject: [PATCH 15/48] Run "Check Go Dependencies" workflow on release branch creation The trunk-based development strategy is used by some tooling projects. Their release branches may contain a subset of the history of the default branch. The status of the GitHub Actions workflows should be evaluated before making a release. However, this is not so simple as checking the status of the commit at the tip of the branch in the project using that strategy. The reason is that, for the sake of efficiency, the workflow is configured to run only when the processes are relevant to the trigger event (e.g., no need to run it for a change to the readme). In the case of the default branch, you can simply set the workflow runs filter to that branch and then check the result of the latest run of each workflow of interest. However, that was not possible to do with the release branch since it might be that the workflow was never run in that branch. The status of the latest run of the workflow in the default branch might not match the status for the release branch if the release branch does not contain the full history. For this reason, it will be helpful to trigger the workflow on the creation of a release branch. This will ensure that the workflow will always have at least one run in the release branch. Subsequent commits pushed to the branch can run based on their usual trigger filters and the status of the latest run of the workflow in the branch will provide an accurate indication of the state of that branch. Branches are created for purposes other than releases, most notably feature branches to stage work for a pull request. Because the collection of workflows in a Tooling project are often very comprehensive, it would not be convenient or efficient to run them on the creation of every feature branch. Unfortunately, GitHub Actions does not support filters on the `create` event of branch creation like it does for the `push` and `pull_request` events. There is support for a `branches` filter of the `push` event, but that filter is an AND to the `paths` filter and this application requires an OR. For this reason, the workflows must be triggered by the creation of any branch. The unwanted job runs are prevented by adding a `run-determination` job with the branch filter handled by Bash commands. The other jobs of the workflow use this `run-determination` job as a dependency, only running when it indicates they should via a job output. Because this minimal `run-determination` job runs very quickly, it is roughly equivalent to the workflow having been skipped entirely for non-release branch creations. This approach has been in use for some time already in other workflows. --- .../workflows/check-go-dependencies-task.yml | 28 +++++++++++++++++++ 1 file changed, 28 insertions(+) diff --git a/.github/workflows/check-go-dependencies-task.yml b/.github/workflows/check-go-dependencies-task.yml index bc2ab4a..be478ab 100644 --- a/.github/workflows/check-go-dependencies-task.yml +++ b/.github/workflows/check-go-dependencies-task.yml @@ -7,6 +7,7 @@ env: # See: https://docs.github.com/actions/using-workflows/events-that-trigger-workflows on: + create: push: paths: - ".github/workflows/check-go-dependencies-task.ya?ml" @@ -34,7 +35,32 @@ on: repository_dispatch: jobs: + run-determination: + runs-on: ubuntu-latest + outputs: + result: ${{ steps.determination.outputs.result }} + steps: + - name: Determine if the rest of the workflow should run + id: determination + run: | + RELEASE_BRANCH_REGEX="refs/heads/[0-9]+.[0-9]+.x" + # The `create` event trigger doesn't support `branches` filters, so it's necessary to use Bash instead. + if [[ + "${{ github.event_name }}" != "create" || + "${{ github.ref }}" =~ $RELEASE_BRANCH_REGEX + ]]; then + # Run the other jobs. + RESULT="true" + else + # There is no need to run the other jobs. + RESULT="false" + fi + + echo "::set-output name=result::$RESULT" + check-cache: + needs: run-determination + if: needs.run-determination.outputs.result == 'true' runs-on: ubuntu-latest steps: @@ -83,6 +109,8 @@ jobs: path: .licenses/ check-deps: + needs: run-determination + if: needs.run-determination.outputs.result == 'true' runs-on: ubuntu-latest steps: From 548284eb2432a592183e33c518e889419324beb9 Mon Sep 17 00:00:00 2001 From: per1234 Date: Mon, 2 May 2022 23:14:21 -0700 Subject: [PATCH 16/48] Configure Dependabot to check for outdated actions used in workflows Dependabot will periodically check the versions of all actions used in the repository's workflows. If any are found to be outdated, it will submit a pull request to update them. NOTE: Dependabot's PRs will occasionally propose to pin to the patch version of the action (e.g., updating `uses: foo/bar@v1` to `uses: foo/bar@v2.3.4`). When the action author has provided a major version ref, use that instead (e.g., `uses: foo/bar@v2`). Dependabot will automatically close its PR once the workflow has been updated. More information: https://docs.github.com/code-security/dependabot/working-with-dependabot/keeping-your-actions-up-to-date-with-dependabot --- .github/dependabot.yml | 13 +++++++++++++ 1 file changed, 13 insertions(+) create mode 100644 .github/dependabot.yml diff --git a/.github/dependabot.yml b/.github/dependabot.yml new file mode 100644 index 0000000..fd7388a --- /dev/null +++ b/.github/dependabot.yml @@ -0,0 +1,13 @@ +# See: https://docs.github.com/code-security/dependabot/dependabot-version-updates/configuration-options-for-the-dependabot.yml-file#about-the-dependabotyml-file +version: 2 + +updates: + # Configure check for outdated GitHub Actions actions in workflows. + # Source: https://github.com/arduino/tooling-project-assets/blob/main/workflow-templates/assets/dependabot/README.md + # See: https://docs.github.com/code-security/dependabot/working-with-dependabot/keeping-your-actions-up-to-date-with-dependabot + - package-ecosystem: github-actions + directory: / # Check the repository's workflows under /.github/workflows/ + schedule: + interval: daily + labels: + - "topic: infrastructure" From ebdaccc10930c99484cdbbe322c9826956993e59 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Tue, 3 May 2022 08:50:57 +0000 Subject: [PATCH 17/48] Bump actions/setup-go from 2 to 3 Bumps [actions/setup-go](https://github.com/actions/setup-go) from 2 to 3. - [Release notes](https://github.com/actions/setup-go/releases) - [Commits](https://github.com/actions/setup-go/compare/v2...v3) --- updated-dependencies: - dependency-name: actions/setup-go dependency-type: direct:production update-type: version-update:semver-major ... Signed-off-by: dependabot[bot] --- .github/workflows/check-go-dependencies-task.yml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/.github/workflows/check-go-dependencies-task.yml b/.github/workflows/check-go-dependencies-task.yml index 683d942..bbb6dc5 100644 --- a/.github/workflows/check-go-dependencies-task.yml +++ b/.github/workflows/check-go-dependencies-task.yml @@ -47,7 +47,7 @@ jobs: version: 3.x - name: Install Go - uses: actions/setup-go@v2 + uses: actions/setup-go@v3 with: go-version: ${{ env.GO_VERSION }} @@ -95,7 +95,7 @@ jobs: version: 3.x - name: Install Go - uses: actions/setup-go@v2 + uses: actions/setup-go@v3 with: go-version: ${{ env.GO_VERSION }} From 7f8d923a353ed9b78d09213157073e5c7e933391 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Tue, 3 May 2022 08:51:00 +0000 Subject: [PATCH 18/48] Bump actions/checkout from 2 to 3 Bumps [actions/checkout](https://github.com/actions/checkout) from 2 to 3. - [Release notes](https://github.com/actions/checkout/releases) - [Changelog](https://github.com/actions/checkout/blob/main/CHANGELOG.md) - [Commits](https://github.com/actions/checkout/compare/v2...v3) --- updated-dependencies: - dependency-name: actions/checkout dependency-type: direct:production update-type: version-update:semver-major ... Signed-off-by: dependabot[bot] --- .github/workflows/check-go-dependencies-task.yml | 4 ++-- .github/workflows/sync-labels.yml | 4 ++-- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/.github/workflows/check-go-dependencies-task.yml b/.github/workflows/check-go-dependencies-task.yml index 683d942..c667cce 100644 --- a/.github/workflows/check-go-dependencies-task.yml +++ b/.github/workflows/check-go-dependencies-task.yml @@ -36,7 +36,7 @@ jobs: steps: - name: Checkout repository - uses: actions/checkout@v2 + uses: actions/checkout@v3 with: submodules: recursive @@ -84,7 +84,7 @@ jobs: steps: - name: Checkout repository - uses: actions/checkout@v2 + uses: actions/checkout@v3 with: submodules: recursive diff --git a/.github/workflows/sync-labels.yml b/.github/workflows/sync-labels.yml index 0273232..28d0397 100644 --- a/.github/workflows/sync-labels.yml +++ b/.github/workflows/sync-labels.yml @@ -27,7 +27,7 @@ jobs: steps: - name: Checkout repository - uses: actions/checkout@v2 + uses: actions/checkout@v3 - name: Download JSON schema for labels configuration file id: download-schema @@ -106,7 +106,7 @@ jobs: echo "::set-output name=flag::--dry-run" - name: Checkout repository - uses: actions/checkout@v2 + uses: actions/checkout@v3 - name: Download configuration files artifact uses: actions/download-artifact@v2 From 85677707ad1213be6a5a49d56ade5fbd7fc481ec Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Tue, 3 May 2022 08:51:03 +0000 Subject: [PATCH 19/48] Bump actions/upload-artifact from 2 to 3 Bumps [actions/upload-artifact](https://github.com/actions/upload-artifact) from 2 to 3. - [Release notes](https://github.com/actions/upload-artifact/releases) - [Commits](https://github.com/actions/upload-artifact/compare/v2...v3) --- updated-dependencies: - dependency-name: actions/upload-artifact dependency-type: direct:production update-type: version-update:semver-major ... Signed-off-by: dependabot[bot] --- .github/workflows/check-go-dependencies-task.yml | 2 +- .github/workflows/sync-labels.yml | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/.github/workflows/check-go-dependencies-task.yml b/.github/workflows/check-go-dependencies-task.yml index 683d942..ff24f08 100644 --- a/.github/workflows/check-go-dependencies-task.yml +++ b/.github/workflows/check-go-dependencies-task.yml @@ -73,7 +73,7 @@ jobs: # Some might find it convenient to have CI generate the cache rather than setting up for it locally - name: Upload cache to workflow artifact if: failure() && steps.diff.outcome == 'failure' - uses: actions/upload-artifact@v2 + uses: actions/upload-artifact@v3 with: if-no-files-found: error name: dep-licenses-cache diff --git a/.github/workflows/sync-labels.yml b/.github/workflows/sync-labels.yml index 0273232..3785be1 100644 --- a/.github/workflows/sync-labels.yml +++ b/.github/workflows/sync-labels.yml @@ -71,7 +71,7 @@ jobs: file-url: https://raw.githubusercontent.com/arduino/tooling-project-assets/main/workflow-templates/assets/sync-labels/${{ matrix.filename }} - name: Pass configuration files to next job via workflow artifact - uses: actions/upload-artifact@v2 + uses: actions/upload-artifact@v3 with: path: | *.yaml From 86baec1a9b2eebaf6561a123b717c7553a5474b3 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Tue, 3 May 2022 08:57:07 +0000 Subject: [PATCH 20/48] Bump actions/download-artifact from 2 to 3 Bumps [actions/download-artifact](https://github.com/actions/download-artifact) from 2 to 3. - [Release notes](https://github.com/actions/download-artifact/releases) - [Commits](https://github.com/actions/download-artifact/compare/v2...v3) --- updated-dependencies: - dependency-name: actions/download-artifact dependency-type: direct:production update-type: version-update:semver-major ... Signed-off-by: dependabot[bot] --- .github/workflows/sync-labels.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/sync-labels.yml b/.github/workflows/sync-labels.yml index 28d0397..5ee9592 100644 --- a/.github/workflows/sync-labels.yml +++ b/.github/workflows/sync-labels.yml @@ -109,7 +109,7 @@ jobs: uses: actions/checkout@v3 - name: Download configuration files artifact - uses: actions/download-artifact@v2 + uses: actions/download-artifact@v3 with: name: ${{ env.CONFIGURATIONS_ARTIFACT }} path: ${{ env.CONFIGURATIONS_FOLDER }} From b52418973b9c677f77de3b8acc258464d9d32630 Mon Sep 17 00:00:00 2001 From: per1234 Date: Tue, 3 May 2022 18:33:46 -0700 Subject: [PATCH 21/48] Update `actions/setup-go` reference URL for new version --- .github/workflows/check-go-dependencies-task.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/check-go-dependencies-task.yml b/.github/workflows/check-go-dependencies-task.yml index bbb6dc5..e336fe7 100644 --- a/.github/workflows/check-go-dependencies-task.yml +++ b/.github/workflows/check-go-dependencies-task.yml @@ -2,7 +2,7 @@ name: Check Go Dependencies env: - # See: https://github.com/actions/setup-go/tree/v2#readme + # See: https://github.com/actions/setup-go/tree/v3#readme GO_VERSION: "1.13" # See: https://docs.github.com/en/actions/reference/events-that-trigger-workflows From b02dcc0dc1a3349893beb493eaabfeb6f8c3595c Mon Sep 17 00:00:00 2001 From: Matteo Pologruto Date: Thu, 18 Aug 2022 09:36:40 +0200 Subject: [PATCH 22/48] Add CI workflow to check the license file Whenever one of the recognized license file names are modified in the repository, the workflow runs to check whether the license can be recognized and whether it is of the expected type. GitHub has a useful automated license detection system that determines the license type used by a repository, and surfaces that information in the repository home page, the search web interface, and the GitHub API. This license detection system requires that the license be defined by a dedicated file with one of several standardized filenames and paths. GitHub's license detection system uses the popular licensee tool, so this file also serves to define the license type for any other usages of licensee, as well as to human readers of the file. For this reason, and to ensure it remains a valid legal instrument, it's important that there be no non-standard modifications to the license file or collisions with other supported license files. This workflow ensures that any changes which would change the license type or which license file is used by the detection are caught automatically. --- .github/workflows/check-license.yml | 96 +++++++++++++++++++++++++++++ README.md | 1 + 2 files changed, 97 insertions(+) create mode 100644 .github/workflows/check-license.yml diff --git a/.github/workflows/check-license.yml b/.github/workflows/check-license.yml new file mode 100644 index 0000000..77c6d18 --- /dev/null +++ b/.github/workflows/check-license.yml @@ -0,0 +1,96 @@ +# Source: https://github.com/arduino/tooling-project-assets/blob/main/workflow-templates/check-license.md +name: Check License + +env: + EXPECTED_LICENSE_FILENAME: LICENSE + # SPDX identifier: https://spdx.org/licenses/ + EXPECTED_LICENSE_TYPE: GPL-2.0 + +# See: https://docs.github.com/actions/using-workflows/events-that-trigger-workflows +on: + create: + push: + paths: + - ".github/workflows/check-license.ya?ml" + # See: https://github.com/licensee/licensee/blob/master/docs/what-we-look-at.md#detecting-the-license-file + - "[cC][oO][pP][yY][iI][nN][gG]*" + - "[cC][oO][pP][yY][rR][iI][gG][hH][tH]*" + - "[lL][iI][cC][eE][nN][cCsS][eE]*" + - "[oO][fF][lL]*" + - "[pP][aA][tT][eE][nN][tT][sS]*" + pull_request: + paths: + - ".github/workflows/check-license.ya?ml" + - "[cC][oO][pP][yY][iI][nN][gG]*" + - "[cC][oO][pP][yY][rR][iI][gG][hH][tH]*" + - "[lL][iI][cC][eE][nN][cCsS][eE]*" + - "[oO][fF][lL]*" + - "[pP][aA][tT][eE][nN][tT][sS]*" + schedule: + # Run periodically to catch breakage caused by external changes. + - cron: "0 6 * * WED" + workflow_dispatch: + repository_dispatch: + +jobs: + run-determination: + runs-on: ubuntu-latest + outputs: + result: ${{ steps.determination.outputs.result }} + steps: + - name: Determine if the rest of the workflow should run + id: determination + run: | + RELEASE_BRANCH_REGEX="refs/heads/[0-9]+.[0-9]+.x" + # The `create` event trigger doesn't support `branches` filters, so it's necessary to use Bash instead. + if [[ + "${{ github.event_name }}" != "create" || + "${{ github.ref }}" =~ $RELEASE_BRANCH_REGEX + ]]; then + # Run the other jobs. + RESULT="true" + else + # There is no need to run the other jobs. + RESULT="false" + fi + + echo "::set-output name=result::$RESULT" + + check-license: + needs: run-determination + if: needs.run-determination.outputs.result == 'true' + runs-on: ubuntu-latest + + steps: + - name: Checkout repository + uses: actions/checkout@v3 + + - name: Install Ruby + uses: ruby/setup-ruby@v1 + with: + ruby-version: ruby # Install latest version + + - name: Install licensee + run: gem install licensee + + - name: Check license file + run: | + EXIT_STATUS=0 + # See: https://github.com/licensee/licensee + LICENSEE_OUTPUT="$(licensee detect --json --confidence=100)" + + DETECTED_LICENSE_FILE="$(echo "$LICENSEE_OUTPUT" | jq .matched_files[0].filename | tr --delete '\r')" + echo "Detected license file: $DETECTED_LICENSE_FILE" + if [ "$DETECTED_LICENSE_FILE" != "\"${EXPECTED_LICENSE_FILENAME}\"" ]; then + echo "::error file=${DETECTED_LICENSE_FILE}::detected license file $DETECTED_LICENSE_FILE doesn't match expected: $EXPECTED_LICENSE_FILENAME" + EXIT_STATUS=1 + fi + + DETECTED_LICENSE_TYPE="$(echo "$LICENSEE_OUTPUT" | jq .matched_files[0].matched_license | tr --delete '\r')" + echo "Detected license type: $DETECTED_LICENSE_TYPE" + if [ "$DETECTED_LICENSE_TYPE" != "\"${EXPECTED_LICENSE_TYPE}\"" ]; then + echo "::error file=${DETECTED_LICENSE_FILE}::detected license type $DETECTED_LICENSE_TYPE doesn't match expected \"${EXPECTED_LICENSE_TYPE}\"" + EXIT_STATUS=1 + fi + + exit $EXIT_STATUS diff --git a/README.md b/README.md index a51bc83..bdd52b5 100644 --- a/README.md +++ b/README.md @@ -1,5 +1,6 @@ [![GoDoc](https://godoc.org/github.com/arduino/go-properties-orderedmap?status.svg)](https://godoc.org/github.com/arduino/go-properties-orderedmap) +[![Check License status](https://github.com/arduino/go-properties-orderedmap/actions/workflows/check-license.yml/badge.svg)](https://github.com/arduino/go-properties-orderedmap/actions/workflows/check-license.yml) Package `properties` is a library for handling maps of hierarchical properties. From 9e1b3688fc0fd9e6ffa614e17cdd46cd187887e6 Mon Sep 17 00:00:00 2001 From: Matteo Pologruto Date: Thu, 18 Aug 2022 10:17:06 +0200 Subject: [PATCH 23/48] Add CI workflow to check Markdown files for problems On every push and pull request that affects relevant files, and periodically, check the repository's Markdown files for problems: - Use markdownlint to check for common problems and formatting. - Use markdown-link-check to check for broken links. The Arduino tooling Markdown style is defined by the file. In the event the repository contains externally maintained Markdown files, markdownlint can be configured to ignore them via a file: https://github.com/igorshubovych/markdownlint-cli#ignoring-files markdown-link-check is configured via the file: https://github.com/tcort/markdown-link-check#config-file-format --- .github/workflows/check-markdown-task.yml | 112 ++ .gitignore | 1 + .markdown-link-check.json | 13 + .markdownlint.yml | 62 + .markdownlintignore | 4 + README.md | 3 +- Taskfile.yml | 85 ++ package-lock.json | 1318 +++++++++++++++++++++ package.json | 6 + 9 files changed, 1603 insertions(+), 1 deletion(-) create mode 100644 .github/workflows/check-markdown-task.yml create mode 100644 .gitignore create mode 100644 .markdown-link-check.json create mode 100644 .markdownlint.yml create mode 100644 .markdownlintignore create mode 100644 package-lock.json create mode 100644 package.json diff --git a/.github/workflows/check-markdown-task.yml b/.github/workflows/check-markdown-task.yml new file mode 100644 index 0000000..8fc37a7 --- /dev/null +++ b/.github/workflows/check-markdown-task.yml @@ -0,0 +1,112 @@ +# Source: https://github.com/arduino/tooling-project-assets/blob/main/workflow-templates/check-markdown-task.md +name: Check Markdown + +env: + # See: https://github.com/actions/setup-node/#readme + NODE_VERSION: 16.x + +# See: https://docs.github.com/actions/using-workflows/events-that-trigger-workflows +on: + create: + push: + paths: + - ".github/workflows/check-markdown-task.ya?ml" + - ".markdown-link-check.json" + - "package.json" + - "package-lock.json" + - "Taskfile.ya?ml" + - "**/.markdownlint*" + - "**.mdx?" + - "**.mkdn" + - "**.mdown" + - "**.markdown" + pull_request: + paths: + - ".github/workflows/check-markdown-task.ya?ml" + - ".markdown-link-check.json" + - "package.json" + - "package-lock.json" + - "Taskfile.ya?ml" + - "**/.markdownlint*" + - "**.mdx?" + - "**.mkdn" + - "**.mdown" + - "**.markdown" + schedule: + # Run every Tuesday at 8 AM UTC to catch breakage caused by external changes. + - cron: "0 8 * * TUE" + workflow_dispatch: + repository_dispatch: + +jobs: + run-determination: + runs-on: ubuntu-latest + outputs: + result: ${{ steps.determination.outputs.result }} + steps: + - name: Determine if the rest of the workflow should run + id: determination + run: | + RELEASE_BRANCH_REGEX="refs/heads/[0-9]+.[0-9]+.x" + # The `create` event trigger doesn't support `branches` filters, so it's necessary to use Bash instead. + if [[ + "${{ github.event_name }}" != "create" || + "${{ github.ref }}" =~ $RELEASE_BRANCH_REGEX + ]]; then + # Run the other jobs. + RESULT="true" + else + # There is no need to run the other jobs. + RESULT="false" + fi + + echo "::set-output name=result::$RESULT" + + lint: + needs: run-determination + if: needs.run-determination.outputs.result == 'true' + runs-on: ubuntu-latest + + steps: + - name: Checkout repository + uses: actions/checkout@v3 + + - name: Setup Node.js + uses: actions/setup-node@v3 + with: + node-version: ${{ env.NODE_VERSION }} + + - name: Initialize markdownlint-cli problem matcher + uses: xt0rted/markdownlint-problem-matcher@v1 + + - name: Install Task + uses: arduino/setup-task@v1 + with: + repo-token: ${{ secrets.GITHUB_TOKEN }} + version: 3.x + + - name: Lint + run: task markdown:lint + + links: + needs: run-determination + if: needs.run-determination.outputs.result == 'true' + runs-on: ubuntu-latest + + steps: + - name: Checkout repository + uses: actions/checkout@v3 + + - name: Setup Node.js + uses: actions/setup-node@v3 + with: + node-version: ${{ env.NODE_VERSION }} + + - name: Install Task + uses: arduino/setup-task@v1 + with: + repo-token: ${{ secrets.GITHUB_TOKEN }} + version: 3.x + + - name: Check links + run: task --silent markdown:check-links diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..096746c --- /dev/null +++ b/.gitignore @@ -0,0 +1 @@ +/node_modules/ \ No newline at end of file diff --git a/.markdown-link-check.json b/.markdown-link-check.json new file mode 100644 index 0000000..c5e178d --- /dev/null +++ b/.markdown-link-check.json @@ -0,0 +1,13 @@ +{ + "httpHeaders": [ + { + "urls": ["https://docs.github.com/"], + "headers": { + "Accept-Encoding": "gzip, deflate, br" + } + } + ], + "retryOn429": true, + "retryCount": 3, + "aliveStatusCodes": [200, 206] +} diff --git a/.markdownlint.yml b/.markdownlint.yml new file mode 100644 index 0000000..65b6ef7 --- /dev/null +++ b/.markdownlint.yml @@ -0,0 +1,62 @@ +# Source: https://github.com/arduino/tooling-project-assets/blob/main/workflow-templates/assets/check-markdown/.markdownlint.yml +# See: https://github.com/DavidAnson/markdownlint/blob/main/doc/Rules.md +# The code style defined in this file is the official standardized style to be used in all Arduino projects and should +# not be modified. +# Note: Rules disabled solely because they are redundant to Prettier are marked with a "Prettier" comment. + +default: false +MD001: false +MD002: false +MD003: false # Prettier +MD004: false # Prettier +MD005: false # Prettier +MD006: false # Prettier +MD007: false # Prettier +MD008: false # Prettier +MD009: + br_spaces: 0 + strict: true + list_item_empty_lines: false # Prettier +MD010: false # Prettier +MD011: true +MD012: false # Prettier +MD013: false +MD014: false +MD018: true +MD019: false # Prettier +MD020: true +MD021: false # Prettier +MD022: false # Prettier +MD023: false # Prettier +MD024: false +MD025: + level: 1 + front_matter_title: '^\s*"?title"?\s*[:=]' +MD026: false +MD027: false # Prettier +MD028: false +MD029: + style: one +MD030: + ul_single: 1 + ol_single: 1 + ul_multi: 1 + ol_multi: 1 +MD031: false # Prettier +MD032: false # Prettier +MD033: false +MD034: false +MD035: false # Prettier +MD036: false +MD037: true +MD038: true +MD039: true +MD040: false +MD041: false +MD042: true +MD043: false +MD044: false +MD045: true +MD046: + style: fenced +MD047: false # Prettier diff --git a/.markdownlintignore b/.markdownlintignore new file mode 100644 index 0000000..0022748 --- /dev/null +++ b/.markdownlintignore @@ -0,0 +1,4 @@ +# Source: https://github.com/arduino/tooling-project-assets/blob/main/workflow-templates/assets/check-markdown/.markdownlintignore +.licenses/ +__pycache__/ +node_modules/ diff --git a/README.md b/README.md index bdd52b5..e423cb2 100644 --- a/README.md +++ b/README.md @@ -1,8 +1,9 @@ [![GoDoc](https://godoc.org/github.com/arduino/go-properties-orderedmap?status.svg)](https://godoc.org/github.com/arduino/go-properties-orderedmap) [![Check License status](https://github.com/arduino/go-properties-orderedmap/actions/workflows/check-license.yml/badge.svg)](https://github.com/arduino/go-properties-orderedmap/actions/workflows/check-license.yml) +[![Check Markdown status](https://github.com/arduino/go-properties-orderedmap/actions/workflows/check-markdown-task.yml/badge.svg)](https://github.com/arduino/go-properties-orderedmap/actions/workflows/check-markdown-task.yml) -Package `properties` is a library for handling maps of hierarchical properties. +Package `properties` is a library for handling maps of hierarchical properties. This library is mainly used in the Arduino platform software to handle configurations made of key/value pairs stored in files with an INI like diff --git a/Taskfile.yml b/Taskfile.yml index 1876b50..4e545dc 100644 --- a/Taskfile.yml +++ b/Taskfile.yml @@ -25,3 +25,88 @@ tasks: - task: general:cache-dep-licenses cmds: - licensed status + + docs:generate: + desc: Create all generated documentation content + # This is an "umbrella" task used to call any documentation generation processes the project has. + # It can be left empty if there are none. + + # Source: https://github.com/arduino/tooling-project-assets/blob/main/workflow-templates/assets/check-markdown-task/Taskfile.yml + markdown:check-links: + desc: Check for broken links + deps: + - task: docs:generate + - task: npm:install-deps + cmds: + - | + if [[ "{{.OS}}" == "Windows_NT" ]]; then + # npx --call uses the native shell, which makes it too difficult to use npx for this application on Windows, + # so the Windows user is required to have markdown-link-check installed and in PATH. + if ! which markdown-link-check &>/dev/null; then + echo "markdown-link-check not found or not in PATH. Please install: https://github.com/tcort/markdown-link-check#readme" + exit 1 + fi + # Default behavior of the task on Windows is to exit the task when the first broken link causes a non-zero + # exit status, but it's better to check all links before exiting. + set +o errexit + STATUS=0 + # Using -regex instead of -name to avoid Task's behavior of globbing even when quoted on Windows + # The odd method for escaping . in the regex is required for windows compatibility because mvdan.cc/sh gives + # \ characters special treatment on Windows in an attempt to support them as path separators. + for file in $( + find . \ + -type d -name '.git' -prune -o \ + -type d -name '.licenses' -prune -o \ + -type d -name '__pycache__' -prune -o \ + -type d -name 'node_modules' -prune -o \ + -regex ".*[.]md" -print + ); do + markdown-link-check \ + --quiet \ + --config "./.markdown-link-check.json" \ + "$file" + STATUS=$(( $STATUS + $? )) + done + exit $STATUS + else + npx --package=markdown-link-check --call=' + STATUS=0 + for file in $( + find . \ + -type d -name '.git' -prune -o \ + -type d -name '.licenses' -prune -o \ + -type d -name '__pycache__' -prune -o \ + -type d -name 'node_modules' -prune -o \ + -regex ".*[.]md" -print + ); do + markdown-link-check \ + --quiet \ + --config "./.markdown-link-check.json" \ + "$file" + STATUS=$(( $STATUS + $? )) + done + exit $STATUS + ' + fi + + # Source: https://github.com/arduino/tooling-project-assets/blob/main/workflow-templates/assets/check-markdown-task/Taskfile.yml + markdown:fix: + desc: Automatically correct linting violations in Markdown files where possible + deps: + - task: npm:install-deps + cmds: + - npx markdownlint-cli --fix "**/*.md" + + # Source: https://github.com/arduino/tooling-project-assets/blob/main/workflow-templates/assets/check-markdown-task/Taskfile.yml + markdown:lint: + desc: Check for problems in Markdown files + deps: + - task: npm:install-deps + cmds: + - npx markdownlint-cli "**/*.md" + + # Source: https://github.com/arduino/tooling-project-assets/blob/main/workflow-templates/assets/npm-task/Taskfile.yml + npm:install-deps: + desc: Install dependencies managed by npm + cmds: + - npm install diff --git a/package-lock.json b/package-lock.json new file mode 100644 index 0000000..8117505 --- /dev/null +++ b/package-lock.json @@ -0,0 +1,1318 @@ +{ + "name": "go-properties-orderedmap", + "lockfileVersion": 2, + "requires": true, + "packages": { + "": { + "devDependencies": { + "markdown-link-check": "^3.10.2", + "markdownlint-cli": "^0.32.1" + } + }, + "node_modules/ansi-styles": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", + "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", + "dev": true, + "dependencies": { + "color-convert": "^2.0.1" + }, + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/chalk/ansi-styles?sponsor=1" + } + }, + "node_modules/argparse": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/argparse/-/argparse-2.0.1.tgz", + "integrity": "sha512-8+9WqebbFzpX9OR+Wa6O29asIogeRMzcGtAINdpMHHyAg10f05aSFVBbcEqGf/PXw1EjAZ+q2/bEBg3DvurK3Q==", + "dev": true + }, + "node_modules/async": { + "version": "3.2.4", + "resolved": "https://registry.npmjs.org/async/-/async-3.2.4.tgz", + "integrity": "sha512-iAB+JbDEGXhyIUavoDl9WP/Jj106Kz9DEn1DPgYw5ruDn0e3Wgi3sKFm55sASdGBNOQB8F59d9qQ7deqrHA8wQ==", + "dev": true + }, + "node_modules/balanced-match": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-1.0.2.tgz", + "integrity": "sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw==", + "dev": true + }, + "node_modules/boolbase": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/boolbase/-/boolbase-1.0.0.tgz", + "integrity": "sha512-JZOSA7Mo9sNGB8+UjSgzdLtokWAky1zbztM3WRLCbZ70/3cTANmQmOdR7y2g+J0e2WXywy1yS468tY+IruqEww==", + "dev": true + }, + "node_modules/brace-expansion": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-2.0.1.tgz", + "integrity": "sha512-XnAIvQ8eM+kC6aULx6wuQiwVsnzsi9d3WxzV3FpWTGA19F621kwdbsAcFKXgKUHZWsy+mY6iL1sHTxWEFCytDA==", + "dev": true, + "dependencies": { + "balanced-match": "^1.0.0" + } + }, + "node_modules/chalk": { + "version": "4.1.2", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz", + "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==", + "dev": true, + "dependencies": { + "ansi-styles": "^4.1.0", + "supports-color": "^7.1.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/chalk/chalk?sponsor=1" + } + }, + "node_modules/cheerio": { + "version": "1.0.0-rc.12", + "resolved": "https://registry.npmjs.org/cheerio/-/cheerio-1.0.0-rc.12.tgz", + "integrity": "sha512-VqR8m68vM46BNnuZ5NtnGBKIE/DfN0cRIzg9n40EIq9NOv90ayxLBXA8fXC5gquFRGJSTRqBq25Jt2ECLR431Q==", + "dev": true, + "dependencies": { + "cheerio-select": "^2.1.0", + "dom-serializer": "^2.0.0", + "domhandler": "^5.0.3", + "domutils": "^3.0.1", + "htmlparser2": "^8.0.1", + "parse5": "^7.0.0", + "parse5-htmlparser2-tree-adapter": "^7.0.0" + }, + "engines": { + "node": ">= 6" + }, + "funding": { + "url": "https://github.com/cheeriojs/cheerio?sponsor=1" + } + }, + "node_modules/cheerio-select": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/cheerio-select/-/cheerio-select-2.1.0.tgz", + "integrity": "sha512-9v9kG0LvzrlcungtnJtpGNxY+fzECQKhK4EGJX2vByejiMX84MFNQw4UxPJl3bFbTMw+Dfs37XaIkCwTZfLh4g==", + "dev": true, + "dependencies": { + "boolbase": "^1.0.0", + "css-select": "^5.1.0", + "css-what": "^6.1.0", + "domelementtype": "^2.3.0", + "domhandler": "^5.0.3", + "domutils": "^3.0.1" + }, + "funding": { + "url": "https://github.com/sponsors/fb55" + } + }, + "node_modules/color-convert": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", + "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", + "dev": true, + "dependencies": { + "color-name": "~1.1.4" + }, + "engines": { + "node": ">=7.0.0" + } + }, + "node_modules/color-name": { + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", + "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==", + "dev": true + }, + "node_modules/commander": { + "version": "6.2.1", + "resolved": "https://registry.npmjs.org/commander/-/commander-6.2.1.tgz", + "integrity": "sha512-U7VdrJFnJgo4xjrHpTzu0yrHPGImdsmD95ZlgYSEajAn2JKzDhDTPG9kBTefmObL2w/ngeZnilk+OV9CG3d7UA==", + "dev": true, + "engines": { + "node": ">= 6" + } + }, + "node_modules/css-select": { + "version": "5.1.0", + "resolved": "https://registry.npmjs.org/css-select/-/css-select-5.1.0.tgz", + "integrity": "sha512-nwoRF1rvRRnnCqqY7updORDsuqKzqYJ28+oSMaJMMgOauh3fvwHqMS7EZpIPqK8GL+g9mKxF1vP/ZjSeNjEVHg==", + "dev": true, + "dependencies": { + "boolbase": "^1.0.0", + "css-what": "^6.1.0", + "domhandler": "^5.0.2", + "domutils": "^3.0.1", + "nth-check": "^2.0.1" + }, + "funding": { + "url": "https://github.com/sponsors/fb55" + } + }, + "node_modules/css-what": { + "version": "6.1.0", + "resolved": "https://registry.npmjs.org/css-what/-/css-what-6.1.0.tgz", + "integrity": "sha512-HTUrgRJ7r4dsZKU6GjmpfRK1O76h97Z8MfS1G0FozR+oF2kG6Vfe8JE6zwrkbxigziPHinCJ+gCPjA9EaBDtRw==", + "dev": true, + "engines": { + "node": ">= 6" + }, + "funding": { + "url": "https://github.com/sponsors/fb55" + } + }, + "node_modules/debug": { + "version": "3.2.7", + "resolved": "https://registry.npmjs.org/debug/-/debug-3.2.7.tgz", + "integrity": "sha512-CFjzYYAi4ThfiQvizrFQevTTXHtnCqWfe7x1AhgEscTz6ZbLbfoLRLPugTQyBth6f8ZERVUSyWHFD/7Wu4t1XQ==", + "dev": true, + "dependencies": { + "ms": "^2.1.1" + } + }, + "node_modules/deep-extend": { + "version": "0.6.0", + "resolved": "https://registry.npmjs.org/deep-extend/-/deep-extend-0.6.0.tgz", + "integrity": "sha512-LOHxIOaPYdHlJRtCQfDIVZtfw/ufM8+rVj649RIHzcm/vGwQRXFt6OPqIFWsm2XEMrNIEtWR64sY1LEKD2vAOA==", + "dev": true, + "engines": { + "node": ">=4.0.0" + } + }, + "node_modules/dom-serializer": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/dom-serializer/-/dom-serializer-2.0.0.tgz", + "integrity": "sha512-wIkAryiqt/nV5EQKqQpo3SToSOV9J0DnbJqwK7Wv/Trc92zIAYZ4FlMu+JPFW1DfGFt81ZTCGgDEabffXeLyJg==", + "dev": true, + "dependencies": { + "domelementtype": "^2.3.0", + "domhandler": "^5.0.2", + "entities": "^4.2.0" + }, + "funding": { + "url": "https://github.com/cheeriojs/dom-serializer?sponsor=1" + } + }, + "node_modules/domelementtype": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/domelementtype/-/domelementtype-2.3.0.tgz", + "integrity": "sha512-OLETBj6w0OsagBwdXnPdN0cnMfF9opN69co+7ZrbfPGrdpPVNBUj02spi6B1N7wChLQiPn4CSH/zJvXw56gmHw==", + "dev": true, + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/fb55" + } + ] + }, + "node_modules/domhandler": { + "version": "5.0.3", + "resolved": "https://registry.npmjs.org/domhandler/-/domhandler-5.0.3.tgz", + "integrity": "sha512-cgwlv/1iFQiFnU96XXgROh8xTeetsnJiDsTc7TYCLFd9+/WNkIqPTxiM/8pSd8VIrhXGTf1Ny1q1hquVqDJB5w==", + "dev": true, + "dependencies": { + "domelementtype": "^2.3.0" + }, + "engines": { + "node": ">= 4" + }, + "funding": { + "url": "https://github.com/fb55/domhandler?sponsor=1" + } + }, + "node_modules/domutils": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/domutils/-/domutils-3.0.1.tgz", + "integrity": "sha512-z08c1l761iKhDFtfXO04C7kTdPBLi41zwOZl00WS8b5eiaebNpY00HKbztwBq+e3vyqWNwWF3mP9YLUeqIrF+Q==", + "dev": true, + "dependencies": { + "dom-serializer": "^2.0.0", + "domelementtype": "^2.3.0", + "domhandler": "^5.0.1" + }, + "funding": { + "url": "https://github.com/fb55/domutils?sponsor=1" + } + }, + "node_modules/entities": { + "version": "4.3.1", + "resolved": "https://registry.npmjs.org/entities/-/entities-4.3.1.tgz", + "integrity": "sha512-o4q/dYJlmyjP2zfnaWDUC6A3BQFmVTX+tZPezK7k0GLSU9QYCauscf5Y+qcEPzKL+EixVouYDgLQK5H9GrLpkg==", + "dev": true, + "engines": { + "node": ">=0.12" + }, + "funding": { + "url": "https://github.com/fb55/entities?sponsor=1" + } + }, + "node_modules/fs.realpath": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/fs.realpath/-/fs.realpath-1.0.0.tgz", + "integrity": "sha512-OO0pH2lK6a0hZnAdau5ItzHPI6pUlvI7jMVnxUQRtw4owF2wk8lOSabtGDCTP4Ggrg2MbGnWO9X8K1t4+fGMDw==", + "dev": true + }, + "node_modules/get-stdin": { + "version": "9.0.0", + "resolved": "https://registry.npmjs.org/get-stdin/-/get-stdin-9.0.0.tgz", + "integrity": "sha512-dVKBjfWisLAicarI2Sf+JuBE/DghV4UzNAVe9yhEJuzeREd3JhOTE9cUaJTeSa77fsbQUK3pcOpJfM59+VKZaA==", + "dev": true, + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/glob": { + "version": "8.0.3", + "resolved": "https://registry.npmjs.org/glob/-/glob-8.0.3.tgz", + "integrity": "sha512-ull455NHSHI/Y1FqGaaYFaLGkNMMJbavMrEGFXG/PGrg6y7sutWHUHrz6gy6WEBH6akM1M414dWKCNs+IhKdiQ==", + "dev": true, + "dependencies": { + "fs.realpath": "^1.0.0", + "inflight": "^1.0.4", + "inherits": "2", + "minimatch": "^5.0.1", + "once": "^1.3.0" + }, + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" + } + }, + "node_modules/has-flag": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", + "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==", + "dev": true, + "engines": { + "node": ">=8" + } + }, + "node_modules/html-link-extractor": { + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/html-link-extractor/-/html-link-extractor-1.0.5.tgz", + "integrity": "sha512-ADd49pudM157uWHwHQPUSX4ssMsvR/yHIswOR5CUfBdK9g9ZYGMhVSE6KZVHJ6kCkR0gH4htsfzU6zECDNVwyw==", + "dev": true, + "dependencies": { + "cheerio": "^1.0.0-rc.10" + } + }, + "node_modules/htmlparser2": { + "version": "8.0.1", + "resolved": "https://registry.npmjs.org/htmlparser2/-/htmlparser2-8.0.1.tgz", + "integrity": "sha512-4lVbmc1diZC7GUJQtRQ5yBAeUCL1exyMwmForWkRLnwyzWBFxN633SALPMGYaWZvKe9j1pRZJpauvmxENSp/EA==", + "dev": true, + "funding": [ + "https://github.com/fb55/htmlparser2?sponsor=1", + { + "type": "github", + "url": "https://github.com/sponsors/fb55" + } + ], + "dependencies": { + "domelementtype": "^2.3.0", + "domhandler": "^5.0.2", + "domutils": "^3.0.1", + "entities": "^4.3.0" + } + }, + "node_modules/iconv-lite": { + "version": "0.6.3", + "resolved": "https://registry.npmjs.org/iconv-lite/-/iconv-lite-0.6.3.tgz", + "integrity": "sha512-4fCk79wshMdzMp2rH06qWrJE4iolqLhCUH+OiuIgU++RB0+94NlDL81atO7GX55uUKueo0txHNtvEyI6D7WdMw==", + "dev": true, + "dependencies": { + "safer-buffer": ">= 2.1.2 < 3.0.0" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/ignore": { + "version": "5.2.0", + "resolved": "https://registry.npmjs.org/ignore/-/ignore-5.2.0.tgz", + "integrity": "sha512-CmxgYGiEPCLhfLnpPp1MoRmifwEIOgjcHXxOBjv7mY96c+eWScsOP9c112ZyLdWHi0FxHjI+4uVhKYp/gcdRmQ==", + "dev": true, + "engines": { + "node": ">= 4" + } + }, + "node_modules/inflight": { + "version": "1.0.6", + "resolved": "https://registry.npmjs.org/inflight/-/inflight-1.0.6.tgz", + "integrity": "sha512-k92I/b08q4wvFscXCLvqfsHCrjrF7yiXsQuIVvVE7N82W3+aqpzuUdBbfhWcy/FZR3/4IgflMgKLOsvPDrGCJA==", + "dev": true, + "dependencies": { + "once": "^1.3.0", + "wrappy": "1" + } + }, + "node_modules/inherits": { + "version": "2.0.4", + "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.4.tgz", + "integrity": "sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ==", + "dev": true + }, + "node_modules/ini": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/ini/-/ini-3.0.0.tgz", + "integrity": "sha512-TxYQaeNW/N8ymDvwAxPyRbhMBtnEwuvaTYpOQkFx1nSeusgezHniEc/l35Vo4iCq/mMiTJbpD7oYxN98hFlfmw==", + "dev": true, + "engines": { + "node": "^12.13.0 || ^14.15.0 || >=16.0.0" + } + }, + "node_modules/is-absolute-url": { + "version": "3.0.3", + "resolved": "https://registry.npmjs.org/is-absolute-url/-/is-absolute-url-3.0.3.tgz", + "integrity": "sha512-opmNIX7uFnS96NtPmhWQgQx6/NYFgsUXYMllcfzwWKUMwfo8kku1TvE6hkNcH+Q1ts5cMVrsY7j0bxXQDciu9Q==", + "dev": true, + "engines": { + "node": ">=8" + } + }, + "node_modules/is-relative-url": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/is-relative-url/-/is-relative-url-3.0.0.tgz", + "integrity": "sha512-U1iSYRlY2GIMGuZx7gezlB5dp1Kheaym7zKzO1PV06mOihiWTXejLwm4poEJysPyXF+HtK/BEd0DVlcCh30pEA==", + "dev": true, + "dependencies": { + "is-absolute-url": "^3.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/isemail": { + "version": "3.2.0", + "resolved": "https://registry.npmjs.org/isemail/-/isemail-3.2.0.tgz", + "integrity": "sha512-zKqkK+O+dGqevc93KNsbZ/TqTUFd46MwWjYOoMrjIMZ51eU7DtQG3Wmd9SQQT7i7RVnuTPEiYEWHU3MSbxC1Tg==", + "dev": true, + "dependencies": { + "punycode": "2.x.x" + }, + "engines": { + "node": ">=4.0.0" + } + }, + "node_modules/js-yaml": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-4.1.0.tgz", + "integrity": "sha512-wpxZs9NoxZaJESJGIZTyDEaYpl0FKSA+FB9aJiyemKhMwkxQg63h4T1KJgUGHpTqPDNRcmmYLugrRjJlBtWvRA==", + "dev": true, + "dependencies": { + "argparse": "^2.0.1" + }, + "bin": { + "js-yaml": "bin/js-yaml.js" + } + }, + "node_modules/jsonc-parser": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/jsonc-parser/-/jsonc-parser-3.1.0.tgz", + "integrity": "sha512-DRf0QjnNeCUds3xTjKlQQ3DpJD51GvDjJfnxUVWg6PZTo2otSm+slzNAxU/35hF8/oJIKoG9slq30JYOsF2azg==", + "dev": true + }, + "node_modules/link-check": { + "version": "5.1.0", + "resolved": "https://registry.npmjs.org/link-check/-/link-check-5.1.0.tgz", + "integrity": "sha512-FHq/9tVnIE/3EVEPb91GcbD+K/Pv5K5DYqb7vXi3TTKIViMYPOWxYFVVENZ0rq63zfaGXGvLgPT9U6jOFc5JBw==", + "dev": true, + "dependencies": { + "is-relative-url": "^3.0.0", + "isemail": "^3.2.0", + "ms": "^2.1.3", + "needle": "^3.0.0" + } + }, + "node_modules/linkify-it": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/linkify-it/-/linkify-it-4.0.1.tgz", + "integrity": "sha512-C7bfi1UZmoj8+PQx22XyeXCuBlokoyWQL5pWSP+EI6nzRylyThouddufc2c1NDIcP9k5agmN9fLpA7VNJfIiqw==", + "dev": true, + "dependencies": { + "uc.micro": "^1.0.1" + } + }, + "node_modules/lodash": { + "version": "4.17.21", + "resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.21.tgz", + "integrity": "sha512-v2kDEe57lecTulaDIuNTPy3Ry4gLGJ6Z1O3vE1krgXZNrsQ+LFTGHVxVjcXPs17LhbZVGedAJv8XZ1tvj5FvSg==", + "dev": true + }, + "node_modules/markdown-it": { + "version": "13.0.1", + "resolved": "https://registry.npmjs.org/markdown-it/-/markdown-it-13.0.1.tgz", + "integrity": "sha512-lTlxriVoy2criHP0JKRhO2VDG9c2ypWCsT237eDiLqi09rmbKoUetyGHq2uOIRoRS//kfoJckS0eUzzkDR+k2Q==", + "dev": true, + "dependencies": { + "argparse": "^2.0.1", + "entities": "~3.0.1", + "linkify-it": "^4.0.1", + "mdurl": "^1.0.1", + "uc.micro": "^1.0.5" + }, + "bin": { + "markdown-it": "bin/markdown-it.js" + } + }, + "node_modules/markdown-it/node_modules/entities": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/entities/-/entities-3.0.1.tgz", + "integrity": "sha512-WiyBqoomrwMdFG1e0kqvASYfnlb0lp8M5o5Fw2OFq1hNZxxcNk8Ik0Xm7LxzBhuidnZB/UtBqVCgUz3kBOP51Q==", + "dev": true, + "engines": { + "node": ">=0.12" + }, + "funding": { + "url": "https://github.com/fb55/entities?sponsor=1" + } + }, + "node_modules/markdown-link-check": { + "version": "3.10.2", + "resolved": "https://registry.npmjs.org/markdown-link-check/-/markdown-link-check-3.10.2.tgz", + "integrity": "sha512-5yQEVtjLxAjxWy82+iTgxrekr1tuD4sKGgwXiyLrCep8RERFH3yCdpZdeA12em2S2SEwXGxp6qHI73jVhuScKA==", + "dev": true, + "dependencies": { + "async": "^3.2.3", + "chalk": "^4.1.2", + "commander": "^6.2.0", + "link-check": "^5.1.0", + "lodash": "^4.17.21", + "markdown-link-extractor": "^3.0.2", + "needle": "^3.1.0", + "progress": "^2.0.3" + }, + "bin": { + "markdown-link-check": "markdown-link-check" + } + }, + "node_modules/markdown-link-extractor": { + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/markdown-link-extractor/-/markdown-link-extractor-3.0.2.tgz", + "integrity": "sha512-vmTTAWSa49Lqojr6L4ALGLV0TLz4+1movDb6saDS6c6FLGGbPFSkhjevpXsQTXEYY9lCWYcVQqb7l41WEZsM7Q==", + "dev": true, + "dependencies": { + "html-link-extractor": "^1.0.3", + "marked": "^4.0.15" + } + }, + "node_modules/markdownlint": { + "version": "0.26.2", + "resolved": "https://registry.npmjs.org/markdownlint/-/markdownlint-0.26.2.tgz", + "integrity": "sha512-2Am42YX2Ex5SQhRq35HxYWDfz1NLEOZWWN25nqd2h3AHRKsGRE+Qg1gt1++exW792eXTrR4jCNHfShfWk9Nz8w==", + "dev": true, + "dependencies": { + "markdown-it": "13.0.1" + }, + "engines": { + "node": ">=14" + } + }, + "node_modules/markdownlint-cli": { + "version": "0.32.1", + "resolved": "https://registry.npmjs.org/markdownlint-cli/-/markdownlint-cli-0.32.1.tgz", + "integrity": "sha512-hVLQ+72b5esQd7I+IqzBEB4x/4C+wJaxS2M6nqaGoDwrtNY6gydGf5CIUJtQcXtqsM615++a8TZPsvEtH6H4gw==", + "dev": true, + "dependencies": { + "commander": "~9.4.0", + "get-stdin": "~9.0.0", + "glob": "~8.0.3", + "ignore": "~5.2.0", + "js-yaml": "^4.1.0", + "jsonc-parser": "~3.1.0", + "markdownlint": "~0.26.1", + "markdownlint-rule-helpers": "~0.17.1", + "minimatch": "~5.1.0", + "run-con": "~1.2.11" + }, + "bin": { + "markdownlint": "markdownlint.js" + }, + "engines": { + "node": ">=14" + } + }, + "node_modules/markdownlint-cli/node_modules/commander": { + "version": "9.4.0", + "resolved": "https://registry.npmjs.org/commander/-/commander-9.4.0.tgz", + "integrity": "sha512-sRPT+umqkz90UA8M1yqYfnHlZA7fF6nSphDtxeywPZ49ysjxDQybzk13CL+mXekDRG92skbcqCLVovuCusNmFw==", + "dev": true, + "engines": { + "node": "^12.20.0 || >=14" + } + }, + "node_modules/markdownlint-rule-helpers": { + "version": "0.17.2", + "resolved": "https://registry.npmjs.org/markdownlint-rule-helpers/-/markdownlint-rule-helpers-0.17.2.tgz", + "integrity": "sha512-XaeoW2NYSlWxMCZM2B3H7YTG6nlaLfkEZWMBhr4hSPlq9MuY2sy83+Xr89jXOqZMZYjvi5nBCGoFh7hHoPKZmA==", + "dev": true, + "engines": { + "node": ">=12" + } + }, + "node_modules/marked": { + "version": "4.0.18", + "resolved": "https://registry.npmjs.org/marked/-/marked-4.0.18.tgz", + "integrity": "sha512-wbLDJ7Zh0sqA0Vdg6aqlbT+yPxqLblpAZh1mK2+AO2twQkPywvvqQNfEPVwSSRjZ7dZcdeVBIAgiO7MMp3Dszw==", + "dev": true, + "bin": { + "marked": "bin/marked.js" + }, + "engines": { + "node": ">= 12" + } + }, + "node_modules/mdurl": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/mdurl/-/mdurl-1.0.1.tgz", + "integrity": "sha512-/sKlQJCBYVY9Ers9hqzKou4H6V5UWc/M59TH2dvkt+84itfnq7uFOMLpOiOS4ujvHP4etln18fmIxA5R5fll0g==", + "dev": true + }, + "node_modules/minimatch": { + "version": "5.1.0", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-5.1.0.tgz", + "integrity": "sha512-9TPBGGak4nHfGZsPBohm9AWg6NoT7QTCehS3BIJABslyZbzxfV78QM2Y6+i741OPZIafFAaiiEMh5OyIrJPgtg==", + "dev": true, + "dependencies": { + "brace-expansion": "^2.0.1" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/minimist": { + "version": "1.2.6", + "resolved": "https://registry.npmjs.org/minimist/-/minimist-1.2.6.tgz", + "integrity": "sha512-Jsjnk4bw3YJqYzbdyBiNsPWHPfO++UGG749Cxs6peCu5Xg4nrena6OVxOYxrQTqww0Jmwt+Ref8rggumkTLz9Q==", + "dev": true + }, + "node_modules/ms": { + "version": "2.1.3", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.3.tgz", + "integrity": "sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA==", + "dev": true + }, + "node_modules/needle": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/needle/-/needle-3.1.0.tgz", + "integrity": "sha512-gCE9weDhjVGCRqS8dwDR/D3GTAeyXLXuqp7I8EzH6DllZGXSUyxuqqLh+YX9rMAWaaTFyVAg6rHGL25dqvczKw==", + "dev": true, + "dependencies": { + "debug": "^3.2.6", + "iconv-lite": "^0.6.3", + "sax": "^1.2.4" + }, + "bin": { + "needle": "bin/needle" + }, + "engines": { + "node": ">= 4.4.x" + } + }, + "node_modules/nth-check": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/nth-check/-/nth-check-2.1.1.tgz", + "integrity": "sha512-lqjrjmaOoAnWfMmBPL+XNnynZh2+swxiX3WUE0s4yEHI6m+AwrK2UZOimIRl3X/4QctVqS8AiZjFqyOGrMXb/w==", + "dev": true, + "dependencies": { + "boolbase": "^1.0.0" + }, + "funding": { + "url": "https://github.com/fb55/nth-check?sponsor=1" + } + }, + "node_modules/once": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/once/-/once-1.4.0.tgz", + "integrity": "sha512-lNaJgI+2Q5URQBkccEKHTQOPaXdUxnZZElQTZY0MFUAuaEqe1E+Nyvgdz/aIyNi6Z9MzO5dv1H8n58/GELp3+w==", + "dev": true, + "dependencies": { + "wrappy": "1" + } + }, + "node_modules/parse5": { + "version": "7.0.0", + "resolved": "https://registry.npmjs.org/parse5/-/parse5-7.0.0.tgz", + "integrity": "sha512-y/t8IXSPWTuRZqXc0ajH/UwDj4mnqLEbSttNbThcFhGrZuOyoyvNBO85PBp2jQa55wY9d07PBNjsK8ZP3K5U6g==", + "dev": true, + "dependencies": { + "entities": "^4.3.0" + }, + "funding": { + "url": "https://github.com/inikulin/parse5?sponsor=1" + } + }, + "node_modules/parse5-htmlparser2-tree-adapter": { + "version": "7.0.0", + "resolved": "https://registry.npmjs.org/parse5-htmlparser2-tree-adapter/-/parse5-htmlparser2-tree-adapter-7.0.0.tgz", + "integrity": "sha512-B77tOZrqqfUfnVcOrUvfdLbz4pu4RopLD/4vmu3HUPswwTA8OH0EMW9BlWR2B0RCoiZRAHEUu7IxeP1Pd1UU+g==", + "dev": true, + "dependencies": { + "domhandler": "^5.0.2", + "parse5": "^7.0.0" + }, + "funding": { + "url": "https://github.com/inikulin/parse5?sponsor=1" + } + }, + "node_modules/progress": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/progress/-/progress-2.0.3.tgz", + "integrity": "sha512-7PiHtLll5LdnKIMw100I+8xJXR5gW2QwWYkT6iJva0bXitZKa/XMrSbdmg3r2Xnaidz9Qumd0VPaMrZlF9V9sA==", + "dev": true, + "engines": { + "node": ">=0.4.0" + } + }, + "node_modules/punycode": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/punycode/-/punycode-2.1.1.tgz", + "integrity": "sha512-XRsRjdf+j5ml+y/6GKHPZbrF/8p2Yga0JPtdqTIY2Xe5ohJPD9saDJJLPvp9+NSBprVvevdXZybnj2cv8OEd0A==", + "dev": true, + "engines": { + "node": ">=6" + } + }, + "node_modules/run-con": { + "version": "1.2.11", + "resolved": "https://registry.npmjs.org/run-con/-/run-con-1.2.11.tgz", + "integrity": "sha512-NEMGsUT+cglWkzEr4IFK21P4Jca45HqiAbIIZIBdX5+UZTB24Mb/21iNGgz9xZa8tL6vbW7CXmq7MFN42+VjNQ==", + "dev": true, + "dependencies": { + "deep-extend": "^0.6.0", + "ini": "~3.0.0", + "minimist": "^1.2.6", + "strip-json-comments": "~3.1.1" + }, + "bin": { + "run-con": "cli.js" + } + }, + "node_modules/safer-buffer": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/safer-buffer/-/safer-buffer-2.1.2.tgz", + "integrity": "sha512-YZo3K82SD7Riyi0E1EQPojLz7kpepnSQI9IyPbHHg1XXXevb5dJI7tpyN2ADxGcQbHG7vcyRHk0cbwqcQriUtg==", + "dev": true + }, + "node_modules/sax": { + "version": "1.2.4", + "resolved": "https://registry.npmjs.org/sax/-/sax-1.2.4.tgz", + "integrity": "sha512-NqVDv9TpANUjFm0N8uM5GxL36UgKi9/atZw+x7YFnQ8ckwFGKrl4xX4yWtrey3UJm5nP1kUbnYgLopqWNSRhWw==", + "dev": true + }, + "node_modules/strip-json-comments": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/strip-json-comments/-/strip-json-comments-3.1.1.tgz", + "integrity": "sha512-6fPc+R4ihwqP6N/aIv2f1gMH8lOVtWQHoqC4yK6oSDVVocumAsfCqjkXnqiYMhmMwS/mEHLp7Vehlt3ql6lEig==", + "dev": true, + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/supports-color": { + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", + "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==", + "dev": true, + "dependencies": { + "has-flag": "^4.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/uc.micro": { + "version": "1.0.6", + "resolved": "https://registry.npmjs.org/uc.micro/-/uc.micro-1.0.6.tgz", + "integrity": "sha512-8Y75pvTYkLJW2hWQHXxoqRgV7qb9B+9vFEtidML+7koHUFapnVJAZ6cKs+Qjz5Aw3aZWHMC6u0wJE3At+nSGwA==", + "dev": true + }, + "node_modules/wrappy": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/wrappy/-/wrappy-1.0.2.tgz", + "integrity": "sha512-l4Sp/DRseor9wL6EvV2+TuQn63dMkPjZ/sp9XkghTEbV9KlPS1xUsZ3u7/IQO4wxtcFB4bgpQPRcR3QCvezPcQ==", + "dev": true + } + }, + "dependencies": { + "ansi-styles": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", + "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", + "dev": true, + "requires": { + "color-convert": "^2.0.1" + } + }, + "argparse": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/argparse/-/argparse-2.0.1.tgz", + "integrity": "sha512-8+9WqebbFzpX9OR+Wa6O29asIogeRMzcGtAINdpMHHyAg10f05aSFVBbcEqGf/PXw1EjAZ+q2/bEBg3DvurK3Q==", + "dev": true + }, + "async": { + "version": "3.2.4", + "resolved": "https://registry.npmjs.org/async/-/async-3.2.4.tgz", + "integrity": "sha512-iAB+JbDEGXhyIUavoDl9WP/Jj106Kz9DEn1DPgYw5ruDn0e3Wgi3sKFm55sASdGBNOQB8F59d9qQ7deqrHA8wQ==", + "dev": true + }, + "balanced-match": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-1.0.2.tgz", + "integrity": "sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw==", + "dev": true + }, + "boolbase": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/boolbase/-/boolbase-1.0.0.tgz", + "integrity": "sha512-JZOSA7Mo9sNGB8+UjSgzdLtokWAky1zbztM3WRLCbZ70/3cTANmQmOdR7y2g+J0e2WXywy1yS468tY+IruqEww==", + "dev": true + }, + "brace-expansion": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-2.0.1.tgz", + "integrity": "sha512-XnAIvQ8eM+kC6aULx6wuQiwVsnzsi9d3WxzV3FpWTGA19F621kwdbsAcFKXgKUHZWsy+mY6iL1sHTxWEFCytDA==", + "dev": true, + "requires": { + "balanced-match": "^1.0.0" + } + }, + "chalk": { + "version": "4.1.2", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz", + "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==", + "dev": true, + "requires": { + "ansi-styles": "^4.1.0", + "supports-color": "^7.1.0" + } + }, + "cheerio": { + "version": "1.0.0-rc.12", + "resolved": "https://registry.npmjs.org/cheerio/-/cheerio-1.0.0-rc.12.tgz", + "integrity": "sha512-VqR8m68vM46BNnuZ5NtnGBKIE/DfN0cRIzg9n40EIq9NOv90ayxLBXA8fXC5gquFRGJSTRqBq25Jt2ECLR431Q==", + "dev": true, + "requires": { + "cheerio-select": "^2.1.0", + "dom-serializer": "^2.0.0", + "domhandler": "^5.0.3", + "domutils": "^3.0.1", + "htmlparser2": "^8.0.1", + "parse5": "^7.0.0", + "parse5-htmlparser2-tree-adapter": "^7.0.0" + } + }, + "cheerio-select": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/cheerio-select/-/cheerio-select-2.1.0.tgz", + "integrity": "sha512-9v9kG0LvzrlcungtnJtpGNxY+fzECQKhK4EGJX2vByejiMX84MFNQw4UxPJl3bFbTMw+Dfs37XaIkCwTZfLh4g==", + "dev": true, + "requires": { + "boolbase": "^1.0.0", + "css-select": "^5.1.0", + "css-what": "^6.1.0", + "domelementtype": "^2.3.0", + "domhandler": "^5.0.3", + "domutils": "^3.0.1" + } + }, + "color-convert": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", + "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", + "dev": true, + "requires": { + "color-name": "~1.1.4" + } + }, + "color-name": { + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", + "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==", + "dev": true + }, + "commander": { + "version": "6.2.1", + "resolved": "https://registry.npmjs.org/commander/-/commander-6.2.1.tgz", + "integrity": "sha512-U7VdrJFnJgo4xjrHpTzu0yrHPGImdsmD95ZlgYSEajAn2JKzDhDTPG9kBTefmObL2w/ngeZnilk+OV9CG3d7UA==", + "dev": true + }, + "css-select": { + "version": "5.1.0", + "resolved": "https://registry.npmjs.org/css-select/-/css-select-5.1.0.tgz", + "integrity": "sha512-nwoRF1rvRRnnCqqY7updORDsuqKzqYJ28+oSMaJMMgOauh3fvwHqMS7EZpIPqK8GL+g9mKxF1vP/ZjSeNjEVHg==", + "dev": true, + "requires": { + "boolbase": "^1.0.0", + "css-what": "^6.1.0", + "domhandler": "^5.0.2", + "domutils": "^3.0.1", + "nth-check": "^2.0.1" + } + }, + "css-what": { + "version": "6.1.0", + "resolved": "https://registry.npmjs.org/css-what/-/css-what-6.1.0.tgz", + "integrity": "sha512-HTUrgRJ7r4dsZKU6GjmpfRK1O76h97Z8MfS1G0FozR+oF2kG6Vfe8JE6zwrkbxigziPHinCJ+gCPjA9EaBDtRw==", + "dev": true + }, + "debug": { + "version": "3.2.7", + "resolved": "https://registry.npmjs.org/debug/-/debug-3.2.7.tgz", + "integrity": "sha512-CFjzYYAi4ThfiQvizrFQevTTXHtnCqWfe7x1AhgEscTz6ZbLbfoLRLPugTQyBth6f8ZERVUSyWHFD/7Wu4t1XQ==", + "dev": true, + "requires": { + "ms": "^2.1.1" + } + }, + "deep-extend": { + "version": "0.6.0", + "resolved": "https://registry.npmjs.org/deep-extend/-/deep-extend-0.6.0.tgz", + "integrity": "sha512-LOHxIOaPYdHlJRtCQfDIVZtfw/ufM8+rVj649RIHzcm/vGwQRXFt6OPqIFWsm2XEMrNIEtWR64sY1LEKD2vAOA==", + "dev": true + }, + "dom-serializer": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/dom-serializer/-/dom-serializer-2.0.0.tgz", + "integrity": "sha512-wIkAryiqt/nV5EQKqQpo3SToSOV9J0DnbJqwK7Wv/Trc92zIAYZ4FlMu+JPFW1DfGFt81ZTCGgDEabffXeLyJg==", + "dev": true, + "requires": { + "domelementtype": "^2.3.0", + "domhandler": "^5.0.2", + "entities": "^4.2.0" + } + }, + "domelementtype": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/domelementtype/-/domelementtype-2.3.0.tgz", + "integrity": "sha512-OLETBj6w0OsagBwdXnPdN0cnMfF9opN69co+7ZrbfPGrdpPVNBUj02spi6B1N7wChLQiPn4CSH/zJvXw56gmHw==", + "dev": true + }, + "domhandler": { + "version": "5.0.3", + "resolved": "https://registry.npmjs.org/domhandler/-/domhandler-5.0.3.tgz", + "integrity": "sha512-cgwlv/1iFQiFnU96XXgROh8xTeetsnJiDsTc7TYCLFd9+/WNkIqPTxiM/8pSd8VIrhXGTf1Ny1q1hquVqDJB5w==", + "dev": true, + "requires": { + "domelementtype": "^2.3.0" + } + }, + "domutils": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/domutils/-/domutils-3.0.1.tgz", + "integrity": "sha512-z08c1l761iKhDFtfXO04C7kTdPBLi41zwOZl00WS8b5eiaebNpY00HKbztwBq+e3vyqWNwWF3mP9YLUeqIrF+Q==", + "dev": true, + "requires": { + "dom-serializer": "^2.0.0", + "domelementtype": "^2.3.0", + "domhandler": "^5.0.1" + } + }, + "entities": { + "version": "4.3.1", + "resolved": "https://registry.npmjs.org/entities/-/entities-4.3.1.tgz", + "integrity": "sha512-o4q/dYJlmyjP2zfnaWDUC6A3BQFmVTX+tZPezK7k0GLSU9QYCauscf5Y+qcEPzKL+EixVouYDgLQK5H9GrLpkg==", + "dev": true + }, + "fs.realpath": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/fs.realpath/-/fs.realpath-1.0.0.tgz", + "integrity": "sha512-OO0pH2lK6a0hZnAdau5ItzHPI6pUlvI7jMVnxUQRtw4owF2wk8lOSabtGDCTP4Ggrg2MbGnWO9X8K1t4+fGMDw==", + "dev": true + }, + "get-stdin": { + "version": "9.0.0", + "resolved": "https://registry.npmjs.org/get-stdin/-/get-stdin-9.0.0.tgz", + "integrity": "sha512-dVKBjfWisLAicarI2Sf+JuBE/DghV4UzNAVe9yhEJuzeREd3JhOTE9cUaJTeSa77fsbQUK3pcOpJfM59+VKZaA==", + "dev": true + }, + "glob": { + "version": "8.0.3", + "resolved": "https://registry.npmjs.org/glob/-/glob-8.0.3.tgz", + "integrity": "sha512-ull455NHSHI/Y1FqGaaYFaLGkNMMJbavMrEGFXG/PGrg6y7sutWHUHrz6gy6WEBH6akM1M414dWKCNs+IhKdiQ==", + "dev": true, + "requires": { + "fs.realpath": "^1.0.0", + "inflight": "^1.0.4", + "inherits": "2", + "minimatch": "^5.0.1", + "once": "^1.3.0" + } + }, + "has-flag": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", + "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==", + "dev": true + }, + "html-link-extractor": { + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/html-link-extractor/-/html-link-extractor-1.0.5.tgz", + "integrity": "sha512-ADd49pudM157uWHwHQPUSX4ssMsvR/yHIswOR5CUfBdK9g9ZYGMhVSE6KZVHJ6kCkR0gH4htsfzU6zECDNVwyw==", + "dev": true, + "requires": { + "cheerio": "^1.0.0-rc.10" + } + }, + "htmlparser2": { + "version": "8.0.1", + "resolved": "https://registry.npmjs.org/htmlparser2/-/htmlparser2-8.0.1.tgz", + "integrity": "sha512-4lVbmc1diZC7GUJQtRQ5yBAeUCL1exyMwmForWkRLnwyzWBFxN633SALPMGYaWZvKe9j1pRZJpauvmxENSp/EA==", + "dev": true, + "requires": { + "domelementtype": "^2.3.0", + "domhandler": "^5.0.2", + "domutils": "^3.0.1", + "entities": "^4.3.0" + } + }, + "iconv-lite": { + "version": "0.6.3", + "resolved": "https://registry.npmjs.org/iconv-lite/-/iconv-lite-0.6.3.tgz", + "integrity": "sha512-4fCk79wshMdzMp2rH06qWrJE4iolqLhCUH+OiuIgU++RB0+94NlDL81atO7GX55uUKueo0txHNtvEyI6D7WdMw==", + "dev": true, + "requires": { + "safer-buffer": ">= 2.1.2 < 3.0.0" + } + }, + "ignore": { + "version": "5.2.0", + "resolved": "https://registry.npmjs.org/ignore/-/ignore-5.2.0.tgz", + "integrity": "sha512-CmxgYGiEPCLhfLnpPp1MoRmifwEIOgjcHXxOBjv7mY96c+eWScsOP9c112ZyLdWHi0FxHjI+4uVhKYp/gcdRmQ==", + "dev": true + }, + "inflight": { + "version": "1.0.6", + "resolved": "https://registry.npmjs.org/inflight/-/inflight-1.0.6.tgz", + "integrity": "sha512-k92I/b08q4wvFscXCLvqfsHCrjrF7yiXsQuIVvVE7N82W3+aqpzuUdBbfhWcy/FZR3/4IgflMgKLOsvPDrGCJA==", + "dev": true, + "requires": { + "once": "^1.3.0", + "wrappy": "1" + } + }, + "inherits": { + "version": "2.0.4", + "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.4.tgz", + "integrity": "sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ==", + "dev": true + }, + "ini": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/ini/-/ini-3.0.0.tgz", + "integrity": "sha512-TxYQaeNW/N8ymDvwAxPyRbhMBtnEwuvaTYpOQkFx1nSeusgezHniEc/l35Vo4iCq/mMiTJbpD7oYxN98hFlfmw==", + "dev": true + }, + "is-absolute-url": { + "version": "3.0.3", + "resolved": "https://registry.npmjs.org/is-absolute-url/-/is-absolute-url-3.0.3.tgz", + "integrity": "sha512-opmNIX7uFnS96NtPmhWQgQx6/NYFgsUXYMllcfzwWKUMwfo8kku1TvE6hkNcH+Q1ts5cMVrsY7j0bxXQDciu9Q==", + "dev": true + }, + "is-relative-url": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/is-relative-url/-/is-relative-url-3.0.0.tgz", + "integrity": "sha512-U1iSYRlY2GIMGuZx7gezlB5dp1Kheaym7zKzO1PV06mOihiWTXejLwm4poEJysPyXF+HtK/BEd0DVlcCh30pEA==", + "dev": true, + "requires": { + "is-absolute-url": "^3.0.0" + } + }, + "isemail": { + "version": "3.2.0", + "resolved": "https://registry.npmjs.org/isemail/-/isemail-3.2.0.tgz", + "integrity": "sha512-zKqkK+O+dGqevc93KNsbZ/TqTUFd46MwWjYOoMrjIMZ51eU7DtQG3Wmd9SQQT7i7RVnuTPEiYEWHU3MSbxC1Tg==", + "dev": true, + "requires": { + "punycode": "2.x.x" + } + }, + "js-yaml": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-4.1.0.tgz", + "integrity": "sha512-wpxZs9NoxZaJESJGIZTyDEaYpl0FKSA+FB9aJiyemKhMwkxQg63h4T1KJgUGHpTqPDNRcmmYLugrRjJlBtWvRA==", + "dev": true, + "requires": { + "argparse": "^2.0.1" + } + }, + "jsonc-parser": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/jsonc-parser/-/jsonc-parser-3.1.0.tgz", + "integrity": "sha512-DRf0QjnNeCUds3xTjKlQQ3DpJD51GvDjJfnxUVWg6PZTo2otSm+slzNAxU/35hF8/oJIKoG9slq30JYOsF2azg==", + "dev": true + }, + "link-check": { + "version": "5.1.0", + "resolved": "https://registry.npmjs.org/link-check/-/link-check-5.1.0.tgz", + "integrity": "sha512-FHq/9tVnIE/3EVEPb91GcbD+K/Pv5K5DYqb7vXi3TTKIViMYPOWxYFVVENZ0rq63zfaGXGvLgPT9U6jOFc5JBw==", + "dev": true, + "requires": { + "is-relative-url": "^3.0.0", + "isemail": "^3.2.0", + "ms": "^2.1.3", + "needle": "^3.0.0" + } + }, + "linkify-it": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/linkify-it/-/linkify-it-4.0.1.tgz", + "integrity": "sha512-C7bfi1UZmoj8+PQx22XyeXCuBlokoyWQL5pWSP+EI6nzRylyThouddufc2c1NDIcP9k5agmN9fLpA7VNJfIiqw==", + "dev": true, + "requires": { + "uc.micro": "^1.0.1" + } + }, + "lodash": { + "version": "4.17.21", + "resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.21.tgz", + "integrity": "sha512-v2kDEe57lecTulaDIuNTPy3Ry4gLGJ6Z1O3vE1krgXZNrsQ+LFTGHVxVjcXPs17LhbZVGedAJv8XZ1tvj5FvSg==", + "dev": true + }, + "markdown-it": { + "version": "13.0.1", + "resolved": "https://registry.npmjs.org/markdown-it/-/markdown-it-13.0.1.tgz", + "integrity": "sha512-lTlxriVoy2criHP0JKRhO2VDG9c2ypWCsT237eDiLqi09rmbKoUetyGHq2uOIRoRS//kfoJckS0eUzzkDR+k2Q==", + "dev": true, + "requires": { + "argparse": "^2.0.1", + "entities": "~3.0.1", + "linkify-it": "^4.0.1", + "mdurl": "^1.0.1", + "uc.micro": "^1.0.5" + }, + "dependencies": { + "entities": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/entities/-/entities-3.0.1.tgz", + "integrity": "sha512-WiyBqoomrwMdFG1e0kqvASYfnlb0lp8M5o5Fw2OFq1hNZxxcNk8Ik0Xm7LxzBhuidnZB/UtBqVCgUz3kBOP51Q==", + "dev": true + } + } + }, + "markdown-link-check": { + "version": "3.10.2", + "resolved": "https://registry.npmjs.org/markdown-link-check/-/markdown-link-check-3.10.2.tgz", + "integrity": "sha512-5yQEVtjLxAjxWy82+iTgxrekr1tuD4sKGgwXiyLrCep8RERFH3yCdpZdeA12em2S2SEwXGxp6qHI73jVhuScKA==", + "dev": true, + "requires": { + "async": "^3.2.3", + "chalk": "^4.1.2", + "commander": "^6.2.0", + "link-check": "^5.1.0", + "lodash": "^4.17.21", + "markdown-link-extractor": "^3.0.2", + "needle": "^3.1.0", + "progress": "^2.0.3" + } + }, + "markdown-link-extractor": { + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/markdown-link-extractor/-/markdown-link-extractor-3.0.2.tgz", + "integrity": "sha512-vmTTAWSa49Lqojr6L4ALGLV0TLz4+1movDb6saDS6c6FLGGbPFSkhjevpXsQTXEYY9lCWYcVQqb7l41WEZsM7Q==", + "dev": true, + "requires": { + "html-link-extractor": "^1.0.3", + "marked": "^4.0.15" + } + }, + "markdownlint": { + "version": "0.26.2", + "resolved": "https://registry.npmjs.org/markdownlint/-/markdownlint-0.26.2.tgz", + "integrity": "sha512-2Am42YX2Ex5SQhRq35HxYWDfz1NLEOZWWN25nqd2h3AHRKsGRE+Qg1gt1++exW792eXTrR4jCNHfShfWk9Nz8w==", + "dev": true, + "requires": { + "markdown-it": "13.0.1" + } + }, + "markdownlint-cli": { + "version": "0.32.1", + "resolved": "https://registry.npmjs.org/markdownlint-cli/-/markdownlint-cli-0.32.1.tgz", + "integrity": "sha512-hVLQ+72b5esQd7I+IqzBEB4x/4C+wJaxS2M6nqaGoDwrtNY6gydGf5CIUJtQcXtqsM615++a8TZPsvEtH6H4gw==", + "dev": true, + "requires": { + "commander": "~9.4.0", + "get-stdin": "~9.0.0", + "glob": "~8.0.3", + "ignore": "~5.2.0", + "js-yaml": "^4.1.0", + "jsonc-parser": "~3.1.0", + "markdownlint": "~0.26.1", + "markdownlint-rule-helpers": "~0.17.1", + "minimatch": "~5.1.0", + "run-con": "~1.2.11" + }, + "dependencies": { + "commander": { + "version": "9.4.0", + "resolved": "https://registry.npmjs.org/commander/-/commander-9.4.0.tgz", + "integrity": "sha512-sRPT+umqkz90UA8M1yqYfnHlZA7fF6nSphDtxeywPZ49ysjxDQybzk13CL+mXekDRG92skbcqCLVovuCusNmFw==", + "dev": true + } + } + }, + "markdownlint-rule-helpers": { + "version": "0.17.2", + "resolved": "https://registry.npmjs.org/markdownlint-rule-helpers/-/markdownlint-rule-helpers-0.17.2.tgz", + "integrity": "sha512-XaeoW2NYSlWxMCZM2B3H7YTG6nlaLfkEZWMBhr4hSPlq9MuY2sy83+Xr89jXOqZMZYjvi5nBCGoFh7hHoPKZmA==", + "dev": true + }, + "marked": { + "version": "4.0.18", + "resolved": "https://registry.npmjs.org/marked/-/marked-4.0.18.tgz", + "integrity": "sha512-wbLDJ7Zh0sqA0Vdg6aqlbT+yPxqLblpAZh1mK2+AO2twQkPywvvqQNfEPVwSSRjZ7dZcdeVBIAgiO7MMp3Dszw==", + "dev": true + }, + "mdurl": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/mdurl/-/mdurl-1.0.1.tgz", + "integrity": "sha512-/sKlQJCBYVY9Ers9hqzKou4H6V5UWc/M59TH2dvkt+84itfnq7uFOMLpOiOS4ujvHP4etln18fmIxA5R5fll0g==", + "dev": true + }, + "minimatch": { + "version": "5.1.0", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-5.1.0.tgz", + "integrity": "sha512-9TPBGGak4nHfGZsPBohm9AWg6NoT7QTCehS3BIJABslyZbzxfV78QM2Y6+i741OPZIafFAaiiEMh5OyIrJPgtg==", + "dev": true, + "requires": { + "brace-expansion": "^2.0.1" + } + }, + "minimist": { + "version": "1.2.6", + "resolved": "https://registry.npmjs.org/minimist/-/minimist-1.2.6.tgz", + "integrity": "sha512-Jsjnk4bw3YJqYzbdyBiNsPWHPfO++UGG749Cxs6peCu5Xg4nrena6OVxOYxrQTqww0Jmwt+Ref8rggumkTLz9Q==", + "dev": true + }, + "ms": { + "version": "2.1.3", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.3.tgz", + "integrity": "sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA==", + "dev": true + }, + "needle": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/needle/-/needle-3.1.0.tgz", + "integrity": "sha512-gCE9weDhjVGCRqS8dwDR/D3GTAeyXLXuqp7I8EzH6DllZGXSUyxuqqLh+YX9rMAWaaTFyVAg6rHGL25dqvczKw==", + "dev": true, + "requires": { + "debug": "^3.2.6", + "iconv-lite": "^0.6.3", + "sax": "^1.2.4" + } + }, + "nth-check": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/nth-check/-/nth-check-2.1.1.tgz", + "integrity": "sha512-lqjrjmaOoAnWfMmBPL+XNnynZh2+swxiX3WUE0s4yEHI6m+AwrK2UZOimIRl3X/4QctVqS8AiZjFqyOGrMXb/w==", + "dev": true, + "requires": { + "boolbase": "^1.0.0" + } + }, + "once": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/once/-/once-1.4.0.tgz", + "integrity": "sha512-lNaJgI+2Q5URQBkccEKHTQOPaXdUxnZZElQTZY0MFUAuaEqe1E+Nyvgdz/aIyNi6Z9MzO5dv1H8n58/GELp3+w==", + "dev": true, + "requires": { + "wrappy": "1" + } + }, + "parse5": { + "version": "7.0.0", + "resolved": "https://registry.npmjs.org/parse5/-/parse5-7.0.0.tgz", + "integrity": "sha512-y/t8IXSPWTuRZqXc0ajH/UwDj4mnqLEbSttNbThcFhGrZuOyoyvNBO85PBp2jQa55wY9d07PBNjsK8ZP3K5U6g==", + "dev": true, + "requires": { + "entities": "^4.3.0" + } + }, + "parse5-htmlparser2-tree-adapter": { + "version": "7.0.0", + "resolved": "https://registry.npmjs.org/parse5-htmlparser2-tree-adapter/-/parse5-htmlparser2-tree-adapter-7.0.0.tgz", + "integrity": "sha512-B77tOZrqqfUfnVcOrUvfdLbz4pu4RopLD/4vmu3HUPswwTA8OH0EMW9BlWR2B0RCoiZRAHEUu7IxeP1Pd1UU+g==", + "dev": true, + "requires": { + "domhandler": "^5.0.2", + "parse5": "^7.0.0" + } + }, + "progress": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/progress/-/progress-2.0.3.tgz", + "integrity": "sha512-7PiHtLll5LdnKIMw100I+8xJXR5gW2QwWYkT6iJva0bXitZKa/XMrSbdmg3r2Xnaidz9Qumd0VPaMrZlF9V9sA==", + "dev": true + }, + "punycode": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/punycode/-/punycode-2.1.1.tgz", + "integrity": "sha512-XRsRjdf+j5ml+y/6GKHPZbrF/8p2Yga0JPtdqTIY2Xe5ohJPD9saDJJLPvp9+NSBprVvevdXZybnj2cv8OEd0A==", + "dev": true + }, + "run-con": { + "version": "1.2.11", + "resolved": "https://registry.npmjs.org/run-con/-/run-con-1.2.11.tgz", + "integrity": "sha512-NEMGsUT+cglWkzEr4IFK21P4Jca45HqiAbIIZIBdX5+UZTB24Mb/21iNGgz9xZa8tL6vbW7CXmq7MFN42+VjNQ==", + "dev": true, + "requires": { + "deep-extend": "^0.6.0", + "ini": "~3.0.0", + "minimist": "^1.2.6", + "strip-json-comments": "~3.1.1" + } + }, + "safer-buffer": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/safer-buffer/-/safer-buffer-2.1.2.tgz", + "integrity": "sha512-YZo3K82SD7Riyi0E1EQPojLz7kpepnSQI9IyPbHHg1XXXevb5dJI7tpyN2ADxGcQbHG7vcyRHk0cbwqcQriUtg==", + "dev": true + }, + "sax": { + "version": "1.2.4", + "resolved": "https://registry.npmjs.org/sax/-/sax-1.2.4.tgz", + "integrity": "sha512-NqVDv9TpANUjFm0N8uM5GxL36UgKi9/atZw+x7YFnQ8ckwFGKrl4xX4yWtrey3UJm5nP1kUbnYgLopqWNSRhWw==", + "dev": true + }, + "strip-json-comments": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/strip-json-comments/-/strip-json-comments-3.1.1.tgz", + "integrity": "sha512-6fPc+R4ihwqP6N/aIv2f1gMH8lOVtWQHoqC4yK6oSDVVocumAsfCqjkXnqiYMhmMwS/mEHLp7Vehlt3ql6lEig==", + "dev": true + }, + "supports-color": { + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", + "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==", + "dev": true, + "requires": { + "has-flag": "^4.0.0" + } + }, + "uc.micro": { + "version": "1.0.6", + "resolved": "https://registry.npmjs.org/uc.micro/-/uc.micro-1.0.6.tgz", + "integrity": "sha512-8Y75pvTYkLJW2hWQHXxoqRgV7qb9B+9vFEtidML+7koHUFapnVJAZ6cKs+Qjz5Aw3aZWHMC6u0wJE3At+nSGwA==", + "dev": true + }, + "wrappy": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/wrappy/-/wrappy-1.0.2.tgz", + "integrity": "sha512-l4Sp/DRseor9wL6EvV2+TuQn63dMkPjZ/sp9XkghTEbV9KlPS1xUsZ3u7/IQO4wxtcFB4bgpQPRcR3QCvezPcQ==", + "dev": true + } + } +} diff --git a/package.json b/package.json new file mode 100644 index 0000000..7584ee5 --- /dev/null +++ b/package.json @@ -0,0 +1,6 @@ +{ + "devDependencies": { + "markdown-link-check": "^3.10.2", + "markdownlint-cli": "^0.32.1" + } +} From 05b5b8fea0c4e0d015034a7ebb8aaaebbd5362c1 Mon Sep 17 00:00:00 2001 From: Matteo Pologruto Date: Thu, 18 Aug 2022 10:26:11 +0200 Subject: [PATCH 24/48] Add CI workflow to validate Taskfiles On every push or pull request that affects the repository's Taskfiles, and periodically, validate them against the JSON schema. --- .github/workflows/check-taskfiles.yml | 71 +++++ README.md | 1 + package-lock.json | 401 ++++++++++++++++++++++++++ package.json | 2 + 4 files changed, 475 insertions(+) create mode 100644 .github/workflows/check-taskfiles.yml diff --git a/.github/workflows/check-taskfiles.yml b/.github/workflows/check-taskfiles.yml new file mode 100644 index 0000000..2bff3ca --- /dev/null +++ b/.github/workflows/check-taskfiles.yml @@ -0,0 +1,71 @@ +# Source: https://github.com/arduino/tooling-project-assets/blob/main/workflow-templates/check-taskfiles.md +name: Check Taskfiles + +env: + # See: https://github.com/actions/setup-node/#readme + NODE_VERSION: 16.x + +# See: https://docs.github.com/actions/using-workflows/events-that-trigger-workflows +on: + push: + paths: + - ".github/workflows/check-taskfiles.ya?ml" + - "package.json" + - "package-lock.json" + - "**/Taskfile.ya?ml" + pull_request: + paths: + - ".github/workflows/check-taskfiles.ya?ml" + - "package.json" + - "package-lock.json" + - "**/Taskfile.ya?ml" + schedule: + # Run every Tuesday at 8 AM UTC to catch breakage resulting from changes to the JSON schema. + - cron: "0 8 * * TUE" + workflow_dispatch: + repository_dispatch: + +jobs: + validate: + name: Validate ${{ matrix.file }} + runs-on: ubuntu-latest + + strategy: + fail-fast: false + + matrix: + file: + - ./**/Taskfile.yml + + steps: + - name: Checkout repository + uses: actions/checkout@v3 + + - name: Setup Node.js + uses: actions/setup-node@v3 + with: + node-version: ${{ env.NODE_VERSION }} + + - name: Download JSON schema for Taskfiles + id: download-schema + uses: carlosperate/download-file-action@v1 + with: + # See: https://github.com/SchemaStore/schemastore/blob/master/src/schemas/json/taskfile.json + file-url: https://json.schemastore.org/taskfile.json + location: ${{ runner.temp }}/taskfile-schema + + - name: Install JSON schema validator + run: npm install + + - name: Validate ${{ matrix.file }} + run: | + # See: https://github.com/ajv-validator/ajv-cli#readme + npx \ + --package=ajv-cli \ + --package=ajv-formats \ + ajv validate \ + --all-errors \ + --strict=false \ + -c ajv-formats \ + -s "${{ steps.download-schema.outputs.file-path }}" \ + -d "${{ matrix.file }}" diff --git a/README.md b/README.md index e423cb2..138c690 100644 --- a/README.md +++ b/README.md @@ -2,6 +2,7 @@ [![GoDoc](https://godoc.org/github.com/arduino/go-properties-orderedmap?status.svg)](https://godoc.org/github.com/arduino/go-properties-orderedmap) [![Check License status](https://github.com/arduino/go-properties-orderedmap/actions/workflows/check-license.yml/badge.svg)](https://github.com/arduino/go-properties-orderedmap/actions/workflows/check-license.yml) [![Check Markdown status](https://github.com/arduino/go-properties-orderedmap/actions/workflows/check-markdown-task.yml/badge.svg)](https://github.com/arduino/go-properties-orderedmap/actions/workflows/check-markdown-task.yml) +[![Check Taskfiles status](https://github.com/arduino/go-properties-orderedmap/actions/workflows/check-taskfiles.yml/badge.svg)](https://github.com/arduino/go-properties-orderedmap/actions/workflows/check-taskfiles.yml) Package `properties` is a library for handling maps of hierarchical properties. diff --git a/package-lock.json b/package-lock.json index 8117505..bdbaf6a 100644 --- a/package-lock.json +++ b/package-lock.json @@ -5,10 +5,135 @@ "packages": { "": { "devDependencies": { + "ajv-cli": "^5.0.0", + "ajv-formats": "^2.1.1", "markdown-link-check": "^3.10.2", "markdownlint-cli": "^0.32.1" } }, + "node_modules/ajv": { + "version": "8.11.0", + "resolved": "https://registry.npmjs.org/ajv/-/ajv-8.11.0.tgz", + "integrity": "sha512-wGgprdCvMalC0BztXvitD2hC04YffAvtsUn93JbGXYLAtCUO4xd17mCCZQxUOItiBwZvJScWo8NIvQMQ71rdpg==", + "dev": true, + "dependencies": { + "fast-deep-equal": "^3.1.1", + "json-schema-traverse": "^1.0.0", + "require-from-string": "^2.0.2", + "uri-js": "^4.2.2" + }, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/epoberezkin" + } + }, + "node_modules/ajv-cli": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/ajv-cli/-/ajv-cli-5.0.0.tgz", + "integrity": "sha512-LY4m6dUv44HTyhV+u2z5uX4EhPYTM38Iv1jdgDJJJCyOOuqB8KtZEGjPZ2T+sh5ZIJrXUfgErYx/j3gLd3+PlQ==", + "dev": true, + "dependencies": { + "ajv": "^8.0.0", + "fast-json-patch": "^2.0.0", + "glob": "^7.1.0", + "js-yaml": "^3.14.0", + "json-schema-migrate": "^2.0.0", + "json5": "^2.1.3", + "minimist": "^1.2.0" + }, + "bin": { + "ajv": "dist/index.js" + }, + "peerDependencies": { + "ts-node": ">=9.0.0" + }, + "peerDependenciesMeta": { + "ts-node": { + "optional": true + } + } + }, + "node_modules/ajv-cli/node_modules/argparse": { + "version": "1.0.10", + "resolved": "https://registry.npmjs.org/argparse/-/argparse-1.0.10.tgz", + "integrity": "sha512-o5Roy6tNG4SL/FOkCAN6RzjiakZS25RLYFrcMttJqbdd8BWrnA+fGz57iN5Pb06pvBGvl5gQ0B48dJlslXvoTg==", + "dev": true, + "dependencies": { + "sprintf-js": "~1.0.2" + } + }, + "node_modules/ajv-cli/node_modules/brace-expansion": { + "version": "1.1.11", + "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz", + "integrity": "sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==", + "dev": true, + "dependencies": { + "balanced-match": "^1.0.0", + "concat-map": "0.0.1" + } + }, + "node_modules/ajv-cli/node_modules/glob": { + "version": "7.2.3", + "resolved": "https://registry.npmjs.org/glob/-/glob-7.2.3.tgz", + "integrity": "sha512-nFR0zLpU2YCaRxwoCJvL6UvCH2JFyFVIvwTLsIf21AuHlMskA1hhTdk+LlYJtOlYt9v6dvszD2BGRqBL+iQK9Q==", + "dev": true, + "dependencies": { + "fs.realpath": "^1.0.0", + "inflight": "^1.0.4", + "inherits": "2", + "minimatch": "^3.1.1", + "once": "^1.3.0", + "path-is-absolute": "^1.0.0" + }, + "engines": { + "node": "*" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" + } + }, + "node_modules/ajv-cli/node_modules/js-yaml": { + "version": "3.14.1", + "resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-3.14.1.tgz", + "integrity": "sha512-okMH7OXXJ7YrN9Ok3/SXrnu4iX9yOk+25nqX4imS2npuvTYDmo/QEZoqwZkYaIDk3jVvBOTOIEgEhaLOynBS9g==", + "dev": true, + "dependencies": { + "argparse": "^1.0.7", + "esprima": "^4.0.0" + }, + "bin": { + "js-yaml": "bin/js-yaml.js" + } + }, + "node_modules/ajv-cli/node_modules/minimatch": { + "version": "3.1.2", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.1.2.tgz", + "integrity": "sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw==", + "dev": true, + "dependencies": { + "brace-expansion": "^1.1.7" + }, + "engines": { + "node": "*" + } + }, + "node_modules/ajv-formats": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/ajv-formats/-/ajv-formats-2.1.1.tgz", + "integrity": "sha512-Wx0Kx52hxE7C18hkMEggYlEifqWZtYaRgouJor+WMdPnQyEK13vgEWyVNup7SoeeoLMsr4kf5h6dOW11I15MUA==", + "dev": true, + "dependencies": { + "ajv": "^8.0.0" + }, + "peerDependencies": { + "ajv": "^8.0.0" + }, + "peerDependenciesMeta": { + "ajv": { + "optional": true + } + } + }, "node_modules/ansi-styles": { "version": "4.3.0", "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", @@ -138,6 +263,12 @@ "node": ">= 6" } }, + "node_modules/concat-map": { + "version": "0.0.1", + "resolved": "https://registry.npmjs.org/concat-map/-/concat-map-0.0.1.tgz", + "integrity": "sha512-/Srv4dswyQNBfohGpz9o6Yb3Gz3SrUDqBH5rTuhGR7ahtlbYKnVxw2bCFMRljaA7EXHaXZ8wsHdodFvbkhKmqg==", + "dev": true + }, "node_modules/css-select": { "version": "5.1.0", "resolved": "https://registry.npmjs.org/css-select/-/css-select-5.1.0.tgz", @@ -251,6 +382,43 @@ "url": "https://github.com/fb55/entities?sponsor=1" } }, + "node_modules/esprima": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/esprima/-/esprima-4.0.1.tgz", + "integrity": "sha512-eGuFFw7Upda+g4p+QHvnW0RyTX/SVeJBDM/gCtMARO0cLuT2HcEKnTPvhjV6aGeqrCB/sbNop0Kszm0jsaWU4A==", + "dev": true, + "bin": { + "esparse": "bin/esparse.js", + "esvalidate": "bin/esvalidate.js" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/fast-deep-equal": { + "version": "3.1.3", + "resolved": "https://registry.npmjs.org/fast-deep-equal/-/fast-deep-equal-3.1.3.tgz", + "integrity": "sha512-f3qQ9oQy9j2AhBe/H9VC91wLmKBCCU/gDOnKNAYG5hswO7BLKj09Hc5HYNz9cGI++xlpDCIgDaitVs03ATR84Q==", + "dev": true + }, + "node_modules/fast-json-patch": { + "version": "2.2.1", + "resolved": "https://registry.npmjs.org/fast-json-patch/-/fast-json-patch-2.2.1.tgz", + "integrity": "sha512-4j5uBaTnsYAV5ebkidvxiLUYOwjQ+JSFljeqfTxCrH9bDmlCQaOJFS84oDJ2rAXZq2yskmk3ORfoP9DCwqFNig==", + "dev": true, + "dependencies": { + "fast-deep-equal": "^2.0.1" + }, + "engines": { + "node": ">= 0.4.0" + } + }, + "node_modules/fast-json-patch/node_modules/fast-deep-equal": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/fast-deep-equal/-/fast-deep-equal-2.0.1.tgz", + "integrity": "sha512-bCK/2Z4zLidyB4ReuIsvALH6w31YfAQDmXMqMx6FyfHqvBxtjC0eRumeSu4Bs3XtXwpyIywtSTrVT99BxY1f9w==", + "dev": true + }, "node_modules/fs.realpath": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/fs.realpath/-/fs.realpath-1.0.0.tgz", @@ -416,6 +584,33 @@ "js-yaml": "bin/js-yaml.js" } }, + "node_modules/json-schema-migrate": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/json-schema-migrate/-/json-schema-migrate-2.0.0.tgz", + "integrity": "sha512-r38SVTtojDRp4eD6WsCqiE0eNDt4v1WalBXb9cyZYw9ai5cGtBwzRNWjHzJl38w6TxFkXAIA7h+fyX3tnrAFhQ==", + "dev": true, + "dependencies": { + "ajv": "^8.0.0" + } + }, + "node_modules/json-schema-traverse": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-1.0.0.tgz", + "integrity": "sha512-NM8/P9n3XjXhIZn1lLhkFaACTOURQXjWhV4BA/RnOv8xvgqtqpAX9IO4mRQxSx1Rlo4tqzeqb0sOlruaOy3dug==", + "dev": true + }, + "node_modules/json5": { + "version": "2.2.1", + "resolved": "https://registry.npmjs.org/json5/-/json5-2.2.1.tgz", + "integrity": "sha512-1hqLFMSrGHRHxav9q9gNjJ5EXznIxGVO09xQRrwplcS8qs28pZ8s8hupZAmqDwZUmVZ2Qb2jnyPOWcDH8m8dlA==", + "dev": true, + "bin": { + "json5": "lib/cli.js" + }, + "engines": { + "node": ">=6" + } + }, "node_modules/jsonc-parser": { "version": "3.1.0", "resolved": "https://registry.npmjs.org/jsonc-parser/-/jsonc-parser-3.1.0.tgz", @@ -665,6 +860,15 @@ "url": "https://github.com/inikulin/parse5?sponsor=1" } }, + "node_modules/path-is-absolute": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/path-is-absolute/-/path-is-absolute-1.0.1.tgz", + "integrity": "sha512-AVbw3UJ2e9bq64vSaS9Am0fje1Pa8pbGqTTsmXfaIiMpnr5DlDhfJOuLj9Sf95ZPVDAUerDfEk88MPmPe7UCQg==", + "dev": true, + "engines": { + "node": ">=0.10.0" + } + }, "node_modules/progress": { "version": "2.0.3", "resolved": "https://registry.npmjs.org/progress/-/progress-2.0.3.tgz", @@ -683,6 +887,15 @@ "node": ">=6" } }, + "node_modules/require-from-string": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/require-from-string/-/require-from-string-2.0.2.tgz", + "integrity": "sha512-Xf0nWe6RseziFMu+Ap9biiUbmplq6S9/p+7w7YXP/JBHhrUDDUhwa+vANyubuqfZWTveU//DYVGsDG7RKL/vEw==", + "dev": true, + "engines": { + "node": ">=0.10.0" + } + }, "node_modules/run-con": { "version": "1.2.11", "resolved": "https://registry.npmjs.org/run-con/-/run-con-1.2.11.tgz", @@ -710,6 +923,12 @@ "integrity": "sha512-NqVDv9TpANUjFm0N8uM5GxL36UgKi9/atZw+x7YFnQ8ckwFGKrl4xX4yWtrey3UJm5nP1kUbnYgLopqWNSRhWw==", "dev": true }, + "node_modules/sprintf-js": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/sprintf-js/-/sprintf-js-1.0.3.tgz", + "integrity": "sha512-D9cPgkvLlV3t3IzL0D0YLvGA9Ahk4PcvVwUbN0dSGr1aP0Nrt4AEnTUbuGvquEC0mA64Gqt1fzirlRs5ibXx8g==", + "dev": true + }, "node_modules/strip-json-comments": { "version": "3.1.1", "resolved": "https://registry.npmjs.org/strip-json-comments/-/strip-json-comments-3.1.1.tgz", @@ -740,6 +959,15 @@ "integrity": "sha512-8Y75pvTYkLJW2hWQHXxoqRgV7qb9B+9vFEtidML+7koHUFapnVJAZ6cKs+Qjz5Aw3aZWHMC6u0wJE3At+nSGwA==", "dev": true }, + "node_modules/uri-js": { + "version": "4.4.1", + "resolved": "https://registry.npmjs.org/uri-js/-/uri-js-4.4.1.tgz", + "integrity": "sha512-7rKUyy33Q1yc98pQ1DAmLtwX109F7TIfWlW1Ydo8Wl1ii1SeHieeh0HHfPeL2fMXK6z0s8ecKs9frCuLJvndBg==", + "dev": true, + "dependencies": { + "punycode": "^2.1.0" + } + }, "node_modules/wrappy": { "version": "1.0.2", "resolved": "https://registry.npmjs.org/wrappy/-/wrappy-1.0.2.tgz", @@ -748,6 +976,96 @@ } }, "dependencies": { + "ajv": { + "version": "8.11.0", + "resolved": "https://registry.npmjs.org/ajv/-/ajv-8.11.0.tgz", + "integrity": "sha512-wGgprdCvMalC0BztXvitD2hC04YffAvtsUn93JbGXYLAtCUO4xd17mCCZQxUOItiBwZvJScWo8NIvQMQ71rdpg==", + "dev": true, + "requires": { + "fast-deep-equal": "^3.1.1", + "json-schema-traverse": "^1.0.0", + "require-from-string": "^2.0.2", + "uri-js": "^4.2.2" + } + }, + "ajv-cli": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/ajv-cli/-/ajv-cli-5.0.0.tgz", + "integrity": "sha512-LY4m6dUv44HTyhV+u2z5uX4EhPYTM38Iv1jdgDJJJCyOOuqB8KtZEGjPZ2T+sh5ZIJrXUfgErYx/j3gLd3+PlQ==", + "dev": true, + "requires": { + "ajv": "^8.0.0", + "fast-json-patch": "^2.0.0", + "glob": "^7.1.0", + "js-yaml": "^3.14.0", + "json-schema-migrate": "^2.0.0", + "json5": "^2.1.3", + "minimist": "^1.2.0" + }, + "dependencies": { + "argparse": { + "version": "1.0.10", + "resolved": "https://registry.npmjs.org/argparse/-/argparse-1.0.10.tgz", + "integrity": "sha512-o5Roy6tNG4SL/FOkCAN6RzjiakZS25RLYFrcMttJqbdd8BWrnA+fGz57iN5Pb06pvBGvl5gQ0B48dJlslXvoTg==", + "dev": true, + "requires": { + "sprintf-js": "~1.0.2" + } + }, + "brace-expansion": { + "version": "1.1.11", + "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz", + "integrity": "sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==", + "dev": true, + "requires": { + "balanced-match": "^1.0.0", + "concat-map": "0.0.1" + } + }, + "glob": { + "version": "7.2.3", + "resolved": "https://registry.npmjs.org/glob/-/glob-7.2.3.tgz", + "integrity": "sha512-nFR0zLpU2YCaRxwoCJvL6UvCH2JFyFVIvwTLsIf21AuHlMskA1hhTdk+LlYJtOlYt9v6dvszD2BGRqBL+iQK9Q==", + "dev": true, + "requires": { + "fs.realpath": "^1.0.0", + "inflight": "^1.0.4", + "inherits": "2", + "minimatch": "^3.1.1", + "once": "^1.3.0", + "path-is-absolute": "^1.0.0" + } + }, + "js-yaml": { + "version": "3.14.1", + "resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-3.14.1.tgz", + "integrity": "sha512-okMH7OXXJ7YrN9Ok3/SXrnu4iX9yOk+25nqX4imS2npuvTYDmo/QEZoqwZkYaIDk3jVvBOTOIEgEhaLOynBS9g==", + "dev": true, + "requires": { + "argparse": "^1.0.7", + "esprima": "^4.0.0" + } + }, + "minimatch": { + "version": "3.1.2", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.1.2.tgz", + "integrity": "sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw==", + "dev": true, + "requires": { + "brace-expansion": "^1.1.7" + } + } + } + }, + "ajv-formats": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/ajv-formats/-/ajv-formats-2.1.1.tgz", + "integrity": "sha512-Wx0Kx52hxE7C18hkMEggYlEifqWZtYaRgouJor+WMdPnQyEK13vgEWyVNup7SoeeoLMsr4kf5h6dOW11I15MUA==", + "dev": true, + "requires": { + "ajv": "^8.0.0" + } + }, "ansi-styles": { "version": "4.3.0", "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", @@ -850,6 +1168,12 @@ "integrity": "sha512-U7VdrJFnJgo4xjrHpTzu0yrHPGImdsmD95ZlgYSEajAn2JKzDhDTPG9kBTefmObL2w/ngeZnilk+OV9CG3d7UA==", "dev": true }, + "concat-map": { + "version": "0.0.1", + "resolved": "https://registry.npmjs.org/concat-map/-/concat-map-0.0.1.tgz", + "integrity": "sha512-/Srv4dswyQNBfohGpz9o6Yb3Gz3SrUDqBH5rTuhGR7ahtlbYKnVxw2bCFMRljaA7EXHaXZ8wsHdodFvbkhKmqg==", + "dev": true + }, "css-select": { "version": "5.1.0", "resolved": "https://registry.npmjs.org/css-select/-/css-select-5.1.0.tgz", @@ -927,6 +1251,35 @@ "integrity": "sha512-o4q/dYJlmyjP2zfnaWDUC6A3BQFmVTX+tZPezK7k0GLSU9QYCauscf5Y+qcEPzKL+EixVouYDgLQK5H9GrLpkg==", "dev": true }, + "esprima": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/esprima/-/esprima-4.0.1.tgz", + "integrity": "sha512-eGuFFw7Upda+g4p+QHvnW0RyTX/SVeJBDM/gCtMARO0cLuT2HcEKnTPvhjV6aGeqrCB/sbNop0Kszm0jsaWU4A==", + "dev": true + }, + "fast-deep-equal": { + "version": "3.1.3", + "resolved": "https://registry.npmjs.org/fast-deep-equal/-/fast-deep-equal-3.1.3.tgz", + "integrity": "sha512-f3qQ9oQy9j2AhBe/H9VC91wLmKBCCU/gDOnKNAYG5hswO7BLKj09Hc5HYNz9cGI++xlpDCIgDaitVs03ATR84Q==", + "dev": true + }, + "fast-json-patch": { + "version": "2.2.1", + "resolved": "https://registry.npmjs.org/fast-json-patch/-/fast-json-patch-2.2.1.tgz", + "integrity": "sha512-4j5uBaTnsYAV5ebkidvxiLUYOwjQ+JSFljeqfTxCrH9bDmlCQaOJFS84oDJ2rAXZq2yskmk3ORfoP9DCwqFNig==", + "dev": true, + "requires": { + "fast-deep-equal": "^2.0.1" + }, + "dependencies": { + "fast-deep-equal": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/fast-deep-equal/-/fast-deep-equal-2.0.1.tgz", + "integrity": "sha512-bCK/2Z4zLidyB4ReuIsvALH6w31YfAQDmXMqMx6FyfHqvBxtjC0eRumeSu4Bs3XtXwpyIywtSTrVT99BxY1f9w==", + "dev": true + } + } + }, "fs.realpath": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/fs.realpath/-/fs.realpath-1.0.0.tgz", @@ -1049,6 +1402,27 @@ "argparse": "^2.0.1" } }, + "json-schema-migrate": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/json-schema-migrate/-/json-schema-migrate-2.0.0.tgz", + "integrity": "sha512-r38SVTtojDRp4eD6WsCqiE0eNDt4v1WalBXb9cyZYw9ai5cGtBwzRNWjHzJl38w6TxFkXAIA7h+fyX3tnrAFhQ==", + "dev": true, + "requires": { + "ajv": "^8.0.0" + } + }, + "json-schema-traverse": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-1.0.0.tgz", + "integrity": "sha512-NM8/P9n3XjXhIZn1lLhkFaACTOURQXjWhV4BA/RnOv8xvgqtqpAX9IO4mRQxSx1Rlo4tqzeqb0sOlruaOy3dug==", + "dev": true + }, + "json5": { + "version": "2.2.1", + "resolved": "https://registry.npmjs.org/json5/-/json5-2.2.1.tgz", + "integrity": "sha512-1hqLFMSrGHRHxav9q9gNjJ5EXznIxGVO09xQRrwplcS8qs28pZ8s8hupZAmqDwZUmVZ2Qb2jnyPOWcDH8m8dlA==", + "dev": true + }, "jsonc-parser": { "version": "3.1.0", "resolved": "https://registry.npmjs.org/jsonc-parser/-/jsonc-parser-3.1.0.tgz", @@ -1251,6 +1625,12 @@ "parse5": "^7.0.0" } }, + "path-is-absolute": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/path-is-absolute/-/path-is-absolute-1.0.1.tgz", + "integrity": "sha512-AVbw3UJ2e9bq64vSaS9Am0fje1Pa8pbGqTTsmXfaIiMpnr5DlDhfJOuLj9Sf95ZPVDAUerDfEk88MPmPe7UCQg==", + "dev": true + }, "progress": { "version": "2.0.3", "resolved": "https://registry.npmjs.org/progress/-/progress-2.0.3.tgz", @@ -1263,6 +1643,12 @@ "integrity": "sha512-XRsRjdf+j5ml+y/6GKHPZbrF/8p2Yga0JPtdqTIY2Xe5ohJPD9saDJJLPvp9+NSBprVvevdXZybnj2cv8OEd0A==", "dev": true }, + "require-from-string": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/require-from-string/-/require-from-string-2.0.2.tgz", + "integrity": "sha512-Xf0nWe6RseziFMu+Ap9biiUbmplq6S9/p+7w7YXP/JBHhrUDDUhwa+vANyubuqfZWTveU//DYVGsDG7RKL/vEw==", + "dev": true + }, "run-con": { "version": "1.2.11", "resolved": "https://registry.npmjs.org/run-con/-/run-con-1.2.11.tgz", @@ -1287,6 +1673,12 @@ "integrity": "sha512-NqVDv9TpANUjFm0N8uM5GxL36UgKi9/atZw+x7YFnQ8ckwFGKrl4xX4yWtrey3UJm5nP1kUbnYgLopqWNSRhWw==", "dev": true }, + "sprintf-js": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/sprintf-js/-/sprintf-js-1.0.3.tgz", + "integrity": "sha512-D9cPgkvLlV3t3IzL0D0YLvGA9Ahk4PcvVwUbN0dSGr1aP0Nrt4AEnTUbuGvquEC0mA64Gqt1fzirlRs5ibXx8g==", + "dev": true + }, "strip-json-comments": { "version": "3.1.1", "resolved": "https://registry.npmjs.org/strip-json-comments/-/strip-json-comments-3.1.1.tgz", @@ -1308,6 +1700,15 @@ "integrity": "sha512-8Y75pvTYkLJW2hWQHXxoqRgV7qb9B+9vFEtidML+7koHUFapnVJAZ6cKs+Qjz5Aw3aZWHMC6u0wJE3At+nSGwA==", "dev": true }, + "uri-js": { + "version": "4.4.1", + "resolved": "https://registry.npmjs.org/uri-js/-/uri-js-4.4.1.tgz", + "integrity": "sha512-7rKUyy33Q1yc98pQ1DAmLtwX109F7TIfWlW1Ydo8Wl1ii1SeHieeh0HHfPeL2fMXK6z0s8ecKs9frCuLJvndBg==", + "dev": true, + "requires": { + "punycode": "^2.1.0" + } + }, "wrappy": { "version": "1.0.2", "resolved": "https://registry.npmjs.org/wrappy/-/wrappy-1.0.2.tgz", diff --git a/package.json b/package.json index 7584ee5..303a36b 100644 --- a/package.json +++ b/package.json @@ -1,5 +1,7 @@ { "devDependencies": { + "ajv-cli": "^5.0.0", + "ajv-formats": "^2.1.1", "markdown-link-check": "^3.10.2", "markdownlint-cli": "^0.32.1" } From 46b1f375aa61f2404b33600cb68614cc4c141455 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Thu, 13 Oct 2022 10:46:11 +0000 Subject: [PATCH 25/48] Bump geekyeggo/delete-artifact from 1 to 2 Bumps [geekyeggo/delete-artifact](https://github.com/geekyeggo/delete-artifact) from 1 to 2. - [Release notes](https://github.com/geekyeggo/delete-artifact/releases) - [Commits](https://github.com/geekyeggo/delete-artifact/compare/v1...v2) --- updated-dependencies: - dependency-name: geekyeggo/delete-artifact dependency-type: direct:production update-type: version-update:semver-major ... Signed-off-by: dependabot[bot] --- .github/workflows/sync-labels.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/sync-labels.yml b/.github/workflows/sync-labels.yml index 9ce51aa..4376e4c 100644 --- a/.github/workflows/sync-labels.yml +++ b/.github/workflows/sync-labels.yml @@ -115,7 +115,7 @@ jobs: path: ${{ env.CONFIGURATIONS_FOLDER }} - name: Remove unneeded artifact - uses: geekyeggo/delete-artifact@v1 + uses: geekyeggo/delete-artifact@v2 with: name: ${{ env.CONFIGURATIONS_ARTIFACT }} From 7921cd1ac38a50f409cb46f93152bb7eea8b6513 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Mon, 24 Oct 2022 10:41:33 +0000 Subject: [PATCH 26/48] Bump carlosperate/download-file-action from 1 to 2 Bumps [carlosperate/download-file-action](https://github.com/carlosperate/download-file-action) from 1 to 2. - [Release notes](https://github.com/carlosperate/download-file-action/releases) - [Commits](https://github.com/carlosperate/download-file-action/compare/v1...v2) --- updated-dependencies: - dependency-name: carlosperate/download-file-action dependency-type: direct:production update-type: version-update:semver-major ... Signed-off-by: dependabot[bot] --- .github/workflows/check-taskfiles.yml | 2 +- .github/workflows/sync-labels.yml | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/.github/workflows/check-taskfiles.yml b/.github/workflows/check-taskfiles.yml index 2bff3ca..cc41d93 100644 --- a/.github/workflows/check-taskfiles.yml +++ b/.github/workflows/check-taskfiles.yml @@ -48,7 +48,7 @@ jobs: - name: Download JSON schema for Taskfiles id: download-schema - uses: carlosperate/download-file-action@v1 + uses: carlosperate/download-file-action@v2 with: # See: https://github.com/SchemaStore/schemastore/blob/master/src/schemas/json/taskfile.json file-url: https://json.schemastore.org/taskfile.json diff --git a/.github/workflows/sync-labels.yml b/.github/workflows/sync-labels.yml index 4376e4c..70085bd 100644 --- a/.github/workflows/sync-labels.yml +++ b/.github/workflows/sync-labels.yml @@ -31,7 +31,7 @@ jobs: - name: Download JSON schema for labels configuration file id: download-schema - uses: carlosperate/download-file-action@v1 + uses: carlosperate/download-file-action@v2 with: file-url: https://raw.githubusercontent.com/arduino/tooling-project-assets/main/workflow-templates/assets/sync-labels/arduino-tooling-gh-label-configuration-schema.json location: ${{ runner.temp }}/label-configuration-schema @@ -66,7 +66,7 @@ jobs: steps: - name: Download - uses: carlosperate/download-file-action@v1 + uses: carlosperate/download-file-action@v2 with: file-url: https://raw.githubusercontent.com/arduino/tooling-project-assets/main/workflow-templates/assets/sync-labels/${{ matrix.filename }} From ead008e57511bc598f96f563ec075910fba12198 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Mon, 24 Oct 2022 10:41:37 +0000 Subject: [PATCH 27/48] Bump xt0rted/markdownlint-problem-matcher from 1 to 2 Bumps [xt0rted/markdownlint-problem-matcher](https://github.com/xt0rted/markdownlint-problem-matcher) from 1 to 2. - [Release notes](https://github.com/xt0rted/markdownlint-problem-matcher/releases) - [Changelog](https://github.com/xt0rted/markdownlint-problem-matcher/blob/main/CHANGELOG.md) - [Commits](https://github.com/xt0rted/markdownlint-problem-matcher/compare/v1...v2) --- updated-dependencies: - dependency-name: xt0rted/markdownlint-problem-matcher dependency-type: direct:production update-type: version-update:semver-major ... Signed-off-by: dependabot[bot] --- .github/workflows/check-markdown-task.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/check-markdown-task.yml b/.github/workflows/check-markdown-task.yml index 8fc37a7..9b53c3a 100644 --- a/.github/workflows/check-markdown-task.yml +++ b/.github/workflows/check-markdown-task.yml @@ -77,7 +77,7 @@ jobs: node-version: ${{ env.NODE_VERSION }} - name: Initialize markdownlint-cli problem matcher - uses: xt0rted/markdownlint-problem-matcher@v1 + uses: xt0rted/markdownlint-problem-matcher@v2 - name: Install Task uses: arduino/setup-task@v1 From 6a9c9bb1f9b9c237bba2b2f9e5887538c90d1ac2 Mon Sep 17 00:00:00 2001 From: Cristian Maglie Date: Tue, 8 Nov 2022 13:36:47 +0100 Subject: [PATCH 28/48] Pass of go-fmt --- properties.go | 252 +++++++++++++++++++++++++------------------------- 1 file changed, 126 insertions(+), 126 deletions(-) diff --git a/properties.go b/properties.go index 933fc1e..2a0f29b 100644 --- a/properties.go +++ b/properties.go @@ -33,26 +33,26 @@ This library is mainly used in the Arduino platform software to handle configurations made of key/value pairs stored in files with an INI like syntax, for example: - ... - uno.name=Arduino/Genuino Uno - uno.upload.tool=avrdude - uno.upload.protocol=arduino - uno.upload.maximum_size=32256 - uno.upload.maximum_data_size=2048 - uno.upload.speed=115200 - uno.build.mcu=atmega328p - uno.build.f_cpu=16000000L - uno.build.board=AVR_UNO - uno.build.core=arduino - uno.build.variant=standard - diecimila.name=Arduino Duemilanove or Diecimila - diecimila.upload.tool=avrdude - diecimila.upload.protocol=arduino - diecimila.build.f_cpu=16000000L - diecimila.build.board=AVR_DUEMILANOVE - diecimila.build.core=arduino - diecimila.build.variant=standard - ... + ... + uno.name=Arduino/Genuino Uno + uno.upload.tool=avrdude + uno.upload.protocol=arduino + uno.upload.maximum_size=32256 + uno.upload.maximum_data_size=2048 + uno.upload.speed=115200 + uno.build.mcu=atmega328p + uno.build.f_cpu=16000000L + uno.build.board=AVR_UNO + uno.build.core=arduino + uno.build.variant=standard + diecimila.name=Arduino Duemilanove or Diecimila + diecimila.upload.tool=avrdude + diecimila.upload.protocol=arduino + diecimila.build.f_cpu=16000000L + diecimila.build.board=AVR_DUEMILANOVE + diecimila.build.core=arduino + diecimila.build.variant=standard + ... This library has methods to parse this kind of file into a Map object. @@ -277,35 +277,35 @@ func (m *Map) Remove(key string) { // FirstLevelOf generates a map-of-Maps using the first level of the hierarchy // of the current Map. For example the following Map: // -// properties.Map{ -// "uno.name": "Arduino/Genuino Uno", -// "uno.upload.tool": "avrdude", -// "uno.upload.protocol": "arduino", -// "uno.upload.maximum_size": "32256", -// "diecimila.name": "Arduino Duemilanove or Diecimila", -// "diecimila.upload.tool": "avrdude", -// "diecimila.upload.protocol": "arduino", -// "diecimila.bootloader.tool": "avrdude", -// "diecimila.bootloader.low_fuses": "0xFF", -// } +// properties.Map{ +// "uno.name": "Arduino/Genuino Uno", +// "uno.upload.tool": "avrdude", +// "uno.upload.protocol": "arduino", +// "uno.upload.maximum_size": "32256", +// "diecimila.name": "Arduino Duemilanove or Diecimila", +// "diecimila.upload.tool": "avrdude", +// "diecimila.upload.protocol": "arduino", +// "diecimila.bootloader.tool": "avrdude", +// "diecimila.bootloader.low_fuses": "0xFF", +// } // // is transformed into the following map-of-Maps: // -// map[string]Map{ -// "uno" : properties.Map{ -// "name": "Arduino/Genuino Uno", -// "upload.tool": "avrdude", -// "upload.protocol": "arduino", -// "upload.maximum_size": "32256", -// }, -// "diecimila" : properties.Map{ -// "name": "Arduino Duemilanove or Diecimila", -// "upload.tool": "avrdude", -// "upload.protocol": "arduino", -// "bootloader.tool": "avrdude", -// "bootloader.low_fuses": "0xFF", -// } -// } +// map[string]Map{ +// "uno" : properties.Map{ +// "name": "Arduino/Genuino Uno", +// "upload.tool": "avrdude", +// "upload.protocol": "arduino", +// "upload.maximum_size": "32256", +// }, +// "diecimila" : properties.Map{ +// "name": "Arduino Duemilanove or Diecimila", +// "upload.tool": "avrdude", +// "upload.protocol": "arduino", +// "bootloader.tool": "avrdude", +// "bootloader.low_fuses": "0xFF", +// } +// } func (m *Map) FirstLevelOf() map[string]*Map { newMap := make(map[string]*Map) for _, key := range m.o { @@ -325,24 +325,24 @@ func (m *Map) FirstLevelOf() map[string]*Map { // FirstLevelKeys returns the keys in the first level of the hierarchy // of the current Map. For example the following Map: // -// properties.Map{ -// "uno.name": "Arduino/Genuino Uno", -// "uno.upload.tool": "avrdude", -// "uno.upload.protocol": "arduino", -// "uno.upload.maximum_size": "32256", -// "diecimila.name": "Arduino Duemilanove or Diecimila", -// "diecimila.upload.tool": "avrdude", -// "diecimila.upload.protocol": "arduino", -// "diecimila.bootloader.tool": "avrdude", -// "diecimila.bootloader.low_fuses": "0xFF", -// } +// properties.Map{ +// "uno.name": "Arduino/Genuino Uno", +// "uno.upload.tool": "avrdude", +// "uno.upload.protocol": "arduino", +// "uno.upload.maximum_size": "32256", +// "diecimila.name": "Arduino Duemilanove or Diecimila", +// "diecimila.upload.tool": "avrdude", +// "diecimila.upload.protocol": "arduino", +// "diecimila.bootloader.tool": "avrdude", +// "diecimila.bootloader.low_fuses": "0xFF", +// } // // will produce the following result: // -// []string{ -// "uno", -// "diecimila", -// } +// []string{ +// "uno", +// "diecimila", +// } // // the order of the original map is preserved func (m *Map) FirstLevelKeys() []string { @@ -363,26 +363,26 @@ func (m *Map) FirstLevelKeys() []string { // of the keys hierarchy as selector. // For example the following Map: // -// properties.Map{ -// "uno.name": "Arduino/Genuino Uno", -// "uno.upload.tool": "avrdude", -// "uno.upload.protocol": "arduino", -// "uno.upload.maximum_size": "32256", -// "diecimila.name": "Arduino Duemilanove or Diecimila", -// "diecimila.upload.tool": "avrdude", -// "diecimila.upload.protocol": "arduino", -// "diecimila.bootloader.tool": "avrdude", -// "diecimila.bootloader.low_fuses": "0xFF", -// } +// properties.Map{ +// "uno.name": "Arduino/Genuino Uno", +// "uno.upload.tool": "avrdude", +// "uno.upload.protocol": "arduino", +// "uno.upload.maximum_size": "32256", +// "diecimila.name": "Arduino Duemilanove or Diecimila", +// "diecimila.upload.tool": "avrdude", +// "diecimila.upload.protocol": "arduino", +// "diecimila.bootloader.tool": "avrdude", +// "diecimila.bootloader.low_fuses": "0xFF", +// } // // after calling SubTree("uno") will be transformed into: // -// properties.Map{ -// "name": "Arduino/Genuino Uno", -// "upload.tool": "avrdude", -// "upload.protocol": "arduino", -// "upload.maximum_size": "32256", -// }, +// properties.Map{ +// "name": "Arduino/Genuino Uno", +// "upload.tool": "avrdude", +// "upload.protocol": "arduino", +// "upload.maximum_size": "32256", +// }, func (m *Map) SubTree(rootKey string) *Map { rootKey += "." newMap := NewMap() @@ -399,7 +399,7 @@ func (m *Map) SubTree(rootKey string) *Map { // ExpandPropsInString uses the Map to replace values into a format string. // The format string should contains markers between braces, for example: // -// "The selected upload protocol is {upload.protocol}." +// "The selected upload protocol is {upload.protocol}." // // Each marker is replaced by the corresponding value of the Map. // The values in the Map may contain other markers, they are evaluated @@ -517,50 +517,50 @@ func DeleteUnexpandedPropsFromString(str string) string { // `root.N.xxx...` as separate subsets. // For example the following Map: // -// properties.Map{ -// "uno.upload_port.vid": "0x1000", -// "uno.upload_port.pid": "0x2000", -// "due.upload_port.0.vid": "0x1000", -// "due.upload_port.0.pid": "0x2000", -// "due.upload_port.1.vid": "0x1001", -// "due.upload_port.1.pid": "0x2001", -// "tre.upload_port.1.vid": "0x1001", -// "tre.upload_port.1.pid": "0x2001", -// "tre.upload_port.2.vid": "0x1002", -// "tre.upload_port.2.pid": "0x2002", -// } +// properties.Map{ +// "uno.upload_port.vid": "0x1000", +// "uno.upload_port.pid": "0x2000", +// "due.upload_port.0.vid": "0x1000", +// "due.upload_port.0.pid": "0x2000", +// "due.upload_port.1.vid": "0x1001", +// "due.upload_port.1.pid": "0x2001", +// "tre.upload_port.1.vid": "0x1001", +// "tre.upload_port.1.pid": "0x2001", +// "tre.upload_port.2.vid": "0x1002", +// "tre.upload_port.2.pid": "0x2002", +// } // // calling ExtractSubIndexSets("uno.upload_port") returns the array: // -// [ properties.Map{ -// "vid": "0x1000", -// "pid": "0x2000", -// }, -// ] +// [ properties.Map{ +// "vid": "0x1000", +// "pid": "0x2000", +// }, +// ] // // calling ExtractSubIndexSets("due.upload_port") returns the array: // -// [ properties.Map{ -// "vid": "0x1000", -// "pid": "0x2000", -// }, -// properties.Map{ -// "vid": "0x1001", -// "pid": "0x2001", -// }, -// ] +// [ properties.Map{ +// "vid": "0x1000", +// "pid": "0x2000", +// }, +// properties.Map{ +// "vid": "0x1001", +// "pid": "0x2001", +// }, +// ] // // the sub-index may start with .1 too, so calling ExtractSubIndexSets("tre.upload_port") returns: // -// [ properties.Map{ -// "vid": "0x1001", -// "pid": "0x2001", -// }, -// properties.Map{ -// "vid": "0x1002", -// "pid": "0x2002", -// }, -// ] +// [ properties.Map{ +// "vid": "0x1001", +// "pid": "0x2001", +// }, +// properties.Map{ +// "vid": "0x1002", +// "pid": "0x2002", +// }, +// ] // // Numeric subindex cannot be mixed with non-numeric, in that case only the numeric sub // index sets will be returned. @@ -597,27 +597,27 @@ func (m *Map) ExtractSubIndexSets(root string) []*Map { // ExtractSubIndexLists extracts a list of arguments from a root `root.N=...`. // For example the following Map: // -// properties.Map{ -// "uno.discovery.required": "item", -// "due.discovery.required.0": "item1", -// "due.discovery.required.1": "item2", -// "due.discovery.required.2": "item3", -// "tre.discovery.required.1": "itemA", -// "tre.discovery.required.2": "itemB", -// "tre.discovery.required.3": "itemC", -// } +// properties.Map{ +// "uno.discovery.required": "item", +// "due.discovery.required.0": "item1", +// "due.discovery.required.1": "item2", +// "due.discovery.required.2": "item3", +// "tre.discovery.required.1": "itemA", +// "tre.discovery.required.2": "itemB", +// "tre.discovery.required.3": "itemC", +// } // // calling ExtractSubIndexLists("uno.discovery.required") returns the array: // -// [ "item" ] +// [ "item" ] // // calling ExtractSubIndexLists("due.discovery.required") returns the array: // -// [ "item1", "item2", "item3" ] +// [ "item1", "item2", "item3" ] // // the sub-index may start with .1 too, so calling ExtractSubIndexLists("tre.discovery.required") returns: // -// [ "itemA", "itemB", "itemC" ] +// [ "itemA", "itemB", "itemC" ] // // Numeric subindex cannot be mixed with non-numeric, in that case only the numeric sub // index sets will be returned. From 484e95dc3c480f6513496544c72b62b4f9a9682b Mon Sep 17 00:00:00 2001 From: Cristian Maglie Date: Tue, 8 Nov 2022 13:37:32 +0100 Subject: [PATCH 29/48] linter: error message should not be capitalized --- properties.go | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/properties.go b/properties.go index 2a0f29b..5000130 100644 --- a/properties.go +++ b/properties.go @@ -139,7 +139,7 @@ func LoadFromBytes(bytes []byte) (*Map, error) { for lineNum, line := range strings.Split(text, "\n") { if err := properties.parseLine(line); err != nil { - return nil, fmt.Errorf("Error parsing data at line %d: %s", lineNum, err) + return nil, fmt.Errorf("error parsing data at line %d: %s", lineNum, err) } } @@ -150,12 +150,12 @@ func LoadFromBytes(bytes []byte) (*Map, error) { func Load(filepath string) (*Map, error) { bytes, err := ioutil.ReadFile(filepath) if err != nil { - return nil, fmt.Errorf("Error reading file: %s", err) + return nil, fmt.Errorf("error reading file: %s", err) } res, err := LoadFromBytes(bytes) if err != nil { - return nil, fmt.Errorf("Error reading file: %s", err) + return nil, fmt.Errorf("error reading file: %s", err) } return res, nil } @@ -172,7 +172,7 @@ func LoadFromSlice(lines []string) (*Map, error) { for lineNum, line := range lines { if err := properties.parseLine(line); err != nil { - return nil, fmt.Errorf("Error reading from slice (index:%d): %s", lineNum, err) + return nil, fmt.Errorf("error reading from slice (index:%d): %s", lineNum, err) } } @@ -189,7 +189,7 @@ func (m *Map) parseLine(line string) error { lineParts := strings.SplitN(line, "=", 2) if len(lineParts) != 2 { - return fmt.Errorf("Invalid line format, should be 'key=value'") + return fmt.Errorf("invalid line format, should be 'key=value'") } key := strings.TrimSpace(lineParts[0]) value := strings.TrimSpace(lineParts[1]) From b884f299fa337ca8f3284ddaf99527b976939d04 Mon Sep 17 00:00:00 2001 From: Cristian Maglie Date: Tue, 8 Nov 2022 13:38:11 +0100 Subject: [PATCH 30/48] linter: use `!strings.Contains` instead of `Index(..)!=-1` --- properties.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/properties.go b/properties.go index 5000130..432a156 100644 --- a/properties.go +++ b/properties.go @@ -309,7 +309,7 @@ func (m *Map) Remove(key string) { func (m *Map) FirstLevelOf() map[string]*Map { newMap := make(map[string]*Map) for _, key := range m.o { - if strings.Index(key, ".") == -1 { + if !strings.Contains(key, ".") { continue } keyParts := strings.SplitN(key, ".", 2) From 60684f0b415b18314bcfb9106e94bedd97e651b5 Mon Sep 17 00:00:00 2001 From: Cristian Maglie Date: Tue, 8 Nov 2022 13:39:20 +0100 Subject: [PATCH 31/48] linter: use verbatim strings with MustCompile to avoid double escaping --- properties.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/properties.go b/properties.go index 432a156..091ba1d 100644 --- a/properties.go +++ b/properties.go @@ -509,7 +509,7 @@ func MergeMapsOfProperties(target map[string]*Map, sources ...map[string]*Map) m // DeleteUnexpandedPropsFromString removes all the brace markers "{xxx}" that are not expanded // into a value using the Map.ExpandPropsInString() method. func DeleteUnexpandedPropsFromString(str string) string { - rxp := regexp.MustCompile("\\{.+?\\}") + rxp := regexp.MustCompile(`\{.+?\}`) return rxp.ReplaceAllString(str, "") } From 1a443e41fa269edb5f3940349896980e2c70c40e Mon Sep 17 00:00:00 2001 From: Cristian Maglie Date: Tue, 8 Nov 2022 13:47:16 +0100 Subject: [PATCH 32/48] Allow ISO8859-1 encoding in properties --- properties.go | 17 ++++++++++++++++- properties_test.go | 6 ++++++ testdata/non-utf8.properties | 1 + 3 files changed, 23 insertions(+), 1 deletion(-) create mode 100644 testdata/non-utf8.properties diff --git a/properties.go b/properties.go index 933fc1e..7e32eef 100644 --- a/properties.go +++ b/properties.go @@ -77,6 +77,7 @@ import ( "regexp" "runtime" "strings" + "unicode/utf8" "github.com/arduino/go-paths-helper" ) @@ -129,9 +130,23 @@ func NewFromHashmap(orig map[string]string) *Map { return res } +func toUtf8(iso8859_1_buf []byte) string { + buf := make([]rune, len(iso8859_1_buf)) + for i, b := range iso8859_1_buf { + buf[i] = rune(b) + } + return string(buf) +} + // LoadFromBytes reads properties data and makes a Map out of it. func LoadFromBytes(bytes []byte) (*Map, error) { - text := string(bytes) + var text string + if utf8.Valid(bytes) { + text = string(bytes) + } else { + // Assume ISO8859-1 encoding and convert to UTF-8 + text = toUtf8(bytes) + } text = strings.Replace(text, "\r\n", "\n", -1) text = strings.Replace(text, "\r", "\n", -1) diff --git a/properties_test.go b/properties_test.go index 46f2c76..d5fa25e 100644 --- a/properties_test.go +++ b/properties_test.go @@ -384,3 +384,9 @@ func TestExtractSubIndexLists(t *testing.T) { s5 := m.ExtractSubIndexLists("cinque.discovery.required") require.Len(t, s5, 0) } + +func TestLoadingNonUTF8Properties(t *testing.T) { + m, err := LoadFromPath(paths.New("testdata/non-utf8.properties")) + require.NoError(t, err) + require.Equal(t, "Aáa", m.Get("maintainer")) +} diff --git a/testdata/non-utf8.properties b/testdata/non-utf8.properties new file mode 100644 index 0000000..34390ea --- /dev/null +++ b/testdata/non-utf8.properties @@ -0,0 +1 @@ +maintainer=Aáa From 7134c6eed6dc6f5847280eb47f6220906ccce504 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Mon, 9 Jan 2023 04:02:04 +0000 Subject: [PATCH 33/48] Bump json5 from 2.2.1 to 2.2.3 Bumps [json5](https://github.com/json5/json5) from 2.2.1 to 2.2.3. - [Release notes](https://github.com/json5/json5/releases) - [Changelog](https://github.com/json5/json5/blob/main/CHANGELOG.md) - [Commits](https://github.com/json5/json5/compare/v2.2.1...v2.2.3) --- updated-dependencies: - dependency-name: json5 dependency-type: indirect ... Signed-off-by: dependabot[bot] --- package-lock.json | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/package-lock.json b/package-lock.json index bdbaf6a..b690fd6 100644 --- a/package-lock.json +++ b/package-lock.json @@ -600,9 +600,9 @@ "dev": true }, "node_modules/json5": { - "version": "2.2.1", - "resolved": "https://registry.npmjs.org/json5/-/json5-2.2.1.tgz", - "integrity": "sha512-1hqLFMSrGHRHxav9q9gNjJ5EXznIxGVO09xQRrwplcS8qs28pZ8s8hupZAmqDwZUmVZ2Qb2jnyPOWcDH8m8dlA==", + "version": "2.2.3", + "resolved": "https://registry.npmjs.org/json5/-/json5-2.2.3.tgz", + "integrity": "sha512-XmOWe7eyHYH14cLdVPoyg+GOH3rYX++KpzrylJwSW98t3Nk+U8XOl8FWKOgwtzdb8lXGf6zYwDUzeHMWfxasyg==", "dev": true, "bin": { "json5": "lib/cli.js" @@ -1418,9 +1418,9 @@ "dev": true }, "json5": { - "version": "2.2.1", - "resolved": "https://registry.npmjs.org/json5/-/json5-2.2.1.tgz", - "integrity": "sha512-1hqLFMSrGHRHxav9q9gNjJ5EXznIxGVO09xQRrwplcS8qs28pZ8s8hupZAmqDwZUmVZ2Qb2jnyPOWcDH8m8dlA==", + "version": "2.2.3", + "resolved": "https://registry.npmjs.org/json5/-/json5-2.2.3.tgz", + "integrity": "sha512-XmOWe7eyHYH14cLdVPoyg+GOH3rYX++KpzrylJwSW98t3Nk+U8XOl8FWKOgwtzdb8lXGf6zYwDUzeHMWfxasyg==", "dev": true }, "jsonc-parser": { From b4906830a02464bb566204ee53665b71ef008907 Mon Sep 17 00:00:00 2001 From: Luca Bianconi Date: Mon, 13 Feb 2023 17:45:53 +0100 Subject: [PATCH 34/48] feat: map as slice --- properties.go | 12 +++++++++++- properties_test.go | 18 ++++++++++++++++++ 2 files changed, 29 insertions(+), 1 deletion(-) diff --git a/properties.go b/properties.go index 792df98..b7cccb6 100644 --- a/properties.go +++ b/properties.go @@ -485,12 +485,22 @@ func (m *Map) Values() []string { return values } -// AsMap return the underlying map[string]string. This is useful if you need to +// AsMap returns the underlying map[string]string. This is useful if you need to // for ... range but without the requirement of the ordered elements. func (m *Map) AsMap() map[string]string { return m.kv } +// AsSlice returns the underlying map[string]string as a slice of +// strings with the pattern `{key}={value}`, maintaining the insertion order of the keys. +func (m *Map) AsSlice() []string { + properties := make([]string, len(m.o)) + for i, key := range m.o { + properties[i] = strings.Join([]string{key, m.kv[key]}, "=") + } + return properties +} + // Clone makes a copy of the Map func (m *Map) Clone() *Map { clone := NewMap() diff --git a/properties_test.go b/properties_test.go index d5fa25e..1283c64 100644 --- a/properties_test.go +++ b/properties_test.go @@ -390,3 +390,21 @@ func TestLoadingNonUTF8Properties(t *testing.T) { require.NoError(t, err) require.Equal(t, "Aáa", m.Get("maintainer")) } + +func TestAsSlice(t *testing.T) { + emptyProperties := NewMap() + require.Len(t, emptyProperties.AsSlice(), 0) + + properties := NewMap() + properties.Set("key1", "value1") + properties.Set("key2", "value2") + properties.Set("key3", "value3=somethingElse") + + require.Len(t, properties.AsSlice(), properties.Size()) + + require.Equal(t, []string{ + "key1=value1", + "key2=value2", + "key3=value3=somethingElse"}, + properties.AsSlice()) +} From f22e4e39f5849e0f1694aa5b8ebb4dfd9a5034cf Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Thu, 16 Mar 2023 11:38:54 +0100 Subject: [PATCH 35/48] Bump actions/setup-go from 3 to 4 (#30) Bumps [actions/setup-go](https://github.com/actions/setup-go) from 3 to 4. - [Release notes](https://github.com/actions/setup-go/releases) - [Commits](https://github.com/actions/setup-go/compare/v3...v4) --- updated-dependencies: - dependency-name: actions/setup-go dependency-type: direct:production update-type: version-update:semver-major ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- .github/workflows/check-go-dependencies-task.yml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/.github/workflows/check-go-dependencies-task.yml b/.github/workflows/check-go-dependencies-task.yml index be478ab..7eb19d1 100644 --- a/.github/workflows/check-go-dependencies-task.yml +++ b/.github/workflows/check-go-dependencies-task.yml @@ -76,7 +76,7 @@ jobs: version: 3.x - name: Install Go - uses: actions/setup-go@v3 + uses: actions/setup-go@v4 with: go-version: ${{ env.GO_VERSION }} @@ -126,7 +126,7 @@ jobs: version: 3.x - name: Install Go - uses: actions/setup-go@v3 + uses: actions/setup-go@v4 with: go-version: ${{ env.GO_VERSION }} From da40cc4e52da01f03f0692c28081b4d079490e51 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Tue, 5 Sep 2023 10:58:49 +0000 Subject: [PATCH 36/48] Bump actions/checkout from 3 to 4 Bumps [actions/checkout](https://github.com/actions/checkout) from 3 to 4. - [Release notes](https://github.com/actions/checkout/releases) - [Changelog](https://github.com/actions/checkout/blob/main/CHANGELOG.md) - [Commits](https://github.com/actions/checkout/compare/v3...v4) --- updated-dependencies: - dependency-name: actions/checkout dependency-type: direct:production update-type: version-update:semver-major ... Signed-off-by: dependabot[bot] --- .github/workflows/check-go-dependencies-task.yml | 4 ++-- .github/workflows/check-license.yml | 2 +- .github/workflows/check-markdown-task.yml | 4 ++-- .github/workflows/check-taskfiles.yml | 2 +- .github/workflows/sync-labels.yml | 4 ++-- 5 files changed, 8 insertions(+), 8 deletions(-) diff --git a/.github/workflows/check-go-dependencies-task.yml b/.github/workflows/check-go-dependencies-task.yml index 7eb19d1..0af4d2d 100644 --- a/.github/workflows/check-go-dependencies-task.yml +++ b/.github/workflows/check-go-dependencies-task.yml @@ -65,7 +65,7 @@ jobs: steps: - name: Checkout repository - uses: actions/checkout@v3 + uses: actions/checkout@v4 with: submodules: recursive @@ -115,7 +115,7 @@ jobs: steps: - name: Checkout repository - uses: actions/checkout@v3 + uses: actions/checkout@v4 with: submodules: recursive diff --git a/.github/workflows/check-license.yml b/.github/workflows/check-license.yml index 77c6d18..9fcd4cf 100644 --- a/.github/workflows/check-license.yml +++ b/.github/workflows/check-license.yml @@ -63,7 +63,7 @@ jobs: steps: - name: Checkout repository - uses: actions/checkout@v3 + uses: actions/checkout@v4 - name: Install Ruby uses: ruby/setup-ruby@v1 diff --git a/.github/workflows/check-markdown-task.yml b/.github/workflows/check-markdown-task.yml index 9b53c3a..8587170 100644 --- a/.github/workflows/check-markdown-task.yml +++ b/.github/workflows/check-markdown-task.yml @@ -69,7 +69,7 @@ jobs: steps: - name: Checkout repository - uses: actions/checkout@v3 + uses: actions/checkout@v4 - name: Setup Node.js uses: actions/setup-node@v3 @@ -95,7 +95,7 @@ jobs: steps: - name: Checkout repository - uses: actions/checkout@v3 + uses: actions/checkout@v4 - name: Setup Node.js uses: actions/setup-node@v3 diff --git a/.github/workflows/check-taskfiles.yml b/.github/workflows/check-taskfiles.yml index cc41d93..8c86550 100644 --- a/.github/workflows/check-taskfiles.yml +++ b/.github/workflows/check-taskfiles.yml @@ -39,7 +39,7 @@ jobs: steps: - name: Checkout repository - uses: actions/checkout@v3 + uses: actions/checkout@v4 - name: Setup Node.js uses: actions/setup-node@v3 diff --git a/.github/workflows/sync-labels.yml b/.github/workflows/sync-labels.yml index 70085bd..9134495 100644 --- a/.github/workflows/sync-labels.yml +++ b/.github/workflows/sync-labels.yml @@ -27,7 +27,7 @@ jobs: steps: - name: Checkout repository - uses: actions/checkout@v3 + uses: actions/checkout@v4 - name: Download JSON schema for labels configuration file id: download-schema @@ -106,7 +106,7 @@ jobs: echo "::set-output name=flag::--dry-run" - name: Checkout repository - uses: actions/checkout@v3 + uses: actions/checkout@v4 - name: Download configuration files artifact uses: actions/download-artifact@v3 From 348fa6aae1bb1b7f2ffdf12ef7e2b09bcb54b4b3 Mon Sep 17 00:00:00 2001 From: Cristian Maglie Date: Thu, 12 Oct 2023 16:36:08 +0200 Subject: [PATCH 37/48] ExtractSubIndexLists now allows non-sequential elements --- properties.go | 47 ++++++++++++++++++++++++++++++++++++---------- properties_test.go | 38 +++++++++++++++---------------------- 2 files changed, 52 insertions(+), 33 deletions(-) diff --git a/properties.go b/properties.go index b7cccb6..216fdee 100644 --- a/properties.go +++ b/properties.go @@ -76,6 +76,8 @@ import ( "reflect" "regexp" "runtime" + "sort" + "strconv" "strings" "unicode/utf8" @@ -630,6 +632,9 @@ func (m *Map) ExtractSubIndexSets(root string) []*Map { // "tre.discovery.required.1": "itemA", // "tre.discovery.required.2": "itemB", // "tre.discovery.required.3": "itemC", +// "quattro.discovery.required.1": "itemA", +// "quattro.discovery.required.4": "itemB", +// "quattro.discovery.required.5": "itemC", // } // // calling ExtractSubIndexLists("uno.discovery.required") returns the array: @@ -644,23 +649,45 @@ func (m *Map) ExtractSubIndexSets(root string) []*Map { // // [ "itemA", "itemB", "itemC" ] // +// also the list may contains holes, so calling ExtractSubIndexLists("quattro.discovery.required") returns: +// +// [ "itemA", "itemB", "itemC" ] +// // Numeric subindex cannot be mixed with non-numeric, in that case only the numeric sub // index sets will be returned. func (m *Map) ExtractSubIndexLists(root string) []string { - // First check the properties with numeric sub index "root.N.xxx" + isNotDigit := func(in string) bool { + for _, r := range in { + if r < '0' || r > '9' { + return true + } + } + return false + } + + // Extract numeric keys + subProps := m.SubTree(root) + indexes := []int{} + for _, key := range subProps.o { + if isNotDigit(key) { + continue + } + if idx, err := strconv.Atoi(key); err == nil { + indexes = append(indexes, idx) + } + } + sort.Ints(indexes) + res := []string{} - portIDPropsSet := m.SubTree(root) - idx := 0 haveIndexedProperties := false - for { - k := fmt.Sprintf("%d", idx) - idx++ - if v, ok := portIDPropsSet.GetOk(k); ok { + for i, idx := range indexes { + if i > 0 && idx == indexes[i-1] { + // de-duplicate cases like "05" and "5" + continue + } + if v, ok := subProps.GetOk(strconv.Itoa(idx)); ok { haveIndexedProperties = true res = append(res, v) - } else if idx > 1 { - // Always check sub-id 0 and 1 (https://github.com/arduino/arduino-cli/issues/456) - break } } diff --git a/properties_test.go b/properties_test.go index 1283c64..16a4c01 100644 --- a/properties_test.go +++ b/properties_test.go @@ -357,32 +357,24 @@ func TestExtractSubIndexLists(t *testing.T) { "quattro.discovery.required.1": "itemB", "quattro.discovery.required.2": "itemC", "cinque.discovery.something": "itemX", + "sei.discovery.something.1": "itemA", + "sei.discovery.something.2": "itemB", + "sei.discovery.something.5": "itemC", + "sei.discovery.something.12": "itemD", + "sette.discovery.something.01": "itemA", + "sette.discovery.something.2": "itemB", + "sette.discovery.something.05": "itemC", + "sette.discovery.something.5": "itemD", } m := NewFromHashmap(data) - s1 := m.ExtractSubIndexLists("uno.discovery.required") - require.Len(t, s1, 1) - require.Equal(t, s1[0], "item") - - s2 := m.ExtractSubIndexLists("due.discovery.required") - require.Len(t, s2, 3) - require.Equal(t, s2[0], "item1") - require.Equal(t, s2[1], "item2") - require.Equal(t, s2[2], "item3") - - s3 := m.ExtractSubIndexLists("tre.discovery.required") - require.Len(t, s3, 3) - require.Equal(t, s3[0], "itemA") - require.Equal(t, s3[1], "itemB") - require.Equal(t, s3[2], "itemC") - - s4 := m.ExtractSubIndexLists("quattro.discovery.required") - require.Len(t, s4, 2) - require.Equal(t, s4[0], "itemB") - require.Equal(t, s4[1], "itemC") - - s5 := m.ExtractSubIndexLists("cinque.discovery.required") - require.Len(t, s5, 0) + require.Equal(t, []string{"item"}, m.ExtractSubIndexLists("uno.discovery.required")) + require.Equal(t, []string{"item1", "item2", "item3"}, m.ExtractSubIndexLists("due.discovery.required")) + require.Equal(t, []string{"itemA", "itemB", "itemC"}, m.ExtractSubIndexLists("tre.discovery.required")) + require.Equal(t, []string{"itemB", "itemC"}, m.ExtractSubIndexLists("quattro.discovery.required")) + require.Equal(t, []string{}, m.ExtractSubIndexLists("cinque.discovery.required")) + require.Equal(t, []string{"itemA", "itemB", "itemC", "itemD"}, m.ExtractSubIndexLists("sei.discovery.something")) + require.Equal(t, []string{"itemB", "itemD"}, m.ExtractSubIndexLists("sette.discovery.something")) } func TestLoadingNonUTF8Properties(t *testing.T) { From 03d5684e89a1c0f40b345061f9e7944a8fbf7ed3 Mon Sep 17 00:00:00 2001 From: Cristian Maglie Date: Thu, 12 Oct 2023 16:58:16 +0200 Subject: [PATCH 38/48] Update check-taskfile workflow --- .github/workflows/check-taskfiles.yml | 33 +++++++++++++++++++++++++-- 1 file changed, 31 insertions(+), 2 deletions(-) diff --git a/.github/workflows/check-taskfiles.yml b/.github/workflows/check-taskfiles.yml index 8c86550..b9a65e4 100644 --- a/.github/workflows/check-taskfiles.yml +++ b/.github/workflows/check-taskfiles.yml @@ -7,6 +7,7 @@ env: # See: https://docs.github.com/actions/using-workflows/events-that-trigger-workflows on: + create: push: paths: - ".github/workflows/check-taskfiles.ya?ml" @@ -26,9 +27,37 @@ on: repository_dispatch: jobs: + run-determination: + runs-on: ubuntu-latest + permissions: {} + outputs: + result: ${{ steps.determination.outputs.result }} + steps: + - name: Determine if the rest of the workflow should run + id: determination + run: | + RELEASE_BRANCH_REGEX="refs/heads/[0-9]+.[0-9]+.x" + # The `create` event trigger doesn't support `branches` filters, so it's necessary to use Bash instead. + if [[ + "${{ github.event_name }}" != "create" || + "${{ github.ref }}" =~ $RELEASE_BRANCH_REGEX + ]]; then + # Run the other jobs. + RESULT="true" + else + # There is no need to run the other jobs. + RESULT="false" + fi + + echo "result=$RESULT" >> $GITHUB_OUTPUT + validate: name: Validate ${{ matrix.file }} + needs: run-determination + if: needs.run-determination.outputs.result == 'true' runs-on: ubuntu-latest + permissions: + contents: read strategy: fail-fast: false @@ -50,8 +79,8 @@ jobs: id: download-schema uses: carlosperate/download-file-action@v2 with: - # See: https://github.com/SchemaStore/schemastore/blob/master/src/schemas/json/taskfile.json - file-url: https://json.schemastore.org/taskfile.json + # Source: https://github.com/SchemaStore/schemastore/blob/master/src/schemas/json/taskfile.json + file-url: https://taskfile.dev/schema.json location: ${{ runner.temp }}/taskfile-schema - name: Install JSON schema validator From 70c55c7aa55cf1697f226cdd49bcd48baf85cad5 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Tue, 24 Oct 2023 10:58:55 +0000 Subject: [PATCH 39/48] Bump actions/setup-node from 3 to 4 Bumps [actions/setup-node](https://github.com/actions/setup-node) from 3 to 4. - [Release notes](https://github.com/actions/setup-node/releases) - [Commits](https://github.com/actions/setup-node/compare/v3...v4) --- updated-dependencies: - dependency-name: actions/setup-node dependency-type: direct:production update-type: version-update:semver-major ... Signed-off-by: dependabot[bot] --- .github/workflows/check-markdown-task.yml | 4 ++-- .github/workflows/check-taskfiles.yml | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/.github/workflows/check-markdown-task.yml b/.github/workflows/check-markdown-task.yml index 8587170..22aea65 100644 --- a/.github/workflows/check-markdown-task.yml +++ b/.github/workflows/check-markdown-task.yml @@ -72,7 +72,7 @@ jobs: uses: actions/checkout@v4 - name: Setup Node.js - uses: actions/setup-node@v3 + uses: actions/setup-node@v4 with: node-version: ${{ env.NODE_VERSION }} @@ -98,7 +98,7 @@ jobs: uses: actions/checkout@v4 - name: Setup Node.js - uses: actions/setup-node@v3 + uses: actions/setup-node@v4 with: node-version: ${{ env.NODE_VERSION }} diff --git a/.github/workflows/check-taskfiles.yml b/.github/workflows/check-taskfiles.yml index b9a65e4..d369f69 100644 --- a/.github/workflows/check-taskfiles.yml +++ b/.github/workflows/check-taskfiles.yml @@ -71,7 +71,7 @@ jobs: uses: actions/checkout@v4 - name: Setup Node.js - uses: actions/setup-node@v3 + uses: actions/setup-node@v4 with: node-version: ${{ env.NODE_VERSION }} From 611a09ab77550cb8deb02f48a9662ce301ad8b51 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Thu, 7 Dec 2023 11:02:35 +0000 Subject: [PATCH 40/48] Bump actions/setup-go from 4 to 5 Bumps [actions/setup-go](https://github.com/actions/setup-go) from 4 to 5. - [Release notes](https://github.com/actions/setup-go/releases) - [Commits](https://github.com/actions/setup-go/compare/v4...v5) --- updated-dependencies: - dependency-name: actions/setup-go dependency-type: direct:production update-type: version-update:semver-major ... Signed-off-by: dependabot[bot] --- .github/workflows/check-go-dependencies-task.yml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/.github/workflows/check-go-dependencies-task.yml b/.github/workflows/check-go-dependencies-task.yml index 0af4d2d..0a368eb 100644 --- a/.github/workflows/check-go-dependencies-task.yml +++ b/.github/workflows/check-go-dependencies-task.yml @@ -76,7 +76,7 @@ jobs: version: 3.x - name: Install Go - uses: actions/setup-go@v4 + uses: actions/setup-go@v5 with: go-version: ${{ env.GO_VERSION }} @@ -126,7 +126,7 @@ jobs: version: 3.x - name: Install Go - uses: actions/setup-go@v4 + uses: actions/setup-go@v5 with: go-version: ${{ env.GO_VERSION }} From f260d7b0be3c6ad3f7bcdc942972a9f86c4db6b2 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Tue, 6 Feb 2024 10:45:22 +0000 Subject: [PATCH 41/48] Bump arduino/setup-task from 1 to 2 Bumps [arduino/setup-task](https://github.com/arduino/setup-task) from 1 to 2. - [Release notes](https://github.com/arduino/setup-task/releases) - [Commits](https://github.com/arduino/setup-task/compare/v1...v2) --- updated-dependencies: - dependency-name: arduino/setup-task dependency-type: direct:production update-type: version-update:semver-major ... Signed-off-by: dependabot[bot] --- .github/workflows/check-go-dependencies-task.yml | 4 ++-- .github/workflows/check-markdown-task.yml | 4 ++-- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/.github/workflows/check-go-dependencies-task.yml b/.github/workflows/check-go-dependencies-task.yml index 0a368eb..c5ff500 100644 --- a/.github/workflows/check-go-dependencies-task.yml +++ b/.github/workflows/check-go-dependencies-task.yml @@ -81,7 +81,7 @@ jobs: go-version: ${{ env.GO_VERSION }} - name: Install Task - uses: arduino/setup-task@v1 + uses: arduino/setup-task@v2 with: repo-token: ${{ secrets.GITHUB_TOKEN }} version: 3.x @@ -131,7 +131,7 @@ jobs: go-version: ${{ env.GO_VERSION }} - name: Install Task - uses: arduino/setup-task@v1 + uses: arduino/setup-task@v2 with: repo-token: ${{ secrets.GITHUB_TOKEN }} version: 3.x diff --git a/.github/workflows/check-markdown-task.yml b/.github/workflows/check-markdown-task.yml index 22aea65..d172c17 100644 --- a/.github/workflows/check-markdown-task.yml +++ b/.github/workflows/check-markdown-task.yml @@ -80,7 +80,7 @@ jobs: uses: xt0rted/markdownlint-problem-matcher@v2 - name: Install Task - uses: arduino/setup-task@v1 + uses: arduino/setup-task@v2 with: repo-token: ${{ secrets.GITHUB_TOKEN }} version: 3.x @@ -103,7 +103,7 @@ jobs: node-version: ${{ env.NODE_VERSION }} - name: Install Task - uses: arduino/setup-task@v1 + uses: arduino/setup-task@v2 with: repo-token: ${{ secrets.GITHUB_TOKEN }} version: 3.x From 69cb83e785205f7dfe401c53fc6e247c9ed12f1b Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Mon, 26 Feb 2024 10:35:43 +0000 Subject: [PATCH 42/48] Bump xt0rted/markdownlint-problem-matcher from 2 to 3 Bumps [xt0rted/markdownlint-problem-matcher](https://github.com/xt0rted/markdownlint-problem-matcher) from 2 to 3. - [Release notes](https://github.com/xt0rted/markdownlint-problem-matcher/releases) - [Changelog](https://github.com/xt0rted/markdownlint-problem-matcher/blob/main/CHANGELOG.md) - [Commits](https://github.com/xt0rted/markdownlint-problem-matcher/compare/v2...v3) --- updated-dependencies: - dependency-name: xt0rted/markdownlint-problem-matcher dependency-type: direct:production update-type: version-update:semver-major ... Signed-off-by: dependabot[bot] --- .github/workflows/check-markdown-task.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/check-markdown-task.yml b/.github/workflows/check-markdown-task.yml index d172c17..5f2a772 100644 --- a/.github/workflows/check-markdown-task.yml +++ b/.github/workflows/check-markdown-task.yml @@ -77,7 +77,7 @@ jobs: node-version: ${{ env.NODE_VERSION }} - name: Initialize markdownlint-cli problem matcher - uses: xt0rted/markdownlint-problem-matcher@v2 + uses: xt0rted/markdownlint-problem-matcher@v3 - name: Install Task uses: arduino/setup-task@v2 From 9ea886b5ffa257b4938d16099276ed92e2cd46e9 Mon Sep 17 00:00:00 2001 From: Cristian Maglie Date: Tue, 4 Jun 2024 16:38:13 +0200 Subject: [PATCH 43/48] SplitQuotedString always returns a result If the function finds an opening quote character and does not find the closing quote character, it will return an error. Previously, in case of error, the returned split array was always empty. Now, in any case, the function will return the split array up to the point where the error occurred. --- strings.go | 26 +++++++++++++++++++++++--- strings_test.go | 11 +++++++---- 2 files changed, 30 insertions(+), 7 deletions(-) diff --git a/strings.go b/strings.go index f64b15e..4eae333 100644 --- a/strings.go +++ b/strings.go @@ -39,9 +39,29 @@ import ( // to use spaces in a single element of the split using quote characters. // // For example the call: -// SplitQuotedString(`This 'is an' "Hello World!" example`, `'"`, false) +// +// SplitQuotedString(`This 'is an' "Hello World!" example`, `'"`, false) +// // returns the following array: -// []string{"This", "is an", "Hello World!", "example"} +// +// []string{"This", "is an", "Hello World!", "example"} +// +// The quoteChars parameter is a string containing all the characters that +// are considered as quote characters. If a quote character is found, the +// function will consider the text between the quote character and the next +// quote character as a single element of the split. +// +// The acceptEmptyArguments parameter is a boolean that indicates if the +// function should consider empty arguments as valid elements of the split. +// If set to false, the function will ignore empty arguments. +// +// If the function finds an opening quote character and does not find the +// closing quote character, it will return an error. In any case, the function +// will return the split array up to the point where the error occurred. +// +// The function does not support escaping of quote characters. +// +// The function is UTF-8 safe. func SplitQuotedString(src string, quoteChars string, acceptEmptyArguments bool) ([]string, error) { // Make a map of valid quote runes isQuote := map[rune]bool{} @@ -83,7 +103,7 @@ func SplitQuotedString(src string, quoteChars string, acceptEmptyArguments bool) } if escapingChar != 0 { - return nil, fmt.Errorf("invalid quoting, no closing `%c` char found", escapingChar) + return result, fmt.Errorf("invalid quoting, no closing `%c` char found", escapingChar) } return result, nil diff --git a/strings_test.go b/strings_test.go index 2f5319d..9245f04 100644 --- a/strings_test.go +++ b/strings_test.go @@ -64,8 +64,11 @@ func TestSplitQuotedStringWithUTF8(t *testing.T) { } func TestSplitQuotedStringInvalid(t *testing.T) { - _, err := SplitQuotedString(`'this is' a 'test of quoting`, `"'`, true) - require.Error(t, err) - _, err = SplitQuotedString(`'this is' a "'test" of "quoting`, `"'`, true) - require.Error(t, err) + res, err := SplitQuotedString(`'this is' a 'test of quoting`, `"'`, true) + require.EqualError(t, err, "invalid quoting, no closing `'` char found") + require.Equal(t, res, []string{"this is", "a"}) + + res, err = SplitQuotedString(`'this is' a "'test" of "quoting`, `"'`, true) + require.EqualError(t, err, "invalid quoting, no closing `\"` char found") + require.Equal(t, res, []string{"this is", "a", "'test", "of"}) } From 7515f2dd7c238320635da8bdb459c2623d2d0e15 Mon Sep 17 00:00:00 2001 From: per1234 Date: Tue, 3 Sep 2024 12:33:30 -0700 Subject: [PATCH 44/48] Configure actions/upload-artifact action to upload required hidden files A breaking change was made in the 3.2.1 release of the "actions/upload-artifact" action, without doing a major version bump as would be done in a responsibly maintained project. The action now defaults to not uploading "hidden" files. This project's "Check Go Dependencies" workflow uses the "Licensed" tool to check for incompatible dependency licenses. The dependencies license metadata cache used by Licensed is stored in a folder named `.licensed`. In order to facilitate updates, the workflow uploads the generated dependencies license metadata cache as a workflow artifact when the current cache is found to be outdated. The `.` at the start of the `.licensed` folder name causes it to now not be uploaded to the workflow artifact. In order to catch such problems, the workflow configures the "actions/upload-artifact" action to fail if no files were uploaded. So in addition to not uploading the artifact, the change in the "actions/upload-artifact" action's behavior also resulted in the workflow runs failing: Error: No files were found with the provided path: .licenses/. No artifacts will be uploaded. The problem is fixed by disabling the "actions/upload-artifact" action's new behavior via the `include-hidden-files` input. After this change, the workflow can once more upload the dependencies license metadata cache to a workflow artifact as needed. --- .github/workflows/check-go-dependencies-task.yml | 1 + 1 file changed, 1 insertion(+) diff --git a/.github/workflows/check-go-dependencies-task.yml b/.github/workflows/check-go-dependencies-task.yml index c5ff500..ec1469a 100644 --- a/.github/workflows/check-go-dependencies-task.yml +++ b/.github/workflows/check-go-dependencies-task.yml @@ -105,6 +105,7 @@ jobs: uses: actions/upload-artifact@v3 with: if-no-files-found: error + include-hidden-files: true name: dep-licenses-cache path: .licenses/ From dab28eb5f1629c879c247b1739ab52e3d14dbe1c Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Wed, 9 Oct 2024 08:37:13 +0000 Subject: [PATCH 45/48] Bump actions/upload-artifact from 3 to 4 Bumps [actions/upload-artifact](https://github.com/actions/upload-artifact) from 3 to 4. - [Release notes](https://github.com/actions/upload-artifact/releases) - [Commits](https://github.com/actions/upload-artifact/compare/v3...v4) --- updated-dependencies: - dependency-name: actions/upload-artifact dependency-type: direct:production update-type: version-update:semver-major ... Signed-off-by: dependabot[bot] --- .github/workflows/check-go-dependencies-task.yml | 2 +- .github/workflows/sync-labels.yml | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/.github/workflows/check-go-dependencies-task.yml b/.github/workflows/check-go-dependencies-task.yml index ec1469a..6cb341d 100644 --- a/.github/workflows/check-go-dependencies-task.yml +++ b/.github/workflows/check-go-dependencies-task.yml @@ -102,7 +102,7 @@ jobs: # Some might find it convenient to have CI generate the cache rather than setting up for it locally - name: Upload cache to workflow artifact if: failure() && steps.diff.outcome == 'failure' - uses: actions/upload-artifact@v3 + uses: actions/upload-artifact@v4 with: if-no-files-found: error include-hidden-files: true diff --git a/.github/workflows/sync-labels.yml b/.github/workflows/sync-labels.yml index 9134495..e1b8658 100644 --- a/.github/workflows/sync-labels.yml +++ b/.github/workflows/sync-labels.yml @@ -71,7 +71,7 @@ jobs: file-url: https://raw.githubusercontent.com/arduino/tooling-project-assets/main/workflow-templates/assets/sync-labels/${{ matrix.filename }} - name: Pass configuration files to next job via workflow artifact - uses: actions/upload-artifact@v3 + uses: actions/upload-artifact@v4 with: path: | *.yaml From 85a79edadcf85c091c59d28036655cf1ae5cb478 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Fri, 15 Dec 2023 10:48:46 +0000 Subject: [PATCH 46/48] Bump actions/download-artifact from 3 to 4 Bumps [actions/download-artifact](https://github.com/actions/download-artifact) from 3 to 4. - [Release notes](https://github.com/actions/download-artifact/releases) - [Commits](https://github.com/actions/download-artifact/compare/v3...v4) --- updated-dependencies: - dependency-name: actions/download-artifact dependency-type: direct:production update-type: version-update:semver-major ... Signed-off-by: dependabot[bot] --- .github/workflows/sync-labels.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/sync-labels.yml b/.github/workflows/sync-labels.yml index e1b8658..34ff6a5 100644 --- a/.github/workflows/sync-labels.yml +++ b/.github/workflows/sync-labels.yml @@ -109,7 +109,7 @@ jobs: uses: actions/checkout@v4 - name: Download configuration files artifact - uses: actions/download-artifact@v3 + uses: actions/download-artifact@v4 with: name: ${{ env.CONFIGURATIONS_ARTIFACT }} path: ${{ env.CONFIGURATIONS_FOLDER }} From 053c17bfe3638c218fd36ef1dd182ada5e742322 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Tue, 19 Mar 2024 10:49:17 +0000 Subject: [PATCH 47/48] Bump geekyeggo/delete-artifact from 2 to 5 Bumps [geekyeggo/delete-artifact](https://github.com/geekyeggo/delete-artifact) from 2 to 5. - [Release notes](https://github.com/geekyeggo/delete-artifact/releases) - [Changelog](https://github.com/GeekyEggo/delete-artifact/blob/main/CHANGELOG.md) - [Commits](https://github.com/geekyeggo/delete-artifact/compare/v2...v5) --- updated-dependencies: - dependency-name: geekyeggo/delete-artifact dependency-type: direct:production update-type: version-update:semver-major ... Signed-off-by: dependabot[bot] --- .github/workflows/sync-labels.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/sync-labels.yml b/.github/workflows/sync-labels.yml index 34ff6a5..e73db2e 100644 --- a/.github/workflows/sync-labels.yml +++ b/.github/workflows/sync-labels.yml @@ -115,7 +115,7 @@ jobs: path: ${{ env.CONFIGURATIONS_FOLDER }} - name: Remove unneeded artifact - uses: geekyeggo/delete-artifact@v2 + uses: geekyeggo/delete-artifact@v5 with: name: ${{ env.CONFIGURATIONS_ARTIFACT }} From 382cd904cf251c4d9f57a524b269d1ded02ec22c Mon Sep 17 00:00:00 2001 From: per1234 Date: Sun, 20 Oct 2024 05:39:17 -0700 Subject: [PATCH 48/48] Don't upload multiple times to same artifact in label sync workflow The "Sync Labels" GitHub Actions workflow is configured to allow the use of multiple shared label configuration files. This is done by using a job matrix in the GitHub Actions workflow to download each of the files from the source repository in a parallel GitHub Actions workflow job. A GitHub Actions workflow artifact was used to transfer the generated files between sequential jobs in the workflow. The "actions/upload-artifact" and "actions/download-artifact" actions are used for this purpose. Previously, a single artifact was used for the transfer of all the shared label configuration files, with each of the parallel jobs uploading its own generated files to that artifact. However, support for uploading multiple times to a single artifact was dropped in version 4.0.0 of the "actions/upload-artifact" action. So it is now necessary to use a dedicated artifact for each of the builds. These can be downloaded in aggregate by using the artifact name globbing and merging features which were introduced in version 4.1.0 of the "actions/download-artifact" action. --- .github/workflows/sync-labels.yml | 13 +++++++------ 1 file changed, 7 insertions(+), 6 deletions(-) diff --git a/.github/workflows/sync-labels.yml b/.github/workflows/sync-labels.yml index e73db2e..78723a3 100644 --- a/.github/workflows/sync-labels.yml +++ b/.github/workflows/sync-labels.yml @@ -19,7 +19,7 @@ on: env: CONFIGURATIONS_FOLDER: .github/label-configuration-files - CONFIGURATIONS_ARTIFACT: label-configuration-files + CONFIGURATIONS_ARTIFACT_PREFIX: label-configuration-file- jobs: check: @@ -77,7 +77,7 @@ jobs: *.yaml *.yml if-no-files-found: error - name: ${{ env.CONFIGURATIONS_ARTIFACT }} + name: ${{ env.CONFIGURATIONS_ARTIFACT_PREFIX }}${{ matrix.filename }} sync: needs: download @@ -108,16 +108,17 @@ jobs: - name: Checkout repository uses: actions/checkout@v4 - - name: Download configuration files artifact + - name: Download configuration file artifacts uses: actions/download-artifact@v4 with: - name: ${{ env.CONFIGURATIONS_ARTIFACT }} + merge-multiple: true + pattern: ${{ env.CONFIGURATIONS_ARTIFACT_PREFIX }}* path: ${{ env.CONFIGURATIONS_FOLDER }} - - name: Remove unneeded artifact + - name: Remove unneeded artifacts uses: geekyeggo/delete-artifact@v5 with: - name: ${{ env.CONFIGURATIONS_ARTIFACT }} + name: ${{ env.CONFIGURATIONS_ARTIFACT_PREFIX }}* - name: Merge label configuration files run: |