fix:meliisearch api, added in config file, readme for getting/creatin… #286
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: Build and Deploy | |
| on: | |
| push: | |
| branches: [main] | |
| workflow_dispatch: # Allows manual triggering | |
| jobs: | |
| build-and-deploy: | |
| # Prod | |
| # runs-on: ubuntu-latest | |
| # Self hosted | |
| runs-on: self-hosted | |
| environment: production # This tells GitHub to use the production environment secrets | |
| steps: | |
| - name: Checkout code | |
| uses: actions/checkout@v4 | |
| with: | |
| # fetch-depth: 0 is recommended for a more reliable diff across multiple commits in a push | |
| fetch-depth: 0 | |
| lfs: true | |
| - name: Verify LFS and database file | |
| run: | | |
| echo "🔎 Verifying Git LFS and SQLite DB presence..." | |
| git lfs version || true | |
| echo "LFS-tracked files:" | |
| git lfs ls-files || true | |
| echo "Listing DB directories:" | |
| ls -l ./db || true | |
| ls -l ./frontend/db || true | |
| echo "File type of DB files (if present):" | |
| for f in ./db/*.db ./frontend/db/*.db; do | |
| if [ -f "$f" ]; then file "$f" || true; fi | |
| done | |
| - name: Pull LFS objects explicitly (workaround) | |
| run: | | |
| echo "⬇️ Pulling LFS objects explicitly..." | |
| git lfs pull --include="db/**,frontend/db/**" || git lfs pull || true | |
| - name: Detect changed sections | |
| id: detect-changes | |
| run: | | |
| echo "🔍 Detecting changes based on custom build rules..." | |
| # Use a more robust diff command that covers all commits in a push | |
| all_changed=$(git diff --name-only ${{ github.event.before }} ${{ github.event.after }} || git diff --name-only HEAD~1 HEAD) | |
| if [ -z "$all_changed" ]; then | |
| echo "❌ No changes detected. Skipping build and deploy." | |
| echo "should_deploy=false" >> $GITHUB_OUTPUT | |
| exit 0 | |
| fi | |
| echo "📁 All changed files:" | |
| echo "$all_changed" | sed 's/^/ - /' | |
| changed_dirs="" | |
| requires_full_rebuild=false | |
| # Helper function to add a directory to the list if it's not already there | |
| add_dir() { | |
| if [[ ! "$changed_dirs" =~ (^|[[:space:]])$1($|[[:space:]]) ]]; then | |
| changed_dirs="$changed_dirs $1" | |
| fi | |
| } | |
| for file in $all_changed; do | |
| case "$file" in | |
| frontend/src/pages/t/*) | |
| add_dir "t" | |
| ;; | |
| frontend/src/pages/markdown_pages/tldr/*|frontend/src/pages/tldr/*) | |
| add_dir "markdown_pages" | |
| add_dir "tldr" | |
| ;; | |
| frontend/src/pages/html_pages/cheatsheets/*|frontend/src/pages/c/*) | |
| add_dir "html_pages" | |
| add_dir "c" | |
| ;; | |
| frontend/src/pages/svg_icons/*) | |
| add_dir "svg_icons" | |
| ;; | |
| frontend/src/pages/png_icons/*) | |
| # If png_icons changes, we build both png_icons and svg_icons | |
| add_dir "png_icons" | |
| add_dir "svg_icons" | |
| ;; | |
| frontend/src/pages/emojies/*) | |
| add_dir "emojies" | |
| ;; | |
| frontend/src/pages/cars/*) | |
| add_dir "cars" | |
| ;; | |
| frontend/src/pages/mcp/*) | |
| add_dir "mcp" | |
| ;; | |
| frontend/public/mcp/*) | |
| add_dir "mcp" | |
| ;; | |
| frontend/src/pages/index.astro) | |
| # Index page changes only need to rebuild the index page | |
| add_dir "index_only" | |
| ;; | |
| frontend/public/*) | |
| # Public assets are served directly, just sync without rebuild | |
| add_dir "public_assets_only" | |
| ;; | |
| frontend/src/*) | |
| # Other src changes (components, layouts, styles, etc.) need full rebuild | |
| requires_full_rebuild=true | |
| ;; | |
| *) | |
| # You can add a default case here if needed, for example, to build everything | |
| # echo "Change detected in unhandled path: $file" | |
| ;; | |
| esac | |
| done | |
| # Clean up leading/trailing whitespace | |
| changed_dirs=$(echo "$changed_dirs" | xargs) | |
| # Determine final build strategy | |
| if [ "$requires_full_rebuild" = true ]; then | |
| echo "🔧 Components/layouts/styles changed - requires full rebuild" | |
| echo "📦 Build strategy: full_rebuild" | |
| echo "should_deploy=true" >> $GITHUB_OUTPUT | |
| echo "changed_sections=full_rebuild" >> $GITHUB_OUTPUT | |
| elif [ -n "$changed_dirs" ]; then | |
| echo "📦 Changed sections to build: $changed_dirs" | |
| echo "should_deploy=true" >> $GITHUB_OUTPUT | |
| echo "changed_sections=$changed_dirs" >> $GITHUB_OUTPUT | |
| else | |
| echo "❌ No changes matched the build rules. Skipping deployment." | |
| echo "should_deploy=false" >> $GITHUB_OUTPUT | |
| fi | |
| # - name: Setup Bun | |
| # if: steps.detect-changes.outputs.should_deploy == 'true' | |
| # uses: oven-sh/setup-bun@v1 | |
| # with: | |
| # bun-version: "1.1.34" | |
| # - name: Cache Bun dependencies | |
| # if: steps.detect-changes.outputs.should_deploy == 'true' | |
| # uses: actions/cache@v4 | |
| # with: | |
| # path: ~/.bun | |
| # key: ${{ runner.os }}-bun-${{ hashFiles('**/bun.lockb') }} | |
| # restore-keys: | | |
| # ${{ runner.os }}-bun- | |
| - name: Setup Node.js | |
| if: steps.detect-changes.outputs.should_deploy == 'true' | |
| uses: actions/setup-node@v4 | |
| with: | |
| node-version: "22.17.0" | |
| - name: Exclude unchanged sections from build | |
| if: steps.detect-changes.outputs.should_deploy == 'true' | |
| run: | | |
| echo "🔧 Excluding unchanged sections from build..." | |
| cd frontend/src/pages | |
| changed_sections="${{ steps.detect-changes.outputs.changed_sections }}" | |
| echo "Building strategy: $changed_sections" | |
| # Only exclude sections if we're doing selective page builds | |
| if [[ "$changed_sections" != "full_rebuild" && "$changed_sections" != "public_assets_only" && "$changed_sections" != "index_only" ]]; then | |
| echo "🎯 Selective build mode" | |
| for dir in */; do | |
| if [ -d "$dir" ]; then | |
| dir_name=${dir%/} | |
| if [[ "$changed_sections" =~ (^|[[:space:]])$dir_name($|[[:space:]]) ]] || [[ "$dir_name" == _* ]]; then | |
| echo "✅ Including: $dir_name" | |
| else | |
| echo "❌ Excluding: $dir_name -> _$dir_name" | |
| mv "$dir" "_$dir" | |
| fi | |
| fi | |
| done | |
| elif [[ "$changed_sections" == "full_rebuild" ]]; then | |
| echo "🔧 Full rebuild mode - building all sections" | |
| for dir in */; do | |
| if [ -d "$dir" ]; then | |
| dir_name=${dir%/} | |
| echo "✅ Including: $dir_name" | |
| fi | |
| done | |
| elif [[ "$changed_sections" == "index_only" ]]; then | |
| echo "🏠 Index page only mode - excluding all other pages" | |
| for dir in */; do | |
| if [ -d "$dir" ]; then | |
| dir_name=${dir%/} | |
| if [[ "$dir_name" == _* ]]; then | |
| echo "✅ Keeping excluded: $dir_name" | |
| else | |
| echo "❌ Excluding: $dir_name -> _$dir_name" | |
| mv "$dir" "_$dir" | |
| fi | |
| fi | |
| done | |
| else | |
| echo "🔧 Public assets only mode - no page exclusions needed" | |
| fi | |
| # - name: Install dependencies | |
| # if: steps.detect-changes.outputs.should_deploy == 'true' && steps.detect-changes.outputs.changed_sections != 'public_assets_only' | |
| # run: | | |
| # echo "📦 Installing dependencies with Bun..." | |
| # cd frontend | |
| # bun install | |
| - name: Install dependencies | |
| if: steps.detect-changes.outputs.should_deploy == 'true' && steps.detect-changes.outputs.changed_sections != 'public_assets_only' | |
| run: | | |
| echo "📦 Installing dependencies..." | |
| cd frontend | |
| npm install | |
| - name: Clean dist directory | |
| if: steps.detect-changes.outputs.should_deploy == 'true' && steps.detect-changes.outputs.changed_sections != 'public_assets_only' | |
| run: | | |
| echo "🧹 Cleaning dist directory before build..." | |
| cd frontend | |
| rm -rf dist | |
| mkdir -p dist | |
| # - name: Build project | |
| # if: steps.detect-changes.outputs.should_deploy == 'true' && steps.detect-changes.outputs.changed_sections != 'public_assets_only' | |
| # run: | | |
| # echo "🔨 Building project with Bun..." | |
| # cd frontend | |
| # bun run astro build | |
| - name: Build project | |
| if: steps.detect-changes.outputs.should_deploy == 'true' && steps.detect-changes.outputs.changed_sections != 'public_assets_only' | |
| run: | | |
| echo "🔨 Building project..." | |
| cd frontend | |
| npx astro build | |
| env: | |
| NODE_OPTIONS: "--max-old-space-size=16384" | |
| UV_THREADPOOL_SIZE: "16" | |
| PUBLIC_GA_ID: ${{ secrets.PUBLIC_GA_ID }} | |
| MEILISEARCH_API_KEY: ${{ secrets.MEILISEARCH_API_KEY }} | |
| - name: Restore original folder structure | |
| if: always() && steps.detect-changes.outputs.should_deploy == 'true' | |
| run: | | |
| echo "🔄 Restoring original folder structure..." | |
| cd frontend/src/pages | |
| for dir in _*/; do | |
| if [ -d "$dir" ]; then | |
| original_name=${dir#_} | |
| original_name=${original_name%/} | |
| echo "Restoring _$original_name to $original_name" | |
| mv "$dir" "$original_name/" | |
| fi | |
| done | |
| - name: Setup SSH | |
| if: steps.detect-changes.outputs.should_deploy == 'true' | |
| uses: webfactory/ssh-agent@v0.8.0 | |
| with: | |
| ssh-private-key: ${{ secrets.SSH_PRIVATE_KEY }} | |
| - name: Add server to known hosts | |
| if: steps.detect-changes.outputs.should_deploy == 'true' | |
| run: | | |
| ssh-keyscan -H ${{ secrets.SSH_HOST }} >> ~/.ssh/known_hosts | |
| - name: Deploy to server | |
| if: steps.detect-changes.outputs.should_deploy == 'true' | |
| run: | | |
| echo "🚀 Deploying to server..." | |
| echo "Deployed sections: ${{ steps.detect-changes.outputs.changed_sections }}" | |
| changed_sections="${{ steps.detect-changes.outputs.changed_sections }}" | |
| if [[ "$changed_sections" == "public_assets_only" ]]; then | |
| echo "📁 Only public assets changed - syncing files only" | |
| rsync -rvz --delete --no-perms --no-owner --no-group --no-times --progress ./frontend/public/ ${{ secrets.SSH_USERNAME }}@${{ secrets.SSH_HOST }}:/tools/ | |
| elif [[ "$changed_sections" == "full_rebuild" ]]; then | |
| echo "📦 Full deployment - deleting old files on server" | |
| rsync -rvz --delete --no-perms --no-owner --no-group --no-times --progress ./frontend/dist/ ${{ secrets.SSH_USERNAME }}@${{ secrets.SSH_HOST }}:/tools/ | |
| else | |
| echo "📦 Partial deployment - keeping existing files on server" | |
| rsync -rvz --no-perms --no-owner --no-group --no-times --progress ./frontend/dist/ ${{ secrets.SSH_USERNAME }}@${{ secrets.SSH_HOST }}:/tools/ | |
| fi | |
| - name: Purge entire Cloudflare cache | |
| if: steps.detect-changes.outputs.should_deploy == 'true' | |
| run: | | |
| echo "Purging entire Cloudflare cache..." | |
| RESPONSE=$(curl -s -X POST "https://api.cloudflare.com/client/v4/zones/${{ secrets.CLOUDFLARE_ZONE_ID }}/purge_cache" \ | |
| -H "Authorization: Bearer ${{ secrets.CLOUDFLARE_CACHE_PURGE_API_KEY }}" \ | |
| -H "Content-Type: application/json" \ | |
| --data '{"purge_everything":true}') | |
| echo "Response:" | |
| echo "$RESPONSE" | |
| - name: Generate search index data and deploy to server | |
| run: | | |
| echo "🔍 Generating search index data..." | |
| cd search-index | |
| make sync-search-index | |
| echo "✅ Search index generation completed" | |
| - name: Skip deployment message | |
| if: steps.detect-changes.outputs.should_deploy == 'false' | |
| run: | | |
| echo "⏭️ Skipping deployment - no changes matched the build rules." |