From 0f47f118f7bb4cf37446a44b2df719c1b0244a0d Mon Sep 17 00:00:00 2001 From: poduck Date: Sat, 20 Dec 2025 23:36:37 -0500 Subject: [PATCH] Fix Activepieces duplicate pieces and SmoothSchedule logo MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - Remove piece_metadata inserts from SQL script (pieces are auto-discovered from filesystem as OFFICIAL, no need for duplicate CUSTOM entries) - SQL now only sets pinnedPieces and cleans up any existing duplicates - Fix SmoothSchedule logo URL to use production URL instead of lvh.me - Fix deploy.sh to read correct POSTGRES_USER from env file 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude Opus 4.5 --- activepieces-fork/custom-pieces-metadata.sql | 122 ++++-------------- .../community/smoothschedule/src/index.ts | 6 +- deploy.sh | 11 +- 3 files changed, 37 insertions(+), 102 deletions(-) diff --git a/activepieces-fork/custom-pieces-metadata.sql b/activepieces-fork/custom-pieces-metadata.sql index 5fcbddf1..dedea22f 100644 --- a/activepieces-fork/custom-pieces-metadata.sql +++ b/activepieces-fork/custom-pieces-metadata.sql @@ -1,16 +1,17 @@ -- ============================================================================== --- Custom SmoothSchedule Pieces Metadata +-- Custom SmoothSchedule Pieces Configuration -- ============================================================================== --- This script registers custom pieces in the Activepieces database. --- It runs on container startup via publish-pieces.sh. +-- This script configures pinned pieces for the Activepieces platform. +-- It runs on container startup via docker-entrypoint.sh. -- --- IMPORTANT: --- - Pieces use pieceType=CUSTOM with platformId to avoid being deleted by sync --- - This script is IDEMPOTENT - safe to run multiple times --- - If platform doesn't exist yet, this script will silently skip +-- NOTE: We do NOT insert pieces into piece_metadata because they are already +-- built into the Docker image in packages/pieces/community/. Activepieces +-- auto-discovers these as OFFICIAL pieces. Adding them to piece_metadata +-- would create duplicates in the UI. +-- +-- We ONLY set pinnedPieces to make our pieces appear first in Highlights. -- ============================================================================== --- Get the platform ID dynamically and only proceed if platform exists DO $$ DECLARE platform_id varchar(21); @@ -20,15 +21,29 @@ BEGIN SELECT COUNT(*) INTO platform_count FROM platform; IF platform_count = 0 THEN - RAISE NOTICE 'No platform found yet - skipping piece metadata registration'; - RAISE NOTICE 'Pieces will be registered on next container restart after platform is created'; + RAISE NOTICE 'No platform found yet - skipping piece configuration'; + RAISE NOTICE 'Pieces will be configured on next container restart after platform is created'; RETURN; END IF; SELECT id INTO platform_id FROM platform LIMIT 1; - RAISE NOTICE 'Registering custom pieces for platform: %', platform_id; + RAISE NOTICE 'Configuring pieces for platform: %', platform_id; - -- Pin our custom pieces in the platform so they appear first + -- Remove any duplicate CUSTOM entries for pieces that are built into the image + -- These cause duplicates in the UI since they're also discovered from filesystem + DELETE FROM piece_metadata WHERE name IN ( + '@activepieces/piece-smoothschedule', + '@activepieces/piece-python-code', + '@activepieces/piece-ruby-code', + '@activepieces/piece-interfaces' + ) AND "pieceType" = 'CUSTOM'; + + IF FOUND THEN + RAISE NOTICE 'Removed duplicate CUSTOM piece entries'; + END IF; + + -- Pin our pieces in the platform so they appear first in Highlights + -- This works with pieces auto-discovered from the filesystem UPDATE platform SET "pinnedPieces" = ARRAY[ '@activepieces/piece-smoothschedule', @@ -38,86 +53,5 @@ BEGIN WHERE id = platform_id AND ("pinnedPieces" = '{}' OR "pinnedPieces" IS NULL OR NOT '@activepieces/piece-smoothschedule' = ANY("pinnedPieces")); - -- Delete existing entries for our custom pieces (to avoid ID conflicts) - DELETE FROM piece_metadata WHERE name IN ( - '@activepieces/piece-smoothschedule', - '@activepieces/piece-python-code', - '@activepieces/piece-ruby-code', - '@activepieces/piece-interfaces' - ); - - -- SmoothSchedule piece - INSERT INTO piece_metadata ( - id, name, "displayName", "logoUrl", description, version, - "minimumSupportedRelease", "maximumSupportedRelease", - actions, triggers, auth, "pieceType", "packageType", categories, authors, "projectUsage", "platformId" - ) VALUES ( - 'smoothschedule001', - '@activepieces/piece-smoothschedule', - 'SmoothSchedule', - 'https://api.smoothschedule.com/images/logo-branding.png', - 'Scheduling and appointment management for your business', - '0.0.1', - '0.36.1', - '99999.99999.9999', - '{"create_event":{"name":"create_event","displayName":"Create Event","description":"Create a new event/appointment","props":{},"requireAuth":true,"errorHandlingOptions":{"continueOnFailure":{"defaultValue":false},"retryOnFailure":{"defaultValue":false}}},"update_event":{"name":"update_event","displayName":"Update Event","description":"Update an existing event","props":{},"requireAuth":true,"errorHandlingOptions":{"continueOnFailure":{"defaultValue":false},"retryOnFailure":{"defaultValue":false}}},"cancel_event":{"name":"cancel_event","displayName":"Cancel Event","description":"Cancel an event","props":{},"requireAuth":true,"errorHandlingOptions":{"continueOnFailure":{"defaultValue":false},"retryOnFailure":{"defaultValue":false}}},"find_events":{"name":"find_events","displayName":"Find Events","description":"Search for events","props":{},"requireAuth":true,"errorHandlingOptions":{"continueOnFailure":{"defaultValue":false},"retryOnFailure":{"defaultValue":false}}},"list_resources":{"name":"list_resources","displayName":"List Resources","description":"List all resources","props":{},"requireAuth":true,"errorHandlingOptions":{"continueOnFailure":{"defaultValue":false},"retryOnFailure":{"defaultValue":false}}},"list_services":{"name":"list_services","displayName":"List Services","description":"List all services","props":{},"requireAuth":true,"errorHandlingOptions":{"continueOnFailure":{"defaultValue":false},"retryOnFailure":{"defaultValue":false}}},"list_inactive_customers":{"name":"list_inactive_customers","displayName":"List Inactive Customers","description":"List customers who havent booked recently","props":{},"requireAuth":true,"errorHandlingOptions":{"continueOnFailure":{"defaultValue":false},"retryOnFailure":{"defaultValue":false}}},"send_email":{"name":"send_email","displayName":"Send Email","description":"Send an email using a SmoothSchedule email template","props":{},"requireAuth":true,"errorHandlingOptions":{"continueOnFailure":{"defaultValue":false},"retryOnFailure":{"defaultValue":false}}},"list_email_templates":{"name":"list_email_templates","displayName":"List Email Templates","description":"Get all available email templates","props":{},"requireAuth":true,"errorHandlingOptions":{"continueOnFailure":{"defaultValue":false},"retryOnFailure":{"defaultValue":false}}},"custom_api_call":{"name":"custom_api_call","displayName":"Custom API Call","description":"Make a custom API request","props":{},"requireAuth":true,"errorHandlingOptions":{"continueOnFailure":{"defaultValue":false},"retryOnFailure":{"defaultValue":false}}}}', - '{"event_created":{"name":"event_created","displayName":"Event Created","description":"Triggers when a new event is created","props":{},"type":"WEBHOOK","handshakeConfiguration":{"strategy":"NONE"},"requireAuth":true,"testStrategy":"SIMULATION"},"event_updated":{"name":"event_updated","displayName":"Event Updated","description":"Triggers when an event is updated","props":{},"type":"WEBHOOK","handshakeConfiguration":{"strategy":"NONE"},"requireAuth":true,"testStrategy":"SIMULATION"},"event_cancelled":{"name":"event_cancelled","displayName":"Event Cancelled","description":"Triggers when an event is cancelled","props":{},"type":"WEBHOOK","handshakeConfiguration":{"strategy":"NONE"},"requireAuth":true,"testStrategy":"SIMULATION"},"event_status_changed":{"name":"event_status_changed","displayName":"Event Status Changed","description":"Triggers when event status changes","props":{},"type":"WEBHOOK","handshakeConfiguration":{"strategy":"NONE"},"requireAuth":true,"testStrategy":"SIMULATION"}}', - '{"type":"CUSTOM_AUTH","displayName":"Connection","description":"Connect to your SmoothSchedule account","required":true,"props":{"baseUrl":{"displayName":"API URL","description":"Your SmoothSchedule API URL","required":true,"type":"SECRET_TEXT"},"apiToken":{"displayName":"API Token","description":"Your API token from Settings","required":true,"type":"SECRET_TEXT"}}}', - 'CUSTOM', - 'REGISTRY', - ARRAY['PRODUCTIVITY', 'SALES_AND_CRM'], - ARRAY['smoothschedule'], - 100, - platform_id - ); - - -- Python Code piece - INSERT INTO piece_metadata ( - id, name, "displayName", "logoUrl", description, version, - "minimumSupportedRelease", "maximumSupportedRelease", - actions, triggers, auth, "pieceType", "packageType", categories, authors, "projectUsage", "platformId" - ) VALUES ( - 'pythoncode00001', - '@activepieces/piece-python-code', - 'Python Code', - 'https://api.smoothschedule.com/images/python-logo.svg', - 'Execute custom Python code in your workflows', - '0.0.1', - '0.36.1', - '99999.99999.9999', - '{"run_python":{"name":"run_python","displayName":"Run Python Code","description":"Execute Python code and return results","props":{"code":{"displayName":"Python Code","description":"The Python code to execute","required":true,"type":"LONG_TEXT"}},"requireAuth":false,"errorHandlingOptions":{"continueOnFailure":{"defaultValue":false},"retryOnFailure":{"defaultValue":false}}}}', - '{}', - NULL, - 'CUSTOM', - 'REGISTRY', - ARRAY['DEVELOPER_TOOLS'], - ARRAY['smoothschedule'], - 0, - platform_id - ); - - -- Ruby Code piece - INSERT INTO piece_metadata ( - id, name, "displayName", "logoUrl", description, version, - "minimumSupportedRelease", "maximumSupportedRelease", - actions, triggers, auth, "pieceType", "packageType", categories, authors, "projectUsage", "platformId" - ) VALUES ( - 'rubycode000001', - '@activepieces/piece-ruby-code', - 'Ruby Code', - 'https://api.smoothschedule.com/images/ruby-logo.svg', - 'Execute custom Ruby code in your workflows', - '0.0.1', - '0.36.1', - '99999.99999.9999', - '{"run_ruby":{"name":"run_ruby","displayName":"Run Ruby Code","description":"Execute Ruby code and return results","props":{"code":{"displayName":"Ruby Code","description":"The Ruby code to execute","required":true,"type":"LONG_TEXT"}},"requireAuth":false,"errorHandlingOptions":{"continueOnFailure":{"defaultValue":false},"retryOnFailure":{"defaultValue":false}}}}', - '{}', - NULL, - 'CUSTOM', - 'REGISTRY', - ARRAY['DEVELOPER_TOOLS'], - ARRAY['smoothschedule'], - 0, - platform_id - ); + RAISE NOTICE 'Piece configuration complete'; END $$; diff --git a/activepieces-fork/packages/pieces/community/smoothschedule/src/index.ts b/activepieces-fork/packages/pieces/community/smoothschedule/src/index.ts index cd7c8858..d78998b2 100644 --- a/activepieces-fork/packages/pieces/community/smoothschedule/src/index.ts +++ b/activepieces-fork/packages/pieces/community/smoothschedule/src/index.ts @@ -56,10 +56,8 @@ export type SmoothScheduleAuth = { props: SmoothScheduleAuthProps; }; -// SmoothSchedule logo - hosted on Django backend -// For local development: http://lvh.me:8000/static/images/logo-branding.png -// For production: https://smoothschedule.com/static/images/logo-branding.png -const SMOOTHSCHEDULE_LOGO = 'http://lvh.me:8000/static/images/logo-branding.png'; +// SmoothSchedule logo - use production URL (works in both environments via DNS) +const SMOOTHSCHEDULE_LOGO = 'https://smoothschedule.com/static/images/logo-branding.png'; export const smoothSchedule = createPiece({ displayName: 'SmoothSchedule', diff --git a/deploy.sh b/deploy.sh index 8de6397a..77645fcd 100755 --- a/deploy.sh +++ b/deploy.sh @@ -240,18 +240,21 @@ echo ">>> Setting up Activepieces database..." AP_DB_USER=\$(grep AP_POSTGRES_USERNAME .envs/.production/.activepieces | cut -d= -f2) AP_DB_PASS=\$(grep AP_POSTGRES_PASSWORD .envs/.production/.activepieces | cut -d= -f2) AP_DB_NAME=\$(grep AP_POSTGRES_DATABASE .envs/.production/.activepieces | cut -d= -f2) +# Get the Django postgres user from env file (this is the superuser for our DB) +DJANGO_DB_USER=\$(grep POSTGRES_USER .envs/.production/.postgres | cut -d= -f2) +DJANGO_DB_USER=\${DJANGO_DB_USER:-postgres} if [ -n "\$AP_DB_USER" ] && [ -n "\$AP_DB_PASS" ] && [ -n "\$AP_DB_NAME" ]; then # Check if user exists, create if not - docker compose -f docker-compose.production.yml exec -T postgres psql -U \${POSTGRES_USER:-postgres} -d postgres -tc "SELECT 1 FROM pg_roles WHERE rolname='\$AP_DB_USER'" | grep -q 1 || { + docker compose -f docker-compose.production.yml exec -T postgres psql -U "\$DJANGO_DB_USER" -d postgres -tc "SELECT 1 FROM pg_roles WHERE rolname='\$AP_DB_USER'" | grep -q 1 || { echo " Creating Activepieces database user..." - docker compose -f docker-compose.production.yml exec -T postgres psql -U \${POSTGRES_USER:-postgres} -d postgres -c "CREATE USER \"\$AP_DB_USER\" WITH PASSWORD '\$AP_DB_PASS';" + docker compose -f docker-compose.production.yml exec -T postgres psql -U "\$DJANGO_DB_USER" -d postgres -c "CREATE USER \"\$AP_DB_USER\" WITH PASSWORD '\$AP_DB_PASS';" } # Check if database exists, create if not - docker compose -f docker-compose.production.yml exec -T postgres psql -U \${POSTGRES_USER:-postgres} -d postgres -tc "SELECT 1 FROM pg_database WHERE datname='\$AP_DB_NAME'" | grep -q 1 || { + docker compose -f docker-compose.production.yml exec -T postgres psql -U "\$DJANGO_DB_USER" -d postgres -tc "SELECT 1 FROM pg_database WHERE datname='\$AP_DB_NAME'" | grep -q 1 || { echo " Creating Activepieces database..." - docker compose -f docker-compose.production.yml exec -T postgres psql -U \${POSTGRES_USER:-postgres} -d postgres -c "CREATE DATABASE \$AP_DB_NAME OWNER \"\$AP_DB_USER\";" + docker compose -f docker-compose.production.yml exec -T postgres psql -U "\$DJANGO_DB_USER" -d postgres -c "CREATE DATABASE \$AP_DB_NAME OWNER \"\$AP_DB_USER\";" } echo " Activepieces database ready." else