[New Plugin] Together AI Image Generator Plugin #5564
Workflow file for this run
This file contains hidden or 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
| name: Pre Check Plugin | |
| on: | |
| pull_request: | |
| types: [opened, synchronize, ready_for_review, review_requested, edited] | |
| branches: | |
| - main | |
| - dev | |
| paths-ignore: | |
| - ".github/**" | |
| - ".gitignore" | |
| - "unpacked_plugin/**" | |
| - "README.md" | |
| - "LICENSE" | |
| env: | |
| REPO_NAME: langgenius/dify-plugins | |
| MARKETPLACE_BASE_URL: https://marketplace.dify.ai | |
| MARKETPLACE_TOKEN: placeholder | |
| GH_TOKEN: ${{ github.token }} | |
| jobs: | |
| pre-check-plugin: | |
| runs-on: ubuntu-latest | |
| steps: | |
| - name: Checkout | |
| uses: actions/checkout@v4 | |
| with: | |
| persist-credentials: false | |
| - name: Clone Marketplace Toolkit | |
| run: | | |
| gh repo clone langgenius/dify-marketplace-toolkit -- .scripts/ | |
| - name: Download Plugin Daemon | |
| run: | | |
| gh release download -R langgenius/dify-plugin-daemon --pattern "dify-plugin-linux-amd64" --dir .scripts | |
| chmod +x .scripts/dify-plugin-linux-amd64 | |
| - name: Setup Python | |
| uses: actions/setup-python@v5 | |
| with: | |
| python-version: 3.12.7 | |
| - name: Install Dependencies | |
| run: | | |
| echo "Installing Python dependencies..." | |
| python -m pip install --upgrade pip | |
| pip install requests | |
| echo "Ensuring required system dependencies are available..." | |
| if ! command -v jq &> /dev/null; then | |
| echo "Installing jq..." | |
| sudo apt-get update -q | |
| sudo apt-get install -y jq | |
| fi | |
| - name: yq - portable yaml processor | |
| uses: mikefarah/yq@v4.44.5 | |
| with: | |
| cmd: yq --version | |
| - name: Get PR Path | |
| run: | | |
| echo "Retrieving PR files information..." | |
| if ! PR_FILES=$(gh pr view -R ${{ env.REPO_NAME }} ${{ github.event.pull_request.number }} --json files --jq .files); then | |
| echo "Failed to retrieve PR files. Make sure PR number and repository are correct." | |
| exit 1 | |
| fi | |
| export PR_FILES | |
| echo "Checking for plugin package file changes..." | |
| if PLUGIN_PATH=$(python3 .scripts/validator/check-pkg-paths.py); then | |
| echo "Found plugin path: $PLUGIN_PATH" | |
| echo "PLUGIN_PATH=$PLUGIN_PATH" >> $GITHUB_ENV | |
| else | |
| echo "ERROR: Only one .difypkg file change is allowed in a single PR." | |
| exit 1 | |
| fi | |
| - name: Unpack File | |
| run: | | |
| # Store the plugin path in a variable | |
| PLUGIN_PATH_VALUE="${PLUGIN_PATH}" | |
| echo "Moving plugin file to add .zip extension" | |
| mv "$PLUGIN_PATH_VALUE" "$PLUGIN_PATH_VALUE.zip" | |
| echo "Creating unpacked_plugin directory" | |
| mkdir -p unpacked_plugin | |
| echo "Unzipping plugin file to unpacked_plugin directory" | |
| unzip "$PLUGIN_PATH_VALUE.zip" -d unpacked_plugin | |
| # Update the PLUGIN_PATH for future steps | |
| echo "PLUGIN_PATH=unpacked_plugin" >> $GITHUB_ENV | |
| - name: Check Plugin Manifest | |
| run: | | |
| # Create error tracking file | |
| ERROR_FILE="/tmp/manifest_errors.txt" | |
| touch $ERROR_FILE | |
| # manifest.yaml author must not be langgenius or dify | |
| if yq '.author' "$PLUGIN_PATH/manifest.yaml" | grep -q "langgenius"; then | |
| ERROR_MSG="!!! Plugin manifest.yaml author must not be 'langgenius'" | |
| echo "$ERROR_MSG" | |
| echo "$ERROR_MSG" >> $ERROR_FILE | |
| exit 1 | |
| fi | |
| if yq '.author' "$PLUGIN_PATH/manifest.yaml" | grep -q "dify"; then | |
| ERROR_MSG="!!! Plugin manifest.yaml author must not be 'dify'" | |
| echo "$ERROR_MSG" | |
| echo "$ERROR_MSG" >> $ERROR_FILE | |
| exit 1 | |
| fi | |
| - name: Check Plugin Icon | |
| run: | | |
| # Create error tracking file | |
| ERROR_FILE="/tmp/icon_errors.txt" | |
| touch $ERROR_FILE | |
| # Get icon filename from manifest.yaml | |
| PLUGIN_ICON_FILENAME=$(yq '.icon' "$PLUGIN_PATH/manifest.yaml") | |
| echo "PLUGIN_ICON_FILENAME=$PLUGIN_ICON_FILENAME" >> $GITHUB_ENV | |
| # Check if icon file exists | |
| if [ ! -f "$PLUGIN_PATH/_assets/$PLUGIN_ICON_FILENAME" ]; then | |
| ERROR_MSG="!!! Plugin icon file not found: _assets/$PLUGIN_ICON_FILENAME" | |
| echo "$ERROR_MSG" | |
| echo "$ERROR_MSG" >> $ERROR_FILE | |
| exit 1 | |
| fi | |
| # Check if icon contains template placeholder text | |
| if grep -q "DIFY_MARKETPLACE_TEMPLATE_ICON_DO_NOT_USE" "$PLUGIN_PATH/_assets/$PLUGIN_ICON_FILENAME"; then | |
| ERROR_MSG="!!! Plugin icon contains template placeholder text 'DIFY_MARKETPLACE_TEMPLATE_ICON_DO_NOT_USE', change default icon before submitting to marketplace." | |
| echo "$ERROR_MSG" | |
| echo "$ERROR_MSG" >> $ERROR_FILE | |
| exit 1 | |
| fi | |
| # Define default icon content | |
| DEFAULT_ICON='<svg width="100" height="100" xmlns="http://www.w3.org/2000/svg"> | |
| <path d="M20 20 V80 M20 20 H60 Q80 20 80 40 T60 60 H20" | |
| fill="none" | |
| stroke="black" | |
| stroke-width="5"/> | |
| </svg>' | |
| # Check if icon content matches default icon (normalize whitespace) | |
| ICON_CONTENT=$(cat "$PLUGIN_PATH/_assets/$PLUGIN_ICON_FILENAME" | tr -d '\n\r\t ' | tr -s ' ') | |
| DEFAULT_ICON_NORMALIZED=$(echo "$DEFAULT_ICON" | tr -d '\n\r\t ' | tr -s ' ') | |
| if [ "$ICON_CONTENT" = "$DEFAULT_ICON_NORMALIZED" ]; then | |
| ERROR_MSG="!!! Plugin icon is using the default template icon and must be customized" | |
| echo "$ERROR_MSG" | |
| echo "$ERROR_MSG" >> $ERROR_FILE | |
| exit 1 | |
| fi | |
| - name: Check If Version Exists | |
| run: | | |
| # Create error tracking file | |
| ERROR_FILE="/tmp/version_errors.txt" | |
| touch $ERROR_FILE | |
| # Extract plugin metadata | |
| VERSION=$(yq '.version' "$PLUGIN_PATH/manifest.yaml") | |
| AUTHOR=$(yq '.author' "$PLUGIN_PATH/manifest.yaml") | |
| NAME=$(yq '.name' "$PLUGIN_PATH/manifest.yaml") | |
| echo "Plugin information:" | |
| echo "- Name: $NAME" | |
| echo "- Author: $AUTHOR" | |
| echo "- Version: $VERSION" | |
| # Check if the version already exists in marketplace | |
| echo "Checking if plugin version already exists in marketplace..." | |
| API_URL="${MARKETPLACE_BASE_URL}/api/v1/plugins/${AUTHOR}/${NAME}/${VERSION}" | |
| echo "API URL: $API_URL" | |
| # Add a timeout to curl to prevent hanging | |
| RESPONSE_CODE=$(curl -s -o /dev/null -w "%{http_code}" "$API_URL" --connect-timeout 10 --max-time 30) | |
| echo "API Response Code: $RESPONSE_CODE" | |
| if [ "$RESPONSE_CODE" = "200" ]; then | |
| RESPONSE=$(curl -s "$API_URL" --connect-timeout 10 --max-time 30) | |
| if [ "$(echo "$RESPONSE" | jq -r '.code')" = "0" ]; then | |
| ERROR_MSG="!!! Plugin version $VERSION by $AUTHOR already exists in the marketplace. Please update the version number in manifest.yaml before submitting." | |
| echo "$ERROR_MSG" | |
| echo "$ERROR_MSG" >> $ERROR_FILE | |
| exit 1 | |
| fi | |
| else | |
| echo "Version check passed: $VERSION is available for use." | |
| fi | |
| - name: Check Plugin Deps | |
| run: | | |
| if [ -f "$PLUGIN_PATH/requirements.txt" ]; then | |
| echo "Trying to install plugin dependencies..." | |
| python3 -m venv .venv | |
| source .venv/bin/activate | |
| python3 -m pip install -r "$PLUGIN_PATH/requirements.txt" | |
| deactivate | |
| else | |
| echo "No requirements.txt found, skipping dependency installation" | |
| fi | |
| - name: Output Plugin Files Content | |
| run: | | |
| # Create temporary directory for comments | |
| mkdir -p /tmp/plugin_comments | |
| # Create a single combined file for all plugin content | |
| COMBINED_FILE="/tmp/plugin_comments/combined.md" | |
| echo "# Plugin Content" > $COMBINED_FILE | |
| echo "" >> $COMBINED_FILE | |
| # Process manifest.yaml | |
| echo "::group::manifest.yaml" | |
| if [ -f "$PLUGIN_PATH/manifest.yaml" ]; then | |
| cat "$PLUGIN_PATH/manifest.yaml" | |
| # Add to combined content file | |
| echo "## Plugin Manifest (manifest.yaml)" >> $COMBINED_FILE | |
| echo '```yaml' >> $COMBINED_FILE | |
| cat "$PLUGIN_PATH/manifest.yaml" >> $COMBINED_FILE | |
| echo '```' >> $COMBINED_FILE | |
| echo "" >> $COMBINED_FILE | |
| else | |
| echo "manifest.yaml not found" | |
| echo "⚠️ **Warning:** manifest.yaml file not found in plugin package" >> $COMBINED_FILE | |
| echo "" >> $COMBINED_FILE | |
| fi | |
| echo "::endgroup::" | |
| # Process README.md | |
| echo "::group::README.md" | |
| if [ -f "$PLUGIN_PATH/README.md" ]; then | |
| cat "$PLUGIN_PATH/README.md" | |
| # Add to combined content file | |
| echo "## Plugin Documentation (README.md)" >> $COMBINED_FILE | |
| echo '```markdown' >> $COMBINED_FILE | |
| cat "$PLUGIN_PATH/README.md" >> $COMBINED_FILE | |
| echo '```' >> $COMBINED_FILE | |
| echo "" >> $COMBINED_FILE | |
| else | |
| echo "README.md not found" | |
| echo "⚠️ **Warning:** README.md file not found in plugin package" >> $COMBINED_FILE | |
| echo "" >> $COMBINED_FILE | |
| fi | |
| echo "::endgroup::" | |
| # Process requirements.txt | |
| echo "::group::requirements.txt" | |
| if [ -f "$PLUGIN_PATH/requirements.txt" ]; then | |
| cat "$PLUGIN_PATH/requirements.txt" | |
| # Add to combined content file | |
| echo "## Plugin Dependencies (requirements.txt)" >> $COMBINED_FILE | |
| echo '```' >> $COMBINED_FILE | |
| cat "$PLUGIN_PATH/requirements.txt" >> $COMBINED_FILE | |
| echo '```' >> $COMBINED_FILE | |
| echo "" >> $COMBINED_FILE | |
| else | |
| echo "requirements.txt not found" | |
| echo "ℹ️ **Note:** No requirements.txt file found in plugin package" >> $COMBINED_FILE | |
| echo "" >> $COMBINED_FILE | |
| fi | |
| echo "::endgroup::" | |
| # Post a single combined comment to the PR | |
| echo "Posting plugin content to PR..." | |
| if ! gh pr comment ${{ github.event.pull_request.number }} -F $COMBINED_FILE -R ${{ env.REPO_NAME }}; then | |
| echo "Warning: Failed to post plugin content comment. This is non-fatal, continuing..." | |
| fi | |
| - name: Check Plugin Install | |
| run: | | |
| # Create error tracking file | |
| ERROR_FILE="/tmp/install_errors.txt" | |
| touch $ERROR_FILE | |
| if [ -f "$PLUGIN_PATH/requirements.txt" ]; then | |
| source .venv/bin/activate || { | |
| echo "Failed to activate virtual environment" >> $ERROR_FILE | |
| echo "Failed to activate virtual environment" | |
| exit 1 | |
| } | |
| # Install packaging for version comparison | |
| echo "Installing packaging module..." | |
| pip install packaging || { | |
| echo "Failed to install packaging module" >> $ERROR_FILE | |
| echo "Failed to install packaging module" | |
| exit 1 | |
| } | |
| # Determine installation method based on dify_plugin version | |
| echo "Detecting dify_plugin version..." | |
| dify_version=$(pip list | grep -o 'dify_plugin\s\+[0-9.]\+' | awk '{print $2}' || echo "not_found") | |
| if [ "$dify_version" = "not_found" ]; then | |
| echo "dify_plugin not found in installed packages, using default configuration" | |
| export INSTALL_METHOD=aws_lambda | |
| export AWS_LAMBDA_PORT=8080 | |
| export AWS_LAMBDA_HOST=0.0.0.0 | |
| else | |
| target_version="0.0.1b64" | |
| echo "Found dify_plugin version: $dify_version" | |
| echo "Comparing with target version: $target_version" | |
| # Set environment variables based on version comparison | |
| if python -c "from packaging.version import Version; exit(0 if Version('$dify_version') > Version('$target_version') else 1)"; then | |
| echo "Using serverless installation method" | |
| export INSTALL_METHOD=serverless | |
| export SERVERLESS_PORT=8080 | |
| export SERVERLESS_HOST=0.0.0.0 | |
| else | |
| echo "Using aws_lambda installation method" | |
| export INSTALL_METHOD=aws_lambda | |
| export AWS_LAMBDA_PORT=8080 | |
| export AWS_LAMBDA_HOST=0.0.0.0 | |
| fi | |
| fi | |
| # Run the plugin installation test with timeout | |
| echo "Running plugin installation test..." | |
| timeout 300 python3 .scripts/validator/test-plugin-install.py -d "$PLUGIN_PATH" || { | |
| echo "Plugin installation test failed or timed out" >> $ERROR_FILE | |
| echo "Plugin installation test failed or timed out" | |
| exit 1 | |
| } | |
| echo "Plugin installation test completed successfully" | |
| else | |
| echo "No requirements.txt found, skipping installation test" | |
| fi | |
| - name: Check Packaging | |
| run: | | |
| # Create error tracking file | |
| ERROR_FILE="/tmp/packaging_errors.txt" | |
| touch $ERROR_FILE | |
| echo "Running packaging check..." | |
| # Check if plugin daemon exists and is executable | |
| if [ ! -f ".scripts/dify-plugin-linux-amd64" ]; then | |
| ERROR_MSG="Plugin daemon file not found" | |
| echo "$ERROR_MSG" >> $ERROR_FILE | |
| echo "$ERROR_MSG" | |
| exit 1 | |
| fi | |
| if [ ! -x ".scripts/dify-plugin-linux-amd64" ]; then | |
| chmod +x .scripts/dify-plugin-linux-amd64 || { | |
| ERROR_MSG="Failed to make plugin daemon executable" | |
| echo "$ERROR_MSG" >> $ERROR_FILE | |
| echo "$ERROR_MSG" | |
| exit 1 | |
| } | |
| fi | |
| # Run the packaging check with a timeout | |
| timeout 300 python3 .scripts/uploader/upload-package.py -d "$PLUGIN_PATH" -t "$MARKETPLACE_TOKEN" --plugin-daemon-path .scripts/dify-plugin-linux-amd64 -u "$MARKETPLACE_BASE_URL" -f --test || { | |
| ERROR_MSG="Packaging check failed or timed out" | |
| echo "$ERROR_MSG" >> $ERROR_FILE | |
| echo "$ERROR_MSG" | |
| exit 1 | |
| } | |
| echo "Packaging check completed successfully" | |
| - name: Comment CI Status on PR | |
| if: always() | |
| run: | | |
| # Create a status report markdown file | |
| echo "# Plugin Pre-Check Results" > /tmp/ci_status.md | |
| echo "" >> /tmp/ci_status.md | |
| # Extract plugin info (if available) | |
| if [ -f "$PLUGIN_PATH/manifest.yaml" ]; then | |
| # Use || to prevent script failure if any field is missing | |
| PLUGIN_NAME=$(yq '.name' "$PLUGIN_PATH/manifest.yaml" 2>/dev/null || echo "Unknown") | |
| PLUGIN_VERSION=$(yq '.version' "$PLUGIN_PATH/manifest.yaml" 2>/dev/null || echo "Unknown") | |
| PLUGIN_AUTHOR=$(yq '.author' "$PLUGIN_PATH/manifest.yaml" 2>/dev/null || echo "Unknown") | |
| PLUGIN_DESCRIPTION=$(yq '.description' "$PLUGIN_PATH/manifest.yaml" 2>/dev/null || echo "No description provided") | |
| echo "## Plugin Information" >> /tmp/ci_status.md | |
| echo "" >> /tmp/ci_status.md | |
| echo "**Name:** $PLUGIN_NAME" >> /tmp/ci_status.md | |
| echo "**Version:** $PLUGIN_VERSION" >> /tmp/ci_status.md | |
| echo "**Author:** $PLUGIN_AUTHOR" >> /tmp/ci_status.md | |
| echo "**Description:** $PLUGIN_DESCRIPTION" >> /tmp/ci_status.md | |
| echo "" >> /tmp/ci_status.md | |
| fi | |
| echo "## CI Steps Status" >> /tmp/ci_status.md | |
| echo "" >> /tmp/ci_status.md | |
| echo "| Check | Status | Details |" >> /tmp/ci_status.md | |
| echo "| ----- | ------ | ------- |" >> /tmp/ci_status.md | |
| # Get job status from GitHub context | |
| if [ "${{ job.status }}" == "success" ]; then | |
| echo "| **Overall Status** | ✅ **Passed** | All checks completed successfully |" >> /tmp/ci_status.md | |
| else | |
| echo "| **Overall Status** | ❌ **Failed** | One or more checks failed |" >> /tmp/ci_status.md | |
| fi | |
| # Check for manifest errors | |
| if [ -f "/tmp/manifest_errors.txt" ] && [ -s "/tmp/manifest_errors.txt" ]; then | |
| ERROR_CONTENT=$(cat /tmp/manifest_errors.txt | sed -e 's/^/- /') | |
| echo "| Manifest Validation | ❌ Failed | $ERROR_CONTENT |" >> /tmp/ci_status.md | |
| else | |
| echo "| Manifest Validation | ✅ Passed | - |" >> /tmp/ci_status.md | |
| fi | |
| # Check for icon errors | |
| if [ -f "/tmp/icon_errors.txt" ] && [ -s "/tmp/icon_errors.txt" ]; then | |
| ERROR_CONTENT=$(cat /tmp/icon_errors.txt | sed -e 's/^/- /') | |
| echo "| Icon Validation | ❌ Failed | $ERROR_CONTENT |" >> /tmp/ci_status.md | |
| else | |
| echo "| Icon Validation | ✅ Passed | - |" >> /tmp/ci_status.md | |
| fi | |
| # Check for version errors | |
| if [ -f "/tmp/version_errors.txt" ] && [ -s "/tmp/version_errors.txt" ]; then | |
| ERROR_CONTENT=$(cat /tmp/version_errors.txt | sed -e 's/^/- /') | |
| echo "| Version Check | ❌ Failed | $ERROR_CONTENT |" >> /tmp/ci_status.md | |
| else | |
| echo "| Version Check | ✅ Passed | - |" >> /tmp/ci_status.md | |
| fi | |
| # Check for install errors | |
| if [ -f "/tmp/install_errors.txt" ] && [ -s "/tmp/install_errors.txt" ]; then | |
| ERROR_CONTENT=$(cat /tmp/install_errors.txt | sed -e 's/^/- /') | |
| echo "| Installation | ❌ Failed | $ERROR_CONTENT |" >> /tmp/ci_status.md | |
| elif [ -f "$PLUGIN_PATH/requirements.txt" ]; then | |
| echo "| Installation | ✅ Passed | Requirements installed successfully |" >> /tmp/ci_status.md | |
| else | |
| echo "| Installation | ⚠️ Skipped | No requirements.txt found |" >> /tmp/ci_status.md | |
| fi | |
| # Check for packaging errors | |
| if [ -f "/tmp/packaging_errors.txt" ] && [ -s "/tmp/packaging_errors.txt" ]; then | |
| ERROR_CONTENT=$(cat /tmp/packaging_errors.txt | sed -e 's/^/- /') | |
| echo "| Packaging | ❌ Failed | $ERROR_CONTENT |" >> /tmp/ci_status.md | |
| else | |
| echo "| Packaging | ✅ Passed | Package valid for marketplace |" >> /tmp/ci_status.md | |
| fi | |
| # Add workflow run link | |
| echo "" >> /tmp/ci_status.md | |
| echo "## Workflow Details" >> /tmp/ci_status.md | |
| echo "" >> /tmp/ci_status.md | |
| echo "**Run ID:** ${{ github.run_id }}" >> /tmp/ci_status.md | |
| echo "**Repository:** ${{ github.repository }}" >> /tmp/ci_status.md | |
| echo "**Ref:** ${{ github.ref }}" >> /tmp/ci_status.md | |
| echo "" >> /tmp/ci_status.md | |
| echo "[View workflow run](https://github.com/${{ github.repository }}/actions/runs/${{ github.run_id }})" >> /tmp/ci_status.md | |
| # Post status comment to PR with better error handling | |
| echo "Posting CI status comment to PR..." | |
| if ! gh pr comment ${{ github.event.pull_request.number }} -F /tmp/ci_status.md -R ${{ env.REPO_NAME }}; then | |
| echo "Warning: Failed to post comment to PR. This is non-fatal, continuing..." | |
| fi |