diff --git a/.github/workflows/base64-templates.yml b/.github/workflows/base64-templates.yml index 98f2e221..80010d10 100644 --- a/.github/workflows/base64-templates.yml +++ b/.github/workflows/base64-templates.yml @@ -2,13 +2,11 @@ name: Generate Base64 Blueprints Table on: pull_request: - paths: - - 'blueprints/**' + branches: + - main push: branches: - main - paths: - - 'blueprints/**' jobs: encode-and-comment: @@ -18,37 +16,43 @@ jobs: - name: Checkout repo uses: actions/checkout@v4 - - name: Generate base64 table + - name: Generate base64 for blueprints id: generate run: | echo "### 📝 Blueprints Base64 Table" > comment.md echo '' >> comment.md - echo '| Template | Base64 |' >> comment.md - echo '|----------|--------|' >> comment.md + + echo "You can use the base64 value to import the blueprint into the UI." >> comment.md + echo "
" >> comment.md + echo "🔍 Show all blueprints base64" >> comment.md + echo '' >> comment.md for dir in blueprints/*; do if [ -d "$dir" ]; then TEMPLATE_NAME=$(basename "$dir") - + COMPOSE_FILE="$dir/docker-compose.yml" TEMPLATE_FILE="$dir/template.yml" - - if [ -f "$COMPOSE_FILE" ] && [ -f "$TEMPLATE_FILE" ]; then - CONTENT=$(cat "$COMPOSE_FILE" "$TEMPLATE_FILE" | base64 -w 0) - SHORT_CONTENT="${CONTENT:0:50}..." # Primera parte para la tabla - echo "| $TEMPLATE_NAME | \`$SHORT_CONTENT\` |" >> comment.md - # Detalle completo - echo '' >> comment.md - echo "#### $TEMPLATE_NAME Full Base64" >> comment.md + if [ -f "$COMPOSE_FILE" ] && [ -f "$TEMPLATE_FILE" ]; then + COMPOSE_CONTENT=$(jq -Rs . < "$COMPOSE_FILE") + TEMPLATE_CONTENT=$(jq -Rs . < "$TEMPLATE_FILE") + + JSON="{\"compose\":$COMPOSE_CONTENT,\"config\":$TEMPLATE_CONTENT}" + BASE64_JSON=$(echo -n "$JSON" | base64 -w 0) + + echo "#### $TEMPLATE_NAME" >> comment.md echo '' >> comment.md echo '```' >> comment.md - echo "$CONTENT" >> comment.md + echo "$BASE64_JSON" >> comment.md echo '```' >> comment.md + echo '' fi fi done + echo '
' >> comment.md + - name: Post comment to PR uses: marocchino/sticky-pull-request-comment@v2 if: github.event_name == 'pull_request' diff --git a/.github/workflows/validate.yml b/.github/workflows/validate.yml new file mode 100644 index 00000000..dfdd0e38 --- /dev/null +++ b/.github/workflows/validate.yml @@ -0,0 +1,105 @@ +name: Validate Blueprints Structure and Meta + +on: + pull_request: + branches: + - main + push: + branches: + - main + +jobs: + validate: + runs-on: ubuntu-latest + + steps: + - name: Checkout repository + uses: actions/checkout@v4 + + - name: Validate blueprint folders and files + run: | + echo "🔍 Validating blueprints folder structure..." + + ERROR=0 + + # Loop through each blueprint folder + for dir in blueprints/*; do + if [ -d "$dir" ]; then + TEMPLATE_NAME=$(basename "$dir") + + COMPOSE_FILE="$dir/docker-compose.yml" + TEMPLATE_FILE="$dir/template.yml" + + if [ ! -f "$COMPOSE_FILE" ]; then + echo "❌ Missing docker-compose.yml in $TEMPLATE_NAME" + ERROR=1 + fi + + if [ ! -f "$TEMPLATE_FILE" ]; then + echo "❌ Missing template.yml in $TEMPLATE_NAME" + ERROR=1 + fi + fi + done + + if [ $ERROR -eq 1 ]; then + echo "❌ Blueprint folder validation failed." + exit 1 + else + echo "✅ Blueprint folders validated successfully." + fi + + - name: Validate meta.json matches blueprint folders and logo files + run: | + echo "🔍 Validating meta.json against blueprint folders and logos..." + + ERROR=0 + + # Read all blueprint folder names into an array + FOLDERS=($(ls -1 blueprints)) + + # Extract ids and logos from meta.json + IDS_AND_LOGOS=$(jq -c '.[] | {id, logo}' meta.json) + + # Validate each id in meta.json exists as a folder + for item in $IDS_AND_LOGOS; do + ID=$(echo "$item" | jq -r '.id') + LOGO=$(echo "$item" | jq -r '.logo') + + # Check if folder exists + if [ ! -d "blueprints/$ID" ]; then + echo "❌ meta.json id \"$ID\" does not have a matching folder in blueprints/" + ERROR=1 + continue + fi + + # Check if logo file exists inside its folder + if [ ! -f "blueprints/$ID/$LOGO" ]; then + echo "❌ Logo \"$LOGO\" defined for \"$ID\" does not exist in blueprints/$ID/" + ERROR=1 + fi + done + + # Validate each folder has a matching id in meta.json + META_IDS=$(jq -r '.[].id' meta.json) + for FOLDER in "${FOLDERS[@]}"; do + FOUND=0 + for ID in $META_IDS; do + if [ "$FOLDER" == "$ID" ]; then + FOUND=1 + break + fi + done + + if [ "$FOUND" -eq 0 ]; then + echo "❌ Folder \"$FOLDER\" has no matching id in meta.json" + ERROR=1 + fi + done + + if [ $ERROR -eq 1 ]; then + echo "❌ meta.json validation failed." + exit 1 + else + echo "✅ meta.json validated successfully." + fi diff --git a/blueprints/pocketbase/template.yml b/blueprints/pocketbase/template.yml index 905d0806..472ad645 100644 --- a/blueprints/pocketbase/template.yml +++ b/blueprints/pocketbase/template.yml @@ -7,6 +7,6 @@ config: port: 80 host: ${main_domain} - env: {} # No hay variables de entorno por defecto + env: {} - mounts: [] # No hay archivos para montar por defecto + mounts: [] diff --git a/blueprints/umami/docker-compose.yml b/blueprints/umami/docker-compose.yml new file mode 100644 index 00000000..26efd337 --- /dev/null +++ b/blueprints/umami/docker-compose.yml @@ -0,0 +1,34 @@ +services: + umami: + image: ghcr.io/umami-software/umami:postgresql-v2.16.1 + restart: always + healthcheck: + test: ["CMD-SHELL", "curl http://localhost:3000/api/heartbeat"] + interval: 5s + timeout: 5s + retries: 5 + depends_on: + db: + condition: service_healthy + environment: + DATABASE_URL: postgresql://umami:umami@db:5432/umami + DATABASE_TYPE: postgresql + APP_SECRET: ${APP_SECRET} + db: + image: postgres:15-alpine + restart: always + healthcheck: + test: ["CMD-SHELL", "pg_isready -U $${POSTGRES_USER} -d $${POSTGRES_DB}"] + interval: 5s + timeout: 5s + retries: 5 + + volumes: + - db-data:/var/lib/postgresql/data + environment: + POSTGRES_DB: umami + POSTGRES_USER: umami + POSTGRES_PASSWORD: umami + +volumes: + db-data: diff --git a/blueprints/umami/template.yml b/blueprints/umami/template.yml new file mode 100644 index 00000000..ece3e01a --- /dev/null +++ b/blueprints/umami/template.yml @@ -0,0 +1,13 @@ +variables: + main_domain: ${randomDomain} + +config: + domains: + - serviceName: umami + port: 3000 + host: ${main_domain} + + env: + APP_SECRET: ${base64:64} + + mounts: [] \ No newline at end of file diff --git a/blueprints/umami/umami.png b/blueprints/umami/umami.png new file mode 100644 index 00000000..de2f7615 Binary files /dev/null and b/blueprints/umami/umami.png differ diff --git a/meta.json b/meta.json index 1ae699dd..3ebaad8e 100644 --- a/meta.json +++ b/meta.json @@ -31,5 +31,21 @@ "analytics", "privacy" ] + }, + { + "id": "umami", + "name": "Umami", + "version": "v2.16.1", + "description": + "Umami is a simple, fast, privacy-focused alternative to Google Analytics.", + "logo": "umami.png", + "links": { + "github": "https://github.com/umami-software/umami", + "website": "https://umami.is", + "docs": "https://umami.is/docs" + }, + "tags": [ + "analytics" + ] } ]