Skip to content

Commit d9b9dda

Browse files
committed
Add infrastructure to check for problems with npm configuration files
A task and GitHub Actions workflow are provided here for checking the project's npm package manager configuration. On every push and pull request that affects relevant files, and periodically: - Validate package.json against its JSON schema. - Check for forgotten package-lock.json syncs.
1 parent b901bd4 commit d9b9dda

File tree

3 files changed

+222
-0
lines changed

3 files changed

+222
-0
lines changed

.github/workflows/check-npm-task.yml

Lines changed: 103 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,103 @@
1+
# Source: https://github.com/arduino/tooling-project-assets/blob/main/workflow-templates/check-npm-task.md
2+
name: Check npm
3+
4+
env:
5+
# See: https://github.com/actions/setup-node/#readme
6+
NODE_VERSION: 16.x
7+
8+
# See: https://docs.github.com/en/actions/reference/events-that-trigger-workflows
9+
on:
10+
create:
11+
push:
12+
paths:
13+
- ".github/workflows/check-npm-task.ya?ml"
14+
- "**/package.json"
15+
- "**/package-lock.json"
16+
- "Taskfile.ya?ml"
17+
pull_request:
18+
paths:
19+
- ".github/workflows/check-npm-task.ya?ml"
20+
- "**/package.json"
21+
- "**/package-lock.json"
22+
- "Taskfile.ya?ml"
23+
schedule:
24+
# Run every Tuesday at 8 AM UTC to catch breakage resulting from changes to the JSON schema.
25+
- cron: "0 8 * * TUE"
26+
workflow_dispatch:
27+
repository_dispatch:
28+
29+
permissions:
30+
contents: read
31+
32+
jobs:
33+
run-determination:
34+
runs-on: ubuntu-latest
35+
outputs:
36+
result: ${{ steps.determination.outputs.result }}
37+
steps:
38+
- name: Determine if the rest of the workflow should run
39+
id: determination
40+
run: |
41+
RELEASE_BRANCH_REGEX="^refs/heads/v[0-9]+$"
42+
# The `create` event trigger doesn't support `branches` filters, so it's necessary to use Bash instead.
43+
if [[
44+
"${{ github.event_name }}" != "create" ||
45+
"${{ github.ref }}" =~ $RELEASE_BRANCH_REGEX
46+
]]; then
47+
# Run the other jobs.
48+
RESULT="true"
49+
else
50+
# There is no need to run the other jobs.
51+
RESULT="false"
52+
fi
53+
54+
echo "result=$RESULT" >> $GITHUB_OUTPUT
55+
56+
validate:
57+
needs: run-determination
58+
if: needs.run-determination.outputs.result == 'true'
59+
runs-on: ubuntu-latest
60+
61+
steps:
62+
- name: Checkout repository
63+
uses: actions/checkout@v3
64+
65+
- name: Setup Node.js
66+
uses: actions/setup-node@v3
67+
with:
68+
node-version: ${{ env.NODE_VERSION }}
69+
70+
- name: Install Task
71+
uses: arduino/setup-task@v1
72+
with:
73+
repo-token: ${{ secrets.GITHUB_TOKEN }}
74+
version: 3.x
75+
76+
- name: Validate package.json
77+
run: task --silent npm:validate
78+
79+
check-sync:
80+
needs: run-determination
81+
if: needs.run-determination.outputs.result == 'true'
82+
runs-on: ubuntu-latest
83+
84+
steps:
85+
- name: Checkout repository
86+
uses: actions/checkout@v3
87+
88+
- name: Setup Node.js
89+
uses: actions/setup-node@v3
90+
with:
91+
node-version: ${{ env.NODE_VERSION }}
92+
93+
- name: Install Task
94+
uses: arduino/setup-task@v1
95+
with:
96+
repo-token: ${{ secrets.GITHUB_TOKEN }}
97+
version: 3.x
98+
99+
- name: Install npm dependencies
100+
run: task npm:install-deps
101+
102+
- name: Check package-lock.json
103+
run: git diff --color --exit-code package-lock.json

README.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
# `arduino/report-size-deltas` action
22

3+
[![Check npm status](https://github.com/arduino/report-size-deltas/actions/workflows/check-npm-task.yml/badge.svg)](https://github.com/arduino/report-size-deltas/actions/workflows/check-npm-task.yml)
34
[![Tests](https://github.com/arduino/report-size-deltas/workflows/libraries/report-size-deltas%20workflow/badge.svg)](https://github.com/arduino/report-size-deltas/actions?workflow=libraries/report-size-deltas+workflow)
45
[![Integration Tests](https://github.com/arduino/report-size-deltas/actions/workflows/test-integration.yml/badge.svg)](https://github.com/arduino/report-size-deltas/actions/workflows/test-integration.yml)
56
[![Spell Check](https://github.com/arduino/report-size-deltas/workflows/Spell%20Check/badge.svg)](https://github.com/arduino/report-size-deltas/actions?workflow=Spell+Check)

Taskfile.yml

Lines changed: 118 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,118 @@
1+
# See: https://taskfile.dev/#/usage
2+
version: "3"
3+
4+
vars:
5+
# Last version of ajv-cli with support for the JSON schema "Draft 4" specification
6+
SCHEMA_DRAFT_4_AJV_CLI_VERSION: 3.3.0
7+
8+
tasks:
9+
check:
10+
desc: Check for problems with the project
11+
deps:
12+
- task: npm:validate
13+
14+
# Source: https://github.com/arduino/tooling-project-assets/blob/main/workflow-templates/assets/npm-task/Taskfile.yml
15+
npm:install-deps:
16+
desc: Install dependencies managed by npm
17+
run: once
18+
cmds:
19+
- npm install
20+
21+
# Source: https://github.com/arduino/tooling-project-assets/blob/main/workflow-templates/assets/check-npm-task/Taskfile.yml
22+
npm:validate:
23+
desc: Validate npm configuration files against their JSON schema
24+
vars:
25+
# Source: https://github.com/SchemaStore/schemastore/blob/master/src/schemas/json/package.json
26+
SCHEMA_URL: https://json.schemastore.org/package.json
27+
SCHEMA_PATH:
28+
sh: task utility:mktemp-file TEMPLATE="package-json-schema-XXXXXXXXXX.json"
29+
# Source: https://github.com/SchemaStore/schemastore/blob/master/src/schemas/json/ava.json
30+
AVA_SCHEMA_URL: https://json.schemastore.org/ava.json
31+
AVA_SCHEMA_PATH:
32+
sh: task utility:mktemp-file TEMPLATE="ava-schema-XXXXXXXXXX.json"
33+
# Source: https://github.com/SchemaStore/schemastore/blob/master/src/schemas/json/eslintrc.json
34+
ESLINTRC_SCHEMA_URL: https://json.schemastore.org/eslintrc.json
35+
ESLINTRC_SCHEMA_PATH:
36+
sh: task utility:mktemp-file TEMPLATE="eslintrc-schema-XXXXXXXXXX.json"
37+
# Source: https://github.com/SchemaStore/schemastore/blob/master/src/schemas/json/jscpd.json
38+
JSCPD_SCHEMA_URL: https://json.schemastore.org/jscpd.json
39+
JSCPD_SCHEMA_PATH:
40+
sh: task utility:mktemp-file TEMPLATE="jscpd-schema-XXXXXXXXXX.json"
41+
# Source: https://github.com/SchemaStore/schemastore/blob/master/src/schemas/json/npm-badges.json
42+
NPM_BADGES_SCHEMA_URL: https://json.schemastore.org/npm-badges.json
43+
NPM_BADGES_SCHEMA_PATH:
44+
sh: task utility:mktemp-file TEMPLATE="npm-badges-schema-XXXXXXXXXX.json"
45+
# Source: https://github.com/SchemaStore/schemastore/blob/master/src/schemas/json/prettierrc.json
46+
PRETTIERRC_SCHEMA_URL: https://json.schemastore.org/prettierrc.json
47+
PRETTIERRC_SCHEMA_PATH:
48+
sh: task utility:mktemp-file TEMPLATE="prettierrc-schema-XXXXXXXXXX.json"
49+
# Source: https://github.com/SchemaStore/schemastore/blob/master/src/schemas/json/semantic-release.json
50+
SEMANTIC_RELEASE_SCHEMA_URL: https://json.schemastore.org/semantic-release.json
51+
SEMANTIC_RELEASE_SCHEMA_PATH:
52+
sh: task utility:mktemp-file TEMPLATE="semantic-release-schema-XXXXXXXXXX.json"
53+
# Source: https://github.com/SchemaStore/schemastore/blob/master/src/schemas/json/stylelintrc.json
54+
STYLELINTRC_SCHEMA_URL: https://json.schemastore.org/stylelintrc.json
55+
STYLELINTRC_SCHEMA_PATH:
56+
sh: task utility:mktemp-file TEMPLATE="stylelintrc-schema-XXXXXXXXXX.json"
57+
INSTANCE_PATH: "**/package.json"
58+
PROJECT_FOLDER:
59+
sh: pwd
60+
WORKING_FOLDER:
61+
sh: task utility:mktemp-folder TEMPLATE="dependabot-validate-XXXXXXXXXX"
62+
cmds:
63+
- wget --quiet --output-document="{{.SCHEMA_PATH}}" {{.SCHEMA_URL}}
64+
- wget --quiet --output-document="{{.AVA_SCHEMA_PATH}}" {{.AVA_SCHEMA_URL}}
65+
- wget --quiet --output-document="{{.ESLINTRC_SCHEMA_PATH}}" {{.ESLINTRC_SCHEMA_URL}}
66+
- wget --quiet --output-document="{{.JSCPD_SCHEMA_PATH}}" {{.JSCPD_SCHEMA_URL}}
67+
- wget --quiet --output-document="{{.NPM_BADGES_SCHEMA_PATH}}" {{.NPM_BADGES_SCHEMA_URL}}
68+
- wget --quiet --output-document="{{.PRETTIERRC_SCHEMA_PATH}}" {{.PRETTIERRC_SCHEMA_URL}}
69+
- wget --quiet --output-document="{{.SEMANTIC_RELEASE_SCHEMA_PATH}}" {{.SEMANTIC_RELEASE_SCHEMA_URL}}
70+
- wget --quiet --output-document="{{.STYLELINTRC_SCHEMA_PATH}}" {{.STYLELINTRC_SCHEMA_URL}}
71+
- |
72+
cd "{{.WORKING_FOLDER}}" # Workaround for https://github.com/npm/cli/issues/3210
73+
npx ajv-cli@{{.SCHEMA_DRAFT_4_AJV_CLI_VERSION}} validate \
74+
--all-errors \
75+
-s "{{.SCHEMA_PATH}}" \
76+
-r "{{.AVA_SCHEMA_PATH}}" \
77+
-r "{{.ESLINTRC_SCHEMA_PATH}}" \
78+
-r "{{.JSCPD_SCHEMA_PATH}}" \
79+
-r "{{.NPM_BADGES_SCHEMA_PATH}}" \
80+
-r "{{.PRETTIERRC_SCHEMA_PATH}}" \
81+
-r "{{.SEMANTIC_RELEASE_SCHEMA_PATH}}" \
82+
-r "{{.STYLELINTRC_SCHEMA_PATH}}" \
83+
-d "{{.PROJECT_FOLDER}}/{{.INSTANCE_PATH}}"
84+
85+
# Make a temporary file named according to the passed TEMPLATE variable and print the path passed to stdout
86+
# Source: https://github.com/arduino/tooling-project-assets/blob/main/workflow-templates/assets/windows-task/Taskfile.yml
87+
utility:mktemp-file:
88+
vars:
89+
RAW_PATH:
90+
sh: mktemp --tmpdir "{{.TEMPLATE}}"
91+
cmds:
92+
- task: utility:normalize-path
93+
vars:
94+
RAW_PATH: "{{.RAW_PATH}}"
95+
96+
# Make a temporary folder named according to the passed TEMPLATE variable and print the path passed to stdout
97+
# Source: https://github.com/arduino/tooling-project-assets/blob/main/workflow-templates/assets/windows-task/Taskfile.yml
98+
utility:mktemp-folder:
99+
vars:
100+
RAW_PATH:
101+
sh: mktemp --directory --tmpdir "{{.TEMPLATE}}"
102+
cmds:
103+
- task: utility:normalize-path
104+
vars:
105+
RAW_PATH: "{{.RAW_PATH}}"
106+
107+
# Print a normalized version of the path passed via the RAW_PATH variable to stdout
108+
# Source: https://github.com/arduino/tooling-project-assets/blob/main/workflow-templates/assets/windows-task/Taskfile.yml
109+
utility:normalize-path:
110+
cmds:
111+
- |
112+
if [[ "{{.OS}}" == "Windows_NT" ]] && which cygpath &>/dev/null; then
113+
# Even though the shell handles POSIX format absolute paths as expected, external applications do not.
114+
# So paths passed to such applications must first be converted to Windows format.
115+
cygpath -w "{{.RAW_PATH}}"
116+
else
117+
echo "{{.RAW_PATH}}"
118+
fi

0 commit comments

Comments
 (0)