Files
setup-task/Taskfile.yml
per1234 e22b976180 Use npm to manage tool dependencies
Some of the assets use tools sourced from the npm software registry.

Previously, the version of the tools used was not controlled. This was problematic because:

- A different version of the tool may be used on the contributor's machine than on the CI runner, resulting in confusing
  failures.
- The project is immediately subject to disruption or breakage resulting from a release of the tool.

---

These tools were installed via either of the following methods:

`npx <pkg>`

This approach has the following behaviors of interest:

https://docs.npmjs.com/cli/v8/commands/npx#description

> If any requested packages are not present in the local project dependencies, then they are installed to a folder in the npm cache, which is added to the PATH environment variable in the executed process.

> Package names provided without a specifier will be matched with whatever version exists in the local project. Package names with a specifier will only be considered a match if they have the exact same name and version as the local dependency.

This means that the version used was:

1. Whatever happens to be present in the local cache
2. The latest available version if it is not already present

`npm install --global <pkg>`

The latest available version of the package is used.

---

The new approach is to specify the version of the tools via the standard npm metadata files (package.json +
package-lock.json). This approach was chosen over the `npx <pkg>@<version>` alternative for the following reasons:

- Enables automated updates via Dependabot PRs
- Enables automated vulnerability alerts
- Separates dependency management from the asset contents (i.e., no need to mess with the taskfile or workflow on every
  update)
- Matches how we are already managing Python dependencies (pyproject.toml + poetry.lock)
2022-12-16 16:19:02 -08:00

351 lines
14 KiB
YAML

version: "3"
vars:
# Last version of ajv-cli with support for the JSON schema "Draft 4" specification
SCHEMA_DRAFT_4_AJV_CLI_VERSION: 3.3.0
tasks:
build:
desc: Build the project
deps:
- task: ts:build
check:
desc: Check for problems with the project
deps:
- task: action:validate
- task: general:check-spelling
- task: markdown:check-links
- task: markdown:lint
- task: npm:validate
- task: ts:lint
- task: ts:test
- task: ts:validate
vars:
TSCONFIG_PATH: "./tsconfig.json"
- task: ts:validate
vars:
TSCONFIG_PATH: "./tsconfig.eslint.json"
fix:
desc: Make automated corrections to the project's files
deps:
- task: general:correct-spelling
- task: general:format-prettier
- task: markdown:fix
- task: ts:build
- task: ts:fix-lint
action:validate:
desc: Validate GitHub Actions metadata against JSON schema
vars:
ACTION_METADATA_SCHEMA_PATH:
sh: mktemp -t github-action-schema-XXXXXXXXXX.json
deps:
- task: npm:install-deps
cmds:
- wget --quiet --output-document="{{.ACTION_METADATA_SCHEMA_PATH}}" https://json.schemastore.org/github-action
- npx ajv-cli validate --strict=false -s "{{.ACTION_METADATA_SCHEMA_PATH}}" -d "action.yml"
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-dependencies-task/Taskfile.yml
general:cache-dep-licenses:
desc: Cache dependency license metadata
deps:
- task: general:install-deps
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
# Source: https://github.com/arduino/tooling-project-assets/blob/main/workflow-templates/assets/spell-check-task/Taskfile.yml
general:check-spelling:
desc: Check for commonly misspelled words
deps:
- task: poetry:install-deps
cmds:
- poetry run codespell
# Source: https://github.com/arduino/tooling-project-assets/blob/main/workflow-templates/assets/spell-check-task/Taskfile.yml
general:correct-spelling:
desc: Correct commonly misspelled words where possible
deps:
- task: poetry:install-deps
cmds:
- poetry run codespell --write-changes
# Source: https://github.com/arduino/tooling-project-assets/blob/main/workflow-templates/assets/check-prettier-formatting-task/Taskfile.yml
general:format-prettier:
desc: Format all supported files with Prettier
deps:
- task: npm:install-deps
cmds:
- npx prettier --write .
# Source: https://github.com/arduino/tooling-project-assets/blob/main/workflow-templates/assets/check-npm-dependencies-task/Taskfile.yml
general:install-deps:
desc: Install project dependencies
deps:
- task: npm:install-deps
# 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 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 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
# Source: https://github.com/arduino/tooling-project-assets/blob/main/workflow-templates/assets/check-npm-task/Taskfile.yml
npm:validate:
desc: Validate npm configuration files against their JSON schema
vars:
# Source: https://github.com/SchemaStore/schemastore/blob/master/src/schemas/json/package.json
SCHEMA_URL: https://json.schemastore.org/package.json
SCHEMA_PATH:
sh: task utility:mktemp-file TEMPLATE="package-json-schema-XXXXXXXXXX.json"
# Source: https://github.com/SchemaStore/schemastore/blob/master/src/schemas/json/ava.json
AVA_SCHEMA_URL: https://json.schemastore.org/ava.json
AVA_SCHEMA_PATH:
sh: task utility:mktemp-file TEMPLATE="ava-schema-XXXXXXXXXX.json"
# Source: https://github.com/SchemaStore/schemastore/blob/master/src/schemas/json/eslintrc.json
ESLINTRC_SCHEMA_URL: https://json.schemastore.org/eslintrc.json
ESLINTRC_SCHEMA_PATH:
sh: task utility:mktemp-file TEMPLATE="eslintrc-schema-XXXXXXXXXX.json"
# Source: https://github.com/SchemaStore/schemastore/blob/master/src/schemas/json/jscpd.json
JSCPD_SCHEMA_URL: https://json.schemastore.org/jscpd.json
JSCPD_SCHEMA_PATH:
sh: task utility:mktemp-file TEMPLATE="jscpd-schema-XXXXXXXXXX.json"
# Source: https://github.com/SchemaStore/schemastore/blob/master/src/schemas/json/npm-badges.json
NPM_BADGES_SCHEMA_URL: https://json.schemastore.org/npm-badges.json
NPM_BADGES_SCHEMA_PATH:
sh: task utility:mktemp-file TEMPLATE="npm-badges-schema-XXXXXXXXXX.json"
# Source: https://github.com/SchemaStore/schemastore/blob/master/src/schemas/json/prettierrc.json
PRETTIERRC_SCHEMA_URL: https://json.schemastore.org/prettierrc.json
PRETTIERRC_SCHEMA_PATH:
sh: task utility:mktemp-file TEMPLATE="prettierrc-schema-XXXXXXXXXX.json"
# Source: https://github.com/SchemaStore/schemastore/blob/master/src/schemas/json/semantic-release.json
SEMANTIC_RELEASE_SCHEMA_URL: https://json.schemastore.org/semantic-release.json
SEMANTIC_RELEASE_SCHEMA_PATH:
sh: task utility:mktemp-file TEMPLATE="semantic-release-schema-XXXXXXXXXX.json"
# Source: https://github.com/SchemaStore/schemastore/blob/master/src/schemas/json/stylelintrc.json
STYLELINTRC_SCHEMA_URL: https://json.schemastore.org/stylelintrc.json
STYLELINTRC_SCHEMA_PATH:
sh: task utility:mktemp-file TEMPLATE="stylelintrc-schema-XXXXXXXXXX.json"
INSTANCE_PATH: "**/package.json"
PROJECT_FOLDER:
sh: pwd
WORKING_FOLDER:
sh: task utility:mktemp-folder TEMPLATE="dependabot-validate-XXXXXXXXXX"
cmds:
- wget --quiet --output-document="{{.SCHEMA_PATH}}" {{.SCHEMA_URL}}
- wget --quiet --output-document="{{.AVA_SCHEMA_PATH}}" {{.AVA_SCHEMA_URL}}
- wget --quiet --output-document="{{.ESLINTRC_SCHEMA_PATH}}" {{.ESLINTRC_SCHEMA_URL}}
- wget --quiet --output-document="{{.JSCPD_SCHEMA_PATH}}" {{.JSCPD_SCHEMA_URL}}
- wget --quiet --output-document="{{.NPM_BADGES_SCHEMA_PATH}}" {{.NPM_BADGES_SCHEMA_URL}}
- wget --quiet --output-document="{{.PRETTIERRC_SCHEMA_PATH}}" {{.PRETTIERRC_SCHEMA_URL}}
- wget --quiet --output-document="{{.SEMANTIC_RELEASE_SCHEMA_PATH}}" {{.SEMANTIC_RELEASE_SCHEMA_URL}}
- wget --quiet --output-document="{{.STYLELINTRC_SCHEMA_PATH}}" {{.STYLELINTRC_SCHEMA_URL}}
- |
cd "{{.WORKING_FOLDER}}" # Workaround for https://github.com/npm/cli/issues/3210
npx ajv-cli@{{.SCHEMA_DRAFT_4_AJV_CLI_VERSION}} validate \
--all-errors \
-s "{{.SCHEMA_PATH}}" \
-r "{{.AVA_SCHEMA_PATH}}" \
-r "{{.ESLINTRC_SCHEMA_PATH}}" \
-r "{{.JSCPD_SCHEMA_PATH}}" \
-r "{{.NPM_BADGES_SCHEMA_PATH}}" \
-r "{{.PRETTIERRC_SCHEMA_PATH}}" \
-r "{{.SEMANTIC_RELEASE_SCHEMA_PATH}}" \
-r "{{.STYLELINTRC_SCHEMA_PATH}}" \
-d "{{.PROJECT_FOLDER}}/{{.INSTANCE_PATH}}"
# Source: https://github.com/arduino/tooling-project-assets/blob/main/workflow-templates/assets/poetry-task/Taskfile.yml
poetry:install-deps:
desc: Install dependencies managed by Poetry
cmds:
- poetry install --no-root
ts:build:
desc: Build the action's TypeScript code.
deps:
- task: ts:install-deps
cmds:
- npx tsc
- npx ncc build
ts:fix-lint:
desc: Fix TypeScript code linting violations
deps:
- task: ts:install-deps
cmds:
- npx eslint --ext .js,.jsx,.ts,.tsx --fix .
ts:install-deps:
desc: Install TypeScript dependencies
deps:
- task: npm:install-deps
ts:lint:
desc: Lint TypeScript code
deps:
- task: ts:install-deps
cmds:
- npx eslint --ext .js,.jsx,.ts,.tsx .
ts:test:
desc: Test the action's TypeScript code.
deps:
- task: ts:install-deps
cmds:
- npx jest
ts:validate:
desc: Validate TypeScript configuration file against its JSON schema
vars:
# Source: https://github.com/SchemaStore/schemastore/blob/master/src/schemas/json/tsconfig.json
SCHEMA_URL: https://json.schemastore.org/tsconfig.json
SCHEMA_PATH:
sh: task utility:mktemp-file TEMPLATE="tsconfig-schema-XXXXXXXXXX.json"
INSTANCE_PATH: '{{default "./tsconfig.json" .TSCONFIG_PATH}}'
WORKING_FOLDER:
sh: task utility:mktemp-folder TEMPLATE="ts-validate-XXXXXXXXXX"
WORKING_INSTANCE_PATH:
sh: echo "{{.WORKING_FOLDER}}/$(basename "{{.INSTANCE_PATH}}")"
deps:
- task: npm:install-deps
cmds:
- |
# TypeScript allows comments in tsconfig.json.
# ajv-cli did not support comments in JSON at the 3.x version in use (support was added in a later version).
npx strip-json-comments-cli \
--no-whitespace \
"{{.INSTANCE_PATH}}" \
> "{{.WORKING_INSTANCE_PATH}}"
- |
wget \
--quiet \
--output-document="{{.SCHEMA_PATH}}" \
{{.SCHEMA_URL}}
- |
cd "{{.WORKING_FOLDER}}" # Workaround for https://github.com/npm/cli/issues/3210
npx ajv-cli@{{.SCHEMA_DRAFT_4_AJV_CLI_VERSION}} validate \
--all-errors \
-s "{{.SCHEMA_PATH}}" \
-d "{{.WORKING_INSTANCE_PATH}}"
# Make a temporary file named according to the passed TEMPLATE variable and print the path passed to stdout
# Source: https://github.com/arduino/tooling-project-assets/blob/main/workflow-templates/assets/windows-task/Taskfile.yml
utility:mktemp-file:
vars:
RAW_PATH:
sh: mktemp --tmpdir "{{.TEMPLATE}}"
cmds:
- task: utility:normalize-path
vars:
RAW_PATH: "{{.RAW_PATH}}"
# Make a temporary folder named according to the passed TEMPLATE variable and print the path passed to stdout
# Source: https://github.com/arduino/tooling-project-assets/blob/main/workflow-templates/assets/windows-task/Taskfile.yml
utility:mktemp-folder:
vars:
RAW_PATH:
sh: mktemp --directory --tmpdir "{{.TEMPLATE}}"
cmds:
- task: utility:normalize-path
vars:
RAW_PATH: "{{.RAW_PATH}}"
# Print a normalized version of the path passed via the RAW_PATH variable to stdout
# Source: https://github.com/arduino/tooling-project-assets/blob/main/workflow-templates/assets/windows-task/Taskfile.yml
utility:normalize-path:
cmds:
- |
if [[ "{{.OS}}" == "Windows_NT" ]] && which cygpath &>/dev/null; then
# Even though the shell handles POSIX format absolute paths as expected, external applications do not.
# So paths passed to such applications must first be converted to Windows format.
cygpath -w "{{.RAW_PATH}}"
else
echo "{{.RAW_PATH}}"
fi