adding new component #444
Workflow file for this run
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
# Reference for adding or expanding schemas: https://ajv.js.org/json-schema.html#json-data-type | |
name: Validate JSONs | |
on: | |
pull_request: | |
workflow_dispatch: | |
inputs: | |
all_files: | |
description: Validate all Components | |
type: boolean | |
default: true | |
jobs: | |
validate-each-component-type-definition: | |
runs-on: ubuntu-latest | |
strategy: | |
matrix: | |
componentType: [pin, i2c, servo, ds18x20, pwm, pixel, uart] | |
name: Validate ${{ matrix.componentType }} Component Definition Files | |
steps: | |
- uses: actions/checkout@v3 | |
- name: Validate ${{ matrix.componentType }} Components | |
uses: lorennorman/validate-json-action@master | |
with: | |
schema: /components/${{ matrix.componentType }}/schema.json | |
jsons: components/${{ matrix.componentType }}/*/definition.json | |
gather-relevant-files: | |
name: Gather Relevant Files | |
runs-on: ubuntu-latest | |
outputs: | |
# All files that were Added, Copied, Modified, or Renamed | |
files: ${{ steps.list-changed-files.outputs.all_changed_files }} ${{ steps.list-all-files.outputs.all_files }} | |
steps: | |
- uses: actions/checkout@v3 | |
- name: List All Changed Files | |
if: ${{ !inputs.all_files }} | |
id: list-changed-files | |
uses: tj-actions/changed-files@v37 | |
- name: List All Component Files | |
if: ${{ inputs.all_files }} | |
id: list-all-files | |
run: echo "all_files=`find components -type f | paste -sd " "`" >> $GITHUB_OUTPUT | |
check-user-permissions: | |
name: Check Write Permission | |
runs-on: ubuntu-latest | |
outputs: | |
# Extract the permission for later jobs to use | |
has-write-permission: ${{ steps.set-permission.outputs.has-permission }} | |
steps: | |
- uses: octokit/[email protected] | |
id: fetch-permissions | |
with: | |
route: GET /repos/${{ github.repository }}/collaborators/${{ github.actor }}/permission | |
env: | |
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} | |
- id: set-permission | |
if: fromJson(steps.fetch-permissions.outputs.data).permission == 'admin' || fromJson(steps.fetch-permissions.outputs.data).permission == 'write' | |
run: echo "has-permission=true" >> "$GITHUB_OUTPUT" | |
validate-expected-filenames: | |
name: Validate Filenames | |
runs-on: ubuntu-latest | |
needs: | |
- gather-relevant-files | |
- check-user-permissions | |
env: | |
FILES: ${{ needs.gather-relevant-files.outputs.files }} | |
CAN_WRITE_TO_REPO: ${{ needs.check-user-permissions.outputs.has-write-permission }} | |
steps: | |
- uses: actions/checkout@v3 | |
- name: Validate Only Expected Filenames | |
run: | | |
EXIT_VALUE=0 | |
# external contributors can modify some files | |
EXTERNAL_REGEX="^components\/(pin|i2c|servo|ds18x20|pwm|pixel|uart)\/.*\/(definition\.json|image\.(png|jpe?g|gif))$" | |
# folks with write access to the repo (Adafruit team) can change more sensitive files | |
INTERNAL_REGEX="^(\.github\/.*|components\/(sensors.json|(pin|i2c|servo|ds18x20|pwm|pixel|uart)\/(schema.json|.*\/(definition\.json|image\.(png|jpe?g|gif)))))$" | |
# apply the appropriate regex based on permissions of the user | |
if [[ $CAN_WRITE_TO_REPO ]]; then | |
component_definition_regex=$INTERNAL_REGEX | |
else | |
component_definition_regex=$EXTERNAL_REGEX | |
fi | |
for file in $FILES; do | |
if [[ $file =~ $component_definition_regex ]]; then | |
if [[ $file =~ [A-Z] ]]; then | |
echo "❌ $file (no uppercase characters allowed)" | |
EXIT_VALUE=1 | |
else | |
echo "✅ $file" | |
fi | |
else | |
if [[ $file =~ $INTERNAL_REGEX ]]; then | |
echo "❌ $file (only Adafruit staff may modify this file)" | |
else | |
echo "❌ $file should not exist" | |
fi | |
EXIT_VALUE=1 | |
fi | |
done | |
if [[ $EXIT_VALUE = 1 ]]; then | |
echo "Are there files listed that this PR didn't modify? Consider merging the "main" branch into this PR, it may have subsequently diverged." | |
fi | |
exit $EXIT_VALUE | |
validate-image-extension-mimetype-agreement: | |
name: Validate Extensions Match Mimetypes | |
runs-on: ubuntu-latest | |
needs: | |
- gather-relevant-files | |
- validate-expected-filenames | |
env: | |
FILES: ${{ needs.gather-relevant-files.outputs.files }} | |
steps: | |
- uses: actions/checkout@v3 | |
- name: Validate Image File Extension<->Mimetype Agreement | |
run: | | |
EXIT_VALUE=0 | |
for FILE in $FILES; do | |
if ! [[ $FILE =~ \.(svg|jpe?g|png)$ ]]; then | |
continue # non-image file | |
fi | |
# extract each file's mimetype and extension | |
MIME=`file -b --mime-type $FILE` | |
EXT="${FILE##*.}" | |
# ad-hoc check that extension matches mimetype | |
if [[ "image/$EXT" == $MIME || ($EXT == "jpg" && $MIME == "image/jpeg") || ($EXT == "svg" && ($MIME == "image/svg+xml" || $MIME == "text/xml")) ]]; then | |
# Match! | |
echo "✅ $FILE" | |
else | |
# Doesn't match? Give helpful report | |
# split the mimetype on '/' | |
IFS='/' | |
read -a SPLIT_MIME <<< "$MIME" | |
IFS=' ' | |
# take the last item | |
MIME_EXT=${SPLIT_MIME[-1]} | |
if [[ "$MIME_EXT" == "xml" ]]; then | |
MIME_EXT="svg" | |
elif [[ "$MIME_EXT" == "jpeg" ]]; then | |
MIME_EXT="jpg" | |
fi | |
echo "❌ $FILE: expected .$MIME_EXT" | |
EXIT_VALUE=1 | |
fi | |
done | |
if [[ $EXIT_VALUE = 1 ]]; then | |
echo "Fix these ☝️ issues by renaming each ❌ file to the indicated extension." | |
fi | |
exit $EXIT_VALUE | |
validate-image-dimensions: | |
name: Validate Image Dimensions | |
runs-on: ubuntu-latest | |
needs: | |
- gather-relevant-files | |
- validate-image-extension-mimetype-agreement | |
env: | |
FILES: ${{ needs.gather-relevant-files.outputs.files }} | |
steps: | |
- uses: actions/checkout@v3 | |
- uses: mfinelli/setup-imagemagick@v2 | |
- name: Validate Image Dimensions | |
run: | | |
EXIT_VALUE=0 | |
MAX_WIDTH=400 | |
MAX_HEIGHT=300 | |
echo "Evaluating Files $FILES" | |
for FILE in $FILES; do | |
if ! [[ $FILE =~ \.(svg|jpe?g|png)$ ]]; then | |
echo "$FILE: not an image" | |
continue # non-image file | |
fi | |
# use imagemagick to pull the dimensions | |
WIDTH=`identify -ping -format "%w" ${FILE}[0]` | |
HEIGHT=`identify -ping -format "%h" ${FILE}[0]` | |
EXPECTED_HEIGHT=$(("$WIDTH"*3/4)) | |
NOT_4_3_RATIO=false | |
if [[ $EXPECTED_HEIGHT -ne "$HEIGHT" ]]; then | |
EXIT_VALUE=1 | |
NOT_4_3_RATIO=true | |
fi | |
BAD_WIDTH=false | |
if [[ "$WIDTH" -gt "$MAX_WIDTH" ]]; then | |
EXIT_VALUE=1 | |
BAD_WIDTH=true | |
fi | |
BAD_HEIGHT=false | |
if [[ "$HEIGHT" -gt "$MAX_HEIGHT" ]]; then | |
EXIT_VALUE=1 | |
BAD_HEIGHT=true | |
fi | |
if [[ $EXIT_VALUE = 1 ]]; then | |
echo "❌ $FILE (${WIDTH}x${HEIGHT})" | |
if [[ $NOT_4_3_RATIO = true ]]; then | |
echo " ▬ width x height must have a 4:3 ratio: resize height to ${EXPECTED_HEIGHT}" | |
fi | |
if [[ $BAD_WIDTH = true ]]; then | |
echo " ↔️ width must be ${MAX_WIDTH} pixels or less" | |
fi | |
if [[ $BAD_HEIGHT = true ]]; then | |
echo " ↕️ height must be ${MAX_HEIGHT} pixels or less" | |
fi | |
else | |
echo "✅ $FILE (${WIDTH}x${HEIGHT})" | |
fi | |
done | |
if [[ $EXIT_VALUE = 1 ]]; then | |
echo "Fix these ☝️ issues by resizing each ❌ image to be 4:3 dimension ratio and fit within ${MAX_WIDTH}x${MAX_HEIGHT}." | |
fi | |
exit $EXIT_VALUE | |
validate-image-file-sizes: | |
name: Validate Image File Sizes | |
runs-on: ubuntu-latest | |
needs: | |
- gather-relevant-files | |
- validate-image-dimensions | |
env: | |
FILES: ${{ needs.gather-relevant-files.outputs.files }} | |
steps: | |
- uses: actions/checkout@v3 | |
- name: Validate Image File Sizes | |
run: | | |
EXIT_VALUE=0 | |
MAX_FILESIZE=$((100*1024)) # 100kb | |
for FILE in $FILES; do | |
if ! [[ $FILE =~ \.(svg|jpe?g|png)$ ]]; then | |
continue # non-image file | |
fi | |
FILESIZE=$(stat -c%s "$FILE") | |
MAX=$MAX_FILESIZE | |
if [[ "$FILESIZE" -gt "$MAX" ]]; then | |
EXIT_VALUE=1 | |
echo "❌ $FILE ($FILESIZE)" | |
else | |
echo "✅ $FILE ($FILESIZE)" | |
fi | |
done | |
if [[ $EXIT_VALUE = 1 ]]; then | |
echo "Fix these issues ☝️ by compressing each ❌ file to be smaller than 100KB. You can try:" | |
echo "- using an image compressor" | |
echo "- exporting at lower quality settings (png or jpg)" | |
echo "- exporting a different image format:" | |
echo " - photos are best saved as jpg" | |
echo " - screenshots and digital images are best saved as png" | |
echo " - svg might be efficient for images with few colors and simple shapes" | |
echo " - gif should not be used" | |
fi | |
exit $EXIT_VALUE |