Skip to content
Closed
2 changes: 2 additions & 0 deletions .github/PULL_REQUEST_TEMPLATE/plugin.md
Original file line number Diff line number Diff line change
Expand Up @@ -11,13 +11,15 @@ One-liner – What does this plugin contribution add or change?
## Plugin Documentation Checklist

- README Validation
- [ ] `README.md` file exists in the plugin root folder
- [ ] Clear installation instructions
- [ ] Usage examples with code snippets
- [ ] List of features and capabilities
- [ ] Troubleshooting guide (if applicable)
- [ ] Contribution guidelines (if applicable)

- Metadata Validation
- [ ] `plugin_metadata.yml` file exists in the plugin root folder
- [ ] Complete metadata provided in reference to [plugin metadata template](../.././plugins/plugin_metadata_template.yml)

## Dev Testing
Expand Down
2 changes: 1 addition & 1 deletion .github/workflows/pr-labeler.yml
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@ name: Auto Label PR
on:
pull_request:
branches: [ "main" ]
types: [opened, edited, reopened, synchronize]
types: [ opened, edited, reopened, synchronize ]

jobs:
label-plugin-pr:
Expand Down
130 changes: 130 additions & 0 deletions .github/workflows/validate-new-plugin-metadata.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,130 @@
name: Validate New Plugin Metadata

on:
pull_request:
branches: [ "main" ]
paths: [ "plugins/**" ]
types: [ opened, edited, reopened, synchronize ]

jobs:
identify-new-plugins:
runs-on: ubuntu-latest
outputs:
plugin_dirs: ${{ steps.find_new_plugins.outputs.plugin_dirs }}
steps:
- name: Checkout Repository
uses: actions/checkout@v4
with:
fetch-depth: 0
ref: ${{ github.event.pull_request.head.ref }}

- name: Identify New Plugin Directories
id: find_new_plugins
run: |
git fetch origin ${{ github.event.pull_request.base.ref }}
BASE_COMMIT=$(git merge-base origin/${{ github.event.pull_request.base.ref }} HEAD)

NEW_PLUGINS=()
for plugin_dir in $(git diff --diff-filter=A --name-only $BASE_COMMIT...HEAD | grep '^plugins/' | cut -d'/' -f1-2 | sort -u); do
if ! git rev-parse --verify origin/${{ github.event.pull_request.base.ref }}:"$plugin_dir" &>/dev/null; then
NEW_PLUGINS+=("$plugin_dir")
fi
done

if [[ ${#NEW_PLUGINS[@]} -eq 0 ]]; then
echo "plugin_dirs=[]" >> $GITHUB_OUTPUT
exit 0
fi

echo "plugin_dirs=$(jq -nc --argjson arr "$(printf '%s\n' "${NEW_PLUGINS[@]}" | jq -R . | jq -s .)" '$arr')" >> $GITHUB_OUTPUT

validate-individual-plugins:
needs: identify-new-plugins
if: ${{ needs.identify-new-plugins.outputs.plugin_dirs != '[]' }}
runs-on: ubuntu-latest
strategy:
matrix:
plugin_dir: ${{ fromJson(needs.identify-new-plugins.outputs.plugin_dirs) }}
steps:
- name: Checkout Repository
uses: actions/checkout@v4

- name: Validate Plugin Metadata
run: |
metadata_file="${{ matrix.plugin_dir }}/plugin_metadata.yml"
if [[ ! -f "$metadata_file" ]]; then
echo "::error file=$metadata_file::Missing plugin_metadata.yml"
exit 1
fi

echo "::group::Validating $metadata_file"

metadata=$(yq '.' "$metadata_file")
errors=0

check_required_field() {
local field="$1"
local value=$(echo "$metadata" | yq ".$field")
if [[ -z "$value" ]]; then
echo "::error file=$metadata_file::'$field' is missing"
((errors++))
fi
}

check_valid_url() {
local field="$1"
local value=$(echo "$metadata" | yq ".$field" || true)

if [[ -z "$value" ]]; then
return 0
fi

if [[ "$value" == "["*"]" ]]; then # Detects if the field is an array
for url in $(echo "$value" | yq '.[]'); do
if [[ ! "$url" =~ ^https?:\/\/[a-zA-Z0-9.-]+(\.[a-zA-Z]{2,})+(:[0-9]{1,5})?(\/.*)?$ ]]; then
echo "::error file=$metadata_file::'$field' contains an invalid URL: $url"
((errors++))
fi
done
else
if [[ ! "$value" =~ ^https?:\/\/[a-zA-Z0-9.-]+(\.[a-zA-Z]{2,})+(:[0-9]{1,5})?(\/.*)?$ ]]; then
echo "::error file=$metadata_file::'$field' is not a valid URL"
((errors++))
fi
fi
}

check_required_field "plugin_name"
check_required_field "author"
check_required_field "short_description"
check_required_field "detailed_description"
check_required_field "support_contact"

check_valid_url "logo_url"
check_valid_url "plugin_logo_url"
check_valid_url "demo_video_url"
check_valid_url "documentation_url"
check_valid_url "changelog_url"
check_valid_url "community_url"
check_valid_url "screenshots"

release_date=$(echo "$metadata" | yq '.release_date')
if [[ ! "$release_date" =~ ^202[0-9]{1}-[0-9]{2}$ ]]; then
echo "::error file=$metadata_file::'release_date' should be in YYYY-MM format"
((errors++))
fi

x_account_handle=$(echo "$metadata" | yq '.x_account_handle')
if [[ -n "$x_account_handle" && ! "$x_account_handle" =~ ^@[a-zA-Z0-9_]{1,15}$ ]]; then
echo "::error file=$metadata_file::'x_account_handle' is not a valid X (Twitter) handle"
((errors++))
fi

support_contact=$(echo "$metadata" | yq '.support_contact')
if [[ ! "$support_contact" =~ ^(https?:\/\/[a-zA-Z0-9.-]+(\.[a-zA-Z]{2,})+(:[0-9]{1,5})?(\/.*)?|[a-zA-Z0-9._%+-]+@[a-zA-Z0-9.-]+\.[a-zA-Z]{2,})$ ]]; then
echo "::error file=$metadata_file::'support_contact' must be a valid URL or email address"
((errors++))
fi

echo "::endgroup::"
exit $errors
Empty file added plugins/allora/try_new_file.txt
Empty file.
23 changes: 23 additions & 0 deletions plugins/new_plugin/plugin_metadata.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
# General Information

Check failure on line 1 in plugins/new_plugin/plugin_metadata.yml

View workflow job for this annotation

GitHub Actions / validate-individual-plugins (plugins/new_plugin)

'screenshots' is not a valid URL
plugin_name: "Plugin's Name"
author: "Plugin's Author"
logo_url: ""
release_date: ""

# Description
short_description: "Plugin's short description"
detailed_description: "Plugin's detailed description"

# Media & Assets
plugin_logo_url: ""
screenshots:
- ""
- ""
demo_video_url: ""
documentation_url: ""
changelog_url: ""

# Contact & Support
x_account_handle: ""
support_contact: "Wrong support_contact format"
community_url: ""
Empty file added plugins/new_plugin/test.txt
Empty file.
12 changes: 6 additions & 6 deletions plugins/plugin_metadata_template.yml
Original file line number Diff line number Diff line change
@@ -1,23 +1,23 @@
# General Information
plugin_name: "" # Name of the plugin
author: "" # Author and team name
logo_url: "" # URL to the author photo or team logo (512x512 recommended)
release_date: "" # Release date (DD-MM-YYYY)
logo_url: "" # URL to the author photo or team logo (512x512 recommended) (if any)
release_date: "" # Release date (YYYY-MM)

# Description
short_description: "" # One-liner description for listings
detailed_description: "" # Full description with features and benefits

# Media & Assets
plugin_logo_url: "" # URL to the plugin logo (512x512 recommended) (if any or fallback to logo_url)
screenshots: # List of screenshots showcasing the plugin
screenshots: # List of screenshots showcasing the plugin (if any)
- "" # e.g., "https://example.com/screenshot1.png"
- ""
demo_video_url: "" # Link to a demo or walkthrough video (if available)
documentation_url: "" # Link to the plugin's official documentation (if available)
demo_video_url: "" # Link to a demo or walkthrough video (if any)
documentation_url: "" # Link to the plugin's official documentation (if any)
changelog_url: "" # Link to the changelog (if maintained)

# Contact & Support
x_account_handle: "" # X (formerly known as Twitter) account handle (ie: @GAME_Virtuals)
support_contact: "" # Email or Slack/Discord link for user support
community_link: "" # Forum or community link (if any)
community_url: "" # Forum or community link (if any)
Loading